Skip to main content
Glama

mcp-project-helper

AIプログラミングアシスタント(特にClaude Code)に、特定の1つのプロジェクトディレクトリを対象とした、小さく安全なツール群(ファイル検索、ファイル読み取り、ローカルドキュメント検索、事前承認済みチェック(テスト)の実行)を提供する、最小限のMCP(Model Context Protocol)サーバーです。

このプロジェクトは段階的に実装されています(Stage 0 → Stage 3、プロンプトの履歴はPROMPTS.mdにあります)。現在のステージはStage 3: 最終化です。4つのツールはすべて実装済みでテストでカバーされています(Stage 1)。サーバーはClaude Codeに接続され、Claude Code CLIを通じた実際のリクエストで手動検証済みです(Stage 2–3、エビデンスはevidence/にあります)。

プロジェクトについて

アシスタントにシェルへの直接アクセスや無制限のファイルシステムアクセスを許可する代わりに、このプロジェクトは4つのツールからなる、狭く監査が容易なインターフェースを提供します:

  • search_project_files — プロジェクトルートに制限されたテキスト検索。

  • read_project_file — プロジェクトルートに制限された単一ファイルの読み取り。

  • get_docs — このリポジトリのdocs/内のローカルドキュメント検索。

  • run_project_check — ホワイトリストに登録されたチェック(現在はtests)の実行。任意のシェルコマンドを実行することは決してありません。

これは学習用プロジェクト(宿題)であり、すべてのユースケースをカバーすることが目的ではなく、MCPサーバーのエンドツーエンドで正直に文書化された例を示すことが目的です:スケルトンとセキュリティプリミティブ(Stage 0)から、ツールの実際の実装(Stage 1)、IDEエージェントとの統合と実際の呼び出しの再現可能なエビデンス(Stage 2–3)まで。

Related MCP server: GPT Commander

MCPとは何か、エージェントの接続がどのように機能するか

MCP(Model Context Protocol) は、JSON-RPCベースのオープンプロトコルであり、AIアシスタント(クライアント/ホスト、例:Claude Code)が、別のプロセス(MCPサーバー)によって提供される外部ツールを、アシスタントがホストのシェル、ネットワーク、ファイルシステムに直接アクセスすることなく、発見して呼び出す方法を記述します。

このプロジェクトではstdioトランスポートを使用しています。これはローカルツールにとって最もシンプルで最も一般的な方法です:

  1. ホスト(Claude Code)は自身のMCP設定(.mcp.json)を読み取り、指定されたコマンド/引数と環境変数を使用して、サーバーを通常のローカルサブプロセスとして起動します。

  2. ホストとサーバーは、このサブプロセスのstdin/stdoutを介してJSON-RPCメッセージを交換します(そのため、stdoutはプロトコル専用に予約されているという要件があります — 「ロギングとデバッグ」セクションを参照)。

  3. ホストはinitialize()を呼び出します — サーバーは自身の名前/バージョン(mcp-project-helper 0.1.0)と機能で応答します。

  4. ホストはlist_tools()を呼び出します — サーバーは登録済みツールのリストを、名前、説明、およびMCP SDKが関数シグネチャから生成した入力パラメータのJSON Schema(inputSchema)とともに返します。

  5. ユーザー(またはモデル自身)がツールの1つを呼び出すことを決定すると、ホストはcall_tool(name, arguments)を送信します。サーバーは対応するPython関数を実行し、構造化された結果(下記の「ツール出力コントラクト」を参照)またはツールレベルのエラーを返します。

  6. ネットワークポートは開かれません。サーバーのライフサイクルは完全にホストによって起動されたサブプロセスに結びついています — ホストが接続を閉じると、サブプロセスは終了します。

ここではLLM/AI API(OpenAI、Anthropicなど)への呼び出しは一切ありません。このサーバーはクライアント(Claude Code)が呼び出すツールを提供するだけです。get_docsの「検索」は、Markdownセクションに対する単純な決定的な部分文字列マッチであり、embeddings/ベクターデータベースは使用しません。サーバーの実行にAPIキーは必要ありません。

このサーバーでツールと見なされるもの

ツールとは、@mcp.tool()でデコレートされた通常のPython関数であり、JSONシリアライズ可能な引数を受け取り、dict[str, Any]を返します。MCP SDKは自動的に以下を行います:

  • 関数の引数のシグネチャと型アノテーションからinputSchema(JSON Schema)を生成します — このスキーマを手動で記述する必要はありません。

  • 戻り値のアノテーション-> dict[str, Any]をツールの構造化出力(outputSchema/structuredContent)に変換します。下記の「ツール出力コントラクト」を参照。

  • ツール関数内の未処理のPython例外を、MCPセッション自体を落とすことなく、ツールレベルのエラーを持つ構造化結果(CallToolResult.is_error = True)に変換します。

4つの登録はすべてserver.py:37-58にまとめられています。各MCP向けの薄いラッパー(そのdocstringがモデルに見えるツールの説明になります)は、実際の実装への呼び出しをtools/*.pyに委譲し、プロトコルレベルのシグネチャをロジックから分離しています。

スタック

  • Python 3.14(pyproject.tomlrequires-python = ">=3.10" — これは使用するMCP SDKの実際の下限であり、3.14でのみ動作するという主張ではありません)。

  • 公式MCP Python SDK(パッケージmcp、インストール済みバージョン2.0.0)— サーバーフレームワーク(mcp.server.MCPServer)、ツール登録(@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       запуск подпроцесса из белого списка

ファイルを扱う各ツールは、パスを開く前にsecurity.resolve_within_root(root, relative_path)を通過します。config.pyは、環境変数MCP_PROJECT_HELPER_ROOT(デフォルトは./demo_project)からプロジェクトルートを決定するため、コードを変更することなくサーバーを任意のプロジェクトに向けることができます。

実装済みのMCPツール

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

path(プロジェクトルートからの相対パス。デフォルトはルート全体)配下のテキストファイルを再帰的に検索し、queryの部分文字列と完全一致するものを探します。config.IGNORED_DIR_NAMES.git.venv__pycache__node_modulesなど)のディレクトリと、*.egg-infoディレクトリをスキップします。ファイルはバイナリコンテンツ(最初の4KB内のNULバイトまたは無効なUTF-8)についてチェックされ、エラーにするのではなく黙ってスキップされます。ルート外のディレクトリやファイルへのシンボリックリンクを辿ることは決してありません — 各候補パスは、ディレクトリへのシンボリックリンクを辿らない標準のos.walk動作に加えて、resolve_within_rootによって追加チェックされます。

max_resultsconfig.SEARCH_RESULTS_CAP(200)によって上限が設定されます。config.SEARCH_MAX_LINE_CHARS(300)より長い一致行は切り詰められます。config.SEARCH_MAX_FILE_BYTES(2MB)より大きいファイルはスキャンされずにスキップされます。

実装: tools/search_project_files.py:41-130

read_project_file(path)

path(プロジェクトルートからの相対パス)にある単一のテキストファイルを読み取ります。ディレクトリ、存在しないファイル、バイナリコンテンツ(NULバイトまたは無効なUTF-8)を拒否します。コンテンツはconfig.READ_MAX_FILE_BYTES(200KB)によって制限されます — より大きなファイルは拒否されるのではなく、切り詰めて返されます。

実装: tools/read_project_file.py:25-69

get_docs(query=None, max_results=10)

Markdownの見出しによってセクションに分割されたdocs/*.md(再帰的)を検索します。queryがある場合、見出しまたは本文に検索文字列(大文字小文字を区別しない)を含むセクションを、ソースファイルと見出しの指定とともに返します。queryがない場合、ファイルごとに1セクションのリスト — どのようなドキュメントが存在するかの一覧を返します。config.get_docs_root()によってのみ制限されます — プロジェクトルートによって制限されることは決してありません。

max_resultsconfig.DOCS_RESULTS_CAP(50)によって上限が設定されます。スニペットは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=...)を介して実行されます:シェルなし、固定された作業ディレクトリ、呼び出し側からコマンドラインに追加されるものはありません。

実装: tools/run_project_check.py:32-90

ホワイトリスト

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

config.py:55-57で定義されています。sys.executable(単なる文字列"pytest"ではなく)が使用されるのは、PATHの先頭にあるものに関係なく、チェックが常にサーバー自体と同じインタープリター/環境で実行されるようにするためです。ここには意図的にlintエントリはありません:このリポジトリにはruffの依存関係も設定もないため、「lint」チェックを接続することは虚構か欺瞞のいずれかになります。ruffが実際の設定を持つプロジェクトの実際の依存関係になった時点で、後で追加できます(config.ALLOWED_CHECKS["lint"] = [sys.executable, "-m", "ruff", "check", "."])— ホワイトリストのメカニズムは、他のコード変更なしでこれをすでにサポートしています。

タイムアウト(config.CHECK_TIMEOUT_SECONDS、デフォルト60秒)と出力量の制限(config.CHECK_MAX_OUTPUT_CHARS、デフォルトでストリームあたり20,000文字)は、各チェック実行に適用されます。

ツール出力コントラクト

各ツールは、-> dict[str, Any]のアノテーションを持つ関数から通常のPython dictを返します。MCP SDKはこれを自動的にツールの構造化出力として認識します(CallToolResult.structured_contentを入力し、outputSchemaを出力します)— 結果を手動でJSON文字列にシリアライズする場所はここにはありません。エラー状況(不正な入力、パス境界の超過、未知のチェック、ファイルが見つからない、バイナリコンテンツなど)は、dictを返すのではなくPython例外を発生させます。SDKはこれを自動的にツールレベルのエラーを持つ結果(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_filesearch_project_files でプロジェクトルートに対して使用され、さらに search_project_files では走査中に各候補ファイルに対して繰り返し使用されます。tests/test_security.py のユニットテストでカバーされ、Claude Code 経由の実際のネガティブテストで手動確認済みです(下記「検証結果」テスト6参照)。

  • 走査時のシンボリックリンクによる範囲外への脱出の防止: search_project_filesget_docs はディレクトリへのシンボリックリンクを辿ることは決してなく(os.walk のデフォルト動作)、ファイルへのシンボリックリンクは完全にスキップします。

  • 任意のシェルコマンドの実行防止: run_project_check は、何かを実行する に、要求されたチェック名を config.ALLOWED_CHECKS (config.py:55-57) と照合します。未知の名前は即座に拒否され、チェック自体は固定の cwdsubprocess.run(argv, shell=False, ...) を通じて実行され、呼び出し側が追加した引数は一切ありません。

  • あらゆる場所での出力制限: 各ツールは返されるデータ量を制限します — 検索と docs には max_results + 厳格な上限、ファイル読み取りにはバイト数制限、チェック出力には文字数制限 + タイムアウト。したがって、どの呼び出しも無制限のデータを返したり、無限に動作したりすることはできません。

  • stdout はクリーンなまま: すべてのログは logging_setup.py を通じて stderr(およびオプションでログファイル)に出力されます。サーバー内の何も stdout には書き込まれません。stdout は MCP プロトコルの JSON-RPC フレーミング用に予約されています。

  • ログに秘密情報なし: サーバーは API キーや認証情報を一切受け取りません。実際のツール呼び出しはそれぞれ、ツール名、その安全な入力パラメータ(クエリ文字列、パス、チェック名、結果の数/サイズ — ただしファイルの内容は決して含まれない)、および最終的な status=success/status=error をログに記録します。

ログとデバッグ

実際のツール呼び出しはそれぞれ、共通ロガー mcp_project_helper を通じて1行をログに記録します(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]"

唯一のランタイム依存関係は mcp パッケージです。pytest は開発/テスト専用の依存関係です(両方とも pyproject.toml に固定されています)。

環境設定

設定は環境変数を通じて行います — .env.example.env にコピーし、必要に応じて値を変更してください:

変数

用途

デフォルト値

MCP_PROJECT_HELPER_ROOT

ファイル系ツールがアクセスできる唯一のディレクトリ(search_project_files, read_project_file, get_docs — その docs/ のみ。get_docsMCP_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サーバーの起動

サーバーを直接起動します(stdio トランスポートの MCP サーバーでは、stdin でクライアントを待機するのは正常です。終了は Ctrl+C):

python -m mcp_project_helper.server

テストスイートの実行:

pytest -q

demo プロジェクトの独自テストを直接実行します(MCP_PROJECT_HELPER_ROOT がデフォルトで demo_project を指すため、run_project_check("tests") がデフォルトで実行するもの):

cd demo_project && pytest -q

Claude Code との統合

このリポジトリは、リポジトリルートに プロジェクトスコープ ファイル .mcp.json を含んでいます — これは Claude Code 専用の設定です(.vscode/mcp.json — ネイティブ MCP ホスト VS Code 用の別個の設定 — とは異なります。詳細な比較は下記参照)。

Claude Code はプロジェクトフォルダを開くと .mcp.json を検出し、サーバーを子プロセスとして起動し、stdio を介して JSON-RPC で通信します — これはこのプロジェクトのすべての自動化テストで使用されているものと同じトランスポートであり、テストハーネスではなく Claude Code 自身によって起動されるだけです。

確認済みのエンドツーエンドシナリオ: Claude Code CLI → MCP server → カスタムツール。 6つの検証リクエストすべて(下記「検証結果」参照)は、このサーバーを .mcp.json で接続した状態で Claude Code CLI を通じて実際に実行されました — 設定されただけでなく、実際に呼び出され、実際のスクリーンショットとサーバーサイドログの記録があります。

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 後の編集は不要です。使用されているのは、フォールバック値付きの ${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 は、このプロジェクト全体で使用されている Unix(macOS/Linux)向けの venv 構造です。Windows では、同等のパスは .venv\Scripts\python.exe です。このプラットフォームもサポートするには、.mcp.json に Windows 固有の2番目のエントリ(またはラッパースクリプト)が必要になりますが、これは行われていません。プロジェクトは macOS でのみ開発・検証されたためです。

VS Code 用の設定

このリポジトリには、.vscode/mcp.json も含まれています — VS Code の組み込み MCP ホスト(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 に設定されています。

なぜ2つのファイルなのか(1つではないのか): .mcp.json.vscode/mcp.json は異なる互換性のないスキーマに従っており、それらのパス置換変数はホスト間で相互に交換できません:

  • .mcp.jsonClaude Code 用設定)はトップレベルのキー mcpServers を使用し、${CLAUDE_PROJECT_DIR:-.} をリポジトリルートに展開します。

  • .vscode/mcp.jsonネイティブ MCP ホスト VS Code 用設定)はトップレベルのキー servers、明示的なフィールド "type": "stdio" を使用し、代わりに ${workspaceFolder} を開いているフォルダのパスに展開します。VS Code の MCP ホストは ${CLAUDE_PROJECT_DIR}理解しません — VS Code から .mcp.json を直接開こうとすると、変数は文字通り渡され、サーバーは起動できません(spawn ${CLAUDE_PROJECT_DIR}/.venv/bin/python ENOENT)— これは実際に観測されたエラーであり、そのために別個の .vscode/mcp.json が作られました。各ホストの設定を独自の変数とともに独自のファイルに保存することで、このエラーを回避し、一方の設定が他方の構文を損なうことなく、両方のツールを同じクローンで使用できます。

.vscode/mcp.json は、.gitignore.vscode/* を無視するという一般規則の唯一の例外です。その他の VS Code のローカル状態(settings.local.json など)は追跡されません。

VS Code の検証ステータス: .vscode/mcp.json は構文的・意味的に正しく(動作する Claude Code 設定と同じサーバー、同じコマンド/環境変数)、JSON として検証済みです。さらに、実際のスクリーンショット evidence/vscode_mcp_server_connected.png によって、組み込みの ネイティブ MCP ホスト VS Code がこの設定で実際にサーバーを起動することが確認されています: Starting server mcp-project-helperConnection state: RunningDiscovered 4 tools。同じ出力内の mcp_project_helper プロセス自身の stderr ログからの確認行もあります。これは、VS Code インターフェイスを介したカスタムツールの呼び出しの確認 とは異なります — このインターフェイスを介したユーザーシナリオ(search_project_files など)は一切実行されておらず、検証済みとして主張されていません。ユーザーによる実際のツール呼び出しまで確認されている唯一の IDE 統合(全6シナリオのスクリーンショット + サーバーサイドログ)は Claude Code CLI です。下記「検証結果」参照。両方とは別に、Claude Code Desktop / VS Code 内の Claude Code 拡張機能 を介した統合は、このセッションではまったく検証されていません — ネイティブ MCP ホスト 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つのツールで接続されていることを確認します。

VS Code(ネイティブ MCP ホスト、Copilot Chat のエージェントモード):

  1. Claude Code の場合と同じように venv を作成します — .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を通じて実際に実行され、統合を確認した6つのシナリオ(結果の全表はevidence/README.mdにあります):

  1. MCPを通じてdemo_project内で関数apply_discountが使われている箇所をすべて検索 → 期待されるのは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の実装を検索し、定義されているファイルを読み、そのパラメータ/戻り値/割引計算を説明 → 期待されるのは2つのツールのチェーン: search_project_files、次にread_project_file

  6. (ネガティブ/セキュリティテスト) MCPを通じてファイル../../../../etc/passwdを読もうとする → 期待されるのはread_project_fileが構造化エラーで拒否されること(パスが許可されたルートを越えている)。

検証結果

6件中6件すべてのクエリが成功(テスト5では期待された2つのツールが正しい順序で実行され、テスト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

成功、2つのツールのチェーン

6

read_project_file

期待通りの拒否(パストラバーサルはブロック済み)

自動化された検証(上記の手動IDEテストを置き換えるものではなく、補完するもの):

  • リポジトリのルートからpytest -q44 passed

  • demo_project/内でpytest -q2 passed

  • プログラム的なstdioハンドシェイク(initialize() + list_tools())— サーバーはmcp-project-helper 0.1.0とちょうど4つのツールを報告: get_docsread_project_filerun_project_checksearch_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