【初心者】MCP サーバをイメージで解説 ― REST API があるのに、なぜ AI には MCP が必要なのか

最近、Claude や ChatGPT、VS Code などの AI ツールの設定画面で「MCP サーバ」という言葉をよく見かけるようになりました。社内のシステムやファイルを AI から使えるようにする仕組みだと説明されますが、REST API がすでにあるのに、なぜ別の仕組みが必要なのかはピンとこないところです。

この記事では、社内の勤怠システムに「明日、有給を申請しておいて」と AI に頼む場面を例に、MCP(Model Context Protocol)がない場合とある場合を比べながら、MCP サーバが何をしているのかを図で説明します。REST API と JSON がなんとなくわかる方を想定しています。

この記事でわかること
  1. AI(LLM)は API を自分で呼ばず、「このツールを呼んで」と返すだけであること
  2. MCP がないと、AI アプリとシステムの組み合わせの数だけ連携が必要になること
  3. MCP サーバは既存の API の前に置く「AI 向けの窓口」で、作る量は思ったより少ないこと
  4. MCP サーバを使うときに、セキュリティで押さえておきたいこと

AI は自分で API を呼んでいない

まず、AI が外部のシステムを使うとき、裏で何が起きているかを確認します。ChatGPT や Claude の中心にある LLM(大規模言語モデル)は、文章を受け取って文章を返すプログラムです。LLM が勤怠システムに HTTP リクエストを送ることはありません。

LLM にできるのは、「この依頼なら、apply_leave というツールを date=2026-10-10 で呼べばよい」と返すところまでです。実際に API を呼ぶのは、LLM を使っている AI アプリ(チャット画面やエディタの拡張機能など)です。この仕組みは Function Calling や Tool Use と呼ばれています。

LLM(AI モデル) ユーザー AI アプリ 勤怠システム (REST API) ① 明日、有給を取りたい ② 依頼+ツールの説明書 ③「apply_leave を date=2026-10-10 で 呼んで」と返すだけ ④ API を呼ぶのはアプリ ⑤ 結果
図1 LLM は「呼んで」と返すだけで、API を呼ぶのは AI アプリ

LLM が正しいツールを選べるように、AI アプリは依頼と一緒に「ツールの説明書」を LLM に渡します。説明書には、ツールの名前、何をするツールなのかの説明、引数の形(JSON Schema)を書きます。

つまり、AI から勤怠システムを使えるようにするには、次の2つを誰かが用意する必要があります。

用意するもの中身勤怠システムの例
ツールの説明書LLM に見せる名前、説明、引数の形apply_leave:有給を申請する。引数は date(YYYY-MM-DD)と reason(任意)
呼び出す処理LLM の返事を受けて、実際に API を呼ぶコードPOST /api/v1/leave にトークンを付けて送り、結果を LLM に返す

MCP がない世界:連携が掛け算で増える

MCP がない場合、この「説明書」と「呼び出す処理」は、AI アプリの中に書きます。社内向けのチャットボットを作るなら、チャットボットのコードに勤怠 API 用の説明書と呼び出し処理を書く、という形です。

1つのアプリだけなら、これで困りません。困るのは AI アプリが増えたときです。開発チームは VS Code の AI 機能から、営業は Claude のデスクトップアプリから、同じ勤怠システムを使いたいとします。説明書の書き方も、呼び出し処理を組み込む方法も製品ごとに違うので、アプリごとに同じような連携を作り直すことになります。

システムの側も勤怠だけでは終わりません。経費精算、ファイル、チケット管理と増えていくと、必要な連携は「AI アプリの数 × システムの数」になります。勤怠 API の項目名が1つ変わっただけで、すべての AI アプリの連携を直すことになります。

MCP チャットボットVS CodeClaude 勤怠経費精算ファイル チャットボットVS CodeClaude 勤怠経費精算ファイル MCP サーバMCP サーバMCP サーバ MCP なし:3 × 3 = 9 MCP あり:3 + 3 = 6 アプリごとに連携を作り直す システムごとに MCP サーバを1つ
図2 MCP がないと組み合わせの数だけ、MCP があると足し算の数だけ連携が必要になる

MCP は、AI アプリと外部のシステムをつなぐ方法を1つに決めた共通の取り決め(プロトコル)です。AI アプリは MCP の話し方を1回覚えればよく、システムの側は MCP サーバを1つ用意すれば、MCP に対応したどの AI アプリからも使えます。必要な連携は「AI アプリの数 + システムの数」になります。

公式ドキュメントでは、MCP を AI アプリ用の USB-C ポートにたとえています。USB-C ならパソコンとどのメーカーの周辺機器でもつながるように、MCP に対応した AI アプリとシステムは、組み合わせを気にせずにつなげられます。

標準規格としての MCP

MCP は 2024 年 11 月に Anthropic が公開したオープンな仕様です。2025 年 12 月には、Linux Foundation の下に作られた Agentic AI Foundation(AAIF)に寄贈されました。AAIF は Anthropic、Block、OpenAI が共同で設立し、Google、Microsoft、AWS なども支援しています。Claude、ChatGPT、VS Code、Cursor など、多くの AI アプリが MCP に対応しています。

MCP でつなぐときの登場人物

MCP では、つなぐ側とつながれる側を次のように呼びます。

ホスト(AI アプリ) MCP クライアント MCP クライアント Claude Desktop VS Code など MCP MCP 勤怠 MCP サーバ ファイル MCP サーバ REST API を呼ぶ ファイル操作 勤怠システム 既存の REST API PC のファイル
図3 ホスト・MCP クライアント・MCP サーバの関係
登場人物役割例
ホストユーザーが使う AI アプリ。画面や LLM とのやり取りを受け持つClaude Desktop、VS Code
MCP クライアントホストの中の部品。MCP サーバ1つにつき1つ作られ、そのサーバとやり取りするホストが自動で作る
MCP サーバツールなどを MCP の形で公開するプログラム。中で既存のシステムを呼ぶ勤怠 MCP サーバ、ファイル MCP サーバ
既存のシステム今まで通りの API やデータ。MCP のために作り直す必要はない勤怠システムの REST API

「サーバ」という名前ですが、専用の機械を用意するとは限りません。ユーザーの PC の中で、AI アプリが起動する小さなプログラムとして動く MCP サーバも多くあります(後で説明します)。

使う側は設定を書くだけ

MCP サーバがあれば、AI アプリの側でコードを書く必要はありません。Claude Desktop の場合は、設定ファイル(claude_desktop_config.json)の mcpServers に、MCP サーバの起動方法を書くだけです。

claude_desktop_config.json(Claude Desktop の例)

{
  "mcpServers": {
    "kintai": {
      "command": "node",
      "args": ["C:\\mcp\\kintai\\build\\index.js"],
      "env": {
        "KINTAI_TOKEN": "(勤怠 API のトークン)"
      }
    }
  }
}

Claude Desktop は起動時にこの MCP サーバを起動し、使えるツールを問い合わせます。設定ファイルの名前や書き方はアプリによって少しずつ違いますが、書く内容は「どの MCP サーバを、どう起動するか(リモートの場合はどの URL にあるか)」です。

勤怠 API の URL も、項目名も、リクエストの組み立て方も、AI アプリの側には出てきません。それらはすべて MCP サーバの中にあります。

中で流れているメッセージ

AI アプリ(MCP クライアント)と MCP サーバの間では、JSON-RPC 2.0 という形式の JSON メッセージがやり取りされます。method に「何をしてほしいか」を書き、id で要求と応答を対応付ける、シンプルな形式です。有給の申請を頼んだときの流れは次のとおりです。

接続したとき 依頼したとき ユーザー AI アプリ LLM MCP サーバ 勤怠 API tools/list(使えるツールを問い合わせ) ツールの説明書(名前・説明・引数の形) 明日、有給を取りたい 依頼+ツールの説明書 apply_leave を呼んで tools/call(apply_leave, date=…) POST /api/v1/leave 申請 ID 結果(テキスト) 申請しました
図4 有給の申請を頼んだときのやり取り(実線が要求、破線が応答)

まず、AI アプリは MCP サーバに tools/list を送り、使えるツールの一覧をもらいます。

AI アプリ → MCP サーバ(tools/list)

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list"
}

MCP サーバ → AI アプリ

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "apply_leave",
        "description": "社内勤怠システムに有給休暇を申請する。date は YYYY-MM-DD 形式。",
        "inputSchema": {
          "type": "object",
          "properties": {
            "date":   { "type": "string", "description": "休む日(YYYY-MM-DD)" },
            "reason": { "type": "string", "description": "理由(任意)" }
          },
          "required": ["date"]
        }
      }
    ]
  }
}

応答の中身は、さきほどの「ツールの説明書」そのものです。AI アプリはこれを LLM に渡します。MCP がない場合は人が AI アプリに書き込んでいた説明書を、MCP では MCP サーバ自身が答えてくれる、ということです。

LLM が「apply_leave を呼ぶ」と返したら、AI アプリは tools/call を送ります。

AI アプリ → MCP サーバ(tools/call)

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "apply_leave",
    "arguments": { "date": "2026-10-10", "reason": "私用" }
  }
}

MCP サーバ → AI アプリ

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      { "type": "text", "text": "申請を受け付けました。申請ID: 98765" }
    ]
  }
}

MCP サーバはこの要求を受けて勤怠 API を呼び、結果をテキストで返します。AI アプリはその結果を LLM に渡し、LLM がユーザーへの返事を作ります。

メッセージの例について

ここに載せたメッセージは、説明に必要な項目だけを残した例です。実際のメッセージには、プロトコルのバージョンなどの項目も付きます。どの MCP サーバでも、使うメソッドは同じ tools/list と tools/call で、変わるのはツールの名前と引数だけです。

REST API との関係

ここまでで、「REST API があるのに、なぜ MCP が必要なのか」の答えが見えてきます。REST API と MCP は競合するものではなく、使う相手が違います。

比べるところREST APIMCP
主な使い手人が書いたプログラムAI アプリ(何を呼ぶかは LLM が決める)
使い方の知り方開発者が API 仕様書を読んでコードを書くtools/list で、説明書をその場で受け取る
呼び出し方API ごとに URL、メソッド、項目名が違うどのサーバでも tools/call にツール名と引数を入れる
何を呼ぶかが決まるとき開発者がコードを書いたとき会話の中で、依頼の内容に応じて

REST API は、仕様書を読んだ開発者が「この画面のこのボタンでこの API を呼ぶ」と決めて使うものです。一方、AI アプリでは、どのツールを呼ぶかを会話の中で LLM が決めます。そのためには、ツールの一覧と説明書をその場で受け取れて、どのツールでも同じ形で呼べる必要があります。MCP はその部分を決めた取り決めです。

MCP サーバの中では、今まで通り REST API を呼びます。MCP は REST API を置き換えるものではなく、既存の API の前に「AI 向けの窓口」を足すもの、と考えるとわかりやすいと思います。

MCP サーバを作るのは大変?

「AI アプリの側が楽になるのはわかったが、その手間を MCP サーバに移しただけでは?」と思うかもしれません。確かに、勤怠 API を呼ぶ処理は MCP サーバに書きます。ただし書くのは1回だけで、その1回で MCP に対応したすべての AI アプリから使えるようになります。

もう1つ、JSON-RPC のメッセージの組み立てや tools/list への応答といった MCP の取り決めの部分は、公式の SDK(TypeScript、Python、Java、Go など)が受け持ちます。開発者が書くのは、ほぼ「説明書」と「呼び出す処理」だけです。

次は、TypeScript の公式 SDK(@modelcontextprotocol/server パッケージ)で、勤怠 API 用の MCP サーバを書いた例です。

src/index.ts(TypeScript SDK の例)

import { McpServer } from "@modelcontextprotocol/server";
import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import { z } from "zod";

// ① サーバの名前とバージョン
const server = new McpServer({ name: "kintai", version: "1.0.0" });

// ② ツールの登録(ここが tools/list で返る説明書になる)
server.registerTool(
  "apply_leave",
  {
    description: "社内勤怠システムに有給休暇を申請する。date は YYYY-MM-DD 形式。",
    inputSchema: z.object({
      date: z.string().describe("休む日(YYYY-MM-DD)"),
      reason: z.string().optional().describe("理由(任意)"),
    }),
  },
  // ③ tools/call を受けたときの処理(既存の REST API を呼ぶ)
  async ({ date, reason }) => {
    const res = await fetch("https://kintai.example.local/api/v1/leave", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${process.env.KINTAI_TOKEN}`,
      },
      body: JSON.stringify({ target_date: date, note: reason ?? "私用" }),
    });
    if (!res.ok) {
      return {
        content: [{ type: "text", text: `申請できませんでした(HTTP ${res.status})` }],
        isError: true,
      };
    }
    const data = (await res.json()) as { request_id: string };
    return {
      content: [{ type: "text", text: `申請を受け付けました。申請ID: ${data.request_id}` }],
    };
  },
);

// ④ 標準入出力(stdio)でメッセージを受け付ける
await server.connect(new StdioServerTransport());
部分書くこと
① サーバの名前MCP サーバの名前とバージョン
② ツールの登録ツール名、description(何をするツールか)、inputSchema(引数の形)。この内容がそのまま tools/list の応答になる
③ 呼び出す処理勤怠 API に POST し、結果を content に入れて返す。失敗したときは isError: true を付けて理由を返すと、LLM が引数を直して呼び直せる
④ 起動標準入出力でメッセージを受け付ける。JSON-RPC の読み書きは SDK が行う

tools/list の応答にあった name、description、inputSchema が、コードの ② にそのまま対応しているのがわかると思います。tools/call を受けたときにどの処理を動かすかの振り分けや、引数が inputSchema に合っているかのチェックも、SDK がこの登録内容をもとに行います。

説明文は LLM が読む

description や引数の説明は、LLM がツールを選ぶときと、引数を作るときの手がかりになります。「いつ使うツールか」「日付はどの形式か」を具体的に書いておくと、LLM が正しい引数で呼びやすくなります。

stdio の MCP サーバでのログ出力

標準入出力でやり取りする MCP サーバでは、標準出力(stdout)がメッセージの通り道です。console.log() などで標準出力に書くとメッセージが壊れるので、ログは console.error() などで標準エラー出力(stderr)に出します。

ツールのほかに公開できるもの

MCP サーバが公開できるものは、ツールのほかに2つあります。勤怠システムに当てはめると、次のようになります。

種類中身使うことを決めるのは勤怠システムでの例
Tools(ツール)呼ぶと何かを実行する関数LLM有給を申請する、残日数を調べる
Resources(リソース)参考資料として読むデータ。URI で指定するAI アプリ(ユーザーが選ぶことも多い)就業規則の文書、今月の勤務表
Prompts(プロンプト)決まった頼み方のひな形ユーザー「/休暇申請」を選ぶと、日付と理由を聞いてから申請する

最初はツールだけ覚えておけば十分です。ツールは「LLM が自分の判断で使う」、リソースは「AI アプリが参考資料として LLM に渡す」、プロンプトは「ユーザーが選んで使う定型の頼み方」と、使うことを決める主体が違う点だけ押さえておくと、仕様を読むときに迷いません。

ローカルの MCP サーバとリモートの MCP サーバ

MCP のメッセージ(JSON-RPC)を運ぶ方法は2つあります。

あなたの PC あなたの PC サービス側 AI アプリ MCP サーバ AI アプリ MCP サーバ stdio Streamable HTTP ローカル:AI アプリが子プロセスとして起動 リモート:HTTPS でつなぎ、OAuth で認証
図5 stdio(ローカル)と Streamable HTTP(リモート)
項目stdioStreamable HTTP
動く場所ユーザーの PC の中サーバやクラウドの上
つながり方AI アプリが MCP サーバを子プロセスとして起動し、標準入出力でやり取りするHTTP の POST でメッセージを送る。応答を少しずつ返すときは SSE(Server-Sent Events)を使う
認証ネットワークを通らないので、MCP の認可の仕組みは使わない。外部 API のトークンは環境変数などで渡すHTTP の認証を使う。トークンの取得には OAuth が推奨されている
向いている使い方PC のファイル操作、自分だけで使うツール社内システムや SaaS を、多くの利用者に提供する

どちらの方法でも、中を流れる JSON-RPC のメッセージ(tools/list や tools/call)は同じです。ネットワークでたとえると、上位のプロトコルはそのままで、下の伝送路だけを選べるようになっている形です。

セキュリティで押さえておきたいこと

MCP サーバをつなぐということは、LLM の判断で外部のシステムを操作できるようにする、ということです。便利になる分、何を許すかを先に考えておく必要があります。MCP の仕様でも、ツールの実行は人が確認して拒否できるようにすべき(SHOULD)とされています。

観点考え方
人の確認申請、送信、削除など書き込みを伴うツールは、実行前にユーザーが内容を見て許可する。多くの AI アプリは、ツールを実行する前に確認を求める仕組みを持っている
最小権限MCP サーバに渡すトークンは、そのツールに必要な権限だけにする。参照しかしないなら読み取り専用のトークンにする
サーバ側のチェックMCP サーバは、入力の検証、アクセス制御、呼び出し回数の制限を行う(仕様で MUST)。LLM が作った引数をそのまま信用しない
MCP サーバの出所ローカルの MCP サーバは、ユーザーの権限で PC 上で動くプログラム。出所のわからないものは入れない
結果に紛れ込む指示ツールが取ってきたメールや Web ページに「〇〇へ送信せよ」のような文章があると、LLM がそれを指示と取り違えることがある(プロンプトインジェクション)。読み取り用のツールと送信用のツールを同時に使わせるときは特に注意する
認証情報の置き場所設定ファイルの env に書いたトークンは、そのまま平文で残る。ファイルのアクセス権を絞り、設定ファイルを人に渡さない

ファイアウォールのポリシーを「何を許可するか」から考えるのと同じで、MCP サーバも「AI に何を許可するか」を決めてからつなぐ、という順番で考えると整理しやすいと思います。

まとめ

項目ポイント
AI と APILLM は「このツールをこの引数で呼んで」と返すだけ。API を呼ぶのは AI アプリ
MCP がない場合AI アプリごとに説明書と呼び出す処理を作るので、連携は「アプリの数 × システムの数」
MCP がある場合システムごとに MCP サーバを1つ作れば、MCP に対応したどの AI アプリからも使える。連携は「アプリの数 + システムの数」
MCP サーバ既存の API の前に置く AI 向けの窓口。tools/list で説明書を返し、tools/call で API を呼ぶ
REST API との関係置き換えではない。MCP サーバの中で今まで通り REST API を呼ぶ
作る手間説明書と呼び出す処理を書けば、JSON-RPC の部分は SDK が受け持つ
つなぎ方PC の中なら stdio、ネットワーク越しなら Streamable HTTP。メッセージは同じ
セキュリティ書き込みは人が確認、トークンは最小権限、信頼できる MCP サーバだけを使う
次に試すなら
  • 公式の確認ツール MCP Inspector で MCP サーバにつなぎ、tools/list で返ってくる説明書を自分の目で見る
  • 公式のリファレンス実装(ファイル操作の MCP サーバなど)を AI アプリにつなぎ、どんな依頼のときにツールが呼ばれるかを見る
  • 普段使っている API を1つ選び、ツールが1つだけの MCP サーバを作ってみる

コメント