> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ctxprotocol.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting

> Common errors and solutions when building MCP servers for the Context Marketplace

## Common Errors

### `{"error":"Unauthorized"}`

**This is the most common error for new tool builders.**

<Warning>
  The `createContextMiddleware()` from `@ctxprotocol/sdk` verifies that requests come from the Context Platform with a valid JWT. Without this JWT, any call to `tools/call` will return `{"error":"Unauthorized"}`.
</Warning>

#### Why This Happens

| Cause                             | Explanation                                                                                                                              |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| **Missing JWT on `tools/call`**   | The middleware requires a JWT from the Context Platform for execution methods.                                                           |
| **HTTP instead of HTTPS**         | Context Platform only connects to HTTPS endpoints. HTTP will silently fail.                                                              |
| **Not registered on marketplace** | Until you register at [ctxprotocol.com/contribute](https://ctxprotocol.com/contribute), the platform won't send requests to your server. |
| **Wrong endpoint URL**            | The URL you registered doesn't match your deployed server.                                                                               |

#### What You CAN Test Locally (No Auth Required)

These MCP methods work without authentication:

```bash theme={null}
# Initialize session (no auth required)
curl -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}},"id":1}'

# List tools (no auth required)
curl -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -H "mcp-session-id: YOUR-SESSION-ID-FROM-INITIALIZE" \
  -d '{"jsonrpc":"2.0","method":"tools/list","id":2}'
```

#### Testing `tools/call` Locally

The `tools/call` method requires a valid JWT from the Context Platform. Options for testing:

1. **Test tool logic directly:** write test files that call your tool handler functions directly, bypassing the MCP transport
2. **Temporarily bypass middleware:** comment out `verifyContextAuth` during development:
   ```typescript theme={null}
   // Development: bypass auth for testing
   // app.post("/mcp", verifyContextAuth, async (req, res) => { ... });
   app.post("/mcp", async (req, res) => { ... });
   ```
3. **Test on deployed server:** SSH into your server and test against localhost after deployment

<Warning>
  **Remember to re-enable the middleware before going live!** Without it, anyone can call your tools for free.
</Warning>

#### End-to-End Testing

For full end-to-end testing through the Context Platform:

1. **Deploy to HTTPS:** use Railway, Vercel, or set up Caddy/nginx
2. **Register on marketplace:** go to [ctxprotocol.com/contribute](https://ctxprotocol.com/contribute)
3. **Test through the Context app:** ask the agent to use your tool

***

### Tool Not Discovered

Your server is deployed but Context can't find your tools.

#### Checklist

* [ ] Health endpoint returns 200: `curl https://your-server.com/health`
* [ ] `initialize` works: Test with curl (see above)
* [ ] `tools/list` returns your tools: Test with curl after initialize
* [ ] URL is HTTPS (not HTTP)
* [ ] URL ends with `/mcp` (e.g., `https://your-server.com/mcp`)
* [ ] Tools have `outputSchema` defined (required by Context)
* [ ] Every `outputSchema` has `type: "object"` at the root (not `anyOf`, `oneOf`, an array, or a primitive) — see [outputSchema root must be object](/guides/build-tools#outputschema-root-must-be-type-object)

***

### Submission Rejected — Schema Validation Failed

If the [contribute form](https://www.ctxprotocol.com/contribute) returns a schema-validation error when you submit your endpoint, the MCP SDK rejected your `tools/list` response. The most common cause is an `outputSchema` whose root is not `{ type: "object" }`.

#### Symptoms

The form shows an error like:

> Schema validation failed on tool `<tool_name>`: `outputSchema.type` must be `"object"` at the root.

#### Fix

Your `outputSchema` root must be an object type. Move nullability, optionality, and error signalling **inside** `properties` — don't express them at the root.

```typescript theme={null}
// ❌ Rejected
outputSchema: {
  anyOf: [
    { type: "object", properties: { ... } },
    { type: "null" },
  ],
}

// ✅ Accepted
outputSchema: {
  type: "object",
  properties: {
    venue: { type: "string" },
    current_price: { type: ["string", "null"] },
  },
}
```

See [outputSchema root must be object](/guides/build-tools#outputschema-root-must-be-type-object) for the full pattern and examples.

#### Validate locally before resubmitting

```bash theme={null}
curl -X POST https://your-server.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","method":"tools/list","id":1}' \
  | jq '.result.tools[] | { name, outputSchemaRoot: .outputSchema.type }'
```

Every tool should print `"outputSchemaRoot": "object"`. Anything else — `null`, `"array"`, or missing — will be rejected.

***

### New/Updated Tools Not Appearing

You deployed new endpoints but they're not showing up in the marketplace.

**This is the most common oversight after updating your MCP server.**

#### Solution

1. Go to [ctxprotocol.com/developer/tools](https://www.ctxprotocol.com/developer/tools) → **Developer Tools** (My Tools)
2. Find your tool and click **"Refresh Skills"**
3. Context will re-call `listTools()` to discover your changes

#### Also Consider

* **Update your description:** if you added significant new functionality, use the [MCP Server Analysis Prompt](https://github.com/ctxprotocol/sdk/blob/main/docs/mcp-server-analysis-prompt.md) to generate an updated description
* **Verify deployment:** make sure your new code is actually deployed (check health endpoint, test `tools/list` via curl)

***

### Server Won't Start

#### Node.js Version

```bash theme={null}
node --version  # Must be 18+
```

#### Missing Dependencies

```bash theme={null}
pnpm install  # or npm install
```

#### TypeScript Errors

```bash theme={null}
pnpm exec tsc --noEmit  # Check for type errors
```

#### Module System Mismatch

Ensure your `package.json` has:

```json theme={null}
{
  "type": "module"
}
```

***

### Railway Deployment Fails

1. Check Railway logs for specific errors
2. Ensure `package.json` has `"type": "module"`
3. Set start command to: `pnpm start` or `npm start`
4. Verify `tsconfig.json` has correct module settings

***

### Response Schema Validation Fails

If your tool responses don't match your `outputSchema`, users can dispute them.

#### Common Causes

```typescript theme={null}
// ❌ Schema says number, response is string
outputSchema: { value: { type: "number" } }
structuredContent: { value: "42" }  // String, not number!

// ✅ Correct: Types match
outputSchema: { value: { type: "number" } }
structuredContent: { value: 42 }  // Number
```

#### Solution

* Ensure all `structuredContent` fields match your `outputSchema` types exactly
* Use TypeScript to catch type mismatches at compile time
* Test your responses against the schema before deploying

***

## MCP Security Model Reference

Understanding which methods require authentication:

| MCP Method       | Auth Required | Why                                        |
| ---------------- | ------------- | ------------------------------------------ |
| `initialize`     | ❌ No          | Session setup                              |
| `tools/list`     | ❌ No          | Discovery: agents need to see your schemas |
| `resources/list` | ❌ No          | Discovery                                  |
| `prompts/list`   | ❌ No          | Discovery                                  |
| `tools/call`     | ✅ **Yes**     | **Execution: costs money, runs your code** |

<Info>
  Discovery methods are intentionally open so AI agents can find your tools. Only execution (`tools/call`) requires payment verification through the Context Platform JWT.
</Info>

***

## Using Developer Mode for Debugging

When your tool is registered on the marketplace but not returning expected results, **Developer Mode** provides detailed execution logs to help diagnose issues.

### Enabling Developer Mode

1. Go to **Settings** in the Context app
2. Scroll to **Developer Settings**
3. Enable **Developer Mode**

### What Developer Mode Shows

When enabled, a **Developer Logs** card appears at the bottom of AI responses. Click to expand and see:

* **User's Original Question**: the prompt that triggered the turn
* **Execution Summary**: orchestration mode (`manual` / `auto` / `query`), success status, tool-loop step count, total MCP calls, and any handshake pause or bounded-answer notice
* **Orchestration Selection**: which policy the runtime used, the candidate method count, and the tools/methods it selected (manual pin collapses discovery, so this section is shorter for manual turns)
* **Execution Contract**: the planner query the iterative loop was working from
* **Execution Diagnostics (tool registry)**: available vs. selected method counts, methods the planner picked that were filtered out at registry build, tool-call attempt/success/failure counts, and failure samples — the most actionable section for "why did my tool fail?"
* **Tool Call History**: every MCP call (and every Python `code_interpreter` sandbox call, flagged) with arguments and a truncated result
* **Execution Trace**: the iterative loop's per-step record (tool name, intent, output alias, duration, artifacts emitted)
* **Verification**: completeness evaluations, repair events, capability-miss signals, and bounded-answer reasons when the runtime stopped before another retry
* **Handshake** (action tools only): confirms the loop paused for your signature/approval rather than failing
* **Code Interpreter Artifacts** (sandbox turns only): image artifacts the Python sandbox emitted, with Vercel Blob URLs
* **Final Execution Result**: the data or error the runtime returned

<Note>
  The runtime is an **iterative AI SDK tool loop** — it does not generate or execute JavaScript. Older docs referenced "Initial Execution Snapshot" / "Final Execution Snapshot" blocks; those sections have been removed because the iterative runtime uses a `// iterative execution: no generated code` sentinel and there is no generated code to snapshot. What you see instead is the **Tool Call History** and **Execution Trace** above.
</Note>

### Copying Logs for Debugging

Click **"Copy All"** to copy the complete debug log. You can then:

1. Paste the logs into an AI coding assistant (Claude, GPT-4, etc.)
2. Ask it to analyze why your MCP server isn't returning expected results
3. The AI can suggest specific fixes based on the execution trace

### Common Issues Found via Developer Logs

<AccordionGroup>
  <Accordion title="Input Schema Problems">
    **Symptom**: Wrong or missing arguments in tool calls

    **Check**: Look at the "Tool Call History" section to see what arguments were passed

    **Fix**: Ensure your `inputSchema` has:

    * Clear `description` fields for each parameter
    * `default` or `examples` values for better AI understanding
    * Correct `type` definitions (string, number, boolean, etc.)

    ```typescript theme={null}
    inputSchema: {
      type: "object",
      properties: {
        symbol: {
          type: "string",
          description: "Trading symbol (e.g., 'BTC', 'ETH')",
          examples: ["BTC", "ETH", "SOL"]
        },
        timeframe: {
          type: "string",
          description: "Time period for data",
          default: "24h",
          enum: ["1h", "24h", "7d", "30d"]
        }
      },
      required: ["symbol"]
    }
    ```
  </Accordion>

  <Accordion title="Output Schema Mismatches">
    **Symptom**: The Execution Diagnostics section shows tool-call failures, or the Verification section reports the answer is still missing required data.

    **Check**: Compare your `outputSchema` with the actual result in "Tool Call History" — does the `structuredContent` you return match the schema you declared?

    **Fix**: Your `structuredContent` must exactly match your declared `outputSchema`:

    ```typescript theme={null}
    // ❌ Schema/response mismatch
    outputSchema: {
      price: { type: "number" },
      change: { type: "number" }
    }
    // Response returns: { price: "1234.56", change: null }

    // ✅ Correct: Types and structure match
    outputSchema: {
      price: { type: "number" },
      change: { type: "number", nullable: true }
    }
    // Response returns: { price: 1234.56, change: -2.5 }
    ```
  </Accordion>

  <Accordion title="Missing structuredContent">
    **Symptom**: AI can't parse your response, retries multiple times

    **Check**: Look at the raw result in "Tool Call History", is it structured data or just text?

    **Fix**: Always return `structuredContent` with your tool results:

    ```typescript theme={null}
    return {
      content: [{ type: "text", text: JSON.stringify(data) }],
      // Required for Context marketplace
      structuredContent: data,
      _meta: {
        outputSchema: yourOutputSchema
      }
    };
    ```
  </Accordion>

  <Accordion title="Poor Tool Descriptions">
    **Symptom**: AI picks the wrong tool or passes incorrect arguments

    **Check**: Review the **Orchestration Selection** and **Tool Call History** sections — did the runtime select your tool, and did it call your method with the arguments you expected?

    **Fix**: Write clear, specific tool descriptions:

    ```typescript theme={null}
    // ❌ Vague description
    description: "Gets market data"

    // ✅ Specific description
    description: "Fetches real-time cryptocurrency price, 24h volume, and price change for a given trading symbol. Returns data from top exchanges. Use this when the user asks about current prices, market cap, or trading volume."
    ```
  </Accordion>

  <Accordion title="Error Handling Issues">
    **Symptom**: Generic errors in execution trace, no useful error messages

    **Check**: Look at the "error" field in failed attempts

    **Fix**: Return meaningful errors that help diagnose the issue:

    ```typescript theme={null}
    // ❌ Generic error
    throw new Error("Failed");

    // ✅ Helpful error
    return {
      content: [{ type: "text", text: "Error: Invalid symbol" }],
      structuredContent: {
        error: "INVALID_SYMBOL",
        message: "Symbol 'XYZ' is not supported. Valid symbols: BTC, ETH, SOL",
        validSymbols: ["BTC", "ETH", "SOL"]
      },
      isError: true
    };
    ```
  </Accordion>
</AccordionGroup>

### Recovery and Retries

The iterative runtime automatically retries when:

1. **Tool-call / data-shape failures**: a managed MCP call returns a shape that does not match your `outputSchema`, or your tool returns a structured error the runtime can recover from.
2. **Capability miss**: no available tool can satisfy the request — the Verification section will show `Needs Different Tools Triggered: YES` and a `Missing Capability`.
3. **Bounded answer**: a safety guardrail (same-endpoint fanout, upstream abort, or explicit empty result) stops further retries and the runtime delivers the best answer from evidence already retrieved. The Verification section shows the `Bounded Answer Reason`.

Retries surface as **extra tool-loop steps** in the Execution Trace and additional entries in the Tool Call History — not as JavaScript code edits. The runtime does not generate or execute code.

If you see repeated calls or a bounded answer in the logs, it usually means:

* Your tool returned unexpected data format (check the Tool Call History result vs your `outputSchema`)
* Your tool returned zero results without an explicit `searchExhausted` / `noResultsReason` signal, so the runtime could not tell whether the absence was the answer
* There may be schema or description improvements you can make (see the Output Schema Mismatches accordion above)

<Tip>
  **Pro Tip**: Copy the Developer Logs, paste them into Claude or another AI assistant along with this troubleshooting page, and ask: "Based on these execution logs, why is my MCP tool not returning the expected results? What should I fix in my server?"
</Tip>

<Info>
  **Full automated QA:** For systematic validation beyond manual debugging, use the [Deep Validation System Prompt](https://github.com/ctxprotocol/sdk/blob/main/docs/mcp-contributor-deep-validation-system-prompt.md). Give it to any coding agent and it will validate your server against the Context Protocol docs, test Query mode and Execute mode through the SDK with developer traces, and iterate fixes until both answer quality and runtime health pass.
</Info>

***

## Still Stuck?

<CardGroup cols={2}>
  <Card title="GitHub Issues" icon="github" href="https://github.com/ctxprotocol/sdk/issues">
    Report bugs or ask questions
  </Card>

  <Card title="Example Servers" icon="code" href="https://github.com/ctxprotocol/sdk/tree/main/examples/server">
    Working reference implementations
  </Card>
</CardGroup>
