Connected with zero tools has a specific meaning

A connected state proves only that the client reached the server. It does not prove the server completed capability negotiation or returned a non-empty tool list. Claude Code's official MCP documentation explicitly distinguishes a server that advertises the tools capability but exposes no tools, and its /mcp panel shows the tool count beside each server.

Use MCP Inspector as the client-independent boundary. Its Tools tab lists tool names, descriptions, and schemas and can invoke them with test inputs. If that view is empty, fix the server implementation or registration. If it is populated, move to the target client's filters, scope, authentication, cache, and session behavior.

Test initialize before blaming tools/list

MCP tool discovery happens after the protocol initialization exchange. Verify the negotiated protocol version, the server's declared capabilities, and the initialized notification before investigating tool schemas. A transport that opens and then fails initialization can look like an empty tool catalog in a client UI.

For local stdio servers, run the exact configured command with the same arguments and environment. Use absolute paths where the working directory may differ, and write diagnostics to stderr because stdout is reserved for protocol messages. For Streamable HTTP, inspect authentication, response status, session headers, and server-side logs.

Separate discovery, loading, and invocation

Discovery asks whether tools/list returns valid tool definitions. Loading asks whether the client makes those definitions available in the current workspace, agent, and session. Invocation asks whether the model selects an available tool and receives permission to call it. Each layer has different proof and a different fix.

Claude Code and GitHub Copilot can load tools on demand to reduce context use. That means a tool may not be expanded into the model context until a matching task triggers tool search. Check the client status and tool policy before treating deferred loading as server failure.

Client-specific checks after Inspector passes

In Claude Code, use /mcp to inspect connection state, authentication, and tool count. Project-scoped configuration may require approval, duplicate names can resolve by scope precedence, and tool search can defer definitions. In GitHub Copilot CLI, inspect /mcp or copilot mcp get, then check enabled-tool filters and any custom-agent tool policy.

In Cursor or another MCP client, use the MCP settings and logs exposed by the installed version, then compare that client view with the same server in Inspector. Product interfaces and policy controls change, so retain the client version and a sanitized status capture in the bug report instead of assuming one universal menu path.

What evidence to collect before filing a bug

Record the client and server versions, transport, operating system, active config scope, exact symptom, expected tool names, initialization result, tools/list result, enabled-tool policy, and sanitized logs. Remove credentials, tokens, private URLs, and sensitive payloads before sharing any record.

The downloadable worksheet on this page follows the same eight-layer order as the debugger. Attach the first failing check and its observable output; a report that says only 'tools are missing' forces maintainers to repeat every layer.

Recommended play

  1. Use MCP Inspector first when the server connects but exposes zero tools; it separates server discovery from client behavior.
  2. Keep discovery, client loading, and model invocation as three different states with separate pass conditions.
  3. Change only the first failing layer, then rerun the same proof before modifying permissions or unrelated configuration.

MCP missing-tools symptom map

Start at the row that matches the observable symptom, then move only after its pass condition is proven.

AreaLikely layerFirst proofDo not confuse with
Server absent from statusConfig load or scopeServer name appears in the active client status viewA tools/list implementation bug
Configured but disconnectedProcess, transport, auth, or initializationExact command stays alive or HTTP connection initializesA model tool-selection problem
Connected with 0 toolsCapability negotiation or tools/listInspector Tools tab returns expected definitionsWrite permission or prompt wording
Inspector passes, client emptyClient scope, authentication, or tool filterTool is enabled for the current workspace and agentA server reinstall
Tool visible but unusedDeferred loading, description, schema, prompt, or approvalExplicit matching request selects and invokes the toolA discovery failure

Execution steps

01

Capture the exact state

Record whether the server is absent, disconnected, connected with zero tools, populated only in Inspector, stale after a change, or visible but never called.

02

Prove process and initialization

Reproduce the exact transport, inspect initialization and declared capabilities, and eliminate stdout noise for local stdio servers.

03

Inspect tools/list independently

Connect MCP Inspector to the same server and verify expected names, descriptions, input schemas, and one safe test invocation.

04

Audit client policy

Check authentication, configuration precedence, workspace scope, enabled tools, allowlists, denylists, custom-agent policy, and on-demand loading.

05

Retest one changed layer

Reconnect or reload as required, repeat the original proof, and retain sanitized evidence for the server and client versions tested.

Common pitfalls

Reinstalling before finding the failing layer

A reinstall changes many variables without proving the cause. Test config, transport, initialize, and tools/list in order.

Writing debug logs to stdout

For stdio servers, keep stdout exclusively for protocol traffic and send diagnostic logs to stderr.

Treating a tool that is not called as a missing tool

First prove the tool is visible. Then check deferred loading, prompt fit, description, schema, permission, and invocation separately.

Widening every tool permission

Enable only the expected tool in the required scope. A broad allow-all rule hides policy mistakes and increases risk.

Implementation checklist

  • Record the exact missing-tools symptom before changing configuration.
  • Confirm the active config source, scope, server name, command or URL, and authentication state.
  • Run the exact stdio command or inspect the Streamable HTTP connection and server logs.
  • Verify initialization, protocol version, declared tools capability, and initialized notification.
  • Inspect tools/list in MCP Inspector and validate names, descriptions, and input schemas.
  • Check client allowlists, denylists, enabled-tool filters, workspace scope, and custom-agent policy.
  • Reconnect or reload after changes and verify dynamic list-change behavior where applicable.
  • Test one explicit, safe request that clearly matches the expected tool.
  • Redact credentials, tokens, private URLs, and sensitive payloads from shared evidence.

Questions this guide answers

Why is my MCP server connected but showing zero tools?

A connected state proves the transport reached the server, not that initialization completed or tools/list returned definitions. Open the same server in MCP Inspector. If its Tools tab is empty, fix capability negotiation, tool registration, tools/list, or invalid schemas. If Inspector lists tools, check the target client's scope, authentication, enabled-tool filters, and refresh behavior.

How do I test MCP tools/list?

Connect the server with the official MCP Inspector and open its Tools tab. Confirm the expected names, descriptions, and input schemas appear, then run one safe test call. This gives client-independent proof before you troubleshoot Claude Code, Cursor, GitHub Copilot, or another client's policy and loading behavior.

Why is an MCP tool visible but never called?

That is usually a selection, loading, permission, or schema problem rather than discovery failure. Use an explicit request that clearly requires the tool, check whether the client defers tools through tool search, review the description and required schema fields, and confirm the invocation is allowed in the current agent and workspace.

Should an MCP stdio server write logs to stdout?

No. For a stdio MCP server, stdout carries protocol messages, so debug output can corrupt JSON-RPC framing. Send diagnostic logs to stderr, run the exact configured command with the same environment, and use absolute paths when the client may launch from a different working directory.