Skip to main content
ClaudeWave

ariadne is an MCP (Model Context Protocol) server that provides AI agents with the ability to identify affected tests.

MCP ServersOfficial Registry1 stars0 forksKotlinApache-2.0Updated today
Install in Claude Code / Claude Desktop
Method: Docker · /path/to/project
Claude Code CLI
claude mcp add ariadne -- docker run -i --rm /path/to/project
claude_desktop_config.json (Claude Desktop)
{
  "mcpServers": {
    "ariadne": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "/path/to/project"]
    }
  }
}
1. Run the command above in your terminal (Claude Code), or paste the JSON config into claude_desktop_config.json (Claude Desktop).
2. Replace any <placeholder> values with your API keys or paths.
3. Restart Claude. The MCP server and its tools appear automatically.
Use cases

MCP Servers overview

<p align="center">
  <img src="doc/ariadne-banner.svg" alt="ariadne banner" width="100%">
</p>

<p align="center">
  <h1 align="center">ariadne</h1>
  <p align="center">
    <strong>MCP Server for Affected Test Selection</strong>
  </p>
  <p align="center">
    <a href="https://github.com/MikhailHal/ariadne/releases"><img src="https://img.shields.io/github/v/release/MikhailHal/ariadne?style=flat-square&color=success" alt="Release"></a>
    <a href="https://registry.modelcontextprotocol.io/v0/servers?search=io.github.MikhailHal/ariadne"><img src="https://img.shields.io/badge/MCP%20Registry-listed-6E56CF.svg?style=flat-square" alt="MCP Registry"></a>
    <a href="https://github.com/MikhailHal/homebrew-tap"><img src="https://img.shields.io/badge/homebrew-mikhailhal%2Ftap-FBB040.svg?style=flat-square&logo=homebrew&logoColor=white" alt="Homebrew"></a>
    <a href="https://github.com/MikhailHal/ariadne/pkgs/container/ariadne"><img src="https://img.shields.io/badge/ghcr.io-ariadne-2496ED.svg?style=flat-square&logo=docker&logoColor=white" alt="Container image"></a>
    <a href="LICENSE"><img src="https://img.shields.io/badge/License-Apache%202.0-blue.svg?style=flat-square" alt="License"></a>
    <a href="https://kotlinlang.org"><img src="https://img.shields.io/badge/Kotlin-2.3.0-7F52FF.svg?style=flat-square&logo=kotlin&logoColor=white" alt="Kotlin"></a>
  </p>
</p>

<br>

**ariadne** is an MCP (Model Context Protocol) server that provides AI agents with the ability to identify affected tests. Powered by [sazanami](https://github.com/MikhailHal/sazanami), it analyzes code changes and returns only the tests that need to be run.

<p align="center">
  <a href="https://glama.ai/mcp/servers/MikhailHal/ariadne">
    <img src="https://glama.ai/mcp/servers/MikhailHal/ariadne/badges/card.svg" alt="ariadne MCP server" />
  </a>
</p>

> [!IMPORTANT]
> ## ⚠️ MUST READ: Speed over Completeness
>
> ariadne is built for the agent inner loop — edit, verify, commit — where fast
> feedback matters more than exhaustive selection. Static analysis cannot trace
> every execution path: reflection, DI frameworks, and data-flow indirection
> (e.g., Flux/MVI dispatch) can hide dependencies from **any**
> affected-test-selection tool, not just ariadne.
>
> **Always keep a final line of defense in CI.** Run the full test suite (or a
> conservative selection) before merging. ariadne narrows what an agent runs
> while iterating; it is not a replacement for CI.
>
> When ariadne detects changes it cannot analyze (build scripts, resources,
> unscanned source sets), it says so explicitly in the tool response instead of
> silently reporting "no affected tests".

## Features

- **MCP Integration** — Works with Claude Code, Claude Desktop, and other MCP-compatible clients
- **Automatic Git Diff** — No need to pass diff manually; ariadne runs `git diff` internally
- **Powered by sazanami** — Uses Kotlin Analysis API for accurate static analysis

## Installation

### Homebrew (recommended)

```bash
brew install mikhailhal/tap/ariadne
```

Then register it with your MCP client — for Claude Code:

```bash
claude mcp add ariadne -- ariadne
```

Or add to your MCP client configuration manually (e.g., Claude Desktop):

```json
{
  "mcpServers": {
    "ariadne": {
      "command": "ariadne"
    }
  }
}
```

### Docker

```bash
docker run -i --rm -v /path/to/project:/workspace ghcr.io/mikhailhal/ariadne
```

Mount the project you want analyzed and pass `/workspace` as `project_path`.
The image is also listed in the [official MCP Registry](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.MikhailHal/ariadne) as `io.github.MikhailHal/ariadne`.

### Manual (release JAR)

Download `ariadne-<version>-all.jar` from [Releases](https://github.com/MikhailHal/ariadne/releases) (requires JDK 21+) and configure your client with `"command": "java", "args": ["-jar", "/path/to/ariadne-<version>-all.jar"]`.

### Build from Source

```bash
git clone --recursive https://github.com/MikhailHal/ariadne.git
cd ariadne
./gradlew shadowJar   # fat JAR: build/libs/ariadne-<version>-all.jar
```

## Usage

Once configured, AI agents can use the `get_affected_tests` tool:

### Tool: `get_affected_tests`

**Parameters:**
- `project_path` (required) — Path to the Kotlin project
- `scope` (optional, `deep` | `shallow`, default `deep`) — how far back to look:
  - **`deep`** — all changes since `base_branch` (committed *and* uncommitted). Safest; the whole branch is covered so nothing you already committed slips through unverified. May select more tests.
  - **`shallow`** — uncommitted changes only (diff against `HEAD`). Fastest, for the tight edit loop. Verifying already-committed work is left to the caller. `base_branch` is ignored.
- `base_branch` (optional, `deep` scope only) — Branch to compare against. When omitted, ariadne uses the repository's default branch (`origin/HEAD`). If that is not set (e.g. a repo with no remote), it returns an error asking you to pass `base_branch` explicitly rather than guessing.

**Returns:**
- List of affected test FQNs (fully qualified names), sorted
- If the diff contains changes outside the analyzed Kotlin sources (build scripts,
  resources, unscanned source sets), a note is appended recommending a full test run
  for those changes
- Analysis is bounded by a 120s timeout; on timeout an explicit error is returned

### Example

Agent request:
```json
{
  "name": "get_affected_tests",
  "arguments": {
    "project_path": "/path/to/your/kotlin/project"
  }
}
```

Response:
```
com.example.UserServiceTest.testCreateUser
com.example.UserRepositoryTest.testSave
```

## How It Works

```
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│  MCP Client │ ──▶ │   ariadne   │ ──▶ │  sazanami   │
│  (Agent)    │     │ (MCP Server)│     │  (Analysis) │
└─────────────┘     └─────────────┘     └─────────────┘
                           │
                           ▼
                    ┌─────────────┐
                    │  git diff   │
                    └─────────────┘
```

1. **Agent calls tool** — Passes project path to ariadne
2. **Run git diff** — ariadne executes `git diff --unified=0` against base branch
3. **Analyze with sazanami** — Build call graph and find affected tests
4. **Return results** — List of test FQNs returned to agent

## Real-World Validation: Now in Android

Measured against [Now in Android](https://github.com/android/nowinandroid)
(Google's reference Android app — 34 modules, ~268 Kotlin files):

| Metric | Result |
|---|---|
| Recall audit — 19 target functions across all layers | **18/18 valid targets detected** (the 19th had no exercising unit test; correctly not selected) |
| End-to-end response time | **~4s** (module discovery + call-graph build + BFS) |
| Module discovery | 34 modules via `settings.gradle.kts`, incl. nested modules and type-safe accessor dependencies |
| Source sets | `main`, `debug`, `prod`, `benchmark`, `testDemo`, … discovered per module (`androidTest*` excluded by design) |

Verified patterns include repositories behind project interfaces, a library-interface
override (`androidx.datastore.Serializer`), `operator fun invoke` use cases,
`@Composable` functions, extension mappers, ViewModel property-initializer chains,
and callable references. Two representative results:

- Changing `core:common`'s `asResult()` selects **14 tests across three modules**,
  including ViewModel tests reachable only through `val uiState = ...stateIn(...)`
- Changing the mapper `PopulatedNewsResource.asExternalModel()` selects **14 tests**,
  including 11 repository tests reachable only through `.map(Type::mapper)` chains

### Test-class selection rate

Every unit-test class in Now in Android was measured by changing a function in the
class it tests and checking whether that test class was selected:

| Test style | Selected |
|---|---|
| Plain unit tests (construct the object, call it) | 13 / 13 valid targets |
| Robolectric / Compose screenshot tests | **12 / 12** |
| Framework-dispatched callbacks (lint `Detector`) | 0 / 2 — see below |

Robolectric turned out **not** to be a barrier: those tests call the composable
themselves (`setContent { NiaTheme { ... } }`), so the call exists in the source.
What decides coverage is not the test runner but whether the test's own code
contains the call.

### What ariadne cannot see

The rule of thumb: **if the framework calls your code instead of your test calling
it, ariadne cannot connect them.** These are limits of static analysis, not bugs —
plan your CI safety net around them:

| Pattern | Status |
|---|---|
| Framework-invoked callbacks — Fragment/Activity lifecycle (`launchFragmentInContainer`), lint `Detector` methods, `Application.onCreate` | Not traced: no call written in the test |
| Reflection / DI-container wiring | Not traced |
| UDF dispatch (Flux/MVI) | `dispatch → collect` is never an edge, but wiring in `init` (or a `start()` the test calls) is covered conservatively via constructor chains. Subscriptions started by DI/lifecycle are **not** covered ([sazanami#38](https://github.com/MikhailHal/sazanami/issues/38)) |
| `stateIn` / `shareIn` chains (`map`, `onEach`, `flatMapLatest`, `combine`) | Covered — verified with exact selection |
| Instrumented tests (`androidTest*`) | Out of scope by design |
| Build scripts, resources, unscanned source sets | Not analyzed — reported explicitly in the tool response |
| Same-name top-level extensions in one package | Over-selected (receiver types are not part of top-level FQNs) — safe direction |
| KMP source sets (`commonMain`, `expect`/`actual`) | Enumerated, but resolution quality unverified ([#1](https://github.com/MikhailHal/ariadne/issues/1)) |

Full audit notes: [sazanami#29](https://github.com/MikhailHal/sazanami/issues/29),
[sazanami#38](https://github.com/MikhailHal/sazanami/issues/38).

## Requirements

- **JDK 21** or later
- **Git** — For diff detection

## Limitations

- Module discovery is convention-based: 

What people ask about ariadne

What is MikhailHal/ariadne?

+

MikhailHal/ariadne is mcp servers for the Claude AI ecosystem. ariadne is an MCP (Model Context Protocol) server that provides AI agents with the ability to identify affected tests. It has 1 GitHub stars and was last updated today.

How do I install ariadne?

+

You can install ariadne by cloning the repository (https://github.com/MikhailHal/ariadne) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.

Is MikhailHal/ariadne safe to use?

+

MikhailHal/ariadne has not been audited yet by our security agent. Review the original repository on GitHub before using it in production.

Who maintains MikhailHal/ariadne?

+

MikhailHal/ariadne is maintained by MikhailHal. The last recorded GitHub activity is from today, with 1 open issues.

Are there alternatives to ariadne?

+

Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.

Deploy ariadne to your cloud

Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.

Maintain this repo? Add a badge to your README

Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.

Featured on ClaudeWave: MikhailHal/ariadne
[![Featured on ClaudeWave](https://claudewave.com/api/badge/mikhailhal-ariadne)](https://claudewave.com/repo/mikhailhal-ariadne)
<a href="https://claudewave.com/repo/mikhailhal-ariadne"><img src="https://claudewave.com/api/badge/mikhailhal-ariadne" alt="Featured on ClaudeWave: MikhailHal/ariadne" width="320" height="64" /></a>

More MCP Servers

ariadne alternatives