Skip to main content
Glama

Ariadne

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

Нить Ариадны — выход из лабиринта микросервисов.

Граф зависимостей API между сервисами и семантическая навигация по коду для микросервисной архитектуры. MCP stdio-сервер для ИИ-ассистентов (Claude Code, Cursor, Windsurf) с CLI-аналогом для скриптов. Статический анализ «только для чтения» на базе SQLite + TF-IDF + эмбеддингов.


Для кого это

  • ИИ-ассистенты (Claude Code, Cursor, Windsurf) — структурированное представление зависимостей между сервисами, подходящее для контекстного окна, вместо сырого вывода grep.

  • Backend-инженеры, отслеживающие функционал через 4+ сервиса — GraphQL, REST, Kafka и вызовы фронтенда, разрешаемые одним запросом.

  • Platform-инженеры и ревьюеры, выполняющие анализ влияния изменений — покажите полную цепочку вызовов, которую затрагивает изменение в одном сервисе, перед его деплоем.

  • Новые инженеры, изучающие топологию незнакомых микросервисов по одному бизнес-термину.


Related MCP server: TempoGraph

Зачем

Ariadne индексирует только слой контрактов — GraphQL-мутации, REST-эндпоинты, Kafka-топики, запросы фронтенда — и ничего больше. Эта узкая специализация позволяет результатам помещаться в контекстное окно ИИ.

Подход

Проблема, которую решает Ariadne

grep / rg по репозиториям

Тонет в DTO, тестах, конфигах

IDE "Find Usages"

Останавливается на границах сервисов

Дашборды сервис-меша

Требуют продакшн-трафика; нет привязки к фичам

Инструменты полного 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 → chargeCustomer

Claude резюмирует: "createOrder — это GraphQL-мутация в gateway, которая перенаправляется в orders-svc через POST /orders, что публикует Kafka-событие order-created, которое потребляет billing-svc для списания средств с клиента."

~500 токенов на запрос-ответ. Эквивалентный grep -r createOrder по четырем репозиториям вернул бы 40+ совпадений в DTO, тестах и конфигах (~2000 токенов), при этом слой контрактов был бы скрыт.


Золотой путь

Рекомендуемый рабочий процесс, когда ИИ-ассистент управляет Ariadne через MCP-сервер.

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.


Быстрый старт

Три команды, затем перезапустите 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-workspace

install идемпотентен — запускайте его повторно после получения нового кода или позвольте ассистенту вызвать rescan, когда он увидит stale_warning. См. --help для флагов (--no-scan, --force, --snippet, --marker).


Инструменты

Что видит ассистент после завершения install и перезапуска Claude Code:

Инструмент

Аргументы

Назначение

query_chains

hint, top_n (по умолчанию 3)

Бизнес-термин → кластеры между сервисами

expand_node

name (поддерживается частичное совпадение)

Соседи известного узла в один прыжок

rescan

(нет)

Обновление индекса на месте при получении stale_warning; инкрементально по git-hash, возвращает {nodes, duration_ms}

ariadne_help

(нет)

Руководство по настройке + диагностика конфигурации (отсутствие БД, пустой индекс, устаревшее сканирование)

log_feedback

hint, accepted, node_ids, ...

Ручной дизлайк (позитивный фидбек неявный — см. Feedback boost в разделе Архитектура)


Конфигурация

Формат конфига

{
  "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" }
        }
      ]
    }
  ]
}

Пути разрешаются относительно файла конфигурации. Каждый репозиторий перечисляет один или несколько сканеров — либо по имени (строка), либо как объект с дополнительными опциями.

Доступные сканеры

Сканер

Что ищет

graphql

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

http

Spring @RestController (Java/Kotlin) → HTTP-эндпоинты

kafka

Топики в Spring application.yaml + @KafkaListener + продюсеры

backend_clients

Исходящие вызовы Spring RestClient / RestTemplate в *Client.*

frontend_graphql

TypeScript gql\`` литералы → фронтенд Query/Mutation

frontend\_rest

Вызовы axios/fetch в TS/TSX файлах, исключая тесты/моки/типы

cube

Определения cube.js cube(...)\

Пользовательские сканеры

Любой язык или фреймворк, не охваченный выше, можно добавить, не меняя исходный код 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). Из диалога с ИИ вызовите rescan(); из терминала — python3 main.py scan --config <path>.

Результаты поначалу кажутся общими — станут ли они лучше? Да. Последующие вызовы expand_node неявно записывают позитивный фидбек; шаг переранжирования (confidence + 0.15 * boost) продвигает кластеры, которые были полезны для похожих подсказок. Результаты в первый день — это чисто лексическое ранжирование; через несколько недель они будут отражать паттерны навигации вашей команды. Основано на подсчетах, а не на обученной модели.

Можно ли использовать его без ИИ-ассистента — просто как 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"]) и сравниваются с помощью Jaccard с весами IDF:

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

Кластеризация

Двухэтапная, O(anchors × neighbours), не зависит от количества репозиториев.

  1. Токенизация подсказки, оценка по всем узлам, сохранение топ-30 якорей с score ≥ 0.15.

  2. Для каждого якоря извлечение его ребер из БД (один запрос IN) и сохранение топ-12 соседей с edge_score ≥ 0.25.

  3. Объединение окрестностей якорей, которые пересекаются на ≥ 25%.

  4. В каждом кластере берется топ-2 узла на (service, type), ограничение 12.

  5. Confidence = средний edge score · 0.6 + разнообразие типов · 0.2 + разнообразие сервисов · 0.2.

Эмбеддинги

TF-IDF — основной канал поиска. bge-small-en-v1.5 (ONNX int8 квантованный) используется для двух узких задач:

  • Резервный поиск: когда лексическое пересечение слабое, найти синонимы (например, assignHomeworkassignStudentsToTask) и добавить их в набор якорей.

  • Переранжирование: сначала строятся top_n × 2 кластеров, затем они пересортировываются по 0.6 · confidence + 0.4 · max_cos(hint, cluster_nodes) и обрезаются до top_n.

Модель ONNX весит ~34 МБ (int8) и работает на CPU через onnxruntime. Холодный старт ~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.py

Pre-commit хук в hooks/pre-commit запускает test_semantic_hint.py — включите его один раз после клонирования:

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

Дорожная карта

  • Больше источников Kafka, помимо application.yaml + @KafkaListener + KafkaTemplate.send

  • Настройка весов TF-IDF для очень высокочастотных доменных токенов

  • Более сильный сигнал фидбека: настройка затухания, веса для сервисов, обобщение между подсказками (текущий буст основан на количестве внутри одной подсказки)

  • Режим наблюдения: хуки в git post-commit / событиях файлов для автоматического запуска rescan вместо ожидания stale_warning

  • Полировка expand_node: более четкие условия триггера, меньшая поверхность ввода, вывод, указывающий на следующий шаг

  • Передача параметров во все инструменты: имена, ориентированные на задачи, вместо имен реализации; унификация префиксов глаголов для согласованности именования

Не является целью

  • LLM как основной судья (медленно, дорого, невоспроизводимо)

  • Визуализация / бэкенд графовой БД

  • Извлечение полного графа вызовов AST


Лицензия

MIT — см. 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