build-mcp-server-sdk-v1
Use if building a TypeScript MCP server on @modelcontextprotocol/sdk v1.x — single-package, Zod.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Use if building a TypeScript MCP server on @modelcontextprotocol/sdk v1.x — single-package, Zod.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Use if driving agent-browser for webpage interaction, screenshots, @ref snapshots, tabs, UI verification, CDP attach, Steel Browser, or cloud providers (Browser Use, Browserbase, Browserless, Kernel).
Use if verifying claimed-done work or auditing session/plan/branch completion with evidence.
Use if creating, redesigning, or merging a Claude skill, with research before writing SKILL.md.
Use skill if you are running repeatable Codex reviews across lenses or branches, optionally verifying and fixing confirmed findings in isolated worktrees.
Use if running deep multi-file research over 5+ entities or a market — wave-dispatched corpus.
Use if finishing a project — review and merge every branch/worktree into main, retire dead branches.
| name | build-mcp-server-sdk-v1 |
| description | Use if building a TypeScript MCP server on @modelcontextprotocol/sdk v1.x — single-package, Zod. |
Build and maintain MCP servers using @modelcontextprotocol/sdk v1.x — the single-package, Zod-based TypeScript SDK (protocol version 2025-11-25). Covers McpServer, registerTool, registerResource, registerPrompt, transports, OAuth 2.1, sessions, and deployment.
@modelcontextprotocol/sdk v1.x (single package)tool(), SSEServerTransport, raw JSON Schema) to current ones (registerTool, StreamableHTTPServerTransport, Zod)mcpAuthRouter, or custom middlewareRequestHandlerExtra access, capability declarations, JSON Schema 2020-12 conversion@modelcontextprotocol/server / @modelcontextprotocol/client / @modelcontextprotocol/node (split packages) → use build-mcp-server-sdk-v2(args, ctx) with ctx.mcpReq.log() / ctx.http?.authInfo (v2 ServerContext) → use build-mcp-server-sdk-v2convert-mcp-sdk-v1-to-v2mcp-use wrapper library, not the raw SDK → use build-mcp-use-serveraudit-agentic-mcpBefore writing any code, confirm v1 by checking three signals. Any one v2 signal means stop and route to a different skill.
| Signal | v1 (this skill) | v2 (build-mcp-server-sdk-v2) |
|---|---|---|
package.json dependency | @modelcontextprotocol/sdk (single, ^1.x) | @modelcontextprotocol/server, /client, /node, /express, /hono (split, 2.0.0-alpha.x) |
| Import path | @modelcontextprotocol/sdk/server/mcp.js, /server/stdio.js, /server/streamableHttp.js | @modelcontextprotocol/server, @modelcontextprotocol/node |
| Handler signature | (args, extra) => … with extra.sendNotification, extra.authInfo, extra.signal flat | (args, ctx) => … with ctx.mcpReq.log(), ctx.mcpReq.signal, ctx.http?.authInfo |
| HTTP transport class | StreamableHTTPServerTransport (or legacy SSEServerTransport) | NodeStreamableHTTPServerTransport |
| Module system | CJS or ESM | ESM-only, "type": "module" required |
| Node engine | Node 18+ | Node 20+ |
| Zod | Zod v3, ZodRawShape accepted ({ name: z.string() }) | Zod v4, full z.object({...}) only |
Legacy low-level v1 code may also import request schemas like ListToolsRequestSchema, CallToolRequestSchema from @modelcontextprotocol/sdk/types.js and call server.setRequestHandler(...) directly. That is still v1 — but it is the deprecated low-level path; the skill recommends migrating it to McpServer.registerTool (see references/patterns/anti-patterns.md).
If package.json exists, run bash scripts/check-mcp-sdk-v1-version.sh [project-dir] (see scripts/check-mcp-sdk-v1-version.sh.md) — it asserts single-package v1 and refuses to run if v2 split packages are present.
McpServer from @modelcontextprotocol/sdk/server/mcp.js — the low-level Server class is deprecated for direct useregisterTool / registerResource / registerPrompt — positional tool() / resource() / prompt() overloads are deprecatedzod for input/output schemas — the SDK auto-converts to JSON Schema 2020-12StreamableHTTPServerTransport for HTTP — SSEServerTransport is deprecatedannotations on tools (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) — LLMs rely on them for safe executionA–Z a–z 0–9 _ - . /; format service_action_resource (e.g. github_search_repos){ isError: true } (tool execution error, LLM-recoverable) — not thrown McpError (protocol error)server.server (the underlying low-level Server) only for sampling, elicitation, resource subscriptions, or custom protocol extensionsRun tree -L 3 and inspect package.json and tsconfig.json. Look for:
@modelcontextprotocol/sdk in dependencies → existing v1 server (go to Step 2A)@modelcontextprotocol/server (split) → wrong skill, redirect to build-mcp-server-sdk-v2mcp-use in dependencies → wrong skill, redirect to build-mcp-use-server.mcp.json or top-level mcp key in package.json → MCP client config, not server codesrc/ with tool handler files → existing implementation to extendFor existing projects, run bash scripts/check-mcp-sdk-v1-version.sh [project-dir] to confirm v1 single-package and zod are present.
When an MCP server already exists, do not rebuild. Read the implementation and assess each axis:
tool() / resource() / setRequestHandler low-level → migrate to registerTool / registerResourceSSEServerTransport → migrate to StreamableHTTPServerTransportreadOnlyHint / destructiveHint / idempotentHint / openWorldHintcreateMcpExpressApp() or hostHeaderValidation middlewaretools, resources, prompts, logging declared correctly during initializationThen proceed to the user's requested change (add tools, fix bugs, add auth, etc.).
Ask or infer:
For empty greenfield, scaffold with bash scripts/scaffold-v1-server.sh <target-dir> <server-name> [stdio|http-stateful|http-stateless] (see scripts/scaffold-v1-server.sh.md).
| Scenario | First read |
|---|---|
| New stdio server | references/guides/quick-start.md |
| New HTTP server (stateful or stateless) | references/guides/transports.md |
| Add tools to existing server | references/guides/tools-and-schemas.md |
| Add resources or prompts | references/guides/resources-and-prompts.md |
| Add authentication | references/guides/authentication.md |
| Build a v1 client | references/guides/client-api.md |
| Add sampling, elicitation, or session resumability | references/guides/sessions-and-lifecycle.md |
| Long-running tools / durable tasks | references/guides/experimental-tasks.md |
| Understand the MCP protocol contract | references/guides/protocol-spec.md |
| Deploy to production | references/patterns/deployment.md |
| Wire logging, error handling, rate limits, monitoring | references/patterns/production-patterns.md |
| Avoid common v1 mistakes | references/patterns/anti-patterns.md |
| Copy-paste working server example | references/examples/server-recipes.md |
globalThis.crypto)npm install @modelcontextprotocol/sdk zod — both required"moduleResolution": "node16" or "nodenext"npm install express (Express 5 recommended)scripts/check-mcp-sdk-v1-version.shMcpServer instance with name, version, optional description and iconsoutputSchema if returning structuredContent)server.registerTool(name, config, handler) — config carries schema, annotations, descriptionserver.registerResource() if exposing dataserver.registerPrompt() if exposing templatesawait server.connect(transport)process.on('SIGINT', async () => { await server.close(); process.exit(0); })See references/examples/server-recipes.md for complete working examples by transport.
npm run build, focused unit teststest-by-mcpc-cli skill, npx @anthropic-ai/mcp-inspector, or raw JSON-RPC. Minimum sequence: initialize/connect → tools/list → one successful tool call → one invalid-argument call returning isError: trueisError: trueaudit-agentic-mcp — do not duplicate that hereimport { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer(
{ name: "my-server", version: "1.0.0" },
{ instructions: "A helpful server" }
);
server.registerTool("greet", {
description: "Greet a user by name",
inputSchema: { name: z.string().describe("The user's name") },
annotations: { readOnlyHint: true, destructiveHint: false },
}, async ({ name }) => ({
content: [{ type: "text", text: `Hello, ${name}!` }],
}));
await server.connect(new StdioServerTransport());
new McpServer(
{ name: string, version: string, description?: string, icons?: Icon[] },
{ capabilities?: ServerCapabilities, instructions?: string }
)
server.connect(transport: Transport): Promise<void>
server.close(): Promise<void>
server.registerTool(name, config, handler): RegisteredTool
server.registerResource(name, uri | template, config, handler): RegisteredResource
server.registerPrompt(name, config, handler): RegisteredPrompt
server.sendToolListChanged(): void
server.sendResourceListChanged(): void
server.sendPromptListChanged(): void
server.sendLoggingMessage(params): Promise<void>
{
title?: string, // Human-readable display name
description?: string, // LLM reads this to decide when to call
inputSchema?: ZodRawShape | ZodSchema,
outputSchema?: ZodRawShape | ZodSchema, // Enables structuredContent validation
annotations?: {
readOnlyHint?: boolean,
destructiveHint?: boolean,
idempotentHint?: boolean,
openWorldHint?: boolean,
},
icons?: Icon[], // 2025-11-25
}
{
content: Array<
| { type: "text", text: string }
| { type: "image", data: string, mimeType: string }
| { type: "audio", data: string, mimeType: string }
| { type: "resource", resource: { uri: string, text?: string, blob?: string } }
| { type: "resource_link", uri: string, name?: string, description?: string }
>,
structuredContent?: Record<string, unknown>,
isError?: boolean,
}
Every handler receives extra as the last argument:
{
signal: AbortSignal, // Cooperative cancellation
authInfo?: AuthInfo, // From OAuth middleware
sessionId?: string,
requestId: RequestId,
requestInfo?: RequestInfo, // Original HTTP request metadata
_meta?: RequestMeta,
sendNotification: (notification) => Promise<void>,
sendRequest: (request, schema, options?) => Promise<Result>,
}
This flat shape is the single biggest v1-vs-v2 tell. v2 nests these fields under ctx.mcpReq / ctx.http. To port an existing v1 server to v2, use convert-mcp-sdk-v1-to-v2.
import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
// Hard protocol errors (tool not found, bad params at the protocol layer):
throw new McpError(ErrorCode.InvalidParams, "Missing required field: query");
// Soft tool errors (recoverable; LLM can retry or self-correct):
return { content: [{ type: "text", text: "Error: rate limit exceeded" }], isError: true };
Per spec: input validation errors SHOULD use isError: true, not thrown McpError — soft errors enable model self-correction.
ZodRawShape ({ name: z.string() }) for simple inputs; use full z.object() only for transforms, refinements, discriminated unionsisError: true soft errors over thrown McpError for recoverable failuressessionIdGenerator) when the server needs progress notifications, resumability, or multi-turn contextsessionIdGenerator: undefined) for simple request-response toolsoutputSchema when the tool returns validated structured data alongside textservice_action_resource, 1–64 chars (SEP-986)tool(), resource(), prompt() positional methodsSSEServerTransport in new serversServer class directly — go through McpServerzod schemas for tool inputs — unvalidated input is a security riskOrigin header MUST be validated (use createMcpExpressApp() or hostHeaderValidation); respond 403 for invalid originsinputSchema: null — for parameterless tools, omit inputSchema entirelyWhen work completes, report:
package.jsonbin/npx command for stdio; HTTP endpoint path for remote; Docker/serverless note when applicableserver-info:{
"name": "example-server",
"sdk": "@modelcontextprotocol/sdk@^1.x",
"transports": ["stdio"],
"tools": 3,
"resources": 0,
"prompts": 0,
"auth": "none",
"validatedWith": ["build", "test-by-mcpc-cli"]
}
Read only what the current branch needs. The full set:
| Script | When to run |
|---|---|
scripts/check-mcp-sdk-v1-version.sh | Existing-project preflight; asserts single-package v1 SDK and zod present, refuses if v2 split packages found. See scripts/check-mcp-sdk-v1-version.sh.md. |
scripts/scaffold-v1-server.sh | Empty greenfield target after picking stdio, http-stateful, or http-stateless. See scripts/scaffold-v1-server.sh.md. |
| Reference | When to read |
|---|---|
references/guides/quick-start.md | Scaffolding a new server from scratch |
references/guides/tools-and-schemas.md | Registering tools, defining Zod schemas, handling tool results |
references/guides/transports.md | Choosing and configuring stdio, Streamable HTTP, or SSE (legacy) |
| Reference | When to read |
|---|---|
references/guides/resources-and-prompts.md | Adding resources (static or template URI) or prompts |
references/guides/authentication.md | OAuth 2.1, bearer tokens, custom middleware |
references/guides/client-api.md | Building MCP clients — connecting, calling tools, reading resources, auth, sampling |
references/guides/sessions-and-lifecycle.md | Sessions, sampling, elicitation, resumability, graceful shutdown |
references/guides/experimental-tasks.md | Durable long-running operations — registerToolTask, InMemoryTaskStore, callToolStream |
references/guides/protocol-spec.md | Protocol lifecycle, capabilities, message format, security requirements |
| Reference | When to read |
|---|---|
references/examples/server-recipes.md | Copy-paste working server examples by transport |
references/patterns/deployment.md | Docker, serverless, cloud deployment |
references/patterns/production-patterns.md | Logging, error handling, rate limiting, monitoring |
references/patterns/anti-patterns.md | Common v1 mistakes and fixes |
| Reference | When to read |
|---|---|
references/seps/overview.md | What SEPs exist and their developer impact |
references/seps/auth-security.md | OAuth flows, enterprise auth, URL elicitation, client security |
references/seps/tools-metadata.md | Tool naming (SEP-986), icons, validation errors, sampling-with-tools, tasks, tracing |
references/seps/protocol-transport.md | JSON Schema 2020-12 dialect, SSE polling, extensions, MCP Apps, elicitation improvements |
references/seps/upcoming.md | Accepted SEPs not yet Final — upcoming breaking changes to prepare for |
This skill targets @modelcontextprotocol/sdk v1.x (stable, v1.x branch). Source-verified against the TypeScript SDK repository.
Key 2025-11-25 spec additions: icons for tools/resources/prompts, tool-name guidance (SEP-986), URL-mode elicitation (SEP-1036), tool calling in sampling (SEP-1577), experimental tasks (SEP-1686), JSON Schema 2020-12 default dialect (SEP-1613), extensions framework (SEP-2133).
v2 (@modelcontextprotocol/server + /client) remains pre-release alpha. Do not silently mix v1 and v2 packages. To port v1 → v2, route to convert-mcp-sdk-v1-to-v2. To start fresh on v2 alpha, route to build-mcp-server-sdk-v2.