Skip to main content
Glama

mcp-project-helper

Минимальный MCP (Model Context Protocol) сервер, который даёт AI-ассистенту для программирования — в частности, Claude Code — небольшой, безопасный набор инструментов (tools) для работы с одной конкретной директорией проекта: поиск по её файлам, чтение файла, поиск по локальной документации и запуск предварительно одобренной проверки (тестов).

Проект реализован поэтапно (Stage 0 → Stage 3, история промптов — в PROMPTS.md); текущая стадия — Stage 3: финализация. Все четыре tool реализованы и покрыты тестами (Stage 1), сервер подключён к Claude Code и проверен вручную реальными запросами через Claude Code CLI (Stage 2–3, evidence — в evidence/).

О проекте

Вместо того чтобы давать ассистенту прямой доступ к shell или неограниченный доступ к файловой системе, проект предоставляет узкую, легко аудируемую поверхность из четырёх tools:

  • search_project_files — поиск текста, ограниченный корнем проекта.

  • read_project_file — чтение одного файла, ограниченное корнем проекта.

  • get_docs — поиск по локальной документации в docs/ этого репозитория.

  • run_project_check — запуск проверки из белого списка (сейчас это tests), но никогда произвольной shell-команды.

Это учебный проект (домашнее задание) — цель которого не покрыть все возможные случаи использования, а показать сквозной, honestly-документированный пример MCP-сервера: от каркаса и примитивов безопасности (Stage 0), через реальную реализацию tools (Stage 1), до интеграции с IDE-агентом и воспроизводимых evidence реальных вызовов (Stage 2–3).

Related MCP server: GPT Commander

Что такое MCP и как работает подключение агента

MCP (Model Context Protocol) — открытый протокол на основе JSON-RPC, описывающий, как AI-ассистент (клиент/хост, например Claude Code) обнаруживает и вызывает внешние инструменты (tools), предоставляемые отдельным процессом (MCP-сервером), без того чтобы ассистент имел прямой доступ к shell, сети или файловой системе хоста.

В этом проекте используется stdio-транспорт — самый простой и самый распространённый способ для локальных инструментов:

  1. Хост (Claude Code) читает свою MCP-конфигурацию (.mcp.json) и запускает сервер как обычный локальный подпроцесс, с указанной командой/аргументами и переменными окружения.

  2. Хост и сервер обмениваются JSON-RPC-сообщениями через stdin/stdout этого подпроцесса (отсюда требование, что stdout зарезервирован только под протокол — см. раздел "Логирование и отладка").

  3. Хост вызывает initialize() — сервер отвечает своим именем/версией (mcp-project-helper 0.1.0) и возможностями.

  4. Хост вызывает list_tools() — сервер возвращает список зарегистрированных tools с их именем, описанием и JSON Schema входных параметров (inputSchema), сгенерированной MCP SDK из сигнатуры функции.

  5. Когда пользователь (или сама модель) решает вызвать один из tools, хост отправляет call_tool(name, arguments); сервер выполняет соответствующую Python-функцию и возвращает структурированный результат (см. "Контракт вывода tools" ниже) либо ошибку уровня tool.

  6. Никакого сетевого порта не открывается: жизненный цикл сервера полностью привязан к подпроцессу, запущенному хостом — если хост закрывает подключение, подпроцесс завершается.

Здесь нет обращений ни к одному LLM/AI API (OpenAI, Anthropic и т. д.): этот сервер только предоставляет tools, которые вызывает клиент (Claude Code); "поиск" в get_docs — простое детерминированное совпадение подстроки по секциям Markdown, без embeddings/векторной БД. Для запуска сервера не нужен никакой API-ключ.

Что считается tool в данном сервере

Tool — это обычная функция Python, декорированная @mcp.tool(), принимающая JSON-сериализуемые аргументы и возвращающая dict[str, Any]. MCP SDK автоматически:

  • генерирует inputSchema (JSON Schema) из сигнатуры и аннотаций типов аргументов функции — отдельно эту схему нигде не приходится описывать руками;

  • превращает аннотацию возвращаемого значения -> dict[str, Any] в структурированный вывод tool (outputSchema/structuredContent), см. "Контракт вывода tools" ниже;

  • превращает необработанное исключение Python внутри tool-функции в структурированный результат с ошибкой на уровне tool (CallToolResult.is_error = True), не роняя саму MCP-сессию.

Все четыре регистрации находятся рядом в server.py:37-58; каждая тонкая обёртка, обращённая к MCP (docstring которой становится описанием tool, видимым модели), делегирует вызов настоящей реализации в tools/*.py, отделяя сигнатуру уровня протокола от логики.

Стек

  • Python 3.14 (requires-python = ">=3.10" в pyproject.toml — это реальная нижняя граница используемого MCP SDK, а не утверждение, что работает только 3.14).

  • Официальный MCP Python SDK (пакет mcp, установленная версия 2.0.0) — предоставляет фреймворк сервера (mcp.server.MCPServer), регистрацию tools (@mcp.tool()) и stdio-транспорт (mcp.run(transport="stdio")).

  • pytest — единственная dev-зависимость, для набора тестов.

  • Нет интеграции с LLM/AI API и нет сетевого транспорта (HTTP/SSE не настроен) — см. предыдущий раздел.

Архитектура

src/mcp_project_helper/
  server.py        точка входа: создаёт MCPServer, регистрирует tools, запускает stdio
  config.py        корень проекта / корень docs / настройки логирования / whitelist проверок / лимиты
  security.py      resolve_within_root() — единый шлюз ограничения путей
  logging_setup.py логирование в stderr (+ опционально файл), не затрагивая stdout
  tools/
    search_project_files.py   поиск текста в пределах корня проекта
    read_project_file.py      чтение одного файла в пределах корня проекта
    get_docs.py                поиск по секциям markdown в docs/
    run_project_check.py       запуск подпроцесса из белого списка

Каждый tool, работающий с файлами, проходит через security.resolve_within_root(root, relative_path) прежде, чем открыть какой-либо путь. config.py определяет корень проекта из переменной окружения MCP_PROJECT_HELPER_ROOT (по умолчанию ./demo_project), поэтому сервер можно направить на любой проект без изменения кода.

Реализованные MCP tools

search_project_files(query, path=".", max_results=50)

Рекурсивно ищет по текстовым файлам под path (относительно корня проекта; по умолчанию — весь корень) точное совпадение подстроки query. Пропускает директории из config.IGNORED_DIR_NAMES (.git, .venv, __pycache__, node_modules, ...) и любые директории *.egg-info. Файлы проверяются на бинарный контент (байт NUL или невалидный UTF-8 в первых 4 КБ) и молча пропускаются, а не приводят к ошибке. Никогда не идёт по символическим ссылкам на директории или файлы за пределами корня — каждый путь-кандидат дополнительно проверяется через resolve_within_root в дополнение к стандартному поведению os.walk, не следующему по символическим ссылкам на директории.

max_results ограничен сверху значением config.SEARCH_RESULTS_CAP (200); совпавшие строки длиннее config.SEARCH_MAX_LINE_CHARS (300) обрезаются; файлы больше config.SEARCH_MAX_FILE_BYTES (2 МБ) пропускаются, а не сканируются.

Реализация: tools/search_project_files.py:41-130.

read_project_file(path)

Читает один текстовый файл по пути path (относительно корня проекта). Отклоняет директории, несуществующие файлы и бинарный контент (байт NUL или невалидный UTF-8). Содержимое ограничено значением config.READ_MAX_FILE_BYTES (200 КБ) — файлы большего размера возвращаются обрезанными, а не отклоняются.

Реализация: tools/read_project_file.py:25-69.

get_docs(query=None, max_results=10)

Ищет по docs/*.md (рекурсивно), разбитым на секции по заголовкам Markdown. При наличии query возвращает секции, чей заголовок или тело содержат искомую подстроку (без учёта регистра), каждая с указанием исходного файла и заголовка. Без query возвращает список из одной секции на файл — перечень того, какая документация существует. Ограничено только config.get_docs_root() — никогда не корнем проекта.

max_results ограничен сверху значением config.DOCS_RESULTS_CAP (50); фрагменты (snippets) ограничены значением config.DOCS_MAX_SNIPPET_CHARS (800 символов).

Реализация: tools/get_docs.py:58-114.

run_project_check(check_name)

Запускает проверку из белого списка. check_name ищется в config.ALLOWED_CHECKS до того, как что-либо запускается — неизвестное имя немедленно вызывает ошибку, подпроцесс при этом никогда не запускается. Argv из белого списка выполняется через subprocess.run(argv, shell=False, cwd=<корень проекта>, timeout=...): без shell, с фиксированной рабочей директорией, и ничего от вызывающей стороны не добавляется в командную строку.

Реализация: tools/run_project_check.py:32-90.

Whitelist

ALLOWED_CHECKS = {
    "tests": [sys.executable, "-m", "pytest", "-q"],
}

Определено в config.py:55-57. sys.executable (а не просто строка "pytest") используется, чтобы проверка всегда выполнялась с тем же интерпретатором/окружением, что и сам сервер, независимо от того, что первым стоит в PATH. Здесь намеренно нет записи lint: в этом репозитории нет зависимости или конфигурации ruff, поэтому подключение проверки "lint" было бы либо фикцией, либо обманом. Добавить её можно позже (config.ALLOWED_CHECKS["lint"] = [sys.executable, "-m", "ruff", "check", "."]), когда ruff станет настоящей зависимостью проекта с реальной конфигурацией — механизм whitelist уже поддерживает это без каких-либо других изменений кода.

Таймаут (config.CHECK_TIMEOUT_SECONDS, по умолчанию 60 с) и ограничение объёма вывода (config.CHECK_MAX_OUTPUT_CHARS, по умолчанию 20 000 символов на поток) применяются к каждому запуску проверки.

Tool outputs contract

Каждый tool возвращает обычный Python dict из функции с аннотацией -> dict[str, Any]; MCP SDK автоматически распознаёт это как структурированный вывод tool (заполняет CallToolResult.structured_content и выводит outputSchema) — здесь нигде вручную не сериализуются результаты в JSON-строку. Ошибочные ситуации (некорректный ввод, выход за пределы пути, неизвестная проверка, файл не найден, бинарный контент и т. д.) вызывают исключение Python, а не возврат dict; SDK автоматически превращает это в результат с ошибкой на уровне tool (CallToolResult.is_error = True). Единственное исключение — таймаут проверки: это легитимный результат выполнения успешно запущенной проверки, а не ошибка входных данных, поэтому он возвращается как структурированный dict {"status": "error", ...}, а не вызывает исключение.

search_project_files

{
  "status": "success",
  "query": "apply_discount",
  "path": ".",
  "matches": [
    {"file": "demo_app/services.py", "line": 12, "text": "def apply_discount(order: Order, percent: float) -> float:"}
  ],
  "count": 4,
  "truncated": false
}

read_project_file

{
  "status": "success",
  "file": "demo_app/models.py",
  "content": "...",
  "size": 397,
  "truncated": false
}

get_docs

{
  "status": "success",
  "query": "whitelist",
  "results": [
    {"file": "architecture.md", "heading": "Whitelist", "snippet": "..."}
  ],
  "count": 1,
  "truncated": false
}

run_project_check

{
  "status": "success",
  "check_name": "tests",
  "exit_code": 0,
  "stdout": "...",
  "stderr": "",
  "truncated": false
}

При таймауте: {"status": "error", "check_name": ..., "error": "check timed out after 60s", "exit_code": null, "stdout": "...", "stderr": "...", "truncated": ...}.

Названия полей и конвенции status/count/truncated выше считаются устойчивым контрактом на будущее, а не деталью реализации.

Ограничения безопасности

  • Ограничение путей: security.resolve_within_root (security.py:19-50) отклоняет абсолютные пути, обход через .. (на любую глубину), байты NUL и символические ссылки, ведущие за пределы настроенного корня. Используется в read_project_file и search_project_files относительно корня проекта, а также повторно в search_project_files для каждого файла-кандидата во время обхода. Покрыто unit-тестами в tests/test_security.py и подтверждено вручную реальным негативным тестом через Claude Code (см. "Результаты проверки" ниже, тест 6).

  • Отсутствие выхода за пределы через символические ссылки при обходе: search_project_files и get_docs никогда не идут по символическим ссылкам на директории (поведение os.walk по умолчанию) и полностью пропускают символические ссылки на файлы.

  • Отсутствие произвольных shell-команд: run_project_check проверяет запрошенное имя проверки по config.ALLOWED_CHECKS (config.py:55-57) до того, как что-либо будет запущено; неизвестные имена отклоняются немедленно, а сама проверка выполняется через subprocess.run(argv, shell=False, ...) с фиксированным cwd и без каких-либо аргументов, добавленных вызывающей стороной.

  • Ограниченный вывод везде: каждый tool ограничивает объём возвращаемых данных — max_results + жёсткие пределы для поиска и docs, ограничение по байтам для чтения файлов, ограничение по символам + таймаут для вывода проверки — так что ни один вызов не может вернуть неограниченный объём данных или работать бесконечно.

  • stdout остаётся чистым: всё логирование идёт через logging_setup.py в stderr (и опционально в файл лога); ничто в сервере не пишет в stdout, который зарезервирован для JSON-RPC framing протокола MCP.

  • Отсутствие секретов в логах: сервер вообще не принимает никаких API-ключей или учётных данных. Каждый реальный вызов tool логирует имя tool, его безопасные входные параметры (строки запроса, пути, имена проверок, количество/размер результатов — но никогда содержимое файла) и финальный status=success/status=error.

Логирование и отладка

Каждый реальный вызов tool логирует одну строку через общий логгер mcp_project_helper (stderr, плюс опциональный файл через MCP_PROJECT_HELPER_LOG_FILE), например (реальные строки из evidence/tool-calls.log):

INFO mcp_project_helper: tool=search_project_files query='apply_discount' path='.' max_results=50 matches=4 truncated=False status=success
INFO mcp_project_helper: tool=read_project_file path='demo_app/models.py' size=397 truncated=False status=success
INFO mcp_project_helper: tool=run_project_check check_name='tests' exit_code=0 status=success
INFO mcp_project_helper: tool=read_project_file path='../../../../etc/passwd' status=error

Содержимое файлов никогда не логируется — только метаданные о вызове (пути, строки запроса, размеры, количество, коды завершения). Настройка логирования — logging_setup.py:20-42.

Для отладки:

  • Уровень логирования регулируется MCP_PROJECT_HELPER_LOG_LEVEL (DEBUG, INFO, WARNING, ERROR, CRITICAL; по умолчанию INFO).

  • Файл лога задаётся MCP_PROJECT_HELPER_LOG_FILE; по умолчанию (без этой переменной) пишется только в stderr. При запуске из Claude Code (.mcp.json) он указывает на evidence/tool-calls.log.

  • Никогда не используйте print() в коде сервера — stdout зарезервирован под JSON-RPC-протокол; любой лишний вывод в stdout ломает stdio-транспорт.

  • Чтобы посмотреть, какие вызовы реально произошли в текущей сессии Claude Code, откройте файл, на который указывает MCP_PROJECT_HELPER_LOG_FILE (evidence/tool-calls.log), либо запустите сервер вручную (python -m mcp_project_helper.server) и смотрите stderr.

Установка

python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

Единственная runtime-зависимость — пакет mcp; pytest — зависимость только для разработки/тестов (обе зафиксированы в pyproject.toml).

Настройка окружения

Конфигурация задаётся через переменные окружения — скопируйте .env.example в .env и при необходимости измените значения:

Переменная

Назначение

Значение по умолчанию

MCP_PROJECT_HELPER_ROOT

Единственная директория, к которой имеют доступ файловые tools (search_project_files, read_project_file, get_docs — только к её docs/, get_docs работает от корня репозитория, а не MCP_PROJECT_HELPER_ROOT).

./demo_project

MCP_PROJECT_HELPER_LOG_FILE

Путь к файлу лога (см. "Логирование и отладка"). Логи всегда также идут в stderr.

не задано (только stderr)

MCP_PROJECT_HELPER_LOG_LEVEL

Один из DEBUG/INFO/WARNING/ERROR/CRITICAL.

INFO

Секреты (API-ключи, токены) серверу не нужны — .env.example содержит только безопасные примеры путей и уровня логирования, а .env игнорируется git'ом (см. "Структура проекта" ниже).

Запуск MCP-сервера

Запуск сервера напрямую (он будет ожидать клиента на stdin — это нормально для MCP-серверов со stdio-транспортом; выход через Ctrl+C):

python -m mcp_project_helper.server

Запуск набора тестов:

pytest -q

Запуск собственных тестов demo-проекта напрямую (то, что по умолчанию запускает run_project_check("tests"), так как MCP_PROJECT_HELPER_ROOT по умолчанию указывает на demo_project):

cd demo_project && pytest -q

Интеграция с Claude Code

Этот репозиторий содержит project-scoped файл .mcp.json в корне репозитория — конфигурация именно для Claude Code (в отличие от .vscode/mcp.json — отдельной конфигурации native MCP host VS Code; см. подробное сравнение ниже).

Claude Code обнаруживает .mcp.json при открытии папки проекта, запускает сервер как дочерний процесс и общается с ним по JSON-RPC через stdio — тот же транспорт, что используется во всех автоматизированных тестах этого проекта, просто запущенный самим Claude Code, а не тестовым harness'ом.

Подтверждённый end-to-end сценарий: Claude Code CLI → MCP server → custom tools. Все 6 проверочных запросов (см. "Результаты проверки" ниже) были реально выполнены через Claude Code CLI с этим сервером, подключённым по .mcp.json — не только сконфигурированы, а фактически вызваны, с реальными скриншотами и записями в server-side логе.

Конфигурация для Claude Code

.mcp.json:

{
  "mcpServers": {
    "mcp-project-helper": {
      "command": "${CLAUDE_PROJECT_DIR:-.}/.venv/bin/python",
      "args": ["-m", "mcp_project_helper.server"],
      "env": {
        "MCP_PROJECT_HELPER_ROOT": "${CLAUDE_PROJECT_DIR:-.}/demo_project",
        "MCP_PROJECT_HELPER_LOG_FILE": "${CLAUDE_PROJECT_DIR:-.}/evidence/tool-calls.log"
      }
    }
  }
}

${CLAUDE_PROJECT_DIR} разворачивается самим Claude Code в абсолютный путь той директории, в которую был клонирован репозиторий, поэтому файл не содержит специфичных для конкретной машины путей и не требует правок после git clone. Используется именно форма с fallback-значением ${CLAUDE_PROJECT_DIR:-.}, а не голое ${CLAUDE_PROJECT_DIR}: без :-. переменная не разворачивалась, и Claude Code пытался буквально запустить ${CLAUDE_PROJECT_DIR}/.venv/bin/python как путь к исполняемому файлу (эта ошибка была реально замечена при первой версии конфигурации Stage 2, см. REPORT.md). MCP_PROJECT_HELPER_ROOT задан явно как ${CLAUDE_PROJECT_DIR:-.}/demo_project, чтобы корень проекта, передаваемый серверу, был однозначным независимо от собственного значения по умолчанию в config.py.

Замечание по платформам: .venv/bin/python — это структура venv для Unix (macOS/Linux), используемая во всём этом проекте. В Windows эквивалентный путь — .venv\Scripts\python.exe; чтобы поддержать эту платформу тоже, .mcp.json потребовал бы второй, специфичной для Windows записи (или скрипта-обёртки) — этого не сделано, так как проект разрабатывался и проверялся только на macOS.

Конфигурация для VS Code

Этот репозиторий также содержит .vscode/mcp.jsonотдельную конфигурацию рабочей области для встроенного MCP-хоста VS Code (используемого агентным режимом GitHub Copilot Chat):

{
  "servers": {
    "mcp-project-helper": {
      "type": "stdio",
      "command": "${workspaceFolder}/.venv/bin/python",
      "args": ["-m", "mcp_project_helper.server"],
      "env": {
        "MCP_PROJECT_HELPER_ROOT": "${workspaceFolder}/demo_project",
        "MCP_PROJECT_HELPER_LOG_FILE": "${workspaceFolder}/evidence/tool-calls.log"
      }
    }
  }
}

Тот же stdio-сервер mcp-project-helper, с MCP_PROJECT_HELPER_ROOT, заданным как ${workspaceFolder}/demo_project, и MCP_PROJECT_HELPER_LOG_FILE, заданным как ${workspaceFolder}/evidence/tool-calls.log.

Почему два файла, а не один: .mcp.json и .vscode/mcp.json следуют разным, несовместимым схемам, а их переменные подстановки путей не взаимозаменяемы между хостами:

  • .mcp.json (конфигурация Claude Code) использует верхнеуровневый ключ mcpServers и разворачивает ${CLAUDE_PROJECT_DIR:-.} в корень репозитория.

  • .vscode/mcp.json (конфигурация native MCP host VS Code) использует верхнеуровневый ключ servers, явное поле "type": "stdio" и разворачивает вместо этого ${workspaceFolder} в путь открытой папки. MCP-хост VS Code не понимает ${CLAUDE_PROJECT_DIR} — при попытке открыть .mcp.json напрямую из VS Code переменная передаётся буквально, и сервер не может запуститься (spawn ${CLAUDE_PROJECT_DIR}/.venv/bin/python ENOENT) — это реально наблюдавшаяся ошибка, из-за которой и появился отдельный .vscode/mcp.json. Хранение конфигурации каждого хоста в своём файле, со своей переменной, избегает этой ошибки и позволяет использовать оба инструмента с одним и тем же клоном без того, чтобы один конфиг шёл на компромисс с синтаксисом другого.

.vscode/mcp.json — единственное исключение из общего правила игнорирования .vscode/* в .gitignore; остальное локальное состояние VS Code (settings.local.json и т. п.) не отслеживается.

Статус проверки VS Code: .vscode/mcp.json синтаксически и семантически корректен (тот же сервер, та же команда/переменные окружения, что и рабочая конфигурация Claude Code) и был провалидирован как JSON. Дополнительно подтверждён реальным скриншотом evidence/vscode_mcp_server_connected.png факт, что встроенный native MCP host VS Code реально запускает сервер по этой конфигурации: Starting server mcp-project-helperConnection state: RunningDiscovered 4 tools, с подтверждающей строкой из собственного stderr-лога процесса mcp_project_helper в этом же выводе. Это не то же самое, что подтверждение вызова custom tools через интерфейс VS Code — ни один пользовательский сценарий (search_project_files и т. д.) через этот интерфейс не выполнялся и не заявляется как проверенный. Единственная IDE-интеграция, подтверждённая вплоть до реальных вызовов tools пользователем (скриншоты + server-side логи для всех 6 сценариев) — Claude Code CLI, см. "Результаты проверки" ниже. Отдельно от обоих: интеграция через Claude Code Desktop / расширение Claude Code внутри VS Code не проверялась в этой сессии вообще — не путать ни с native MCP host VS Code (этот раздел), ни с Claude Code CLI.

Как включить MCP

Кратко (подробности — в подразделах выше):

Claude Code:

  1. Создайте venv и установите зависимости (раздел "Установка").

  2. Откройте корень репозитория в Claude Code (claude из корня репозитория).

  3. Claude Code обнаруживает .mcp.json и один раз предлагает подтвердить доверие рабочей области для сервера mcp-project-helper — подтвердите.

  4. Выполните /mcp (или claude mcp list в терминале) и убедитесь, что mcp-project-helper подключён с 4 tools.

VS Code (native MCP host, агентный режим Copilot Chat):

  1. Создайте venv так же, как для Claude Code — .vscode/mcp.json ожидает тот же .venv/bin/python.

  2. Откройте корень репозитория как папку в VS Code.

  3. VS Code обнаруживает .vscode/mcp.json и предлагает запустить сервер — запустите/подтвердите доверие.

  4. Проверьте состояние через MCP: List Servers.

Оба варианта предполагают Unix-структуру venv (.venv/bin/python); в Windows — .venv\Scripts\python.exe (не настроено, см. выше).

Проверочные запросы

Шесть сценариев, реально выполненных через Claude Code CLI для подтверждения интеграции (полная таблица с результатами — в evidence/README.md):

  1. Найди через MCP все места использования функции apply_discount в demo_project → ожидается search_project_files.

  2. Прочитай через MCP файл demo_app/models.py и кратко объясни, какие модели там определены → ожидается read_project_file.

  3. Используя MCP-документацию проекта, расскажи, какие ограничения безопасности есть у MCP-сервера → ожидается get_docs.

  4. Проверь через MCP-инструмент, проходят ли тесты demo_project → ожидается run_project_check.

  5. Используя только MCP-инструменты, найди в demo_project реализацию apply_discount, затем прочитай файл, где она определена, и объясни её параметры/возврат/расчёт скидки → ожидается цепочка из двух tools: search_project_files, затем read_project_file.

  6. (негативный / security-тест) Попробуй через MCP прочитать файл ../../../../etc/passwd → ожидается отказ read_project_file со структурированной ошибкой (путь выходит за пределы разрешённого корня).

Результаты проверки

Все 6 из 6 запросов выполнены успешно (в тесте 5 — оба ожидаемых tool, в правильном порядке; в тесте 6 успехом является ожидаемый отказ). Каждая строка подтверждена и реальным скриншотом, и независимой строкой в evidence/tool-calls.log. Полная таблица — evidence/README.md; подробный разбор с ссылками на код и логи — REPORT.md.

Tool

Итог

1

search_project_files

Успех, 4 совпадения

2

read_project_file

Успех, size=397

3

get_docs

Успех, найден раздел «Безопасность»

4

run_project_check

Успех, exit_code=0, 2/2 тестов пройдено

5

search_project_filesread_project_file

Успех, цепочка из двух tools

6

read_project_file

Успешный отказ (path traversal заблокирован)

Автоматизированные проверки (не заменяют, а дополняют ручное IDE-тестирование выше):

  • pytest -q из корня репозитория — 44 passed.

  • pytest -q внутри demo_project/2 passed.

  • Программный stdio-хендшейк (initialize() + list_tools()) — сервер сообщает mcp-project-helper 0.1.0 и ровно 4 tools: get_docs, read_project_file, run_project_check, search_project_files.

Структура проекта

mcp-project-helper/
  .mcp.json                конфигурация MCP для Claude Code (project-scoped)
  .vscode/mcp.json          конфигурация MCP для native MCP host VS Code
  .env.example              безопасные примеры переменных окружения (без секретов)
  pyproject.toml            зависимости, entry point, конфигурация pytest
  README.md                 этот файл
  REPORT.md                 итоговый отчёт по всем стадиям, со ссылками файл:строки
  PROMPTS.md                история фактически использованных промптов (Этапы 0-3)
  docs/
    architecture.md          документация, которую обслуживает get_docs
  src/mcp_project_helper/
    server.py                 точка входа: MCPServer, регистрация tools, stdio
    config.py                  корень проекта/docs, лимиты, whitelist проверок
    security.py                resolve_within_root() — ограничение путей
    logging_setup.py           логирование в stderr (+ опционально файл)
    tools/
      search_project_files.py
      read_project_file.py
      get_docs.py
      run_project_check.py
  tests/                     unit- и интеграционные тесты mcp_project_helper (44 теста)
  demo_project/              демонстрационный проект — цель для файловых tools
    demo_app/
      models.py                Product, Order
      services.py               apply_discount, OrderBuilder
      tests/test_services.py    2 теста, запускаемые run_project_check("tests")
  evidence/                  реальные доказательства ручного тестирования через Claude Code и VS Code
    README.md                  реестр всех 6 тестов с результатами + доп. evidence по VS Code
    tool-calls.log              реальный server-side лог всех 6 тестов (закоммичен)
    tool-calls.log.example      формат строки лога (шаблон)
    test1_search_project_files.png … test6_path_traversal.png   скриншоты 6 тестов Claude Code CLI (закоммичены)
    vscode_mcp_server_connected.png   доп. скриншот: native MCP host VS Code подключился, 4 tools (закоммичен)
F
license - not found
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Agent-safe code retrieval MCP server that indexes repositories and provides semantic search, file navigation, call graph analysis, and bounded file reading tools for coding agents.
    3,977,962
    3
    AGPL 3.0
  • A
    license
    A
    quality
    C
    maintenance
    Zero-config MCP server that connects local codebases to AI assistants, providing secure project tree, regex search, file reading, and tech stack tools locally.
    4
    33
    MIT

View all related MCP servers

Related MCP Connectors

  • Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.

  • MCP server for generating rough-draft project plans from natural-language prompts.

  • An MCP server that gives your AI access to the source code and docs of all public github repos

View all MCP Connectors

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/pw5rhn4tnn-dotcom/mcp-project-helper'

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