Skip to main content
Glama

Ariadne

License: MIT Python 3.10+ MCP Status ariadne MCP server Awesome MCP Servers

Ariadnes Faden — ein Ausweg aus dem Microservice-Labyrinth.

Dienstübergreifender API-Abhängigkeitsgraph und semantische Codenavigation für Microservice-Architekturen. MCP-stdio-Server für KI-Coding-Assistenten (Claude Code, Cursor, Windsurf), mit einem CLI-Zwilling für Skripte. Statische Read-only-Analyse auf Basis von SQLite + TF-IDF + Embeddings.


Für wen ist das gedacht?

  • KI-Coding-Assistenten (Claude Code, Cursor, Windsurf) — eine strukturierte, dienstübergreifende Abhängigkeitsansicht, die in das Kontextfenster passt, anstelle von roher grep-Ausgabe.

  • Backend-Entwickler, die ein Feature über 4+ Dienste hinweg verfolgen — GraphQL-, REST-, Kafka- und Frontend-Aufrufe in einer einzigen Abfrage aufgelöst.

  • Plattform- und Review-Teams, die dienstübergreifende Auswirkungsanalysen durchführen — zeigen Sie die gesamte Aufrufkette auf, die eine Änderung in einem Dienst betrifft, bevor sie veröffentlicht wird.

  • Neue Entwickler (Onboarding), die eine unbekannte Microservice-Topologie ausgehend von einem einzigen Geschäftsbegriff kartieren.


Related MCP server: TempoGraph

Warum?

Ariadne indexiert nur die Vertragsebene — GraphQL-Mutationen, REST-Endpunkte, Kafka-Topics, Frontend-Abfragen — sonst nichts. Diese Fokussierung sorgt dafür, dass die Ergebnisse in ein KI-Kontextfenster passen.

Ansatz

Problem, das Ariadne löst

grep / rg über Repos hinweg

Ertrinkt in DTOs, Tests, Konfigurationen

IDE "Find Usages"

Stoppt an Dienstgrenzen

Service-Mesh-Dashboards

Benötigt Produktionsdatenverkehr; kein Feature-Mapping

Vollständige AST / Call-Graph-Tools

Langsam im Aufbau; zu viele Details


Beispiel

Sie fragen Claude: "Wo lebt createOrder im gesamten Stack?" Claude ruft mitten im Gespräch query_chains auf und erhält:

Top Cluster #1  [confidence: 0.91]
  Services: gateway, orders-svc, billing-svc, web
  - [web]          Frontend Mutation: createOrder
  - [gateway]      GraphQL Mutation:  createOrder
  - [orders-svc]   HTTP POST /orders: createOrder
  - [orders-svc]   Kafka Topic:       order-created
  - [billing-svc]  Kafka Listener:    order-created → chargeCustomer

Claude fasst dann zusammen: "createOrder ist eine GraphQL-Mutation im gateway, die via POST /orders an orders-svc weitergeleitet wird, welcher ein order-created Kafka-Event veröffentlicht, das von billing-svc konsumiert wird, um den Kunden zu belasten."

~500 Token Round-Trip. Ein äquivalenter grep -r createOrder über vier Repos hinweg würde 40+ Treffer in DTOs, Tests und Konfigurationen bei ~2000 Token liefern, wobei die Vertragsebene verborgen bliebe.


Der goldene Pfad

Der beabsichtigte Workflow, wenn ein KI-Assistent Ariadne über den MCP-Server steuert.

1. query_chains(hint="createOrder")
     → ranked clusters across services. Start here for cross-service context.

2. expand_node(name="order-created")
     → one-hop neighbours of a known node. Within 10 min of a matching
       query_chains, this auto-logs positive feedback — the expand IS the signal.

3. Read the files the returned clusters / neighbours point at.

4. log_feedback(hint, accepted=False, ...)
     → manual thumbs-down only. Positive feedback is captured in step 2.

Bei einer stale_warning rufen Sie rescan() auf und versuchen es erneut. Siehe FAQ.


Schnellstart

Drei Befehle, dann Claude Code neu starten.

pip install mcp onnxruntime tokenizers huggingface_hub
cp ariadne.config.example.json ariadne.config.json   # edit repos inside
python3 main.py install ariadne.config.json ~/your-workspace

install ist idempotent — führen Sie es nach dem Abrufen von neuem Code erneut aus oder lassen Sie den Assistenten rescan aufrufen, wenn er eine stale_warning sieht. Siehe --help für Flags (--no-scan, --force, --snippet, --marker).


Tools

Was der Assistent sieht, sobald install abgeschlossen und Claude Code neu gestartet wurde:

Tool

Argumente

Zweck

query_chains

hint, top_n (Standard 3)

Geschäftsbegriff → dienstübergreifende Cluster

expand_node

name (Teilübereinstimmung unterstützt)

Nachbarn eines bekannten Knotens (ein Hop)

rescan

(keine)

Aktualisiert den Index, wenn eine Antwort eine stale_warning enthält; git-hash-inkrementell, gibt {nodes, duration_ms} zurück

ariadne_help

(keine)

Einrichtungsanleitung + Laufzeit-Konfigurationsdiagnose (fehlende DB, leerer Index, veralteter Scan)

log_feedback

hint, accepted, node_ids, ...

Manuelles "Daumen runter" (positives Feedback ist implizit — siehe Feedback-Boost unter Architektur)


Konfiguration

Konfigurationsformat

{
  "repos": [
    {
      "name": "gateway",
      "path": "../gateway",
      "scanners": ["graphql"]
    },
    {
      "name": "orders-svc",
      "path": "../orders-svc",
      "scanners": [
        "http",
        "kafka",
        {
          "type": "backend_clients",
          "client_target_map": { "billing": "billing-svc", "user": "user-svc" }
        }
      ]
    },
    {
      "name": "web",
      "path": "../web",
      "scanners": [
        "frontend_graphql",
        {
          "type": "frontend_rest",
          "base_class_service": { "OrdersApiService": "orders-svc" }
        }
      ]
    }
  ]
}

Die Pfade werden relativ zur Konfigurationsdatei aufgelöst. Jedes Repo listet einen oder mehrere Scanner auf — entweder nach Namen (String) oder als Objekt mit zusätzlichen Optionen.

Verfügbare Scanner

Scanner

Sucht nach

graphql

.graphql / .gql SDL → Query / Mutation / Subscription / Type

http

Spring @RestController (Java/Kotlin) → HTTP-Endpunkte

kafka

Spring application.yaml Topics + @KafkaListener + Producer

backend_clients

Spring RestClient / RestTemplate ausgehende Aufrufe in *Client.*

frontend_graphql

TypeScript gql\`literals → Frontend Query/Mutation

frontend_rest

axios/fetch-Aufrufe in TS/TSX-Dateien, exklusive Tests/Mocks/Types

cube

cube.js cube(...)\ Definitionen

Benutzerdefinierte Scanner

Jede Sprache oder jedes Framework, das oben nicht abgedeckt ist, kann hinzugefügt werden, ohne den Quellcode von Ariadne zu ändern. Implementieren Sie scanner.BaseScanner, legen Sie das Modul an einen Ort, den Python importieren kann, und referenzieren Sie die Klasse über den punktierten Pfad in ariadne.config.json:

{
  "name": "my-go-service",
  "path": "../my-go-service",
  "scanners": [
    {
      "type": "my_scanners.go_scanner:GoRouteScanner",
      "route_file": "cmd/server/routes.go"
    }
  ]
}

"type" ist "module.path:ClassName". Jeder andere Schlüssel wird an __init__ übergeben.

# my_scanners/go_scanner.py
from scanner import BaseScanner

class GoRouteScanner(BaseScanner):
    def __init__(self, route_file: str = "routes.go"):
        self.route_file = route_file

    def scan(self, repo_path: str, service: str) -> list[dict]:
        # parse repo_path/self.route_file, return node dicts
        return [{"id": f"{service}::http::GET::/ping", "type": "http_endpoint",
                 "raw_name": "ping", "service": service,
                 "source_file": self.route_file,
                 "method": "GET", "path": "/ping", "fields": []}]

FAQ

Benötigt Ariadne einen laufenden Cluster, Server oder Netzwerk? Nein. Reine statische Analyse. Quelle → lokales SQLite (ariadne.db, embeddings.db, feedback.db). Keine Netzwerkaufrufe, keine Uploads.

Woher weiß es, wann ein erneuter Scan erforderlich ist? Wenn der älteste Scan älter als 7 Tage ist, enthalten MCP-Antworten ein stale_warning-Feld (das CLI gibt dieselbe Warnung an stderr aus). Rufen Sie aus einem KI-Gespräch rescan() auf; von der Shell aus python3 main.py scan --config <path>.

Die Ergebnisse wirken anfangs generisch — werden sie besser? Ja. expand_node-Folgeaufrufe protokollieren implizit positives Feedback; der Boost-Rerank-Schritt (confidence + 0.15 * boost) fördert Cluster, die für ähnliche Hinweise nützlich waren. Die Ergebnisse am ersten Tag sind rein lexikalisches Ranking; nach einigen Wochen spiegeln sie die Navigationsmuster Ihres Teams wider. Zählerbasiert, kein gelerntes Modell.

Kann ich es ohne KI-Assistenten verwenden — nur als CLI? Ja. python3 main.py scan / query / expand / stats — null Abhängigkeiten über Python 3.10 hinaus. MCP ist dennoch der empfohlene Weg.


Architektur

ariadne/
├── scanner/       # per-framework extractors → node dicts
├── normalizer/    # camelCase/snake/kebab → tokens
├── scoring/       # IDF-Jaccard engine + bge-small embedder
├── store/         # SQLite: ariadne.db / embeddings.db / feedback.db
├── query/         # query / expand entry points
├── mcp_server.py  # MCP stdio server
├── main.py        # CLI
└── tests/         # pytest suite

Scoring

Die Mathematik dahinter ist Information Retrieval, nicht Graphentheorie. Knotennamen werden tokenisiert (createOrder["create", "order"]) und mit IDF-gewichteter Jaccard-Ähnlichkeit verglichen:

idf_jaccard(A, B) = Σ idf(t)  (t ∈ A ∩ B)  /  Σ idf(t)  (t ∈ A ∪ B)
idf(t)           = log(N / df(t))

Seltene Token dominieren; hochfrequente Domänenwörter (task, id, service) dämpfen sich selbst, keine Stoppwortliste erforderlich.

base  = idf_jaccard(name) * 0.55 + idf_jaccard(fields) * 0.45
score = min(base * role_mult * service_mult, 1.0)

role_mult    = 1.3   for complementary pairs
                     (GraphQL Mutation ↔ Kafka topic ↔ HTTP POST,
                      GraphQL Query ↔ Cube Query ↔ HTTP GET)
service_mult = 1.25  cross-service / 0.8 same-service

Clustering

Zweistufig, O(Anker × Nachbarn), unabhängig von der Anzahl der Repos.

  1. Tokenisiere den Hinweis, bewerte ihn gegen alle Knoten, behalte die Top 30 Anker mit score ≥ 0.15.

  2. Ziehe für jeden Anker seine Kanten aus der DB (einzelne IN-Abfrage) und behalte die Top 12 Nachbarn mit edge_score ≥ 0.25.

  3. Führe Anker-Nachbarschaften zusammen, die sich zu ≥ 25% überschneiden.

  4. Nimm pro Cluster die Top 2 Knoten pro (service, type), begrenzt auf 12.

  5. Konfidenz = mittlerer Kantenscore · 0.6 + Typ-Diversität · 0.2 + Dienst-Diversität · 0.2.

Embeddings

TF-IDF ist der primäre Abrufkanal. bge-small-en-v1.5 (ONNX int8 quantisiert) wird für zwei enge Aufgaben verwendet:

  • Abruf-Fallback: Wenn die Token-Überschneidung schwach ist, finde Synonyme (z. B. assignHomeworkassignStudentsToTask) und füge sie dem Anker-Set hinzu.

  • Reranking: Erstelle zuerst top_n × 2 Cluster, sortiere dann neu nach 0.6 · confidence + 0.4 · max_cos(hint, cluster_nodes) und kürze auf top_n.

Das ONNX-Modell ist ~34 MB groß (int8 quantisiert) und läuft auf der CPU via onnxruntime. Kaltstart ~0.3s. Vektoren werden in embeddings.db zwischengespeichert; nur der Abfragehinweis wird zur Abfragezeit eingebettet.

Feedback-Boost

Ein abschließender Rerank-Schritt, der das Ranking an das Vokabular Ihres Teams anpasst — kein Modelltraining, keine Uploads. feedback.db ist lokal pro Entwickler.

Jeder query_chains-Aufruf speichert zurückgegebene Cluster für 10 Minuten zwischen. Ein nachfolgender expand_node(name), der einen Teilstring-Treffer eines Knotens in einem ausstehenden Cluster findet, schreibt automatisch eine accepted=True-Zeile — das Expandieren IST das Signal. log_feedback(hint, accepted, ...) ist der manuelle Ausweg für "Daumen runter".

Beim nächsten query() für denselben Hinweis:

final_score = confidence + 0.15 * sum(prior_accepted_count per node in cluster)

Gewichtung (0.15) und Zerfallsfenster (90 Tage) sind bewusst konservativ gewählt — lexikalische Konfidenz dominiert weiterhin. Deaktivieren mit export ARIADNE_FEEDBACK_BOOST=0.


Tests

python3 tests/test_semantic_hint.py
python3 tests/test_feedback_boost.py
python3 tests/test_implicit_feedback.py
python3 tests/test_onnx_embedder.py

A Pre-Commit-Hook unter hooks/pre-commit führt test_semantic_hint.py aus — einmal pro Klon aktivieren mit:

ln -sf ../../hooks/pre-commit .git/hooks/pre-commit

Roadmap

  • Mehr Kafka-Quellen über application.yaml + @KafkaListener + KafkaTemplate.send hinaus

  • TF-IDF-Gewichtungsoptimierung für sehr hochfrequente Domänen-Token

  • Stärkeres Feedback-Signal: Zerfalls-Tuning, dienstspezifische Gewichtung, hinweisübergreifende Generalisierung (der aktuelle Boost ist zählerbasiert innerhalb desselben Hinweises)

  • Watch-Modus: Hook in Git Post-Commit / Datei-Events, um rescan automatisch auszulösen, anstatt auf eine stale_warning zu warten

  • expand_node Produkt-Politur: klarere Auslösebedingungen, kleinere Eingabeoberfläche, Ausgabe, die auf den nächsten Schritt hinweist

  • Parameterübergabe über alle Tools hinweg: aufgabenorientierte Namen statt Implementierungsnamen; Vereinheitlichung von Verb-Präfixen für Namenskonsistenz

Nicht-Ziele

  • LLM als primärer Richter (langsam, teuer, nicht reproduzierbar)

  • Visualisierung / Graph-Datenbank-Backend

  • Vollständige AST-Call-Graph-Extraktion


Lizenz

MIT — siehe LICENSE.

Install Server
A
security – no known vulnerabilities
A
license - permissive license
A
quality - A tier

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/whyy9527/ariadne'

If you have feedback or need assistance with the MCP directory API, please join our Discord server