AgentStack
SKILL verified MIT Self-run

Build Mcp Server Sdk V1

skill-yigitkonur-skills-by-yigitkonur-build-mcp-server-sdk-v1 · by yigitkonur

Use if building a TypeScript MCP server on @modelcontextprotocol/sdk v1.x — single-package, Zod.

No reviews yet
0 installs
8 views
0.0% view→install

Install

$ agentstack add skill-yigitkonur-skills-by-yigitkonur-build-mcp-server-sdk-v1

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No 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 No
  • 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.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README — it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-yigitkonur-skills-by-yigitkonur-build-mcp-server-sdk-v1)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
16d ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming — see below.

Preview Execution monitoring

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 →
Are you the author of Build Mcp Server Sdk V1? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Build MCP Server (SDK v1.x)

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.

When to use this skill

  • Building a new MCP server on @modelcontextprotocol/sdk v1.x (single package)
  • Adding tools, resources, or prompts to an existing v1 server
  • Migrating a v1 server from deprecated APIs (tool(), SSEServerTransport, raw JSON Schema) to current ones (registerTool, StreamableHTTPServerTransport, Zod)
  • Wiring authentication on a v1 server — bearer token, OAuth 2.1 via mcpAuthRouter, or custom middleware
  • Hardening transports, sessions, or capabilities on a v1 server (Origin validation, session resumability, sampling/elicitation)
  • Diagnosing v1-specific runtime errors — RequestHandlerExtra access, capability declarations, JSON Schema 2020-12 conversion

Do NOT use this skill when

  • Project imports from @modelcontextprotocol/server / @modelcontextprotocol/client / @modelcontextprotocol/node (split packages) → use build-mcp-server-sdk-v2
  • Handlers receive (args, ctx) with ctx.mcpReq.log() / ctx.http?.authInfo (v2 ServerContext) → use build-mcp-server-sdk-v2
  • Goal is porting an existing v1 server to v2 (not new build, not v1 maintenance) → use convert-mcp-sdk-v1-to-v2
  • Project depends on the mcp-use wrapper library, not the raw SDK → use build-mcp-use-server
  • Goal is an agentic-quality / hardening / context-budget audit beyond SDK correctness → use audit-agentic-mcp

Detect v1 vs v2 (do this first)

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

Core rules

  • Always use McpServer from @modelcontextprotocol/sdk/server/mcp.js — the low-level Server class is deprecated for direct use
  • Always use registerTool / registerResource / registerPrompt — positional tool() / resource() / prompt() overloads are deprecated
  • Always use zod for input/output schemas — the SDK auto-converts to JSON Schema 2020-12
  • Always use StreamableHTTPServerTransport for HTTP — SSEServerTransport is deprecated
  • Always set annotations on tools (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) — LLMs rely on them for safe execution
  • Tool names per SEP-986: 1–64 chars from A–Z a–z 0–9 _ - . /; format service_action_resource (e.g. github_search_repos)
  • Input validation failures SHOULD return { isError: true } (tool execution error, LLM-recoverable) — not thrown McpError (protocol error)
  • Access server.server (the underlying low-level Server) only for sampling, elicitation, resource subscriptions, or custom protocol extensions

Workflow

1 — Detect what exists

Run 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-v2
  • mcp-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 code
  • src/ with tool handler files → existing implementation to extend
  • Empty/greenfield → go to Step 2B

For existing projects, run bash scripts/check-mcp-sdk-v1-version.sh [project-dir] to confirm v1 single-package and zod are present.

2A — Audit an existing v1 server

When an MCP server already exists, do not rebuild. Read the implementation and assess each axis:

  • API style: deprecated tool() / resource() / setRequestHandler low-level → migrate to registerTool / registerResource
  • Schemas: raw JSON Schema objects → convert to Zod (preserves type inference and JSON Schema generation)
  • Transport: SSEServerTransport → migrate to StreamableHTTPServerTransport
  • Annotations: missing on any tool → add readOnlyHint / destructiveHint / idempotentHint / openWorldHint
  • Origin validation: HTTP transport without DNS-rebinding protection → add createMcpExpressApp() or hostHeaderValidation middleware
  • Capabilities: verify tools, resources, prompts, logging declared correctly during initialization

Then proceed to the user's requested change (add tools, fix bugs, add auth, etc.).

2B — Scope a new v1 server

Ask or infer:

  1. What does the server wrap? API, database, file system, CLI tool
  2. Transport? stdio (local CLI), Streamable HTTP stateful (sessions, resumability), Streamable HTTP stateless (simple req/resp)
  3. Auth? None (local stdio), static bearer, OAuth 2.1, custom middleware
  4. Surfaces? Tools (most common), resources (data access), prompts (reusable templates)
  5. Client features? Sampling (LLM completions), elicitation (user input), roots (filesystem access)

For empty greenfield, scaffold with bash scripts/scaffold-v1-server.sh [stdio|http-stateful|http-stateless] (see scripts/scaffold-v1-server.sh.md).

3 — Branch by scenario

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

4 — Preflight

  • [ ] Node.js 18+ (required for globalThis.crypto)
  • [ ] npm install @modelcontextprotocol/sdk zod — both required
  • [ ] TypeScript 5+ with "moduleResolution": "node16" or "nodenext"
  • [ ] HTTP transport: also npm install express (Express 5 recommended)
  • [ ] Existing project passed scripts/check-mcp-sdk-v1-version.sh

5 — Build sequence

  1. Create McpServer instance with name, version, optional description and icons
  2. Define Zod schemas for each tool's input (and outputSchema if returning structuredContent)
  3. Register tools with server.registerTool(name, config, handler) — config carries schema, annotations, description
  4. Register resources with server.registerResource() if exposing data
  5. Register prompts with server.registerPrompt() if exposing templates
  6. Create transport and connect: await server.connect(transport)
  7. Handle graceful shutdown: process.on('SIGINT', async () => { await server.close(); process.exit(0); })

See references/examples/server-recipes.md for complete working examples by transport.

6 — Validate

  1. Local checks first: npm run build, focused unit tests
  2. Live smoke test with the bundled test-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: true
  3. Verify Zod catches bad input — pass invalid args, confirm isError: true
  4. Verify annotations are accurate per tool
  5. Verify capabilities are declared (initialize response)
  6. For deeper hardening or agentic-quality audits, route to audit-agentic-mcp — do not duplicate that here

Quick start — minimal stdio server

import { 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());

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

registerTool config

{
  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
}

CallToolResult

{
  content: Array,
  structuredContent?: Record,
  isError?: boolean,
}

RequestHandlerExtra (v1-specific — flat shape)

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,
  sendRequest: (request, schema, options?) => Promise,
}

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.

Error handling

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.

Decision rules

  • Prefer ZodRawShape ({ name: z.string() }) for simple inputs; use full z.object() only for transforms, refinements, discriminated unions
  • Prefer isError: true soft errors over thrown McpError for recoverable failures
  • Prefer stdio for local-only servers (zero infra, single client)
  • Prefer Streamable HTTP for remote or multi-client servers
  • Prefer stateful HTTP (with sessionIdGenerator) when the server needs progress notifications, resumability, or multi-turn context
  • Prefer stateless HTTP (sessionIdGenerator: undefined) for simple request-response tools
  • Use outputSchema when the tool returns validated structured data alongside text
  • Tool names: service_action_resource, 1–64 chars (SEP-986)

Guardrails

  • Never use deprecated tool(), resource(), prompt() positional methods
  • Never use deprecated SSEServerTransport in new servers
  • Never use the Server class directly — go through McpServer
  • Never expose internal error details to clients — return user-friendly messages
  • Never skip zod schemas for tool inputs — unvalidated input is a security risk
  • Never hardcode secrets — use environment variables
  • Never omit graceful shutdown for HTTP servers
  • Never run HTTP servers without DNS-rebinding protection — Origin header MUST be validated (use createMcpExpressApp() or hostHeaderValidation); respond 403 for invalid origins
  • Never set inputSchema: null — for parameterless tools, omit inputSchema entirely

Output contract

When work completes, report:

  • Target path; new build vs existing-server maintenance
  • SDK package and version range from package.json
  • Transport(s): stdio, stateful Streamable HTTP, stateless Streamable HTTP
  • Tool / resource / prompt counts and names
  • Auth mode: none, static bearer, OAuth 2.1, custom middleware
  • Validation actually run and verification rung reached
  • Publish/deploy path: npm bin/npx command for stdio; HTTP endpoint path for remote; Docker/serverless note when applicable
  • server-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"]
}

Reference routing

Read only what the current branch needs. The full set:

Bundled scripts

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

Start-here guides

| 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) |

Server capabilities

| Reference | When to read | |---|---| | references/guides/resources-and-prompts.md | Adding resources (static or template URI) or prompts | | `references/guides/aut

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.