A1. 逆引き

「〜したい」から引く

📅 作成: 2026-09-07 / 更新: 2026-09-07

この資料の内容

  1. 作る
  2. 登録する・確かめる
  3. 入力と出力
  4. 伝える
  5. 運ぶ

作る

したいことやり方詳しく
SDK を入れるnpm install @modelcontextprotocol/sdk03
サーバーを作るnew McpServer({ name, version })03
stdio に繋ぐawait server.connect(new StdioServerTransport())03
ツールを足すserver.registerTool(name, config, handler)03
読ませるデータを足すserver.registerResource(name, uri, config, handler)05
URI に変数を入れるnew ResourceTemplate('note://{date}', { list: undefined })05
定型の指示を足すserver.registerPrompt(name, config, handler)05
SDK を使わずに書くreadline で 1 行ずつ読み、process.stdout.write で返す02
C# で書くcsc.exeSystem.Web.Extensions.dllA3

ひな形

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';

const server = new McpServer({ name: 'my-server', version: '1.0.0' });

server.registerTool(
	'my_tool',
	{
		title: '表示名',
		description: 'いつ使うかを書く。モデルはこれを読んで呼ぶ',
		inputSchema: { arg: z.string().describe('引数の説明') },
	},
	async ({ arg }) => ({ content: [{ type: 'text', text: `受け取った: ${arg}` }] }),
);

await server.connect(new StdioServerTransport());

登録する・確かめる

したいことやり方
Claude Code に登録claude mcp add --scope project 名前 -- node server.mjs
Codex に登録codex mcp add 名前 -- node server.mjs
Antigravity に登録antigravity --add-mcp '{"name":"名前","command":"node","args":["server.mjs"]}'
HTTP のサーバーを登録claude mcp add --transport http 名前 http://localhost:3333/mcp
環境変数を渡すclaude mcp add 名前 -e KEY=値 -- node server.mjs
一覧を見るclaude mcp listcodex mcp list
詳細を見るclaude mcp get 名前
消すclaude mcp remove 名前codex mcp remove 名前
設定を汚さずに試すcodex exec -c 'mcp_servers.名前={command="node", args=["server.mjs"]}' "..."

手で叩く

@(
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"手","version":"1.0"}}}'
'{"jsonrpc":"2.0","method":"notifications/initialized"}'
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
) -join "`n" | node server.mjs

版を確かめる

対象コマンド
Node.jsnode --version
SDKnpm view @modelcontextprotocol/sdk version
Claude Codeclaude --version
Codexcodex --version
Antigravityantigravity --version
ホストが喋る MCP の版観測用サーバーのログを見る

入力と出力

入力の形(zod)

したいこと書き方
文字列z.string()
空を禁じるz.string().min(1)
整数z.number().int()
範囲z.number().min(1).max(50)
真偽z.boolean()
省略できるz.string().optional()
既定値z.number().default(10)
選択肢z.enum(['a', 'b'])
配列z.array(z.string())
説明を足す.describe('説明')
引数なしinputSchema: {}

返し方

したいこと書き方
文字列を返す{ content: [{ type: 'text', text: '...' }] }
失敗を返す{ content: [...], isError: true }
複数行text の中で \n で繋ぐ
Resource を返す{ contents: [{ uri: uri.href, text: '...' }] }
Prompt を返す{ messages: [{ role: 'user', content: { type: 'text', text: '...' } }] }

失敗は isError で返します。例外を投げると JSON-RPC のエラーになり、モデルは理由を読めません。詳しくは 05 章

伝える

したいことやり方詳しく
進捗を送るextra.sendNotification({ method: 'notifications/progress', params: {...} })08
進捗の宛先を得るextra._meta?.progressToken08
利用者に尋ねるextra.sendRequest({ method: 'elicitation/create', params: {...} }, schema)08
画面に出すPowerShell 5.1 経由でトースト08
ログを出すconsole.error(...)(stdio のとき console.log は禁止)02
長い処理を投げるserver.experimental.tasks.registerToolTask(...)09
ツールの一覧が変わったと知らせるserver.sendToolListChanged()

進捗を送る(そのまま使える形)

async ({ seconds }, extra) => {
	const token = extra._meta?.progressToken;

	for (let i = 1; i <= seconds; i++) {
		await sleep(1000);
		if (token === undefined) continue;
		await extra.sendNotification({
			method: 'notifications/progress',
			params: { progressToken: token, progress: i, total: seconds, message: `${i}/${seconds}` },
		});
	}

	return { content: [{ type: 'text', text: '終わった' }] };
}

できないこと。何も呼ばれていないときに、サーバーから会話へ割り込むことはできません。人に知らせたいなら OS の通知など MCP の外の手を使います。08 章に線が引いてあります。

運ぶ

したいことやり方詳しく
HTTP にするnew StreamableHTTPServerTransport({ sessionIdGenerator: undefined })07
同じ PC に限るhttp.listen(PORT, '127.0.0.1')10
1 本を共有するHTTP で常駐 + stdio ブリッジ10
HTTP を手で叩くAccept: application/json, text/event-stream を忘れない07
SSE の本文を解くdata: で始まる行を取り出す07

テストから呼ぶ

import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';

const transport = new StdioClientTransport({
	command: process.execPath,
	args: ['server.mjs'],
	env: { ...process.env, MEMO_FILE: '...' },
	stderr: 'ignore',
});

const client = new Client({ name: 'tests', version: '1.0.0' }, { capabilities: {} });
await client.connect(transport);

const { tools } = await client.listTools();
const result = await client.callTool({ name: 'add', arguments: { a: 2, b: 3 } });

await client.close();
クライアント側の操作書き方
ツールの一覧client.listTools()
ツールを呼ぶclient.callTool({ name, arguments })
進捗を受けるclient.callTool(params, undefined, { onprogress })
Resource を読むclient.readResource({ uri })
Prompt を取るclient.getPrompt({ name, arguments })
尋ねられたら答えるclient.setRequestHandler(ElicitRequestSchema, handler)
相手の名乗りを見るclient.getServerVersion()