> ## 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.

# Build & List Your Tool

> Step-by-step guide to building an MCP server and listing it on the Context marketplace

<Info>
  **New to MCP?** Start with our [5-Minute Quickstart](/guides/quickstart) to build and deploy your first server, then come back here for advanced features.
</Info>

## Overview

Want to earn revenue from your data? **Turn the insights people pay \$500/year for into \$0.10/response revenue you keep.** Build an MCP server and register it as an **MCP Tool** on the Context marketplace.

***

## Start With A Product Contract

Before you write code, decide which product you are actually shipping:

| Surface     | What you are selling                                       | What good looks like                                                                                                                                               |
| ----------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Query**   | A premium answer contract                                  | Context can return `answer_with_evidence` in chat and `evidence_only` for external agents with the right facts, source refs, freshness, confidence, and view hints |
| **Execute** | A normalized primitive contract                            | Agents get stable typed fields, consistent pagination/filtering, and explicit execute pricing without having to normalize fragmented APIs themselves               |
| **Both**    | A normalized primitive that can also power premium answers | The same canonical data can support Query synthesis and direct Execute calls                                                                                       |

Every serious builder brief should specify:

* the exact premium feature or normalized primitive
* the target paying user
* 5 must-win prompts or requests
* the expected evidence fields or normalized schema
* the ideal output surface (`Query`, `Execute`, or `both`)
* freshness / latency expectations
* why free substitutes or direct APIs are insufficient

<Info>
  If your pitch still reads like a category label such as "crypto analytics" or "company data," it is too vague. Name the exact feature users would pay for.
</Info>

## Optional Search Helpers For Search-Hard Venues

Most contributors should rely on strong upstream search plus clean tool schemas. If your venue's native search is too weak to reliably resolve the right market, entity, or series from real user prompts, you may adopt the optional contributor-side pattern described in [Optional Contributor Search Helpers](/guides/optional-contributor-search-helpers).

Treat that pattern as a **contributor utility**, not a marketplace requirement:

* keep Context discovery generic
* keep candidate gathering, normalization, provenance, and validation deterministic inside the contributor
* inject any model judge behind a provider-agnostic boundary
* keep provider credentials and model spend contributor-owned
* return honest degraded outcomes when the judge is disabled, malformed, slow, unavailable, or over budget
* keep the helper optional even after it ships in both SDKs; contributors with strong upstream search should still avoid it
* save replayable validation artifacts for named regressions, generic overlap, still-ambiguous, and capability-miss cases before you recommend it more broadly

If your upstream venue already exposes reliable search and candidate selection, do **not** add this helper just because it exists. For the full adoption checklist, parity contract, and rollout gate, see [Optional Contributor Search Helpers](/guides/optional-contributor-search-helpers).

***

## AI-Assisted Builder (TL;DR)

**Have an API subscription you want to unbundle?** Use Cursor, Claude, or any AI coding agent to build and optimize your MCP server automatically.

<Warning>
  **Prerequisite**: You need [Context7 MCP](https://github.com/upstash/context7) configured in your AI coding environment to fetch API documentation automatically.
</Warning>

### Three-Step Workflow

<Steps>
  <Step title="Build the MCP Server">
    Use the **[MCP Builder Template](https://github.com/ctxprotocol/sdk/blob/main/docs/mcp-builder-template.md)** as a system prompt to:

    * Fetch API docs via Context7 and discover all endpoints
    * Define the exact feature, target user, must-win prompts, evidence fields, and ideal surface before writing code
    * Design premium answer products or normalized primitives (not just API passthroughs)
    * Generate complete schemas with `outputSchema`
    * Implement the full MCP server

    ```
    Use the mcp-builder-template.md with Context7 for [your-api-library-id].
    Fetch the documentation and design tools that answer complex questions.
    ```
  </Step>

  <Step title="Register on the Marketplace">
    Go to [ctxprotocol.com/contribute](https://ctxprotocol.com/contribute) to register your tool. You'll get a **Tool ID** and can generate an **API key** at [Developer → API Keys](https://ctxprotocol.com/developer). You'll need both for the next step.
  </Step>

  <Step title="Optimize and Ship">
    **Before you start:** Make sure your wallet has a small balance (a few dollars is enough). The optimization process makes real query calls through the Context platform to validate your tool's responses. If your wallet is empty, the librarian cannot complete the agentic flow and validation will fail. Deposit funds at [Developer Dashboard](https://ctxprotocol.com/developer).

    Load the **[MCP Tool Optimization Skill](https://github.com/ctxprotocol/sdk/blob/main/docs/mcp-tool-optimization-skill.md)** into your AI coding agent with your API key and Tool ID. The skill automatically:

    * Researches your vertical to find where your tool creates unique value
    * Generates tough, realistic test prompts and proves they beat free LLMs
    * Checks data quality from a buyer's perspective
    * Audits latency metadata for correctness
    * Fixes issues and retests in a loop until everything passes
    * Generates the optimal marketplace description with proven `suggestedPrompts`
    * Pushes the description and clickable example questions directly to your listing via the SDK, with no manual copy-paste

    ```
    Load the mcp-tool-optimization-skill.md from context-sdk/docs/.
    My server code is in ./server.ts
    My MCP endpoint is https://my-tool.example.com/mcp
    My CONTEXT_API_KEY is sk_live_...
    My TOOL_ID is abc-123-def
    Run the full optimization workflow.
    ```
  </Step>
</Steps>

<Info>
  A tool that works is table stakes. A tool that delivers insights users cannot get from ChatGPT for free is what earns revenue and may qualify for future grant batches.
</Info>

<Tip>
  **Lightweight QA alternative:** If you just need a quick protocol-compliance check without full optimization, use the [Deep Validation System Prompt](https://github.com/ctxprotocol/sdk/blob/main/docs/mcp-contributor-deep-validation-system-prompt.md) instead.
</Tip>

### Example Prompt for Cursor/Claude

```
I want to build an MCP server for the Context Marketplace using the CoinGecko API.

1. Use context7 to fetch the CoinGecko API documentation
2. Follow the mcp-builder-template.md workflow:
   - PHASE 1: Discover all endpoints
   - PHASE 2: Generate the product contract: target user, 5 must-win prompts, evidence fields, and ideal output surface (STOP for my review)
   - PHASE 3: Design and implement tools after I approve

Focus on a premium feature users would actually pay for, not a generic
API wrapper. The end result should either power Query answers with evidence
or provide Execute primitives with a clean normalized schema.
```

<Tip>
  The builder template includes checkpoints where the AI will stop and ask for your approval before proceeding. This ensures you get tools that match your vision.
</Tip>

***

<Info>
  **Earnings Model**: You earn **90%** of usage fees. Set a **listing response price** (e.g., \$0.01/response) and get paid in USDC when agents use your tool. Want SDK developers to call your methods directly with per-call pricing too? See [Enable Execute Pricing](#enable-execute-pricing) after you're live.
</Info>

***

## Step 1: Build a Standard MCP Server

Use the official `@modelcontextprotocol/sdk` to build your server, plus `@ctxprotocol/sdk` to secure your endpoint.

### Install Dependencies

```bash theme={null}
pnpm add @modelcontextprotocol/sdk express
pnpm add @ctxprotocol/sdk
pnpm add -D @types/express
```

### Implement Structured Output

<Warning>
  **Required for Context**: You must implement the MCP structured output standard:

  * `outputSchema` in your tool definitions (JSON Schema describing your response structure)
  * `structuredContent` in your responses (the machine-readable data matching your schema)
</Warning>

#### outputSchema root must be `type: "object"`

The MCP specification requires the **root** of every `outputSchema` to be an object type. You cannot use `anyOf`, `oneOf`, a bare `array`, or a primitive at the top level — the MCP SDK will reject your `tools/list` response and Context will refuse to register the tool.

Express variability **inside** `properties`, not at the root:

| Need                       | Don't                                                                    | Do                                                                                      |
| -------------------------- | ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- |
| Nullable value             | `outputSchema: { anyOf: [ { type: "object", ... }, { type: "null" } ] }` | `outputSchema: { type: "object", properties: { price: { type: ["string", "null"] } } }` |
| Optional field             | Union the whole schema                                                   | Omit the field from `required`                                                          |
| "No data" / upstream error | Discriminated union in the schema                                        | Return `{ content: [...], isError: true }` in the response                              |
| One of several shapes      | `oneOf` at the root                                                      | One `type: "object"` root with all possible fields, each nullable as needed             |

```typescript theme={null}
// ❌ Rejected — anyOf at the root
outputSchema: {
  anyOf: [
    { type: "object", properties: { venue: { type: "string" } } },
    { type: "null" },
  ],
}

// ✅ Correct — object at the root, nullability expressed per-field
outputSchema: {
  type: "object",
  properties: {
    venue: { type: "string" },
    current_price: { type: ["string", "null"] },
    funding_rate: { type: ["string", "null"] },
  },
}
```

Every reference server in [`@ctxprotocol/sdk/examples/server`](https://github.com/ctxprotocol/sdk/tree/main/examples/server) follows this pattern. If you need to signal a no-data / upstream-error case at runtime, use the MCP `isError: true` response flag — don't encode it in the schema.

```typescript theme={null}
const TOOLS = [{
  name: "get_gas_price",
  description: "Get current gas prices for any EVM chain",
  inputSchema: {
    type: "object",
    properties: {
      chainId: {
        type: "number",
        description: "EVM chain ID",
        default: 1,
        examples: [1, 10, 8453],
      },
    },
  },
  outputSchema: {
    type: "object",
    properties: {
      gasPrice: { type: "number" },
      unit: { type: "string" },
    },
    required: ["gasPrice", "unit"],
  },
}];

return {
  content: [{ type: "text", text: JSON.stringify(data) }],
  structuredContent: data,
};
```

<Tip>
  Use standard JSON Schema keys in `inputSchema` properties to guide argument generation:

  * **`default`:** fallback value the AI uses when the user doesn't specify one (e.g., `"default": "BTC"`)
  * **`examples`:** sample values the AI references to understand valid inputs (e.g., `"examples": ["BTC", "ETH", "SOL"]`)

  The platform reads these fields when generating arguments for your methods and when selecting the right method for a query. Without strong schema hints, the runtime has to guess valid values from the description alone, leading to more retries and lower first-pass success rates.

  Do not add custom `_meta.inputExamples`; `_meta` should only carry tool metadata such as pricing, context requirements, and rate-limit hints.
</Tip>

<AccordionGroup>
  <Accordion title="Optimizing Outputs for AI Context Windows" icon="sparkles">
    Context's query pipeline uses model-aware data budgets when preparing tool output for synthesis. To maximize answer quality:

    **Best practices for `structuredContent`:**

    * Return **structured objects** (not one giant serialized string blob)
    * Keep **textual analysis/news** in dedicated string fields (these are prioritized first)
    * Keep **large time-series arrays** in separate keys from analysis text
    * Include a compact `summary` object alongside deep raw data when possible
    * Aim for payloads under **\~500K chars** for full visibility across all supported models

    ```typescript theme={null}
    // ✅ Good: separated and prioritizable
    return {
      summary: { direction: "outflow", confidence: 0.82 },
      news: "ETF outflows accelerated this week due to ...",
      chart: { timestamps: [...], values: [...] },
    };

    // ❌ Bad: giant opaque blob (hard to prioritize/truncate safely)
    return JSON.stringify(allData);
    ```
  </Accordion>

  <Accordion title="Write Detailed Output Schemas (Performance Critical)" icon="bolt">
    Your `outputSchema` is the **single most impactful thing** you can do to reduce latency and cost for users.

    Context's managed runtime reads your `outputSchema` to decide how to call your tool with schema-guided arguments, how to interpret the `structuredContent` you return, and when to retry. If your schema is vague, the iterative loop has to *guess* property names, and it will guess wrong. Each bad guess triggers an extra tool-loop step that:

    * Adds **\~30-60 seconds** of latency
    * Costs **\~\$0.02 extra** in model inference
    * Consumes retry budget within the turn

    The #1 cause of these retries? **Property name mismatches** between what the iterative loop expects (from your `outputSchema`) and what your tool actually returns in `structuredContent`.

    The runtime retries likely **tool-call / data-shape** issues. Infrastructure failures (rate limits, auth failures, upstream timeouts) are treated as non-healable for that turn.

    If your tool explicitly reports plan/tier capability limits (for example, "long/short ratio unavailable on current tier"), the platform treats that as a constraint signal and returns best-effort output plus limitations instead of looping.

    Expose capability flags in `structuredContent` (for example, `supportsLongShortThresholdCheck: false`) and include a human-readable `limitations` field to help the verifier distinguish true parsing bugs from plan constraints.

    **Document the exact property names your API returns.** If your API returns `snake_case`, declare `snake_case` in your `outputSchema` so the runtime reads the right paths. The iterative loop calls your tool with schema-guided arguments and reads `structuredContent` directly — there is no generated JavaScript that "defaults to camelCase" — but the schema still has to name the fields you actually return, or the loop will look for fields that are not there.

    ```typescript theme={null}
    // ❌ Bad: Vague schema; loop must guess property names
    outputSchema: {
      type: "object",
      properties: {
        data: { type: "array" }
      }
    }

    // ✅ Good: Detailed schema with exact property names and descriptions
    outputSchema: {
      type: "object",
      properties: {
        data: {
          type: "array",
          description: "Array of exchange balance objects, one per exchange",
          items: {
            type: "object",
            properties: {
              exchange_name: { type: "string", description: "Exchange name (e.g. 'Binance')" },
              total_balance: { type: "number", description: "Total balance in the queried coin" },
              balance_change_1d: { type: "number", description: "Balance change in last 24 hours" },
              balance_change_percent_1d: { type: "number", description: "Percent change in last 24 hours" },
            }
          }
        },
        fetchedAt: { type: "string", description: "ISO 8601 timestamp" }
      }
    }
    ```

    **Output schema checklist:**

    * Document **every property name** in the response, especially if they're `snake_case`
    * Include **`items.properties`** for arrays, don't just say `{ type: "array" }`
    * Add **descriptions** that explain what values mean (units, ranges, interpretation)
    * If the response is an **object** (not an array), say so, `{ type: "object" }` not `{ type: "array" }`
    * Document **wrapper properties** your handler adds (e.g., `fetchedAt`, `count`, `symbol`)

    For third-party APIs with strict quotas, publish pacing hints via `_meta.rateLimit`. The runtime uses these hints to pace calls to your API. See [Tool Metadata](/guides/tool-metadata#rate-limit-hints). Reference implementation: [Coinglass contributor server](https://github.com/ctxprotocol/sdk/tree/main/examples/server/coinglass-contributor).
  </Accordion>
</AccordionGroup>

### Secure Your Endpoint

Add Context's middleware to verify that requests are legitimate:

```typescript theme={null}
import express from "express";
import { createContextMiddleware } from "@ctxprotocol/sdk";

const app = express();
app.use(express.json());

app.use("/mcp", createContextMiddleware());
```

<Accordion title="Returning Images from Tools" icon="image">
  If your tool generates charts, heatmaps, screenshots, or other visual content, **you are responsible for hosting the images** and returning URLs that the AI can reference.

  **Do not return base64-encoded images** in your tool responses. Large base64 strings bloat the response, slow down processing, and may hit token limits. Instead, host your images and return URLs.

  **Recommended: Return Image URLs**

  ```typescript theme={null}
  return {
    content: [
      { type: "text", text: "Analysis complete. Here's the chart:" }
    ],
    structuredContent: {
      summary: "Market analysis shows bullish signals...",
      chart_url: "https://your-cdn.com/charts/eth-analysis-12345.png",
      chart_alt: "ETH price chart with support levels marked"
    }
  };
  ```

  **Image Hosting Options**

  | Option                                  | Best For                                   |
  | --------------------------------------- | ------------------------------------------ |
  | **Your existing CDN**                   | If you already have infrastructure         |
  | **Cloud storage** (S3, GCS, Azure Blob) | Pre-signed URLs for generated content      |
  | **Vercel Blob / Cloudflare R2**         | Simple, cheap storage for generated images |
  | **Imgix / Cloudinary**                  | Image transformation and optimization      |

  **Output Schema for Image Tools**

  ```json theme={null}
  {
    "type": "object",
    "properties": {
      "summary": {
        "type": "string",
        "description": "Text summary of the analysis"
      },
      "chart_url": {
        "type": "string",
        "format": "uri",
        "description": "URL to the hosted chart image"
      },
      "chart_alt": {
        "type": "string",
        "description": "Accessible description of the image"
      }
    },
    "required": ["summary", "chart_url"]
  }
  ```

  The AI will include your image URL in its response, and users can click to view. For the best experience, use publicly accessible URLs (no auth required) with reasonable cache headers.
</Accordion>

<Info>
  **Free vs Paid Security Requirements:**

  | Tool Type                | Security Middleware | Rationale                                                          |
  | ------------------------ | ------------------- | ------------------------------------------------------------------ |
  | **Free Tools (\$0.00)**  | **Optional**        | Great for distribution and adoption, anyone can call your endpoint |
  | **Paid Tools (\$0.01+)** | **Mandatory**       | We cannot route payments to insecure endpoints                     |

  If you're building a free tool, you can skip the middleware entirely. However, if you ever want to charge for your tool, you'll need to add it.
</Info>

### MCP Security Model

<Warning>
  **Understanding what's protected:** Not all MCP methods require authentication. Discovery methods are open so agents can find your tools, but execution requires payment verification.
</Warning>

| 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>
  **This means:**

  * Anyone can call `/mcp` with `initialize` or `tools/list` to discover your tools
  * Only requests with a valid Context Protocol JWT can call `tools/call`
  * The middleware handles this automatically - you don't need to implement it yourself
</Info>

***

## Step 2: Test Your Tool Locally

Before deploying, ensure your server works as expected. You can use the [official MCP Inspector](https://github.com/modelcontextprotocol/inspector) or `curl` to test your tool locally.

### Using Curl

```bash theme={null}
curl -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tools/list",
    "id": 1
  }'
```

***

## Step 3: Deploy Your Server

Your server needs to be **publicly accessible**. We support both transport methods:

| Transport                | URL Format                    | Recommendation |
| ------------------------ | ----------------------------- | -------------- |
| HTTP Streaming           | `https://your-server.com/mcp` | ✅ Recommended  |
| SSE (Server-Sent Events) | `https://your-server.com/sse` | Supported      |

<Tip>
  Deploy to any platform: Vercel, Railway, Render, AWS, or your own infrastructure. The only requirement is a publicly accessible HTTPS endpoint.
</Tip>

***

## Step 4: Register in the App

<Steps>
  <Step title="Go to /contribute">
    Navigate to the contribute page in the running Context app
  </Step>

  <Step title="Select MCP Tool">
    Choose "MCP Tool" (the default option)
  </Step>

  <Step title="Paste Your Endpoint URL">
    Enter your publicly accessible endpoint URL
  </Step>

  <Step title="Auto-Discovery">
    We'll auto-discover your skills via `listTools()`
  </Step>
</Steps>

***

## Step 5: Set a Price

Set a **listing response price.** This is what users pay per response when your tool is used in the Context app or via `client.query.run()`.

<Info>
  **Two pricing surfaces:** Your listing response price (\~\$0.10) covers Query mode, where Context is the librarian. If you also want SDK developers calling your methods directly, enable Execute pricing at ~~1/100 of your response price (~~\$0.001/call). See [Enable Execute Pricing](#enable-execute-pricing) below.
</Info>

| Price       | What happens                                    |
| ----------- | ----------------------------------------------- |
| **\$0.00**  | Free, great for adoption and getting discovered |
| **\$0.01+** | Paid, you earn 90% of each response fee         |

<Note>
  Response fees are paid **once per chat turn**. The runtime may call your methods up to 100 times within that turn as a safety-capped orchestration limit.
</Note>

<Warning>
  **Security requirement depends on price:**

  * **Free tools:** Security middleware is **optional**; your endpoint works without JWT verification
  * **Paid tools:** Security middleware is **mandatory**. See [Secure Your Endpoint](#secure-your-endpoint)
</Warning>

<Note>
  Compatibility: SDK/API payloads still expose legacy field names like `price` / `pricePerQuery` for now. Their billing meaning in Query mode is listing-level **price per response turn**.
  A future major release can introduce response-named aliases (for example, `pricePerResponse`) before deprecating legacy names.
</Note>

***

## Step 6: Stake USDC

All tools require a minimum USDC stake, enforced on-chain.

| Tool Type  | Minimum Stake                                          |
| ---------- | ------------------------------------------------------ |
| Free Tools | \$10 USDC                                              |
| Paid Tools | \$10 USDC or 100× response price (whichever is higher) |

<Info>
  Stakes are **fully refundable** with a 7-day withdrawal delay. This creates accountability and enables slashing for fraud.
</Info>

***

## Step 7: You're Live!

Your MCP Tool is now available on the marketplace. Users can discover and use your tool through the Context app or `client.query.run()` in the SDK.

**Want SDK developers to also call your methods directly with per-call pricing?** See [Enable Execute Pricing](#enable-execute-pricing) below.

***

## Validate Your Tool

Now that your tool is live, validate it works correctly through the marketplace, not just on your local server.

<Steps>
  <Step title="Recommended: Full Optimization Skill">
    The **[MCP Tool Optimization Skill](https://github.com/ctxprotocol/sdk/blob/main/docs/mcp-tool-optimization-skill.md)** is the recommended validation path. It goes beyond protocol compliance to prove your tool delivers genuine alpha:

    * Researches your vertical and identifies unique value angles
    * Generates and validates must-win prompts that beat free LLMs
    * Checks data quality from a buyer's perspective (including external accuracy)
    * Audits latency metadata and fixes misclassifications
    * Iterates on fixes until pass rate exceeds 85%
    * Generates and pushes an optimized marketplace description automatically

    **Requires a funded wallet.** The skill makes real query calls through the platform. If your balance is zero, validation will fail. [Deposit funds](https://ctxprotocol.com/developer) before running.

    Load it into any AI coding agent with your API key and Tool ID.
  </Step>

  <Step title="Manual: Test in the Chat App">
    Enable **Developer Mode** in Settings → Developer Settings. In the right sidebar, turn off **Auto mode** and select your tool. Send one of your **must-win prompts** and check the **Developer Logs** preview card at the bottom of the response for errors. See the [Debugging Guide](/guides/troubleshooting#using-developer-mode-for-debugging) for details.
  </Step>

  <Step title="Manual: Test via the SDK">
    Use the [TypeScript SDK](/sdk/reference) or [Python SDK](/sdk/python-reference) to test both surfaces:

    * **Query mode:** `client.query.run({ query: "...", tools: ["your-tool-id"], responseShape: "answer_with_evidence", includeDeveloperTrace: true })`, validates your tool can support the same premium answer contract the first-party chat uses
    * **Agent-facing Query mode:** rerun the same must-win prompt with `responseShape: "evidence_only"` and confirm the evidence package is still useful without prose synthesis
    * **Execute mode** (if enabled): `client.tools.execute({ toolId: "...", toolName: "...", args: {...} })`, validates per-method call responses match your declared schemas
  </Step>
</Steps>

<Tip>
  **Lightweight QA alternative:** For a quick protocol-compliance check without full optimization, use the **[Deep Validation System Prompt](https://github.com/ctxprotocol/sdk/blob/main/docs/mcp-contributor-deep-validation-system-prompt.md)**. It validates your server against the Context Protocol docs, tests both surfaces, and provides actionable fixes. Use this when you just want to confirm things work, use the optimization skill when you want to prove your tool is worth paying for.
</Tip>

<Note>
  If you are validating a local or preview runtime on your own machine, prefer omitting `agentModelId` (uses the managed default) unless you are intentionally comparing models. Kimi K2.6 is the platform default used by the chat app.
</Note>

***

## Updating Your Tool

When you add new endpoints, modify schemas, or change your tool's functionality:

<Steps>
  <Step title="Deploy Changes">
    Push your updated code to your server/hosting
  </Step>

  <Step title="Refresh Skills on Context">
    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 re-calls `listTools()` to discover changes
  </Step>

  <Step title="Update Description (if needed)">
    If you've added significant new tools, update your description. Two options:

    * **Recommended:** Re-run the [Optimization Skill](https://github.com/ctxprotocol/sdk/blob/main/docs/mcp-tool-optimization-skill.md), it regenerates and pushes the description plus validated `suggestedPrompts` automatically via the SDK
    * **Programmatic:** Use `client.developer.updateTool(toolId, { description: "...", suggestedPrompts: [{ text: "What are the top markets right now?", source: "sdk" }] })` directly from the [TypeScript SDK](/sdk/reference) or [Python SDK](/sdk/python-reference)
    * **Manual:** Edit your tool in the Developer Tools page
  </Step>
</Steps>

<Info>
  `Try asking:` is now first-class marketplace metadata. Context parses that section into clickable prompt chips in the chat sidebar. If the section is missing or too weak, Context can generate example prompts from your discovered MCP methods so legacy and newly submitted tools render consistently.
</Info>

<Warning>
  **Don't forget to Refresh Skills!** Deploying new code doesn't automatically update the marketplace listing. You must click "Refresh Skills" for Context to re-discover your tools.
</Warning>

***

## Complete Server Example

Here's a full working example of an MCP server ready for Context:

```typescript theme={null}
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import express from "express";
import { createContextMiddleware } from "@ctxprotocol/sdk";

const app = express();
app.use(express.json());

app.use("/mcp", createContextMiddleware());

const TOOLS = [{
  name: "get_gas_price",
  description: "Get current gas prices",
  inputSchema: {
    type: "object",
    properties: {
      chainId: {
        type: "number",
        description: "EVM chain ID",
        default: 1,
        examples: [1, 10, 8453],
      },
    },
  },
  outputSchema: {
    type: "object",
    properties: {
      gasPrice: { type: "number" },
      unit: { type: "string" },
    },
    required: ["gasPrice", "unit"],
  },
}];

const server = new Server(
  { name: "my-gas-tool", version: "1.0.0" },
  { capabilities: { tools: {} } }
);

server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: TOOLS,
}));

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const data = await fetchGasData(request.params.arguments.chainId);
  
  return {
    content: [{ type: "text", text: JSON.stringify(data) }],
    structuredContent: data,
  };
});

app.listen(3000, () => {
  console.log("MCP server running on port 3000");
});
```

***

## Enable Execute Pricing

By default, your tool is available in **Query mode:** users ask questions and Context handles orchestration for a flat per-response fee. If you also want SDK developers to call your methods directly with per-call pricing (Execute mode):

<Steps>
  <Step title="Set a default execute price">
    In the marketplace contribute form, enter a **default execute price** (e.g., \$0.001). This fans out to every method's `_meta.pricing.executeUsd` automatically.
  </Step>

  <Step title="Or declare pricing per method in code">
    For fine-grained control, add `_meta` to each method in your MCP server:

    ```typescript theme={null}
    const TOOLS = [{
      name: "get_gas_price",
      description: "Get current gas prices",
      _meta: {
        surface: "both",
        queryEligible: true,
        latencyClass: "instant",
        pricing: {
          executeUsd: "0.001",
        },
        rateLimit: {
          maxRequestsPerMinute: 60,
          cooldownMs: 1000,
          maxConcurrency: 5,
        },
      },
      inputSchema: { /* ... */ },
      outputSchema: { /* ... */ },
    }];
    ```
  </Step>
</Steps>

<Warning>
  **Visibility is bidirectional:**

  * **No execute price → invisible in Execute.** Methods without `_meta.pricing.executeUsd` will not appear in SDK Execute discovery (`client.tools.execute()`). Set execute pricing to unlock per-call revenue.
  * **Execute-only → invisible in Query.** If you set `surface: "execute"` and `queryEligible: false`, your methods will not appear in the Context app or `client.query.run()`. They become SDK-only tools.

  See [Choosing a Mode](/guides/tool-metadata#choosing-a-mode) for the full visibility matrix.
</Warning>

<Tip>
  Execute pricing is typically **\~1/100 of your listing response price** (e.g., \$0.10 response → \$0.001 per execute call) because a single Query response can invoke up to 100 method calls internally.
</Tip>

See [Tool Metadata](/guides/tool-metadata#pricing--execute-mode-eligibility) for the full metadata reference. For production examples, see the [Coinglass contributor server](https://github.com/ctxprotocol/sdk/tree/main/examples/server/coinglass-contributor) (rate limit hints + per-method pricing) and the [Normalized Data Provider](https://github.com/ctxprotocol/sdk/tree/main/examples/server/normalized-data-provider) (Execute-mode data broker with background ingestion).

***

## Advanced Topics

<AccordionGroup>
  <Accordion title="Schema Accuracy & Dispute Resolution" icon="gavel">
    Your `outputSchema` isn't just documentation, **it's a contract**.

    Context uses automated schema validation as part of our crypto-native dispute resolution system:

    1. Users can dispute tool outputs by providing their `transaction_hash` (proof of payment)
    2. **Robot judge** auto-adjudicates by validating your actual output against your declared `outputSchema`
    3. If schema mismatches, the dispute is resolved against you automatically
    4. Repeated violations (5+ flags) lead to tool deactivation

    **Example: Schema Compliance**

    ```typescript theme={null}
    // ❌ BAD: Schema says number, but you return string
    outputSchema: { temperature: { type: "number" } }
    structuredContent: { temperature: "72" }  // GUILTY - schema mismatch!

    // ✅ GOOD: Output matches schema exactly
    outputSchema: { temperature: { type: "number" } }
    structuredContent: { temperature: 72 }  // Valid
    ```

    Unlike Web2 "star ratings" that can be gamed by bots, Context disputes require **economic proof** (you paid for the query). This protects honest developers from spam while ensuring bad actors face consequences.
  </Accordion>

  <Accordion title="Execution Limits & Product Design" icon="clock">
    **Critical**: MCP tool execution on the Context platform has a **60-second timeout per call**. This is a single, uniform budget: it is identical in Query and Execute mode, and identical for every method regardless of its `latencyClass`. (`latencyClass` controls *discovery eligibility* — e.g. Query skips `streaming` methods — it does **not** grant a method more execution time.) It shapes the marketplace toward high-quality data products, but what "high-quality" means depends on which mode you're designing for.

    **Where the Timeout Comes From**

    The timeout is enforced by the **platform infrastructure** (and in standard MCP setups like Claude Desktop, by the LLM client itself). When your tool is called, the system waits for a response; if it doesn't arrive within 60 seconds, execution fails. The platform passes this same value to the underlying MCP request timer, so there is no second, hidden timeout that can cut a call short earlier.

    When a timeout is hit, the runtime propagates cancellation to in-flight MCP calls to avoid post-timeout "zombie" traffic. Tool authors should still return explicit failure/degraded states quickly so agents can recover gracefully.

    This isn't an MCP protocol limitation, SSE connections can stay open indefinitely. The timeout exists at the application layer and serves as a **quality forcing function** for both modes.

    **Designing for Query Mode**

    In Query mode, Context is the librarian. Your tool output feeds into a synthesized response that costs the user \~\$0.10. The user expects curated intelligence, not raw data dumps.

    The timeout forces you to **pre-compute insights** rather than running heavy queries at request time:

    | Raw Access (❌ Bad Query Tool) | Curated Intelligence (✅ Good Query Tool) |
    | ----------------------------- | ---------------------------------------- |
    | "Run any SQL on Dune"         | "Smart Money Wallet Tracker"             |
    | "Query 4 years of NFT data"   | "NFT Alpha Signals"                      |
    | "Scan all whale wallets"      | "Whale Alert Feed"                       |
    | Timeout after 60s ❌           | Instant response ✅                       |

    The best data businesses don't sell raw database access. They sell curated, **pre-computed insights**. This is exactly how Bloomberg, Nansen, Arkham, and Messari work, and it's the right model for Query mode.

    ```
    ┌─────────────────────────────────────────────────────────────────────┐
    │              QUERY MODE: DATA BROKER'S JOB (offline)                │
    │                                                                     │
    │  1. Run heavy queries on your data source (30 min timeout - OK)    │
    │  2. Pre-compute valuable insights ("wallets that sold tops")       │
    │  3. Store results in your own database                             │
    │  4. Update daily/hourly via cron jobs                              │
    │                                                                     │
    └─────────────────────────────────────────────────────────────────────┘
                                  ↓
    ┌─────────────────────────────────────────────────────────────────────┐
    │                    MCP TOOL (instant)                               │
    │                                                                     │
    │  User: "What are the smart money wallets holding?"                 │
    │  Tool: SELECT * FROM my_precomputed_smart_money LIMIT 10           │
    │  Response: < 1 second ✅                                            │
    │                                                                     │
    └─────────────────────────────────────────────────────────────────────┘
    ```

    **Designing for Execute Mode**

    In Execute mode, the developer's agent is the librarian. The agent makes many sequential calls within a session, iterating over structured data to build its own analysis. The user pays \~\$0.001 per call.

    Here, **normalized data endpoints ARE the product**. The value isn't in pre-digested insights, it's in clean, typed, consistent data that an agent can iterate over without parsing 15 different exchange APIs.

    The timeout still applies per-call (a single normalized price lookup shouldn't take 60 seconds), but the design principles are different:

    | Inconsistent Data (❌ Bad Execute Tool) | Normalized Data (✅ Good Execute Tool)                               |
    | -------------------------------------- | ------------------------------------------------------------------- |
    | Different schema per exchange          | Unified `{ exchange, price, volume }` across all exchanges          |
    | Untyped JSON blobs                     | Strict `outputSchema` with typed fields                             |
    | One method returns everything          | Focused methods: `get_prices`, `get_orderbook`, `get_funding_rates` |
    | No pagination or filtering             | Parametric access: symbol, exchange, time range                     |
    | Inconsistent error formats             | Structured error responses with codes                               |

    ```
    ┌─────────────────────────────────────────────────────────────────────┐
    │            EXECUTE MODE: DATA NORMALIZER'S JOB (ongoing)            │
    │                                                                     │
    │  1. Connect to upstream sources (exchange APIs, data providers)     │
    │  2. Normalize schemas into consistent typed formats                │
    │  3. Expose focused, single-purpose methods                         │
    │  4. Return clean, paginated, parametric data per call              │
    │                                                                     │
    └─────────────────────────────────────────────────────────────────────┘
                                  ↓
    ┌─────────────────────────────────────────────────────────────────────┐
    │                    AGENT PIPELINE (iterative)                       │
    │                                                                     │
    │  Agent: get_prices("BTC/USDT", exchanges=["binance","coinbase"])   │
    │  Agent: get_orderbook("BTC/USDT", exchange="binance", depth=20)    │
    │  Agent: get_funding_rates("BTC/USDT")                              │
    │  Agent: → runs own analysis across all results                     │
    │                                                                     │
    └─────────────────────────────────────────────────────────────────────┘
    ```

    **Product Tiers by Mode**

    *Query mode tiers:*

    * **Real-time curated (\< 60s):** direct API calls that return analyzed results quickly (portfolio risk score, gas price recommendation)
    * **Pre-computed intelligence (instant):** heavy analysis run offline via cron, insights served instantly (smart money wallets, whale alerts, trending signals)

    *Execute mode tiers:*

    * **Normalized data endpoints:** clean, typed, paginated data across multiple sources with a consistent schema (cross-exchange prices, historical time-series, order book snapshots). The value is in the normalization and reliability.
    * **Specialized computation methods:** one method does one calculation well (risk score for a wallet, correlation between two assets, signal detection). The developer chains these together.

    **What if my analysis takes longer than 60 seconds?**

    For Query mode: pre-compute it. Run heavy analysis offline, store results in your database, serve instantly through MCP.

    For Execute mode: break it into smaller methods. Instead of one method that analyzes all wallets, expose `get_wallet_activity` per wallet, let the agent iterate.

    ```typescript theme={null}
    // ❌ BAD (either mode): Long-running analysis at request time
    { name: "analyze_all_wallets", returns: "timeout after 60s" }

    // ✅ GOOD (Query): Pre-computed results served instantly
    { name: "get_smart_money_wallets", returns: "instant curated insight from your DB" }

    // ✅ GOOD (Execute): Focused method the agent calls per-wallet
    { name: "get_wallet_activity", inputs: "{ address, timeRange }", returns: "normalized activity data" }
    ```

    |                       | Query Mode                     | Execute Mode                  |
    | --------------------- | ------------------------------ | ----------------------------- |
    | **Value proposition** | Curated insights (quality)     | Normalized data (consistency) |
    | **Competes on**       | Analysis depth                 | Schema reliability, coverage  |
    | **Moat**              | Expertise in pre-computation   | Normalization across sources  |
    | **User expectation**  | One response = complete answer | Many calls = building blocks  |
  </Accordion>
</AccordionGroup>

***

## Advanced: User Actions (Handshakes)

Need your tool to execute transactions or get user signatures? Use the **Handshake Architecture**:

```typescript theme={null}
import { createSignatureRequest, wrapHandshakeResponse } from "@ctxprotocol/sdk";

if (needsUserSignature) {
  return wrapHandshakeResponse(
    createSignatureRequest({
      domain: { name: "MyProtocol", version: "1", chainId: 1 },
      types: { Order: [{ name: "amount", type: "uint256" }] },
      primaryType: "Order",
      message: { amount: 1000 },
      meta: { description: "Place order", protocol: "MyProtocol" },
    })
  );
}
```

The Context app will show an approval card, the user signs, and the signature is returned to your tool.

<Card title="Handshake Architecture Guide" icon="handshake" href="/guides/handshake-architecture">
  Full guide: signatures, transactions, OAuth flows
</Card>

***

## Example Servers

Check out these complete working examples:

### TypeScript (Express + MCP SDK)

<CardGroup cols={2}>
  <Card title="Blocknative" icon="gas-pump" href="https://github.com/ctxprotocol/sdk/tree/main/examples/server/blocknative-contributor">
    **Query mode:** Gas price API (3 tools), great starting point for your first tool
  </Card>

  <Card title="Hyperliquid" icon="chart-line" href="https://github.com/ctxprotocol/sdk/tree/main/examples/server/hyperliquid-contributor">
    **Query mode:** DeFi analytics (16+ tools, includes handshake example)
  </Card>

  <Card title="Polymarket" icon="chart-pie" href="https://github.com/ctxprotocol/sdk/tree/main/examples/server/polymarket-contributor">
    **Query mode:** prediction market intelligence
  </Card>

  <Card title="Normalized Data Provider" icon="database" href="https://github.com/ctxprotocol/sdk/tree/main/examples/server/normalized-data-provider">
    **Execute mode:** reference with background ingestion, `_meta` pricing, and multi-exchange normalization
  </Card>
</CardGroup>

### Python (FastMCP + ctxprotocol)

<CardGroup cols={2}>
  <Card title="Hummingbot Market Intel" icon="python" href="https://github.com/ctxprotocol/sdk-python/tree/main/examples/server/hummingbot-contributor">
    **Query mode:** multi-exchange market data (6 tools): prices, order books, funding rates, trade impact analysis
  </Card>
</CardGroup>

<Tip>
  The Python example uses [FastMCP](https://gofastmcp.com) which auto-generates `outputSchema` from Pydantic models and includes `structuredContent` in responses automatically.
</Tip>
