
MCP のツールアノテーションでユーザーにヒントを提供する
MCP ではツールアノテーションを使用して、ユーザーにツールの動作に関するヒントを提供できます。例えば `readOnlyHint` を設定することで、ツールがデータを変更しないことを示すことができます。この記事では TypeScript SDK を使用して MCP サーバーでツールアノテーションを設定し、Claude Code クライアントでどのように表示されるかを確認します。
Model Context Protocol (MCP) は、LLM が外部のツールと対話するための標準的な方法を提供します。MCP では LLM が利用できるツールを MCP サーバーが提供し、LLM はそのツールを呼び出してタスクを実行します。
MCP を利用すると外部で保存された情報を参照してより正確な回答を生成したり、カレンダーに予定を追加するといったタスクを実行したりすることが可能になります。しかし MCP のツールの実行はユーザーの操作なしに思わぬ動作を引き起こす可能性があるため、基本的に LLM がツールを呼び出す際にはユーザーの許可を求める動作になっています。
MCP ではツールの利用に関するユーザー体験を向上させるために、ツールがアノテーションを提供できる仕組みが導入されています。ツールアノテーションはユーザーがツールの動作を理解するのを助け、ツールの利用に関する意思決定を支援します。ツールのアノテーションには以下のようなものがあります。
title
: 人間が読めるツールの名前readOnlyHint
:true
の場合、ツールはデータを変更しないことを示すdestructiveHint
:true
の場合、ツールは破壊的な変更を行う可能性があることを示す(readOnlyHint
がfalse
の場合にのみ意味を持つ)idempotentHint
:true
の場合、ツールは冪等であることを示す。つまり、同じ入力に対して何度呼び出しても同じ副作用が生じる(readOnlyHint
がfalse
の場合にのみ意味を持つ)openWorldHint
:true
の場合、ツールは外部のエンティティと相互作用する可能性があることを示す。例えば Web 検索ツールはopenWorldHint
をtrue
に設定することが推奨されるが、メモリツールはfalse
に設定される
ただし、これらのアノテーションはあくまでヒントであり、MCP サーバーがツールの動作を保証するものではありません。例えば readOnlyHint
が true
に設定されていても、ツールが実際にはデータを変更する可能性があります。そのためセキュリティ上の判断として利用するべきではありません。
この記事では実際に、MCP サーバーでツールアノテーションを設定し、クライアントでどのように表示されるかを確認します。
ツールアノテーションを設定する
MCP サーバーの TypeScript SDK を使用して簡単な MCP サーバーを作成し、ツールアノテーションを設定します。メモリ上で TODO リストを管理する MCP サーバーを作成してみましょう。
まずは必要なパッケージをインストールします。
npm install @modelcontextprotocol/sdk zod
npm install -D @types/node typescript
package.json
に build
スクリプトを追加します。
{
"scripts": {
"build": "tsc && chmod 755 build/index.js"
}
}
プロジェクトのルートに tsconfig.json
を作成します。
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./build",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
src/index.ts
に以下のコードを追加します。このコードでは add_todo
と list_todos
という 2 つのツールを定義し、それぞれにツールアノテーションを設定しています。add_todo
ツールは TODO 項目を追加するためのもので、データを変更するため readOnlyHint
はデフォルトの false
のままにしています。一方、list_todos
ツールは TODO 項目を読み取るだけなので、readOnlyHint
を true
に設定しています。そしてそれぞれのツールには title
も設定しています。
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
// サーバーインスタンスの作成
export const server = new McpServer({
name: "todo-mcp-server",
version: "0.1.0",
});
const todos: string[] = ["buy milk", "walk dog"];
// ツールの定義
server.tool(
"add_todo",
{
title: "Add a new todo item",
description: "Adds a new todo item to the list",
inputSchema: { title: z.string().describe("The todo item to add") },
outputSchema: {
success: z.boolean().describe("Whether the todo was added successfully"),
},
},
async ({ title }) => {
todos.push(title);
return {
content: [{ type: "text", text: JSON.stringify({ success: true }) }],
structuredContent: { success: true },
};
}
);
server.tool(
"list_todos",
{
title: "List all todo items",
description: "Returns a list of all todo items",
inputSchema: {},
outputSchema: {
todos: z.array(z.string()).describe("The list of todo items"),
},
readOnlyHint: true,
},
async () => {
return {
content: [{ type: "text", text: JSON.stringify({ todos }) }],
structuredContent: { todos },
};
}
);
async function main() {
// サーバーの起動
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP server is running...");
}
main();
MCP サーバーをビルドします。
npm run build
build/index.js
ファイルが生成されていれば成功です。
クライアントでツールアノテーションを確認する
クライアント側でツールアノテーションがどのように表示されるかを確認します。まずは Claude Code をクライアントとして MCP サーバーに接続しましょう。Claude Code で MCP サーバーを登録するには claude add mcp <name> -- <command>
コマンドを使用します。
claude add mcp todo -- node /path/to/your/project/build/index.js
claude
コマンドで Claude Code を起動した後、/mcp
コマンドを実行して現在登録されている MCP サーバーの一覧を表示します。
/mcp
「1. View Tools」を選択すると TODO MCP サーバーで利用可能なツールの一覧が表示されます。ツール名はアノテーションで指定した title
が表示されていることがわかります。readOnlyHint
が true
に設定されている list_todos
ツールには「(read-only)」と表示されていることがわかります。
なお、ツールを実行前の許可を求めるダイアログにはツールアノテーションは表示されないようでした。このあたりはクライアントツールの実装に依存しているため、ツールによって異なる可能性があります。
まとめ
- MCP のツールアノテーションを使用すると、ユーザーにツールの動作に関するヒントを提供できる
- ツールアノテーションには以下の項目がある
title
: 人間が読めるツールの名前readOnlyHint
:true
の場合、ツールはデータを変更しないことを示すdestructiveHint
:true
の場合、ツールは破壊的な変更を行う可能性があることを示す(readOnlyHint
がfalse
の場合にのみ意味を持つ)idempotentHint
:true
の場合、ツールは冪等であることを示す。つまり、同じ入力に対して何度呼び出しても同じ副作用が生じる(readOnlyHint
がfalse
の場合にのみ意味を持つ)openWorldHint
:true
の場合、ツールは外部のエンティティと相互作用する可能性があることを示す。例えば Web 検索ツールはopenWorldHint
をtrue
に設定することが推奨されるが、メモリツールはfalse
に設定される
- これらのアノテーションはあくまでヒントであり、MCP サーバーがツールの動作を保証するものではないため、セキュリティ上の判断として利用するべきではない
- Claude Code ではツール一覧画面で設定したタイトルが表示されたことと、
readOnlyHint
がtrue
のツールには「(read-only)」と表示されたことを確認できた - クライアントツールによってはツールアノテーションを表示しない場合もあるため、ユーザー体験はクライアントツールに依存する