/mcp-best-practices
Claude Code client-side cap on MCP tool result size, referenced in the result-size budget guidance
Claude Code
$ npx -y skills add tenequm/skills --skill mcp-best-practices --agent claude-code
Codex
$ npx skills add tenequm/skills --skill mcp-best-practices -a codex -y
Cursor
$ npx skills add tenequm/skills --skill mcp-best-practices -a cursor -y
Gemini CLI
$ npx skills add tenequm/skills --skill mcp-best-practices -a gemini-cli -y
GitHub Copilot
$ npx skills add tenequm/skills --skill mcp-best-practices -a github-copilot -y
OpenCode
$ npx skills add tenequm/skills --skill mcp-best-practices -a opencode -y
Windsurf
$ npx skills add tenequm/skills --skill mcp-best-practices -a windsurf -y
SKILL.md
mcp-best-practices.SKILL.mdname: mcp-best-practices
description: Build, harden, and debug production MCP servers with the TypeScript SDK. Use when writing or reviewing an MCP server - transports, tool schemas, errors, OAuth, token bloat, SDK migrations, MCP Apps, Registry. Assumes a server already exists.
metadata:
version: "1.3.1"
categories: "development, integrations"
topics: "mcp, typescript-sdk, tool-design, transports, server-hardening"
upstream: "@modelcontextprotocol/sdk@1.32.1, @modelcontextprotocol/server@2.3.1, @modelcontextprotocol/ext-apps@2.0.3, modelcontextprotocol-spec@2026-07-28"
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 guidanceMCP 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 | Notes | |-----------|---------|-------| | Spec (released) | **2026-07-28** ([specification](https://modelcontextprotocol.io/specification/latest)) | Stateless/sessionless overhaul - see "Spec 2026-07-28" below and `references/spec-2026-07-28.md` | | Spec (still deployed) | **2025-11-25** | Still the bulk of deployed software and the TS client default - but Claude Code now negotiates 2026-07-28 with HTTP servers that offer it | | TS SDK (current) | **v2.3.1** (2026-10-05): `/server`, `/client`, `/core` 2.3.1; `/node` 2.1.1, `/express` + `/hono` 2.0.2, `/fastify` 2.0.1 (no longer lockstep) | `createMcpHandler` serves both eras by default; the client speaks 2025-era unless told otherwise | | TS SDK (legacy) | **v1.32.1** (`@modelcontextprotocol/sdk`) | Bug + security fixes for >=6 months after v2 GA, never a revision past 2025-11-25; source on the [`v1.x` branch](https://github.com/modelcontextprotocol/typescript-sdk/tree/v1.x) | | JSON Schema | **2020-12** default (2019-09 / draft-07 accepted since v2.0.0) | - | | Transport | **Streamable HTTP** (remote), **stdio** (local) | SSE + WebSocket removed in v2 | | Extensions | **MCP Apps** (Stable, SEP-1865), **Auth Extensions** (official), **Tasks** ([ext-tasks](https://github.com/modelcontextprotocol/ext-tasks)) | Domain-specific WGs | | Registry | **Preview** with v0.1 API freeze since 2025-10-24 ([registry](https://modelcontextprotocol.io/registry/about)) | GA pending |
**v2 imports** (current):
import { McpServer } from "@modelcontextprotocol/server";
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/server";
import { ProtocolError, ProtocolErrorCode } from "@modelcontextprotocol/core";**v1 imports** (legacy line, still widely deployed):
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";The Two Eras
The most decision-relevant fact after the 2026-07-28 release: **upgrading the TS SDK does not move your *client* to the new spec**, but other SDKs and clients do not share that default. `rmcp` (Rust) >= 3.0 advertises 2026-07-28 out of the box, so a dependency bump can silently put a server on the modern wire - re-check which revisions you advertise after every SDK upgrade.
Every revision from `2024-10-07` through `2025-11-25` opens with `initialize` and shares one wire behavior - the SDK calls that family **legacy**. `2026-07-28` starts the **modern** era: no `initialize`, a `server/discover` advertisement instead, a `_meta` envelope on every request. Selection is explicit:
| `versionNegotiation.mode` | Behavior | |---|---| | absent / `'legacy'` | The 2025 `initialize` handshake, byte for byte. No probe. **This is the default.** | | `'auto'` | Probe with `server/discover`; fall back to `initialize` against a 2025-only server | | `{ pin: '2026-07-28' }` | That revision or nothing - a pin never falls back |
**Servers: serve both eras.** Claude Code's current MCP runtime asks HTTP servers whether they support 2026-07-28 and uses it when they do (stdio is rolling out), so a server that advertises modern support gets modern traffic from a mainstream client today. v2's `createMcpHandler` serves 2025-era requests alongside modern ones by default (`legacy: 'stateless'`); test both eras. The stateless design guidance throughout this skill is what makes that cheap.
Tooling: [SDK docs](https://ts.sdk.modelcontextprotocol.io) ([v2](https://ts.sdk.modelcontextprotocol.io/v2/)); [MCP Inspector](https://modelcontextprotocol.io/docs/2026-07-28/tools/inspector), which **connects as `legacy` by default** - pass `--protocol-era modern` (see "Testing Against Each Era" in `references/spec-2026-07-28.md`); the [conformance suite](https://github.com/modelcontextprotocol/conformance); and the [`mcp-server-dev` plugin](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/mcp-server-dev) for scaffolding.
Server Setup
Transport Decision
| Scenario | Transport | Key Config | |----------|-----------|------------| | Remote, v2 (K8s, CF Workers, Node) | `createMcpHandler(factory)` | Serves both eras; stateless per request | | Remote, v1 / stateless | `WebStandardStreamableHTTPServerTransport` | `sessionIdGenerator: undefined`, `enableJsonResponse: true` | | Remote, stateful (2025-era only) | `WebStandardStreamableHTTPServerTransport` | `sessionIdGenerator: () => randomUUID()` | | Local CLI / Claude Desktop | `StdioServerTransport` / v2 `serveStdio(factory)` | Default | | Legacy SSE clients | SSE removed in v2 - migrate to Streamable HTTP | - |
Stateless Pattern (recommended for remote deployment)
A fresh server per
Read more
name: mcp-best-practices
description: Build, harden, and debug production MCP servers with the TypeScript SDK. Use when writing or reviewing an MCP server - transports, tool schemas, errors, OAuth, token bloat, SDK migrations, MCP Apps, Registry. Assumes a server already exists.
metadata:
version: "1.3.1"
categories: "development, integrations"
topics: "mcp, typescript-sdk, tool-design, transports, server-hardening"
upstream: "@modelcontextprotocol/sdk@1.32.1, @modelcontextprotocol/server@2.3.1, @modelcontextprotocol/ext-apps@2.0.3, modelcontextprotocol-spec@2026-07-28"
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 guidanceMCP 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 | Notes | |-----------|---------|-------| | Spec (released) | **2026-07-28** ([specification](https://modelcontextprotocol.io/specification/latest)) | Stateless/sessionless overhaul - see "Spec 2026-07-28" below and `references/spec-2026-07-28.md` | | Spec (still deployed) | **2025-11-25** | Still the bulk of deployed software and the TS client default - but Claude Code now negotiates 2026-07-28 with HTTP servers that offer it | | TS SDK (current) | **v2.3.1** (2026-10-05): `/server`, `/client`, `/core` 2.3.1; `/node` 2.1.1, `/express` + `/hono` 2.0.2, `/fastify` 2.0.1 (no longer lockstep) | `createMcpHandler` serves both eras by default; the client speaks 2025-era unless told otherwise | | TS SDK (legacy) | **v1.32.1** (`@modelcontextprotocol/sdk`) | Bug + security fixes for >=6 months after v2 GA, never a revision past 2025-11-25; source on the [`v1.x` branch](https://github.com/modelcontextprotocol/typescript-sdk/tree/v1.x) | | JSON Schema | **2020-12** default (2019-09 / draft-07 accepted since v2.0.0) | - | | Transport | **Streamable HTTP** (remote), **stdio** (local) | SSE + WebSocket removed in v2 | | Extensions | **MCP Apps** (Stable, SEP-1865), **Auth Extensions** (official), **Tasks** ([ext-tasks](https://github.com/modelcontextprotocol/ext-tasks)) | Domain-specific WGs | | Registry | **Preview** with v0.1 API freeze since 2025-10-24 ([registry](https://modelcontextprotocol.io/registry/about)) | GA pending |
**v2 imports** (current):
import { McpServer } from "@modelcontextprotocol/server";
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/server";
import { ProtocolError, ProtocolErrorCode } from "@modelcontextprotocol/core";**v1 imports** (legacy line, still widely deployed):
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";The Two Eras
The most decision-relevant fact after the 2026-07-28 release: **upgrading the TS SDK does not move your *client* to the new spec**, but other SDKs and clients do not share that default. `rmcp` (Rust) >= 3.0 advertises 2026-07-28 out of the box, so a dependency bump can silently put a server on the modern wire - re-check which revisions you advertise after every SDK upgrade.
Every revision from `2024-10-07` through `2025-11-25` opens with `initialize` and shares one wire behavior - the SDK calls that family **legacy**. `2026-07-28` starts the **modern** era: no `initialize`, a `server/discover` advertisement instead, a `_meta` envelope on every request. Selection is explicit:
| `versionNegotiation.mode` | Behavior | |---|---| | absent / `'legacy'` | The 2025 `initialize` handshake, byte for byte. No probe. **This is the default.** | | `'auto'` | Probe with `server/discover`; fall back to `initialize` against a 2025-only server | | `{ pin: '2026-07-28' }` | That revision or nothing - a pin never falls back |
**Servers: serve both eras.** Claude Code's current MCP runtime asks HTTP servers whether they support 2026-07-28 and uses it when they do (stdio is rolling out), so a server that advertises modern support gets modern traffic from a mainstream client today. v2's `createMcpHandler` serves 2025-era requests alongside modern ones by default (`legacy: 'stateless'`); test both eras. The stateless design guidance throughout this skill is what makes that cheap.
Tooling: [SDK docs](https://ts.sdk.modelcontextprotocol.io) ([v2](https://ts.sdk.modelcontextprotocol.io/v2/)); [MCP Inspector](https://modelcontextprotocol.io/docs/2026-07-28/tools/inspector), which **connects as `legacy` by default** - pass `--protocol-era modern` (see "Testing Against Each Era" in `references/spec-2026-07-28.md`); the [conformance suite](https://github.com/modelcontextprotocol/conformance); and the [`mcp-server-dev` plugin](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/mcp-server-dev) for scaffolding.
Server Setup
Transport Decision
| Scenario | Transport | Key Config | |----------|-----------|------------| | Remote, v2 (K8s, CF Workers, Node) | `createMcpHandler(factory)` | Serves both eras; stateless per request | | Remote, v1 / stateless | `WebStandardStreamableHTTPServerTransport` | `sessionIdGenerator: undefined`, `enableJsonResponse: true` | | Remote, stateful (2025-era only) | `WebStandardStreamableHTTPServerTransport` | `sessionIdGenerator: () => randomUUID()` | | Local CLI / Claude Desktop | `StdioServerTransport` / v2 `serveStdio(factory)` | Default | | Legacy SSE clients | SSE removed in v2 - migrate to Streamable HTTP | - |
Stateless Pattern (recommended for remote deployment)
A fresh server per
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.
Other skills on skills.
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about mcp-best-practices.
- Which coding agents can use mcp-best-practices?
- mcp-best-practices installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

