Привет, Хабр! В предыдущих | двух статьях я рассказывал про наш мультиагентный сервер и фрактальную оркестрацию, где пул ИИ-агентов совместно решает сложные задачи разработки. Но чтобы эта фрактальная группа могла работать с кодовой базой и понимать зависимости, ей нужен инструмент навигации.

Мы написали project-graph-mcp - MCP-сервер для структурного анализа кода. Агент работает зная полную архитектуру проекта, не тратя на это лишние токены. Сервер строит граф зависимостей и отдает минифицированный JSON.

Скелетон проекта

Главная фича сервера - “скелетон” проекта. Сервер парсит исходники и выдает сжатый JSON.

Сжатие получается в 10-50 раз.

{
  "L": { "SN": "SymNode", "SNG": "SymNodeGraph" },
  "s": { "files": 23, "classes": 10, "functions": 65 },
  "n": { "SN": { "m": 11, "$": 7 }, "SNG": { "m": 16, "$": 5 } },
  "e": 35, "o": 7, "d": 5, "F": 63
}

Здесь L - легенда с именами, s - общая статистика. Узел n описывает классы с количеством методов (m) и свойств ($). Модель читает этот JSON и понимает общую структуру. Если нужно копнуть глубже - вызывает expand или deps.

Мульти-язык: не только JavaScript

Изначально парсер работал только с JavaScript через AST-дерево (Acorn). Но реальные проекты редко пишутся на одном языке - серверные куски на Go часто соседствуют с фронтом на TS и питоновскими скриптами.

В версии 1.1 мы добавили парсеры для TypeScript, Python и Go. У каждого языка свои особенности синтаксиса: от специфики декораторов TS до хитрых строковых литералов в Go. Все три новых парсера построены на regex-based подходе вместо AST. Хороших AST-парсеров для этих языков на чистом JavaScript нет, а тащить тяжеловесные внешние библиотеки ради базового уровня абстракции (классы, методы, импорты) нецелесообразно. Языки имеют базовые настройки - регулярки можно адаптировать под специфичный стиль проекта.

Общая утилита stripStringsAndComments вынесена в lang-utils.js и принимает опции под каждый язык:

// Python - тройные кавычки, решётка-комментарии
stripStringsAndComments(code, { tripleQuote: true, hashComment: true })

// Go - бэктик-строки без интерполяции
stripStringsAndComments(code, { backtick: true, templateInterpolation: false })

// TypeScript - полное меню, включая ${} в шаблонных литералах
stripStringsAndComments(code) // дефолтные опции

Все парсеры возвращают единый ParseResult (классы, функции, импорты, вызовы) - одна структура для любого языка.

Метрики кода и Health Score

Помимо графа, в MCP встроены инструменты анализа: get_dead_code находит неиспользуемый код, get_complexity оценивает цикломатическую сложность, get_large_files - файлы-кандидаты на рефакторинг.

Но интереснее всего цепочки вызовов. Как authMiddleware связан с renderDashboard? get_call_chain вернет путь: authMiddleware → validateToken → loadUser → renderDashboard. Сервер собирает результаты всех проверок в Health Score от 0 до 100.

# Ищем легаси и избыточные зависимости
npx project-graph-mcp outdated .

# Проверяем цикломатическую сложность
npx project-graph-mcp complexity src/

После каждого ответа инструменты отдают подсказки (Response Hints): например, если модель нашла громоздкую функцию, сервер предложит проверить ее сложность.

Тестовые чеклисты

В project-graph-mcp мы используем паттерн JSDoc аннотаций @test и @expect для тестовых чеклистов.

/**
 * Create new user via API
 * 
 * @test request: POST /api/users with valid data
 * @expect status: 201 Created
 */
async createUser(data) { ... }

Вызов get_pending_tests возвращает список незакрытых тестов. Написав код, агент дергает mark_test_passed. Поддерживаются API, CLI, интеграционные и браузерные сценарии.

Кастомные правила и фреймворки

Из коробки в сервер зашито 11 базовых наборов (86 правил) для React 18/19, Vue 3, Express 5, TypeScript 5 и Symbiote.js. Проект распознается автоматически, модель получает адаптированную документацию через get_framework_reference.

Этого хватает для типовых случаев. Если у проекта свои конвенции - добавляй правила вручную в rules/ или поручи это агенту через set_custom_rule.

Связка с пулом агентов

Оба инструмента работают в паре. Читая граф проекта, основной IDE-агент сразу делегирует подзадачи фоновым воркерам через agent-pool-mcp. Для этого он запрашивает скелетон и передает конкретную работу Gemini-воркеру, который поднимает у себя аналогичный project-graph MCP и навигирует по графу через expand, deps и другие методы.

Подробнее о фрактальной оркестрации - в предыдущих статьях про Agent Pool.

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

Для работы нужен только Node.js 18+. Пропиши вызов npx в конфиг IDE - при следующем старте сервер скачается сам:

{
  "mcpServers": {
    "project-graph": {
      "command": "npx",
      "args": ["-y", "project-graph-mcp"]
    }
  }
}

Весь пакет - 132 кБ (47 файлов), внешних зависимостей нет. Конфигурации для Antigravity, Gemini CLI, Cursor, Claude Desktop, VS Code, Zed и других описаны в CONFIGURATION.md.

Безопасность

В сервер встроена Path Traversal Protection: все входящие пути валидируются через resolve + startsWith, поэтому агент не может выйти за пределы рабочей директории. MCP-инструменты, работающие с файлами (expand, deps, get_skeleton), наследуют эту проверку - попытка обратиться к ../../etc/passwd вернет ошибку, а не содержимое файла.

З. Ы. Исходники на GitHub, пакет в npm (версия 1.2.0).