Install
$ agentstack add skill-yigitkonur-skills-by-yigitkonur-build-mcp-server-sdk-v2 ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README — it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming — see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps — measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Build MCP Server (SDK v2 Alpha)
Build and maintain MCP servers on the v2 alpha split-package SDK: @modelcontextprotocol/server, @modelcontextprotocol/client, @modelcontextprotocol/core, plus /node, /express, /hono adapters. ESM-only, Node 20+, Zod v4. Status as of 2026-05-09: latest npm tag is 2.0.0-alpha.2 — pin exact, plan rollback.
When to use
Trigger this skill if any of these are true:
- Building a brand-new MCP server and the user picks v2, "the alpha", or split packages.
package.jsonalready depends on@modelcontextprotocol/server,@modelcontextprotocol/client, or@modelcontextprotocol/core.- Existing code uses
new McpServer(...)from@modelcontextprotocol/serverandserver.registerTool(...)with the high-level API. - Tool/resource/prompt handlers use
(args, ctx)withctx.mcpReq.signal,ctx.mcpReq.log(),ctx.mcpReq.notify(), orctx.http?.authInfo. - HTTP work uses
NodeStreamableHTTPServerTransportfrom@modelcontextprotocol/node, orcreateMcpExpressApp()/createMcpHonoApp()from the official adapters. - Schemas are full
z.object({...})fromzod/v4, not raw-shape shorthand.
Do NOT use this skill if any of these are true:
package.jsondepends on the single-package@modelcontextprotocol/sdk(v1) — usebuild-mcp-server-sdk-v1instead.- Handlers use
(args, extra)withextra.sendNotification,extra.authInfo, orextra.signal— that is v1; usebuild-mcp-server-sdk-v1. - The job is porting an existing v1 server to v2 — use
convert-mcp-sdk-v1-to-v2(covers package split, import rewrite,extra → ctxmapping, OAuth replacement, staging strategy). - The project uses the
mcp-usewrapper or@hono/mcpcommunity middleware — usebuild-mcp-use-server, or migrate before applying official adapter patterns. - The user wants an agentic-quality / hardening / context-budget audit, not SDK correctness — pair this skill with the relevant
build-mcp-*reference for protocol patterns.
Detect v2 vs v1
Run tree -L 3 and read package.json. v2 fingerprints (any one is sufficient):
| Signal | Where | Means | |---|---|---| | @modelcontextprotocol/server (or /client, /core, /node, /express, /hono) | package.json dependencies | v2 split package | | import { McpServer, StdioServerTransport } from "@modelcontextprotocol/server" | source | v2 server entrypoint | | Handler signature (args, ctx) => … and ctx.mcpReq.* | source | v2 ServerContext | | import * as z from "zod/v4" | source | v2 Zod v4 path | | "type": "module" + Node 20+ | package.json / engines | v2 ESM-only target |
v1 anti-fingerprints (treat as wrong skill, redirect):
@modelcontextprotocol/sdksingle package →build-mcp-server-sdk-v1extra.sendNotification,extra.authInfo,extra.signal→build-mcp-server-sdk-v1SSEServerTransport→ v1 only; v2 removed it
Core rules
- Always use
McpServerfrom@modelcontextprotocol/server. The low-levelServerclass is deprecated for direct use. - Always use
registerTool/registerResource/registerPrompt. Positional overloads were removed in v2. - Always pass full Zod v4 schemas (
z.object({...})). Raw shapes are a v1 pattern; if a current alpha still accepts them, treat that as a migration shim, not the target. - Always import HTTP transport from
@modelcontextprotocol/node(e.g.NodeStreamableHTTPServerTransport).SSEServerTransportis removed. - For Express, use
@modelcontextprotocol/express(createMcpExpressApp()). For Hono, use@modelcontextprotocol/hono. Do not silently substitute the community@hono/mcppackage. - Server-side OAuth is removed from the SDK. Wire authentication at the HTTP layer (Passport, custom Bearer middleware,
jose) and forward auth intoctx.http?.authInfo. Treat any@modelcontextprotocol/server-auth-legacyas planned/open until npm publish is confirmed. - ESM-only. No CommonJS dual-publish. Node.js 20+ required.
- Pin alpha versions exactly (
--save-exact); never use^ranges across alphas.
Workflow
1 — Detect what exists
Inspect package.json and src/. Decide: existing v2 server (go to 2A), new v2 server (go to 2B), or wrong skill (redirect per When to use and stop).
2A — Maintain or fix an existing v2 server
Read the implementation. Verify:
- Context usage:
ctx.mcpReq.signal,ctx.mcpReq.log(),ctx.mcpReq.notify(),ctx.http?.authInfo. Flag anyextra.*access — that is v1 leakage. - Schemas: full
z.object()(not raw shapes) for new code.outputSchemapresent whenever the tool returnsstructuredContent. - Transport:
NodeStreamableHTTPServerTransportfrom@modelcontextprotocol/nodefor HTTP;StdioServerTransportfrom@modelcontextprotocol/serverfor stdio. - Framework:
createMcpExpressApp()orcreateMcpHonoApp()for HTTP framework wiring (DNS rebinding protection lives in the adapter). - Annotations:
readOnlyHint,destructiveHint,idempotentHint,openWorldHintset deliberately for tools with side effects.
Then make the requested change (add tool, fix bug, add auth middleware, etc.).
2B — Scope a new v2 server
Decide:
- Wraps what? API, database, filesystem, CLI, or in-process logic.
- Transport?
stdiofor local;Streamable HTTPfor remote/multi-client. - Framework? Express or Hono if HTTP — both have first-party adapters.
- Auth? External AS + middleware; SDK no longer hosts an authorization server.
3 — Choose the implementation branch
| Scenario | Read | |---|---| | New stdio server | references/guides/quick-start.md | | New HTTP server (Express) | references/guides/transports.md + references/guides/framework-adapters.md | | New HTTP server (Hono) | references/guides/transports.md + references/guides/framework-adapters.md | | Add tools | references/guides/tools-and-schemas.md | | Add resources or prompts | references/guides/resources-and-prompts.md | | Add auth middleware | references/guides/authentication.md | | Build an MCP client | references/guides/client-api.md | | Sampling, elicitation, sessions, shutdown | references/guides/context-and-lifecycle.md | | Working server examples | references/examples/server-recipes.md | | Production hardening | references/patterns/production-patterns.md | | Deploy (Docker, serverless, Workers) | references/patterns/deployment.md | | Avoid common mistakes / v1 leakage | references/patterns/anti-patterns.md |
4 — Preflight setup
- [ ] Node.js 20+ installed
- [ ] If existing: run
bash scripts/check-mcp-server-v2-version.shfrom the project root (seescripts/check-mcp-server-v2-version.sh.md); unsafe alpha ranges must fail - [ ]
npm install --save-exact @modelcontextprotocol/server@2.0.0-alpha.2 - [ ]
npm install zod@^4 - [ ] HTTP also:
npm install --save-exact @modelcontextprotocol/node@2.0.0-alpha.2 - [ ] Express also:
npm install --save-exact @modelcontextprotocol/express@2.0.0-alpha.2 express - [ ] Hono also:
npm install --save-exact @modelcontextprotocol/hono@2.0.0-alpha.2 hono - [ ]
"type": "module"inpackage.json - [ ] TypeScript 5+,
"module": "Node16","moduleResolution": "Node16"
5 — Build
Default sequence:
- Construct
McpServerwith{ name, version }and optional{ instructions, capabilities }. - Define Zod v4 schemas:
z.object({ field: z.string() })(full schemas, not raw shapes). - Register tools with
server.registerTool(name, config, handler)—inputSchema,annotations, handler(args, ctx) => CallToolResult. - Register resources with
server.registerResource()if exposing data. - Register prompts with
server.registerPrompt()if providing templates. - Construct transport, then
await server.connect(transport). - Handle graceful shutdown (
SIGINT/SIGTERM→await server.close()).
6 — Validate
- Local checks first:
npm run build, focused tests if present. - stdio:
npx @anthropic-ai/mcp-inspector npx tsx src/index.ts. - HTTP: start server; probe with
curlor Inspector. - Live CLI smoke: if
mcpcis installed, hand off totest-by-mcpc-cli. Minimum sequence: initialize →tools/list→ one successful call → one invalid-arg call returningisError: true. - Schemas: invalid input → tool error (
isError: true), not a thrown protocol error. - Context: confirm
ctx.mcpReqis the access path, neverextra.
Quick start — minimal v2 stdio server
import { McpServer, StdioServerTransport } from "@modelcontextprotocol/server";
import * as z from "zod/v4";
const server = new McpServer(
{ name: "my-server", version: "1.0.0" },
{ instructions: "A helpful server" }
);
server.registerTool("greet", {
title: "Greet User",
description: "Greet a user by name",
inputSchema: z.object({ name: z.string().describe("The user's name") }),
annotations: { readOnlyHint: true, destructiveHint: false },
}, async ({ name }, ctx) => {
await ctx.mcpReq.log("info", `Greeting ${name}`);
return { content: [{ type: "text" as const, text: `Hello, ${name}!` }] };
});
const transport = new StdioServerTransport();
await server.connect(transport);
Core API summary
McpServer
new McpServer(
{ name: string, version: string, description?: string, icons?: Icon[] },
{ capabilities?: ServerCapabilities, instructions?: string }
)
server.connect(transport: Transport): Promise
server.close(): Promise
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
server.isConnected(): boolean
server.experimental.tasks // ExperimentalMcpServerTasks
registerTool config
{
title?: string,
description?: string,
inputSchema?: AnySchema, // z.object({...}) — full Zod v4 schema
outputSchema?: AnySchema, // enables structuredContent validation
annotations?: ToolAnnotations,
_meta?: Record,
}
ServerContext (handler second argument)
// Tool handler: (args, ctx) => CallToolResult
// No-arg tool: (ctx) => CallToolResult
ctx.sessionId?: string
ctx.mcpReq.id: RequestId
ctx.mcpReq.method: string
ctx.mcpReq.signal: AbortSignal
ctx.mcpReq._meta?: RequestMeta
ctx.mcpReq.send(request, schema, options?): Promise
ctx.mcpReq.notify(notification): Promise
ctx.mcpReq.log(level, data, logger?): Promise
ctx.mcpReq.elicitInput(params): Promise
ctx.mcpReq.requestSampling(params): Promise
ctx.http?.authInfo?: AuthInfo
ctx.http?.req?: RequestInfo
ctx.http?.closeSSE?(): void
ctx.http?.closeStandaloneSSE?(): void
ctx.task?.id?: string
ctx.task?.store?: RequestTaskStore
Error handling
import { ProtocolError, ProtocolErrorCode } from "@modelcontextprotocol/core";
// Hard protocol errors:
throw new ProtocolError(ProtocolErrorCode.InvalidParams, "Bad input");
// Soft tool errors (LLM can self-correct):
return { content: [{ type: "text", text: "Error: not found" }], isError: true };
Decision rules
- Use full
z.object({...})for every new tool schema. Raw shapes are v1 style; even if accepted, do not target them. - Prefer
isError: truefor recoverable failures — the LLM self-corrects from soft errors. - Prefer
ctx.mcpReq.log()overconsole.error()so logs reach the client. - Prefer
ctx.mcpReq.elicitInput()over hand-rolledctx.mcpReq.send()for user input requests. - Use
createMcpExpressApp()/createMcpHonoApp()instead of raw Express/Hono setup — DNS rebinding is handled inside. - Set every relevant
annotationsfield deliberately; fill all four when safety or side-effects matter.
Guardrails
- Never write new v2-native code with raw Zod shapes — always full
z.object(). - Never use
extra.sendNotification/extra.authInfo/extra.signal— those are v1; the v2 access path isctx.mcpReq.*andctx.http?.authInfo. - Never import from
@modelcontextprotocol/sdk— that is the v1 single package; in v2 you import from/server,/client,/core,/node,/express,/hono. - Never use
SSEServerTransport— removed in v2; use Streamable HTTP. - Never implement server-side OAuth in the SDK — removed in v2; integrate at the HTTP layer.
- Never use CommonJS — v2 is ESM-only.
- Never run on Node < 20.
- Never use
^ranges for alpha packages — pin exact and plan rollback.
Compatibility and adoption note
v2 is pre-release alpha as of 2026-05-09. The latest npm split packages are at 2.0.0-alpha.2; main-branch PRs labeled v2.0.0-bc may not yet be published. Most production servers should remain on v1.x until v2 cuts a non-alpha stable release.
In practice:
- Pin alpha versions exactly (no
^); alphas can break between patches. - Plan rollback before deploying — keep the v1 branch deployable.
- The
@modelcontextprotocol/sdkmeta-package remains v1 on npm unless freshnpm viewproves otherwise. @modelcontextprotocol/server-auth-legacyis planned/open; treat it as unpublished untilnpm viewsucceeds.- Verify each MCP host (Claude Desktop, Cursor, Cline, custom) end-to-end on v2 features before depending on them.
Output contract
Report v2 server work with:
- Target path and detected channel/version.
- Transport (stdio, Streamable HTTP) and framework (none, Express, Hono).
- Tools, resources, and prompts added or changed.
- Auth shape (none, Bearer middleware, Passport, jose, external AS).
- Validation rung reached and exact commands run.
- Alpha-risk caveats and rollback status.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: yigitkonur
- Source: yigitkonur/skills-by-yigitkonur
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.