MCPサーバー自体は正常に起動しているのに、Claude CodeやMCPクライアント、MCP Inspectorなどから見るとツール一覧が空になることがあります。
接続エラーが出ていないため、「MCPサーバーには接続できているからTool側も正常」と考えがちですが、MCPではサーバーへの接続とTool Discoveryは別の処理です。
クライアントが利用可能なToolを知るためには、MCPサーバーへtools/listを送信し、そのレスポンスにTool Definitionが含まれている必要があります。MCPの仕様でも、利用可能なツールを検出するためにクライアントがtools/listを送ることが定められています。
そのため、MCPサーバーは起動しているのにツールが表示されない場合は、まず「Toolの処理が動くか」ではなく、tools/listで本当にToolが返されているかを確認するのが近道です。
この記事では、MCPサーバーへ接続できるのにTool一覧が表示されない原因と、tools/list、Tool登録、Capabilities、動的Tool、キャッシュなどを確認する方法を解説します。
- MCPのツール一覧はtools/listから取得される
- サーバー起動成功とTool登録成功は別
- 最初にlist_toolsを直接実行する
- 別のMCPServerインスタンスへToolを登録していないか確認する
- Toolを定義したモジュールがImportされていない
- @mcp.tool()の書き方が間違っていないか確認する
- Tool名が重複していると片方が表示されない
- Low-level Serverではtools/list Handlerが必要
- inputSchemaが不正だとtools/list自体が失敗することがある
- tools Capabilityが見えているか確認する
- 2026-07-28ではProtocol Versionの確認も重要
- 起動後に追加したToolはクライアント側へ反映されない場合がある
- 2026-07-28ではlist_changedの受け取り方が変わっている
- クライアントが古いtools/listをキャッシュしている
- 認証ユーザーによってTool一覧を変えている場合も確認する
- tools/listのページネーションを確認する
- stdioではstdoutへのログ出力にも注意する
- MCP Inspectorでtools/listまで確認する
- tools/listの生レスポンスを見ると原因を切り分けやすい
- Toolを追加した直後だけ表示されないなら再接続して確認する
- サーバーが起動するのにToolが表示されないときはtools/listを基準に調べる
- tools/listが空になる原因に関するよくある質問
- まとめ
MCPのツール一覧はtools/listから取得される
MCPクライアントは、サーバー内部のPythonやJavaScriptコードを直接見てToolを探しているわけではありません。
利用可能なToolを知るために、次のようなJSON-RPC Requestを送ります。
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}
サーバーにToolが登録されていれば、概念的には次のようなResponseが返ります。
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "search_products",
"description": "商品を検索する",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string" }
},
"required": ["query"]
}
}
]
}
}
つまりホスト側にToolが表示されるかどうかは、最終的にはtools/listの結果で決まります。
MCP Python SDKでもclient.list_tools()を実行するとListToolsResultが返り、.toolsに「ホストがモデルへ渡す完全なTool Definition」が格納される仕組みになっています。
サーバー起動成功とTool登録成功は別
MCPサーバーがポートをListenしていたり、stdioプロセスが起動していたりしても、Toolが登録されているとは限りません。
たとえばPython SDKで次のようにサーバーを作ったとします。
from mcp.server import MCPServer
mcp = MCPServer("MyServer")
この時点でサーバーオブジェクトは存在しますが、まだToolはありません。
Toolを追加するなら、たとえば次のように登録します。
from mcp.server import MCPServer
mcp = MCPServer("MyServer")
@mcp.tool()
def search_products(query: str) -> str:
"""商品を検索する。"""
return f"Search: {query}"
このsearch_productsが登録されたmcpを実際にホストが起動している必要があります。
「Functionを書いた」「ファイルにToolが存在する」というだけでは、そのToolがMCPサーバーへ登録されたことにはなりません。
最初にlist_toolsを直接実行する
AIホスト側からToolが見えない場合は、LLMやClaude Codeなどを一度切り離して確認すると原因を絞りやすくなります。
Python SDKなら、クライアントから直接Tool一覧を取得できます。
import anyio
from mcp import Client
async def main():
async with Client("http://localhost:8000/mcp") as client:
result = await client.list_tools()
for tool in result.tools:
print(tool.name)
anyio.run(main)
ここで、
search_products get_product
などが表示されるなら、少なくともMCPサーバーのtools/listはToolを返しています。
逆に、
何も表示されない
のであれば、Claude CodeやMCP InspectorのUIを調べる前にServer側のTool登録を確認するべきです。
「ホストに表示されるツールが0個」という場合、SDK側が登録済みToolをtools/listから勝手に落とすことは通常考えにくいため、まずToolが実際にどのサーバーオブジェクトへ登録されているかを確認する価値があります。
別のMCPServerインスタンスへToolを登録していないか確認する
意外に見つけにくい原因が、MCPServerを複数作っているケースです。
たとえばtools.pyに次のコードがあります。
from mcp.server import MCPServer
mcp = MCPServer("MyServer")
@mcp.tool()
def search_products(query: str) -> str:
return query
一方、server.pyでも新しいServerを作っていたとします。
from mcp.server import MCPServer
mcp = MCPServer("MyServer")
mcp.run()
見た目は同じmcpですが、実際には別のオブジェクトです。
Toolを登録したのはtools.py側のMCPServerで、ホストが起動しているのはserver.py側の空のMCPServerという状態になります。
この場合、サーバーは正常に起動します。
しかしtools/listを呼ぶとToolは0件になります。
同じファイル名で複数のMCPServer(...)を作っている実装では、ホストが実際にどのオブジェクトをImportして起動しているかを確認してください。別モジュールの2つ目のMCPServer(...)が、Toolを何も持たない空のサーバーになっているケースは典型的な原因のひとつです。
Toolを定義したモジュールがImportされていない
Decoratorによってツールを登録している場合は、Toolを含むモジュールそのものが実行されている必要があります。
たとえば、
server.py
tools/
search.py
という構成にして、
@mcp.tool()
def search_products(query: str):
...
をsearch.pyへ書いたとしても、search.pyがどこからもImportされなければDecoratorは実行されません。
結果としてMCPServerにはToolが登録されないままです。
この問題はToolファイルを分割したときに発生しやすくなります。
開発中は1ファイルだったため正常だったものを、
tools/github.py tools/slack.py tools/database.py
のように分割した後、Import処理だけ追加し忘れるケースです。
Tool Definitionのファイルが存在するかではなく、サーバー起動時にその登録コードが実際に実行されたかを確認してください。
@mcp.tool()の書き方が間違っていないか確認する
Python SDKではDecoratorの書き方にも注意が必要です。
正しくは、
@mcp.tool()
def forecast(city: str) -> str:
return f"Sunny in {city}"
のように@mcp.tool()と括弧を付けます。
MCP Python SDK v2では、
@mcp.tool
のように括弧なしで利用すると、Tool Decoratorの使い方が正しくないことを示すTypeErrorが発生します。
このエラーはモジュールImport時に発生するため、本来はサーバー起動失敗になります。
しかし利用しているホストによっては、サーバーがクラッシュしている状態が「接続されたがToolが0件」のように見えることがあります。
そのためホスト画面だけで判断せず、一度ServerコマンドをTerminalから直接実行し、起動時の標準エラー出力を確認するとよいでしょう。
Tool名が重複していると片方が表示されない
複数のToolを登録しているのに一部だけ表示されない場合は、Tool名の重複も確認してください。
たとえば次のようなコードです。
@mcp.tool(name="search")
def search_products(query: str):
return query
@mcp.tool(name="search")
def search_users(query: str):
return query
どちらもsearchという名前で登録しようとしています。
MCP Python SDKでは同じTool名を複数登録すると、先に登録されたToolが残り、後の登録は破棄され、Server LogにTool already exists:という警告が出ます。
そのため、
Toolは10個作ったはずなのに9個しか表示されない
という場合は、Server Logで、
Tool already exists:
を検索してみるとよいでしょう。
ツール名は、
search_products search_users
のように用途を区別できる名前にします。
Low-level Serverではtools/list Handlerが必要
高レベルのMCPServerを利用している場合は、登録したToolからSDKがtools/listを処理してくれます。
一方、Low-levelのServerを利用している場合は、自分でProtocol Handlerを構築します。
MCP Python SDKのLow-level Serverでは、たとえば次のようにListToolsResultを返すHandlerを用意します。
from mcp.types import ListToolsResult, Tool
SEARCH_TOOL = Tool(
name="search_products",
description="商品を検索する",
input_schema={
"type": "object",
"properties": {
"query": { "type": "string" }
},
"required": ["query"],
},
)
async def list_tools(ctx, params):
return ListToolsResult(tools=[SEARCH_TOOL])
Tool実行Handlerだけ作って、
tools/call
を処理できるようにしても、tools/listでそのToolを公開しなければクライアントは存在を発見できません。
この状態は、Capability自体を宣言していないためにtools/listそのものがMethod not foundになるケースとは別問題です。ここではMethodは正常に応答しているものの、返す一覧に対象のToolが含まれていないという違いになります。
Low-level実装を利用している場合は、
Tool Handlerが存在する
ことと、
tools/listにそのToolが含まれる
ことを別々に確認してください。
inputSchemaが不正だとtools/list自体が失敗することがある
ToolのinputSchemaも確認する必要があります。
特にLow-level ServerでJSON Schemaを手書きしている場合に注意してください。
MCP Python SDK v2では、手動で作成したToolのinput_schemaが空の、
{}
になっている場合、仕様でルートのtype: "object"が要求されるためtools/listで失敗するようになっています。
最低限、引数がないToolでも、
{
"type": "object"
}
のようなSchemaが必要になります。
@mcp.tool()の高レベルAPIを利用している場合はSDKがSchemaを生成してくれるため、この問題は発生しにくくなります。
自前でTool(...)を構築している場合は、tools/listが本当に正常なレスポンスを返しているか確認してください。
tools Capabilityが見えているか確認する
MCPには、サーバーがどの機能を持つかを表すCapabilitiesがあります。
Toolを提供するMCP Serverなら、Clientから見たServer Capabilitiesにtoolsが存在することを確認します。
Python SDKでは接続後に、
client.server_capabilities
からServer Capabilityを確認できます。
client.server_capabilitiesにはサーバーが提供するtools、resources、promptsなどの機能が反映され、存在しないCapabilityはNoneになります。
2026-07-28世代では従来のinitialize / initialized Handshakeが廃止され、必要に応じてserver/discoverによって対応Protocol VersionやCapabilitiesを取得する方式へ変更されました。
Toolを提供しているつもりなのにCapabilities上でtoolsが見えない場合は、Server構成やProtocol実装を確認する必要があります。MCP InspectorのUIからCapabilityを確認する手順はMCP Inspectorの使い方で解説しています。
2026-07-28ではProtocol Versionの確認も重要
MCPは2026年7月28日の仕様でProtocol Coreが大きく変更されています。
現在の2026-07-28ではProtocol LevelのSessionと従来のInitialization Handshakeが廃止され、各RequestにProtocol情報を含めるStatelessな構成になりました。また、Capabilitiesを事前確認するためのserver/discoverも導入されています。
そのため、
Serverは新しいSDK Clientは古いSDK
または逆の組み合わせでは、Tool Discoveryまで正しく進まない可能性があります。
Python SDKでは、
client.protocol_version
から実際に利用しているProtocol Versionを確認できます。公式Clientでは新しいServerをDiscoveryし、必要に応じてLegacy HandshakeへFallbackする仕組みもあります。
SDK更新後から突然Toolが表示されなくなった場合は、Tool登録コードだけでなくClientとServerのProtocol Versionも確認してください。Method自体が認識されないケースの原因分類はMCPサーバーが「Method not found」になる原因で解説しています。
起動後に追加したToolはクライアント側へ反映されない場合がある
MCPではTool一覧を動的に変更することもできます。
たとえば最初は、
enable_recommendations
だけを公開し、このToolを呼んだ後に、
recommend_book
を追加するような構成です。
Python SDKでは、
mcp.add_tool(recommend_book)
によって実行中にToolを追加できます。
しかし、サーバー内部へ追加しただけでは、すでにTool一覧を取得したクライアントが自動的に再取得するとは限りません。
MCP Python SDKではToolを動的に追加した後、Tool Listが変化したことをクライアントへ通知できます。通知を受け取ったクライアントが再びtools/listを実行すると、新しいToolが見えるようになります。
つまり、
サーバー内部ではToolが存在する
のに、
ホストには表示されない
場合は、ホスト側が古いTool Listを持っている可能性があります。
2026-07-28ではlist_changedの受け取り方が変わっている
動的Toolを利用している場合は、2026年仕様の変更にも注意が必要です。
2026-07-28では、tools/prompts/resourcesのlist_changed通知は、Client自身が開いたsubscriptions/listenストリーム上で受け取る方式になっています。Serverが一方的に通知を送る従来方式とは異なります。
そのためServer側ではToolを追加し、変更通知も発行しているのに、Client側が変更通知を購読していなければUIへ反映されない可能性があります。
この場合、Serverを調べ続けるより、ClientがTool List変更を購読しているか確認する必要があります。
最も単純な切り分け方法は、Clientやホストを再接続してtools/listを取り直すことです。
クライアントが古いtools/listをキャッシュしている
2026-07-28ではtools/listなどのList Resultをキャッシュできる仕組みも導入されています。
ServerはToolやResourceのList結果にttlMsとcacheScopeという2つの情報を付けて返します。ttlMsはClientやGatewayがその結果をどの程度新鮮な情報として扱ってよいかを示す時間、cacheScopeはそのキャッシュを複数の呼び出し元で共有してよいか(public)、呼び出し元ごとに限定するべきか(private)を示します。
たとえば、
ttlMs: 60000
なら、ClientやGatewayはTool Listを一定時間キャッシュできます。
そのためServer側へToolを追加した直後でも、Clientが以前取得した一覧を使い続ける可能性があります。
この仕組みには安全なデフォルト値が存在しません。ユーザーごとに異なるTool一覧を誤って共有キャッシュしてしまう事故を避けるため、Serverはtools/listなどのList Resultを返すたびにttlMsとcacheScopeを明示的に指定する必要があります。
自分で長いTTLを指定している場合は、
cache_hints={
"tools/list": CacheHint(
ttl_ms=60_000,
scope="public"
)
}
のような設定を確認してください。
Tool Listを頻繁に変更するServerなら、長すぎるキャッシュ時間やpublicスコープは適していません。
認証ユーザーによってTool一覧を変えている場合も確認する
MCP Serverによっては、接続しているユーザーや権限に応じて公開するToolを変える場合があります。
たとえば管理者には、
search_user update_user delete_user
を公開し、一般ユーザーには、
search_user
だけを公開する設計です。
この場合、開発者のテスト環境ではToolが見えているのに、本番ユーザーからは表示されないことがあります。
tools/listがユーザーごとに異なる構成なら、Server内部のTool Registryだけを見るのではなく、問題が発生している認証情報を使って実際にtools/listを取得することが重要です。
2026-07-28のキャッシュ機能を利用する場合も、ユーザーごとにTool Listが異なるならcacheScope: "public"を安易に利用しないよう注意が必要です。publicは、すべての呼び出し側へ同一の結果を返せる場合だけ利用します。
tools/listのページネーションを確認する
Toolが非常に多いMCP Serverでは、tools/listのPaginationも確認する必要があります。
MCPのtools/listはPaginationに対応しており、RequestへCursorを指定できます。MCPのTool仕様でも、Tool Discoveryはtools/listを使い、Paginationを利用できることが定義されています。
Serverから、
{
"tools": [ ... ],
"nextCursor": "50"
}
のような結果が返っているなら、まだ次のページがあります。
独自Clientを実装していて最初のtools/listだけ取得し、nextCursorを無視していると、後半のToolが表示されません。
Toolが0件になる原因としては少ないものの、
特定のToolだけ見えない
場合には確認する価値があります。
大量のMCP Toolを扱うClientでは、全ページを取得できているか確認してください。
stdioではstdoutへのログ出力にも注意する
stdio Transportを利用している場合、Protocol Message自体がstdoutを利用するため、アプリケーションの通常ログを同じ場所へ出すとMCPメッセージへ余計な文字列が混ざります。
混入したログの内容によっては、Hostが接続を切ったり、Toolが1つも読み込まれていないように見えたりすることがあります。この現象自体は、Windowsのパス・環境変数と並ぶstdio起動トラブルの代表例としてMCPサーバーが起動しない原因で詳しく扱っているため、この記事では「Toolが表示されない」原因の一つとして位置付けるだけにとどめます。
stdio Serverで、
Terminalから見ると起動している ホスト上ではToolが0件
となる場合は、Import時のprint()やWrapper Scriptの出力も確認してください。
MCP Inspectorでtools/listまで確認する
ホスト固有の問題かServer側の問題かを分けるには、MCP Inspectorなど別のClientから接続すると分かりやすくなります。
重要なのは、単に、
Connected
と表示されるかではありません。
接続した後にTool一覧を開き、実際にtools/listの結果としてToolが表示されるか確認します。具体的な操作手順はMCP Inspectorの使い方で解説しています。
Inspectorでは表示されるのにClaude Codeなど特定ホストでは表示されない場合は、Server側のTool RegistryよりClient側のキャッシュ、Protocol対応、設定などを疑えます。
Inspectorでも0件ならServer側を優先して調べます。
この切り分けだけでも調査範囲をかなり狭められます。
tools/listの生レスポンスを見ると原因を切り分けやすい
可能であれば、最終的にはtools/listの生の結果まで確認すると確実です。
正常なら、
{
"result": {
"tools": [
{
"name": "search_products",
"inputSchema": { "type": "object" }
}
]
}
}
のようになっています。
Toolが本当に登録されていないなら、
{
"result": {
"tools": []
}
}
になります。
この場合、UI表示の問題ではありません。
逆にtools/listにはToolが入っているのにHost UIへ出てこないなら、ServerのTool登録は成功しており、Client側へ原因を絞れます。
「ツール一覧が表示されない」という見た目だけを追うより、
Server Registry ↓ tools/list ↓ MCP Client ↓ Host UI
のどこまでTool Definitionが届いているかを確認する考え方が有効です。
Toolを追加した直後だけ表示されないなら再接続して確認する
開発中によくあるのが、Serverを起動した後で新しいToolを追加したケースです。
Tool List変更通知へ対応しているClientなら再取得できますが、すべてのHostが同じように動くとは限りません。
そのため、新しくToolを追加した直後だけ表示されないなら、一度MCP ServerとClientの接続を再作成してみると原因を切り分けられます。
再接続後には表示されるなら、
Tool登録失敗
ではなく、
古いtools/listをClientが保持していた
可能性が高くなります。
本番環境で動的Toolを使うなら、その後にlist_changed通知やCache Policyを正しく実装します。
サーバーが起動するのにToolが表示されないときはtools/listを基準に調べる
MCPサーバーが正常に起動しているように見えるのにTool一覧が表示されない場合、最初に確認するべきなのはLLMやToolの実行処理ではありません。
MCPクライアントがToolを発見する入口であるtools/listを確認します。
tools/listが空なら、Toolを別のMCPServerインスタンスへ登録していないか、Tool ModuleがImportされているか、Decoratorが正しいか、Tool名が重複していないかを確認します。
Low-level Serverを利用している場合は、tools/list Handlerが登録され、正しいListToolsResultを返しているかも重要です。
一方、tools/listにはToolが含まれているのにHostへ表示されないなら、Client側のTool Listキャッシュ、list_changed通知、Pagination、Protocol Versionなどへ調査対象を移せます。
2026-07-28仕様ではMCPがStateless化されただけでなく、List Resultのキャッシュやsubscriptions/listenによる変更通知など、Tool Discovery周辺の仕組みも変化しています。
そのため動的にToolを追加するServerでは、「サーバーへ登録したから表示される」と考えず、Clientが最新のtools/listを取得しているところまで確認する必要があります。
MCPサーバーでToolが表示されない問題を切り分けるポイントは、コード内にToolが存在するかではなく、実際のtools/listレスポンスにそのToolが存在するかを見ることです。
ここを基準にすれば、Server側の登録問題なのか、MCP ClientやHost側の表示問題なのかを効率よく特定できます。
tools/listが空になる原因に関するよくある質問
Qサーバーは起動しているのにtools/listが空になるのはなぜですか
Aサーバーの起動とTool登録は別の処理だからです。別のMCPServerインスタンスへ登録している、Toolを定義したモジュールがImportされていない、Decoratorの書き方が間違っている、input_schemaが不正で検証に失敗しているなど、起動自体は成功しつつToolだけ登録されない原因がいくつもあります。
Qtools/callは動くのにtools/listに一部のToolが出てこないのはなぜですか
ALow-level Serverでtools/call用のHandlerだけを実装し、tools/list用のHandlerがそのToolを一覧へ含めていない場合に発生します。Tool Handlerが存在することと、tools/listのレスポンスにそのToolが含まれることは別々に確認する必要があります。
Q動的に追加したToolがホストに表示されないのはなぜですか
Aサーバー内部にToolを追加しただけでは、すでにtools/listを取得済みのクライアントが自動的に再取得するとは限らないためです。list_changedの通知にClientが対応しているか、2026-07-28では対応するsubscriptions/listenストリームを購読しているかを確認してください。
Qtools/listのキャッシュが原因で新しいToolが反映されないことはありますか
Aあります。2026-07-28ではtools/listなどのList ResultにttlMsとcacheScopeを付けてキャッシュを制御する仕組みが導入されています。長いttlMsやpublicスコープを指定していると、Toolを追加した直後でも古い一覧がキャッシュから返される可能性があります。
QMCP Inspectorでは表示されるのに特定のホストだけツールが表示されない場合はどうすればよいですか
AInspectorで正常に表示されるなら、MCPサーバー側のTool登録自体は成功しています。原因はそのホスト固有のキャッシュ、Protocol対応、設定などに絞れます。Server側のコードを追うより、ホストとサーバーの再接続やログ確認を先に行うと効率的です。
Qユーザーによってツール一覧が異なるサーバーではどう調査すればよいですか
AServer内部のTool Registryだけを見るのではなく、問題が発生している認証情報を使って実際にtools/listを取得し、そのユーザーに返される結果を直接確認する必要があります。cacheScope: publicを安易に使うと、別ユーザーの一覧が混ざって返る事故にもつながります。
Qtools/listのレスポンス自体を確認する一番確実な方法は何ですか
AMCP Inspectorなどでホストを介さずに直接tools/listを実行し、生のJSON-RPCレスポンスを見る方法です。resultのtoolsが空配列なら登録側の問題、Toolが入っているのにホストへ表示されないならクライアント側の問題と、レイヤーを分けて切り分けられます。
まとめ
MCPサーバーが起動しているのにツール一覧が表示されない場合は、まずLLMやTool実行処理を疑うのではなく、tools/listのレスポンスを直接確認することが近道です。
別のMCPServerインスタンスへ登録していないか、Toolモジュールがimportされているか、Decoratorの書き方やinputSchemaが正しいか、Tool名が重複していないかを順に確認してください。
Low-level Serverを使っている場合はtools/list Handlerの実装自体も見直します。
tools/listにToolが含まれているのにホストへ表示されない場合は、動的Toolのlist_changed通知、2026-07-28のキャッシュ設定(ttlMs/cacheScope)、ユーザーごとのTool一覧、Paginationなど、Client側・運用側の要因を確認してください。
「コード上にToolが存在するか」ではなく「tools/listの実際のレスポンスにToolが存在するか」を基準にすれば、Server側の登録問題なのかClient・Host側の表示問題なのかを効率よく切り分けられます。

