PRACTICAL GUIDE / MCP tools not showing debugging

Debugging MCP Tools Missing After Capability Negotiation

Debug missing MCP tools by tracing initialize negotiation, tools/list pagination, authorization, schema validation, notifications, and client cache behavior.

By The Testing AcademyUpdated July 11, 20269 min read
All field guides
In this guide10 sections
  1. Define the exact missing-tool symptom
  2. Build the lifecycle root-cause tree
  3. Capture a complete initialization transcript
  4. Diff advertised and stored capabilities
  5. Probe every tools/list page directly
  6. Run isolation experiments across boundaries
  7. Diagnose authorization without leaking catalog data
  8. Assign protocol ownership clearly
  9. Gate the repair and prevent recurrence
  10. Execute the missing-tool action plan

What you will learn

  • Define the exact missing-tool symptom
  • Build the lifecycle root-cause tree
  • Capture a complete initialization transcript
  • Diff advertised and stored capabilities

When MCP tools vanish after capability negotiation, debug the protocol transcript before touching model prompts. Tool discovery is a client-server state machine: transport startup, initialization, version and capability agreement, readiness notification, paginated listing, schema validation, authorization filtering, and client registration. A blank tool picker only tells you the final state failed.

Capture both wire messages and the client's internal acceptance decisions. If the server returned a tool but the client discarded it, server logs alone will send the investigation in the wrong direction. If no tools/list request was sent, changing the server's tool registry cannot fix the client lifecycle.

Animated field map

MCP Missing-Tool Diagnostic Flow

The investigation follows the missing-tool symptom through the initialization transcript and capability state to a direct list probe and client repair.

  1. 01 / missing tool

    Missing Tool Symptom

    Identify the client, server, identity, transport, expected tool, and session window.

  2. 02 / initialize transcript

    Initialize Transcript

    Capture version exchange, capabilities, implementation data, and readiness order.

  3. 03 / capability diff

    Capability Diff

    Compare server declaration with client session state and feature routing.

  4. 04 / tools list probe

    Tools List Probe

    Request every page directly and record schema and authorization decisions.

  5. 05 / client fix

    Client Fix

    Repair lifecycle, pagination, validation, refresh, or cache behavior and retest.

Define the exact missing-tool symptom

Write down the expected tool name with case preserved, the server endpoint or command, transport, client build, authenticated principal, granted scopes, workspace, and connection time. Determine whether all tools are absent, one page is absent, one identity sees fewer tools, or definitions appear but are unavailable to the model. Those are different failures.

Distinguish discovery from presentation and invocation. A tool can be present in the tools/list response, accepted into the client registry, hidden by product policy, omitted from a model request, or rejected only when called. Add a trace event at each transition with a stable connection ID and a reason code. Do not log secret tokens or sensitive tool arguments.

Reproduce in a fresh session. A reconnect that fixes the issue points toward cache invalidation or list-change handling, while a consistent failure is easier to localize. Preserve the failing session before restarting it.

Build the lifecycle root-cause tree

Use six branches. Transport includes wrong command, missing environment, mixed stdout logs, HTTP routing, framing, and premature close. Initialization includes no response, unsupported negotiated version, wrong message order, or missing initialized notification. Capability state includes a server response without tools or a client that fails to store it.

Listing includes no tools/list, ignored nextCursor, repeated cursors, timeout, or malformed result. Acceptance includes invalid tool names, unsupported JSON Schema, duplicate names, and a client validator that rejects the entire page because one item is bad. Policy and cache includes scope-filtered catalogs, workspace policy, stale negative cache, and missed notifications/tools/list_changed refresh.

The official MCP lifecycle specification requires initialization to be the first interaction, defines capability and protocol-version negotiation, and places the initialized notification before normal operation. Use the negotiated session record as the source of truth instead of inferring support from server source code.

Capture a complete initialization transcript

At the wire boundary, retain direction, connection ID, sequence number, timestamp, JSON-RPC ID, method, result or error category, and a redacted payload. At the client boundary, retain the negotiated protocol value, advertised server capability keys, readiness state, and the component that decided whether to list tools.

A minimized transcript should resemble this structure:

JSON
{
  "connectionId": "conn-42",
  "events": [
    {"seq": 1, "direction": "client-to-server", "method": "initialize", "id": 1},
    {"seq": 2, "direction": "server-to-client", "id": 1, "resultCapabilities": ["tools"]},
    {"seq": 3, "direction": "client-to-server", "method": "notifications/initialized"},
    {"seq": 4, "direction": "client-to-server", "method": "tools/list", "id": 2},
    {"seq": 5, "direction": "server-to-client", "id": 2, "toolCount": 3, "nextCursorPresent": false}
  ]
}

This is an illustrative diagnostic projection, not a replacement protocol schema. Retain raw redacted messages separately. Check request-response ID correlation and message ordering; concurrent logs sorted only by wall clock can misrepresent the sequence.

Diff advertised and stored capabilities

Inspect the server's initialize result. A server that supports tool discovery must declare the tools capability. Then inspect the client immediately after decoding the response: did it preserve that capability under the active connection, or did a compatibility layer drop an unknown field? Compare a working and failing session as normalized JSON rather than visual log lines.

Do not require a client to advertise a server capability in its own request. Client and server capability sets describe different optional features. Also avoid treating listChanged as permission to list tools; it describes support for change notifications, while the tools capability establishes tool support.

Test the readiness boundary by instrumenting when the client permits tools/list. A race can schedule discovery before the initialization result is committed or before the initialized notification is sent, then cache the resulting error as an empty catalog.

Probe every tools/list page directly

After a successful handshake, send tools/list without a cursor, save the returned tools, and follow each nextCursor until none remains. The MCP tools specification defines the listing request, pagination, capability declaration, and list-changed notification. Compare the raw list with the client's accepted registry.

Instrument per-tool validation rather than one all-or-nothing exception. Record name, schema hash, validation outcome, and a safe reason code. A production UI may hide invalid definitions, but diagnostics should show that the server returned three tools and one was rejected. Never expose a policy-filtered tool name to a principal who is not authorized to discover it.

The following TypeScript control loop makes pagination and rejection visible:

TypeScript
async function collectTools(session: McpSession) {
  const accepted = [];
  let cursor: string | undefined;

  do {
    const page = await session.listTools({ cursor });
    for (const tool of page.tools) {
      const result = validateToolDefinition(tool);
      session.trace("tool.validation", { name: tool.name, ok: result.ok });
      if (result.ok) accepted.push(tool);
    }
    cursor = page.nextCursor;
  } while (cursor);

  return accepted;
}

In real code, add repeated-cursor detection, page and time budgets, cancellation, and a policy for partial results. Whether one malformed tool should quarantine only itself or fail the connection is an explicit product and security decision.

Run isolation experiments across boundaries

First, connect the official MCP Inspector using the same server command, environment, transport, and credentials where possible. If Inspector lists the expected tools, compare its handshake and pages with the product client. If both fail, reduce the server to one static no-argument tool and remove authorization and dynamic registry logic.

Second, connect the product client to a minimal known-good server. This isolates client lifecycle and schema support from the real server. Third, use the same principal with a direct list probe and then a different principal with declared permissions. A difference localizes policy or scope behavior. Fourth, return two pages intentionally to expose clients that stop after the first.

Finally, trigger a catalog change after connection. Verify that a server declaring listChanged sends the notification and that the client schedules a fresh complete listing without merging stale entries incorrectly. Also test a server that does not declare listChanged; the client needs a documented reconnect or refresh policy rather than assuming live notifications.

Diagnose authorization without leaking catalog data

Tool visibility may depend on tenant, role, resource audience, or consent. Trace an opaque policy decision ID, requested operation, principal ID hash, granted scope names when safe, and allow or deny outcome. Keep the detailed policy explanation in protected logs. A generic empty list can be correct for an unprivileged user but should not be indistinguishable from a parser failure to operators.

Validate token audience and server-side authorization independently of UI visibility. Capability negotiation is not authorization. A client seeing a tool definition does not prove it may invoke the tool, and hiding a definition does not replace enforcement at tools/call.

Use least privilege during experiments. Do not solve discovery by granting a broad wildcard scope. Test with a dedicated principal and the minimum scope expected to reveal the target tool.

Assign protocol ownership clearly

The server team owns truthful capability declarations, valid paginated lists, stable unique names, input schemas, notifications, and policy enforcement. The client transport team owns framing, lifecycle ordering, correlation, timeouts, and cancellation. The client registry team owns pagination, schema compatibility, per-tool acceptance, caching, and refresh. The product and model integration team owns which accepted tools are exposed in a particular workflow.

Identity engineering owns token acquisition and scope semantics; security owns discovery leakage policy and call-time authorization. Observability owners define redaction and retention. Each boundary should emit a reasoned count so an operator can answer: returned, accepted, policy-visible, model-exposed, and callable.

Gate the repair and prevent recurrence

Create contract tests for a tools-capable initialization, no-tools initialization, multiple pages, malformed single definition, duplicate name, changed-list notification, insufficient scope, timeout, and reconnect. The following values are illustrative thresholds only:

JSON
{
  "illustrativeThresholds": true,
  "releaseGate": {
    "requiredHandshakeScenariosPassing": 10,
    "maximumUnknownToolAcceptance": 0,
    "maximumPaginationLoopCount": 0,
    "requiredAuthorizedCatalogMatch": 1.0,
    "requiredUnauthorizedCatalogLeakCount": 0
  }
}

Canary the fix with counts at every registry boundary and alert on sudden zero-tool sessions among previously successful server-client pairs. A release should fail if it restores display by bypassing schema validation or authorization.

Execute the missing-tool action plan

Preserve one failing session, verify lifecycle order, diff capability state, probe all list pages, compare returned and accepted definitions, test with Inspector and a minimal counterpart, then isolate authorization and cache refresh. Repair the narrowest failing boundary and add its transcript to the contract suite.

The incident is resolved only when a fresh session discovers the correct authorized catalog, a catalog change follows the declared refresh behavior, malformed definitions are handled by policy, and unauthorized identities learn nothing they should not know. A visible tool list is the outcome; a correct protocol state machine is the fix.

// LIVE COURSE / THE TESTING ACADEMY

AI Tester Blueprint

Master GenAI, AI Agents, MCP, RAG, CrewAI. Build 23+ real AI projects.

From the instructor behind this guide.

AI testing roles are up 180% and pay 12-22 LPA. 12+ weeks / 65+ live hrs / Sat-Sun 8:30 AM IST.

Code PROMODE / 10% offJoin the batch

The Testing Academy editorial desk

Practical QA guidance built around test evidence, production tradeoffs, and interview-ready explanations.

Published July 11, 2026 / Reviewed July 11, 2026

PRIMARY REFERENCES

Verify the details at the source

QABattle guides are practical explanations. Product behavior, standards, and APIs can change, so use these primary references for the canonical details.

  1. 01
    Model Context Protocol documentation

    Model Context Protocol

    Canonical architecture, transport, server, client, and security concepts.

  2. 02
    AI Risk Management Framework

    NIST

    A primary risk framework for measuring and governing AI system behavior.

FAQ / QUICK ANSWERS

Questions testers ask

Does declaring the MCP tools capability automatically send tool definitions?

No. The declaration says the server supports tools. The client still discovers definitions through tools/list and must handle pagination and validation correctly.

Why can MCP Inspector show tools while the product client shows none?

The product client may negotiate a different version, send different credentials, omit the initialized notification, reject a schema, stop at one page, or use stale cache state.

Can authorization make only some MCP tools disappear?

Yes. A server may expose tools according to the authenticated principal and granted scopes. Compare identities and record the policy reason without leaking unauthorized names.

When should a client refresh its MCP tool list?

It should list tools after successful initialization and follow its refresh policy. If listChanged was declared, it should also handle tools/list_changed notifications.

What is the smallest useful missing-tool trace?

Capture transport startup, initialize request and response, initialized notification, every tools/list page, validation decisions, authorization context, and client cache writes.