MCP(Model Context Protocol)とは何か ── Bugoon の実装コードで理解する仕組み
MCP とは ── AI エディタとツールを繋ぐ共通規格
Claude Code や Cursor などの AI エディタが普及するにつれ、「AI にコードを書かせるだけでなく、外部サービスと連携させたい」というニーズが急増しています。 しかしエディタごとにプラグイン API が異なると、開発者は同じ統合コードを何度も書き直す羽目になります。 この問題を解決するために Anthropic が策定したのが MCP(Model Context Protocol) です。
MCP は「AI ホストがどのようにして外部ツールやデータを呼び出すか」を定めたオープンな通信プロトコルです。 USB が周辺機器とコンピュータを繋ぐ共通規格であるように、MCP は AI エージェントと外部ツールを繋ぐ標準インターフェースです。 一度 MCP サーバーを実装すれば、対応するあらゆる AI エディタから同じサーバーを利用できます。
3 層モデル: Host / Server / Client
MCP のアーキテクチャは 3 つの役割で構成されます。
- Host ── Claude Code や Cursor など、ユーザーが直接操作する AI エディタ。MCP サーバーへの接続を管理し、LLM の推論に基づいてどのツールを呼ぶか判断します。
- Server ── Tool・Prompt・Resource を公開する独立したプロセス。Bugoon では
@rubyjobs-jp/bugoon-mcp-serverがこれに相当し、バグレポートの取得・更新ロジックを集約します。 - Client(SDK) ── Host が MCP サーバーと通信するために使うライブラリ。サーバー側では
@modelcontextprotocol/sdkのMcpServerクラスがプロトコルの低レイヤーを抽象化します。
STDIO transport の仕組み ── プロセス間通信の実際
MCP の通信方式には HTTP と STDIO の 2 種類があります。Bugoon MCP サーバーは STDIO transport を採用しています。
// src/index.ts
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { createServer } from "./server.js";
async function main() {
const server = createServer();
const transport = new StdioServerTransport();
await server.connect(transport);
}
STDIO transport では、Host が MCP サーバーを子プロセスとして起動し、標準入力(stdin)と標準出力(stdout)で JSON-RPC メッセージをやり取りします。 ネットワークポートが不要なため設定が簡単です。 Claude Code の設定ファイルに "command": "npx @rubyjobs-jp/bugoon-mcp-server" と書くだけで接続が確立されます。
Tool / Prompt / Resource の違い
Tool ── アクションを実行する関数
Tool は AI が「呼び出す」もので、外部 API の実行や副作用を伴う操作に使います。 Bugoon には次の Tool が登録されています。
list_bug_reports── ステータス・severity でフィルタしてバグレポート一覧を返すget_bug_report── 指定 ID のバグレポート詳細(コンソールエラー・DOM セレクタ等)を返すupdate_bug_report_status── ステータスや severity を更新するget_screenshot── Firebase Storage からスクリーンショット画像を取得する
Tool の入力は Zod スキーマで型付けし、LLM は describe を手がかりに引数を自動推論します。
Prompt ── コンテキストを自動注入するテンプレート
Prompt は「AI への指示文を動的に組み立てる」仕組みです。 引数を受け取り外部データを取得してメッセージテキストに埋め込み、LLM に渡します。 ユーザーが詳細を知らなくても、引数一つで充実したコンテキストが自動注入されます。
Resource ── 読み取り専用のデータソース
Resource はファイルやレコードを URI で公開する仕組みで、副作用のない読み取り専用データに適します。 Bugoon では Tool と Prompt で主要機能を提供しており、Resource は将来の拡張として位置づけています。
fix_bug プロンプトがどうコンテキストを注入するか
Bugoon で最も重要な Prompt が fix_bug です。 /fix_bug 42 と入力するだけで、バグレポート #42 の全情報が LLM への指示文として自動組み立てされます。
// src/prompts/fix-bug.ts(抜粋)
server.prompt(
"fix_bug",
"Fetch bug report details and generate a fix-oriented prompt",
{ bug_report_id: z.string().describe("Bug report ID") },
async ({ bug_report_id }) => {
const br = await client.getBugReport(Number(bug_report_id));
const sections: string[] = [];
sections.push(`## Bug Report #${br.id}`);
sections.push(`**Severity:** ${br.severity} **Page:** ${br.page_url}`);
if (br.actual_behavior) sections.push(`### What happened\n${br.actual_behavior}`);
if (br.expected_behavior) sections.push(`### Expected\n${br.expected_behavior}`);
if (br.console_errors) sections.push(`### Console errors\n\`\`\`\n${br.console_errors}\n\`\`\``);
if (br.browser) sections.push(`### Environment\nBrowser: ${br.browser} ${br.browser_version}`);
sections.push(
"After fixing, update the bug report status to `in_progress` " +
"using the `update_bug_report_status` tool."
);
return {
messages: [{
role: "user",
content: { type: "text", text: sections.join("\n\n") },
}],
};
}
);
このプロンプトは再現手順・コンソールエラー・DOM セレクタ・ブラウザ情報まで自動で埋め込みます。 開発者がバグレポートをコピー&ペーストする手間はゼロです。 さらに修正後に update_bug_report_status Tool を呼ぶよう指示が含まれるため、ステータス更新まで一気通貫で自動化されます。
まとめ
実装から見えてきたポイントを整理します。
- STDIO transport により、複雑なサーバー設定なしに子プロセスとして起動できる
- Tool は Zod スキーマで型安全に定義でき、LLM が自動で適切な引数を推論する
- Prompt はビジネスデータを動的取得してコンテキストを自動注入し、「バグ ID だけ渡せば AI が全情報を把握できる」体験を実現する
- 一度 MCP サーバーを実装すれば、Claude Code・Cursor など MCP 対応エディタすべてから同じ機能を利用できる
Bugoon では、QA 担当者がブラウザ上で報告したバグが GitHub Issue になり、開発者が /fix_bug と打つだけで AI が修正を開始するフローが MCP によって実現されています。 小さな MCP サーバーを一つ実装してみることで、AI と外部ツール連携の威力を体感できるはずです。