MCP入門|LLMツール接続の標準規格

Claude Code活用

※ この記事にはアフィリエイトリンクが含まれています。詳細はプライバシーポリシーをご確認ください。

「Claude DesktopやCursorからGitHubやSlackを操作したい」。そんな問いを調べると、必ずMCP(Model Context Protocol)という単語に行き当たります。

MCPはAIとツールをつなぐ仕組みで、いま急速に標準化が進んでいる規格です。MCP公式サイトが一次情報、Anthropic主導で開発が進んでいます。

この記事は、コードが書けるエンジニア向けにMCPの全体像を整理します。「なぜ必要か」から「自前サーバーの最小実装」まで、実装視点で解説します。Function Callingとの違いや、既存MCPサーバーの活用法もコード付きで扱います。

僕は普段、Claude Codeでファイルシステム・GitHub・Postgres等のMCPサーバーを日常的に呼び出して開発しています。その中で「MCPは『AIエージェント時代のUSB-C規格』だ」と感じる場面が増えてきました。本記事はそこで得た知見を実装ガイドとしてまとめたものです。

本記事はAI学び直し|エンジニアの実務スキル4階層のシリーズ第7回(第3階層:AIアプリ開発)にあたります。前回のAIエージェント入門で扱った「AIに行動させる」仕組みを、規格レベルで標準化したのがMCPです。

こんな方に読んでほしい

  • Claude DesktopやCursorで「MCPサーバー」という言葉を見て、概念を整理したい方
  • Function Callingは触ったが、MCPとの違いがあいまいな方
  • 自社ツールをAIから呼び出せるようにしたいバックエンドエンジニアの方
  • AIエージェント開発の標準規格動向を、抽象論ではなく実装で押さえたい方

MCPとは何か|LLMとツールをつなぐ標準規格

結論:AIアプリ開発の「USB-C規格」

MCPはModel Context Protocolの略で、Anthropicが2024年11月に公開したオープン規格です。LLMアプリケーションと外部ツール/データソースの接続方法を標準化することを目的としています。

公式仕様はmodelcontextprotocol.ioで公開されており、SDKもTypeScript/Python/Java等で提供されています。

役割としては、AIアプリにとってのUSB-C規格に近いです。これまで個別アプリごとに違う形で実装していたツール接続を、一つの仕様で統一するという考え方です。

なぜMCPが必要になったのか

MCP登場前は、AIに新しいツールを使わせるたびに以下の手順が必要でした。

  • 各AIアプリ(Claude/ChatGPT/Cursor等)ごとにラッパーを実装
  • Function Callingのスキーマを毎回手書き
  • 同じツール(例:GitHub操作)を複数アプリ向けに重複実装
  • ツール側のAPI変更時に、すべてのラッパーを追従更新

つまり、「AIアプリ × ツール」の組み合わせ数だけ実装が必要になっていました。MはNと書くと、組み合わせ爆発が起きていた状態です。

MCPは間に標準層を挟むことで、この組み合わせをM+Nに減らします。AIアプリ側は1回MCPクライアントを実装すれば任意のMCPサーバーを呼べ、ツール側は1回MCPサーバーを実装すれば任意のAIアプリから呼ばれます。

MCPアーキテクチャ|Host/Client/Serverの3層

MCPは3つの登場人物で構成されます。図で押さえると理解が早いです。

MCPアーキテクチャ|Host(Claude/Cursor)⇔Client⇔Server(GitHub/Slack/独自)構成図

Host|AIアプリ本体

HostはユーザーがLLMと対話する場所そのものです。Claude Desktop、Cursor、Claude Code、Zed等が該当します。Host内部でMCPクライアントを生成し、外部のMCPサーバーと接続します。

1つのHostは複数のMCPサーバーに同時接続できます。「ファイルシステム+GitHub+Postgres」を全部つないだ状態で会話を始められる、というのがMCPの面白いところです。

Client|Hostに内蔵される接続マネージャ

ClientはHostとServerの仲介役です。プロトコルレベルでJSON-RPCメッセージをやり取りし、利用可能なリソース・ツール・プロンプトをHostに伝えます。Host側のSDKに含まれる実装で、開発者が直接書くことは少ないです。

Server|実際のツール/データを公開する層

Serverが本記事のメインターゲットです。外部APIやローカルファイル等の機能をMCP規格に沿って公開するのが役割で、自前で実装するのも、既存の公式・コミュニティ実装を使うのも自由です。

1つのServerが提供できる「機能」は3種類あります。

  • Resources:ファイル内容やDBクエリ結果など、AIに読ませる静的/動的データ
  • Tools:APIを呼ぶ・コマンドを実行するなど、AIに実行させる関数
  • Prompts:再利用可能なプロンプトテンプレート(スラッシュコマンド等で起動)

通信プロトコル|stdio/SSEの2方式

Host⇔Server間の通信はJSON-RPC 2.0をベースにしています。トランスポート層は2種類あります。

  • stdio:Hostが子プロセスとしてServerを起動し、標準入出力で通信。ローカル限定だが設定がシンプル
  • SSE(Server-Sent Events):HTTP上でServer-Sent Eventsを使う。リモート接続が可能

個人開発ではstdio方式が扱いやすく、本記事のサンプルもstdioで進めます。

既存MCPサーバーを使う|Claude Desktopでの実装例

自前で書く前に、まず既存サーバーを使ってみるのが理解の近道です。Anthropic公式リポジトリには10種類以上のリファレンス実装が公開されています。

主要な公式サーバー一覧

2026年5月時点で、よく使われる公式・準公式サーバーは次の通りです。

サーバー名 主な用途
filesystem ローカルファイルの読み書き
github Issue/PR操作、コード検索
postgres 読み取り専用のSQL実行
slack チャンネル投稿、履歴検索
brave-search Web検索
puppeteer ブラウザ自動操作

Claude Desktopの設定ファイル例

Claude Desktopの設定ファイルclaude_desktop_config.jsonに以下のように書くだけです。これでファイルシステムMCPサーバーが有効化されます。

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "/Users/yourname/Documents/projects"
      ]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxx"
      }
    }
  }
}

commandでServerの起動コマンドを、envで環境変数(APIキー等)を渡します。Claude Desktopを再起動すると、Hostが自動でServerを起動し、Toolsが会話に登場するようになります。

この時点で「ファイル読んで」「このIssueに返信して」をClaudeに依頼できる状態になります。設定ファイル1枚でAIの能力が一段拡張される、というのがMCPの実用的な価値です。

自前MCPサーバーを書く|TypeScript SDKでの最小実装

既存サーバーで足りない場合、自前実装に進みます。TypeScript SDK(@modelcontextprotocol/sdk)を使うと、数十行で動くサーバーが書けます。

最小構成のhello-toolサーバー

挨拶を返すだけのToolを公開する例です。MCPサーバーの骨格をつかむのに向いています。

// server.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";

const server = new Server(
  { name: "hello-server", version: "0.1.0" },
  { capabilities: { tools: {} } }
);

// 提供するToolを宣言
server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [
    {
      name: "say_hello",
      description: "指定した名前に挨拶を返します",
      inputSchema: {
        type: "object",
        properties: { name: { type: "string" } },
        required: ["name"],
      },
    },
  ],
}));

// Toolが呼ばれたときの処理
server.setRequestHandler(CallToolRequestSchema, async (req) => {
  if (req.params.name === "say_hello") {
    const userName = req.params.arguments?.name as string;
    return {
      content: [{ type: "text", text: `こんにちは、${userName}さん!` }],
    };
  }
  throw new Error("Unknown tool");
});

// stdioで起動
const transport = new StdioServerTransport();
await server.connect(transport);

ポイントは2つのsetRequestHandlerです。ListToolsで「何が呼べるか」を宣言し、CallToolで「呼ばれたら何をするか」を実装します。

Claude Desktopから呼び出す

上のサーバーをnpx tsx server.tsで起動できる状態にしたら、設定ファイルにエントリを追加します。

{
  "mcpServers": {
    "hello": {
      "command": "npx",
      "args": ["tsx", "/path/to/server.ts"]
    }
  }
}

Claude Desktopを再起動して「太郎さんに挨拶して」と話しかけると、Claudeがsay_hello Toolを自動で選んで呼び出します。

実用的な拡張例|社内APIのラッパー

実務で価値が出るのは、社内APIをMCPサーバー化するパターンです。例えば社内勤怠APIを公開するなら、骨格はこうなります。

server.setRequestHandler(CallToolRequestSchema, async (req) => {
  if (req.params.name === "get_attendance") {
    const userId = req.params.arguments?.user_id as string;
    const res = await fetch(
      `https://internal-api.example.com/attendance/${userId}`,
      { headers: { Authorization: `Bearer ${process.env.API_TOKEN}` } }
    );
    const data = await res.json();
    return { content: [{ type: "text", text: JSON.stringify(data) }] };
  }
  throw new Error("Unknown tool");
});

Tool定義側でuser_idを受け取るスキーマを追加すれば完成です。これだけで「Aさんの今月の勤怠を集計して」のような自然言語指示が、社内APIへの構造化呼び出しに変換されます。

MCP実装でハマる失敗パターン

実装中に踏みやすい落とし穴を3つ挙げます。事前に知っておくと、原因切り分けが早くなります。

失敗1|Function CallingとMCPを混同する

両者は階層が違います。混同すると設計が歪みます。

  • Function Calling:LLMが構造化された関数呼び出しを生成する機構(モデル側の能力)
  • MCP:その関数定義と実行をアプリ間で共有する規格(プロトコル)

MCPの内部では各HostがLLMのFunction Calling機能を使ってToolを呼び出します。Function Callingは「機構」、MCPは「規格」と覚えると整理がつきます。

失敗2|stdio通信のバッファリングを誤る

stdio方式では、ServerがHostの標準入出力に直接JSONを書き出します。ここで標準出力にデバッグログを混ぜると、JSONパースが壊れて通信が即死します。

対策はシンプルで、ログは必ずconsole.error(stderr)か外部ログファイルに書き出すことです。console.logを残したまま動かすと、原因不明の接続エラーで時間を溶かします。

失敗3|大量のToolsを一気に公開する

1つのMCPサーバーに50個も100個もToolsを定義すると、Hostがすべての宣言をシステムプロンプトに詰め込みます。結果としてコンテキストウィンドウが圧迫され、肝心の会話に使える容量が減ります

対策は機能をドメイン単位で分割して複数サーバーに分けることと、Tool数は1サーバーあたり10〜20個程度に抑えることです。「使われないTool」を整理する運用も必要になります。

コンテキストウィンドウの考え方はコンテキストウィンドウ入門で詳しく扱っています。

もっと深く学ぶなら|キャリアの武器として

MCPはまだ標準化途上の新領域で、実装経験は転職市場での差別化要因になりやすいです。AI領域への転職を本気で狙う段階なら、転職保証付きのDMM WEBCAMPエンジニア転職が選択肢の一つになります。

  • デメリット:受講料は数十万円規模/途中で離脱すると費用対効果が悪化
  • メリット:転職保証制度(条件付き)/キャリアサポートまでセット

DMM WEBCAMPエンジニア転職の無料カウンセリングを予約する

シリーズの位置づけと次回予告

本記事はAI学び直し|エンジニアの実務スキル4階層シリーズの第7回です。第3階層「AIアプリ開発」の中核として、MCPを取り上げました。

前回のAIエージェント入門で扱った「ツールを使って自律的に動くAI」は、ツール接続部分の標準化があってこそ実用化が進みます。MCPはその標準化の最先端の取り組みです。

次回(5月9日公開予定)は、LLM活用で避けて通れないハルシネーションを扱います。原因の分類と、業務スクリプトでの抑制策を実装視点で解説します。

まとめ|MCPは「AIエージェント時代のUSB-C」

MCPはAIアプリと外部ツールの接続を標準化するオープン規格です。Host/Client/Serverの3層構成Resources/Tools/Promptsの3機能を押さえるだけで、全体像はつかめます。

まずは既存の公式サーバー(filesystem/github/postgres等)をClaude Desktopにつないでみてください。設定ファイルだけでAIの能力が拡張される体験ができます。

そのうえでTypeScript SDKで自前サーバーを書き、社内APIや個人ツールを接続していくと、AIエージェント開発の解像度が一段上がります。公式MCPサーバーリポジトリに多数のサンプル実装があるので、写経から始めるのが近道です。

進展があったらこのブログで共有します。自前MCPサーバーの運用Tipsや、リモート(SSE)方式での社内展開についても、できたら定点観測の記事を書いてみたいと考えています。

コメント

タイトルとURLをコピーしました