Skip to content

/mcp-best-practices

Claude Code client-side cap on MCP tool result size, referenced in the result-size budget guidance

shell
$ npx -y skills add tenequm/skills --skill mcp-best-practices --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/mcp-best-practices
How auto-invocation works

Context preview

The summary Claude sees to decide when to auto-load this skill.

Claude Code client-side cap on MCP tool result size, referenced in the result-size budget guidance

SKILL.md

mcp-best-practices.SKILL.md
name: mcp-best-practices
description: Build, secure, and optimize production MCP servers with the TypeScript SDK (spec 2025-11-25, SDK v1.29 / v2 beta). Use when building or reviewing MCP servers or tools - covering transports, tool and schema design, error handling, security and OAuth, performance, known SDK bugs, content vs structuredContent delivery, v2 migration, MCP Apps, extensions, and the Registry.
metadata:
  version: "0.8.2"
  upstream: "@modelcontextprotocol/sdk@1.29.0, @modelcontextprotocol/server@2.0.0-beta.3, @modelcontextprotocol/ext-apps@1.7.4"
  openclaw:
    homepage: https://github.com/tenequm/skills/tree/main/skills/mcp-best-practices
    emoji: "๐Ÿ”Œ"
    envVars:
      - name: MAX_MCP_OUTPUT_TOKENS
        required: false
        description: Claude Code client-side cap on MCP tool result size, referenced in the result-size budget guidance

MCP Best Practices

Decision reference for building production MCP servers with the TypeScript SDK. Not a tutorial - assumes you already have a working server and need to make it correct, fast, and secure.

Quick Reference

| Component | Current | Next | |-----------|---------|------| | Spec | **2025-11-25** ([specification](https://modelcontextprotocol.io/specification/latest)) | [2026-07-28 Release Candidate](https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/), locked 2026-05-21: stateless/sessionless overhaul (see "Spec 2026-07-28 RC Direction") | | TS SDK (stable) | **v1.29.0** (`@modelcontextprotocol/sdk`) | v2 beta published | | TS SDK (v2) | **Beta** (`2.0.0-beta.3` on npm, 2026-07-09; the `latest` dist-tag points at the beta, so a plain `npm install` resolves to the prerelease): `/server`, `/client`, `/core`, `/hono`, `/express`, `/node`, `/fastify`, `/codemod` (+ `/server-legacy`, deprecated, frozen at beta.2) | Stable ships with the final spec on 2026-07-28 | | JSON Schema | **2020-12** default (explicit `$schema` supported) | - | | Transport | **Streamable HTTP** (remote), **stdio** (local) | SSE + WebSocket removed in v2 | | Extensions | **MCP Apps** (Stable, SEP-1865), **Auth Extensions** (official) | Domain-specific WGs | | Registry | **Preview** with v0.1 API freeze since 2025-10-24 ([registry](https://modelcontextprotocol.io/registry/about)) | GA pending |

**v1 imports** (production today):

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

**v2 imports** (v2 beta, installable now; stable pending 2026-07-28):

import { McpServer } from "@modelcontextprotocol/server";
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/server";

Canonical SDK docs: [ts.sdk.modelcontextprotocol.io](https://ts.sdk.modelcontextprotocol.io) (v1) and [/v2/](https://ts.sdk.modelcontextprotocol.io/v2/) (tutorial, troubleshooting, generated API reference). Test servers with the [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector); debugging guide at [docs/tools/debugging](https://modelcontextprotocol.io/docs/tools/debugging).

Server Setup

Transport Decision

| Scenario | Transport | Key Config | |----------|-----------|------------| | Remote, stateless (K8s, CF Workers) | `WebStandardStreamableHTTPServerTransport` | `sessionIdGenerator: undefined`, `enableJsonResponse: true` | | Remote, stateful (long tasks, SSE) | `WebStandardStreamableHTTPServerTransport` | `sessionIdGenerator: () => randomUUID()` | | Local CLI / Claude Desktop | `StdioServerTransport` | Default | | Legacy SSE clients | SSE removed in v2 - migrate to Streamable HTTP | - |

Stateless Pattern (recommended for remote deployment)

Per-request server+transport creation is the canonical pattern. Maintainer @ihrpr confirms: "each transport should have an instance of MCPServer" ([#343](https://github.com/modelcontextprotocol/typescript-sdk/issues/343)). Sharing instances leaks cross-client data (GHSA-345p-7cg4-v4c7).

app.post("/mcp", async (c) => {
  const server = new McpServer({ name: "my-server", version: "1.0.0" });
  // Register tools, resources, prompts...
  registerTools(server);

  const transport = new WebStandardStreamableHTTPServerTransport({
    sessionIdGenerator: undefined,   // stateless - no session tracking
    enableJsonResponse: true,        // JSON responses, no SSE streaming
  });

  // All tools/resources must be registered before connect() (#893)
  try {
    await server.connect(transport);
    return transport.handleRequest(c.req.raw);
  } finally {
    await transport.close();
    await server.close();
  }
});

**What to hoist to module level** (don't recreate per request):

  • Zod schemas (they never change)
  • Annotation objects (`{ readOnlyHint: true, ... }`)
  • Tool description strings
  • Payment configs, upstream API clients

The McpServer itself must be per-request, but its constant inputs should not be.

**If you only route POST** (the common stateless layout), answer `GET /mcp` with an explicit **405 Method Not Allowed** - the spec requires 405 when no SSE stream is offered, and the official TS client treats 405 as the benign no-stream signal, while an empty `200` sends it into a reconnect storm. See `references/transport-patterns.md`.

> For deep dive on transports, sessions, HTTP/2 gotchas, and K8s deployment: see `references/transport-patterns.md`

Framework Integration

**Hono** (web-standard):

import { Hono } from "hono";
const app = new Hono();
app.post("/mcp", handleMcpRequest);  // WebStandardStreamableHTTPServerTransport
app.get("/mcp", handleMcpSse);       // Optional: SSE for server notifications
app.delete("/mcp", handleMcpDelete); // Optional: session termination

**Cloudflare Workers**: Same pattern - `WebStandardStreamableHTTPServerTransport` works nati

Read more
Read it on GitHub โ†—

Showing the first part of this file.

Ships withtenequm-skills

Claude Code skills for founders, developers, and web3 builders. This repository publishes reusable skill folders under skills//, ships stable bundle downloads through GitHub Releases, and publishes changed skills to ClawHub.

Get the whole plugin, auto-invoked

Other skills on tenequm-skills.