ariadne
Ariadne
Ariadne's thread — マイクロサービス迷路からの脱出方法。
マイクロサービスアーキテクチャ向けのサービス間API依存関係グラフおよびセマンティックコードナビゲーション。 AIコーディングアシスタント(Claude Code, Cursor, Windsurf)用のMCP stdioサーバーであり、スクリプト作成用のCLIも備えています。SQLite + TF-IDF + エンベディングを使用した読み取り専用の静的解析ツールです。
対象ユーザー
AIコーディングアシスタント(Claude Code, Cursor, Windsurf) — 生の
grep出力の代わりに、コンテキストウィンドウに収まる構造化されたサービス間依存関係ビューを提供します。バックエンドエンジニア — 4つ以上のサービスにまたがる機能を追跡する際、GraphQL、REST、Kafka、フロントエンドの呼び出しを1つのクエリで解決します。
プラットフォームエンジニアおよびレビュアー — サービス間影響分析を行う際、あるサービスの変更がリリース前にどの呼び出しチェーンに影響を与えるかを可視化します。
オンボーディング中のエンジニア — 単一のビジネス用語から、馴染みのないマイクロサービスのトポロジーをマッピングします。
Related MCP server: TempoGraph
なぜAriadneなのか
Ariadneはコントラクト層(GraphQLミューテーション、RESTエンドポイント、Kafkaトピック、フロントエンドクエリ)のみをインデックス化します。この絞り込みにより、結果がAIのコンテキストウィンドウに収まるようになります。
アプローチ | Ariadneが解決する問題 |
リポジトリをまたぐ | DTO、テスト、設定に埋もれてしまう |
IDEの「使用箇所の検索」 | サービスの境界で止まってしまう |
サービスメッシュダッシュボード | 本番トラフィックが必要で、機能マッピングがない |
完全なAST / コールグラフツール | ビルドが遅く、詳細すぎる |
例
Claudeに「createOrderはスタック全体でどこに存在するか?」と尋ねると、Claudeは会話の途中で query_chains を呼び出し、以下のような結果を得ます:
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 → chargeCustomerClaudeは次のように要約します:「createOrderは gateway のGraphQLミューテーションであり、POST /orders を介して orders-svc に転送されます。その後、order-created Kafkaイベントが発行され、billing-svc がそれを消費して顧客に課金します。」
約500トークンのラウンドトリップです。4つのリポジトリで grep -r createOrder を実行すると、DTO、テスト、設定にまたがって40件以上のヒットが約2000トークンで返され、コントラクト層が埋もれてしまいます。
ゴールデンパス
AIアシスタントがMCPサーバーを介してAriadneを操作する際の推奨ワークフロー。
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.stale_warning が表示されたら、rescan() を呼び出して再試行してください。FAQを参照してください。
クイックスタート
3つのコマンドを実行し、Claude Codeを再起動します。
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-workspaceinstall は冪等です。新しいコードをプルした後に再実行するか、stale_warning が表示されたらアシスタントに rescan を呼び出させてください。フラグ(--no-scan, --force, --snippet, --marker)については --help を参照してください。
ツール
install が完了し、Claude Codeが再起動された後にアシスタントが利用できるツール:
ツール | 引数 | 目的 |
|
| ビジネス用語 → サービス間クラスター |
|
| 既知のノードの隣接ノード |
| (なし) |
|
| (なし) | セットアップガイド + ランタイム設定診断(DB欠落、空のインデックス、古いスキャン) |
|
| 手動での低評価(高評価は暗黙的 — アーキテクチャの「フィードバックブースト」を参照) |
設定
設定フォーマット
{
"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" }
}
]
}
]
}パスは設定ファイルからの相対パスとして解決されます。各リポジトリには1つ以上のスキャナーをリストします(名前(文字列)または追加オプションを持つオブジェクトとして)。
利用可能なスキャナー
スキャナー | 検索対象 |
|
|
| Spring |
| Spring |
| Spring |
| TypeScript |
| TS/TSXファイル内の |
| cube.js |
カスタムスキャナー
上記に含まれていない言語やフレームワークは、Ariadneのソースコードを触らずに追加できます。scanner.BaseScanner を実装し、Pythonがインポートできる場所にモジュールを配置し、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" は "module.path:ClassName" です。その他のキーはすべて __init__ に渡されます。
# 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
Ariadneは実行中のクラスター、サーバー、ネットワークを必要としますか?
いいえ。純粋な静的解析です。ソース → ローカルSQLite(ariadne.db, embeddings.db, feedback.db)。ネットワーク呼び出しやアップロードは一切ありません。
いつ再スキャンすべきかどうやってわかりますか?
最後のスキャンから7日以上経過している場合、MCPのレスポンスに stale_warning フィールドが含まれます(CLIは同じ警告をstderrに出力します)。AIとの会話からは rescan() を呼び出し、シェルからは python3 main.py scan --config <path> を実行してください。
最初は結果が一般的ですが、改善されますか?
はい。expand_node のフォローアップは暗黙的に高評価として記録されます。ブースト再ランクステップ(confidence + 0.15 * boost)により、同様のヒントで役立ったクラスターが優先されます。初日の結果は純粋な語彙ランキングですが、数週間後にはチームのナビゲーションパターンが反映されます。学習モデルではなく、カウントベースです。
AIアシスタントなしで、CLIとしてのみ使用できますか?
はい。python3 main.py scan / query / expand / stats — Python 3.10以外の依存関係はゼロです。MCPの使用が推奨されるパスであることに変わりはありません。
アーキテクチャ
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スコアリング
数学的にはグラフ理論ではなく情報検索です。ノード名はトークン化され(createOrder → ["create", "order"])、IDF加重Jaccard係数と比較されます:
idf_jaccard(A, B) = Σ idf(t) (t ∈ A ∩ B) / Σ idf(t) (t ∈ A ∪ B)
idf(t) = log(N / df(t))希少なトークンが支配的であり、高頻度のドメイン単語(task, id, service)は自己減衰するため、ストップワードリストは不要です。
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クラスタリング
2段階、O(anchors × neighbours)、リポジトリ数に依存しません。
ヒントをトークン化し、すべてのノードとスコアを比較し、
score ≥ 0.15の上位30個のアンカーを保持します。各アンカーについて、DBからエッジを取得し(単一の
INクエリ)、edge_score ≥ 0.25の上位12個の隣接ノードを保持します。25%以上重複するアンカー近傍をマージします。
クラスターごとに、
(service, type)あたり上位2ノードを取得し、最大12個に制限します。信頼度 = 平均エッジスコア × 0.6 + 型の多様性 × 0.2 + サービスの多様性 × 0.2。
エンベディング
TF-IDFが主要なリコールチャネルです。bge-small-en-v1.5(ONNX int8量子化)は2つの限定的なタスクに使用されます:
リコールフォールバック: トークンの重複が弱い場合に同義語(例:
assignHomework↔assignStudentsToTask)を見つけ、アンカーセットに追加します。再ランキング: まず
top_n × 2のクラスターを構築し、0.6 · confidence + 0.4 · max_cos(hint, cluster_nodes)で再ソートし、top_nに切り詰めます。
ONNXモデルは約34MB(int8量子化)で、onnxruntime を介してCPU上で実行されます。コールドスタートは約0.3秒です。ベクトルは embeddings.db にキャッシュされ、クエリ時に埋め込まれるのはクエリヒントのみです。
フィードバックブースト
チームの語彙にランキングを適応させる最終再ランクステップ。モデルトレーニングやアップロードは不要です。feedback.db は開発者ごとにローカルに保存されます。
すべての query_chains 呼び出しは、返されたクラスターを10分間キャッシュします。保留中のクラスター内のノードと部分一致する expand_node(name) のフォローアップは、自動的に accepted=True 行を書き込みます(展開自体がシグナルとなります)。log_feedback(hint, accepted, ...) は低評価のための手動の回避策です。
同じヒントに対する次の query() では:
final_score = confidence + 0.15 * sum(prior_accepted_count per node in cluster)重み(0.15)と減衰ウィンドウ(90日)は意図的に保守的に設定されており、語彙的な信頼度が依然として支配的です。export ARIADNE_FEEDBACK_BOOST=0 で無効化できます。
テスト
python3 tests/test_semantic_hint.py
python3 tests/test_feedback_boost.py
python3 tests/test_implicit_feedback.py
python3 tests/test_onnx_embedder.pyhooks/pre-commit のプリコミットフックが test_semantic_hint.py を実行します。クローンごとに一度有効にしてください:
ln -sf ../../hooks/pre-commit .git/hooks/pre-commitロードマップ
application.yaml+@KafkaListener+KafkaTemplate.send以外のKafkaソースの追加非常に高頻度なドメイントークンのためのTF-IDF重み調整
より強力なフィードバックシグナル:減衰調整、サービスごとの重み付け、ヒントをまたぐ一般化(現在のブーストは同じヒント内でのカウントベース)
ウォッチモード:git post-commit / ファイルイベントにフックし、stale_warningを待たずに
rescanを自動トリガーexpand_nodeの製品としての洗練:より明確なトリガー条件、より小さな入力インターフェース、次のステップを指し示す出力すべてのツール間でのパラメータ受け渡し:実装名よりもタスク指向の名前、命名の一貫性のための動詞プレフィックスの統一
非目標
LLMを主要な判定者にする(遅く、コストがかかり、再現性がない)
可視化 / グラフデータベースバックエンド
完全なASTコールグラフ抽出
ライセンス
MIT — LICENSE を参照してください。
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