Install this skill
npx skills add jezweb/claude-skillsWorks across Claude Code, Cursor, Codex, Copilot & Antigravity
The typescript-mcp skill provides an integration layer for deploying Model Context Protocol servers on Cloudflare Workers. By combining the official MCP SDK with Hono and Zod, this setup facilitates high-performance serverless agents. It prioritizes the StreamableHTTPServerTransport over legacy SSE methods, ensuring stable bidirectional communication and efficient error handling in production environments. Developers can implement complex agentic logic, including long-running tasks and sampling requests, directly within the edge runtime. This architecture enables servers to manage stateful workflows or orchestrate external tool execution without needing separate infrastructure. The implementation requires specific handling of request streams and lifecycle events to prevent memory leaks in the Cloudflare execution environment, making it a professional-grade solution for building fast, edge-hosted AI assistants that adhere to the 2025-11-25 MCP specification.
When to Use This Skill
- β’Building AI assistants that process data from Cloudflare KV stores
- β’Orchestrating multi-step LLM reasoning tasks across edge functions
- β’Creating low-latency tool interfaces for Claude or other MCP-capable agents
- β’Implementing authenticated API endpoints that mediate between agents and private databases
How to Invoke This Skill
Example prompts that trigger this skill in Claude Code, Cursor, or Antigravity:
- βset up an MCP server on Cloudflare Workers
- βcreate an agent with tasks using the MCP SDK
- βconfigure a streamable HTTP transport for an MCP server
- βimplement tool definitions for sampling in my MCP server
- βhow to secure my MCP endpoint on Cloudflare
Pro Tips
- π‘Prioritize `StreamableHTTPServerTransport` for production deployments to leverage its superior error recovery and bidirectional communication over SSE.
- π‘Utilize Zod extensively for input schema validation to ensure robust, type-safe interactions between your AI agent and its tools.
- π‘Leverage Cloudflare Workers' global network for low-latency responses, placing your AI tools closer to the users or calling agents.
What this skill does
- β’Deploy MCP servers using Hono and the StreamableHTTPServerTransport
- β’Support for long-running asynchronous tasks with polling-based results
- β’Server-initiated sampling allowing the agent to request LLM reasoning
- β’Strict input validation and schema definition using Zod
- β’Integrated support for Cloudflare D1 and KV authentication patterns
When not to use it
- βWhen your logic requires persistent server-side sockets rather than request/response streams
- βWhen your infrastructure constraints prohibit the use of Cloudflare Workers
- βFor simple local scripts that do not require an edge-hosted network endpoint
Example workflow
- Install the required MCP SDK, Hono, and Zod dependencies
- Define your tool schema using Zod within the McpServer instance
- Initialize the StreamableHTTPServerTransport inside a Hono post route
- Set up the response connection handling to clear transport resources
- Deploy the server to the edge using the wrangler command
- Connect your local MCP client to the published worker URL
Prerequisites
- βCloudflare account with Wrangler CLI configured
- βFamiliarity with Hono routing patterns
- βKnowledge of Zod schema definitions
Pitfalls & limitations
- !Failing to close the transport instance will cause memory leaks in Worker isolates
- !Using deprecated SSE transport instead of StreamableHTTP leads to unstable production behavior
- !Misconfiguring the Hono route can lead to unauthorized access if JWT validation is missing
FAQ
How it compares
Unlike standard generic prompts that rely on ephemeral execution, this approach provides a permanent, scalable API surface for agents that integrates directly into your existing infrastructure stack.
π Full skill instructions β original source: jezweb/claude-skills
**Last Updated**: 2026-01-21
**Versions**: @modelcontextprotocol/[email protected], [email protected], [email protected]
**Spec Version**: 2025-11-25
---
## Quick Start
npm install @modelcontextprotocol/sdk@latest hono zod
npm install -D @cloudflare/workers-types wrangler typescript**Transport Recommendation**: Use
StreamableHTTPServerTransport for production. SSE transport is deprecated and maintained for backwards compatibility only. Streamable HTTP provides better error recovery, bidirectional communication, and simplified deployment.**Basic MCP Server**:
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import { Hono } from 'hono';
import { z } from 'zod';
const server = new McpServer({ name: 'my-mcp-server', version: '1.0.0' });
server.registerTool(
'echo',
{
description: 'Echoes back input',
inputSchema: z.object({ text: z.string() })
},
async ({ text }) => ({ content: [{ type: 'text', text }] })
);
const app = new Hono();
app.post('/mcp', async (c) => {
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined,
enableJsonResponse: true
});
// CRITICAL: Set error handler to catch transport errors
transport.onerror = (error) => {
console.error('MCP transport error:', error);
};
// CRITICAL: Close transport to prevent memory leaks
c.res.raw.on('close', () => transport.close());
await server.connect(transport);
await transport.handleRequest(c.req.raw, c.res.raw, await c.req.json());
return c.body(null);
});
export default app; // CRITICAL: Direct export, not { fetch: app.fetch }**Deploy**:
wrangler deploy---
## Authentication
**API Key** (KV-based):
app.use('/mcp', async (c, next) => {
const apiKey = c.req.header('Authorization')?.replace('Bearer ', '');
const isValid = await c.env.MCP_API_KEYS.get(key:${apiKey});
if (!isValid) return c.json({ error: 'Unauthorized' }, 403);
await next();
});**Cloudflare Zero Trust**:
const jwt = c.req.header('Cf-Access-Jwt-Assertion');
const payload = await verifyJWT(jwt, c.env.CF_ACCESS_TEAM_DOMAIN);---
## Tasks (v1.24.0+)
Tasks enable **long-running operations** that return a handle for polling results later. Useful for expensive computations, batch processing, or operations that may need input.
**Task States**:
working β input_required β completed / failed / cancelled**Server Capability Declaration**:
const server = new McpServer({
name: 'my-server',
version: '1.0.0',
capabilities: {
tasks: {
list: {},
cancel: {},
requests: {
tools: { call: {} }
}
}
}
});**Tool with Task Support**:
server.registerTool(
'long-running-analysis',
{
description: 'Analyze large dataset',
inputSchema: z.object({ datasetId: z.string() }),
execution: { taskSupport: 'optional' } // 'forbidden' | 'optional' | 'required'
},
async ({ datasetId }, extra) => {
// If invoked as task, extra.task contains taskId
const result = await performAnalysis(datasetId);
return { content: [{ type: 'text', text: JSON.stringify(result) }] };
}
);**Client Task Request**:
{
"method": "tools/call",
"params": {
"name": "long-running-analysis",
"arguments": { "datasetId": "abc123" },
"task": { "ttl": 60000 }
}
}**Task Lifecycle**:
1. Client sends request with
task param β receives taskId2. Client polls via
tasks/get with taskId3. When status is
completed, client calls tasks/result to get output4. Optional: Client can
tasks/cancel to abortπ **Spec**: https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks
---
## Sampling with Tools (v1.24.0+)
Servers can now include **tool definitions in sampling requests**, enabling server-side agent loops.
**Use Case**: Server needs to orchestrate multi-step reasoning using LLM + tools without custom frameworks.
// Server initiates sampling with tools available
const result = await server.requestSampling({
messages: [{ role: 'user', content: 'Analyze this data and fetch more if needed' }],
maxTokens: 4096,
tools: [
{
name: 'fetch_data',
description: 'Fetch additional data from API',
inputSchema: { type: 'object', properties: { query: { type: 'string' } } }
}
]
});
// Handle tool calls in response
if (result.content[0].type === 'tool_use') {
const toolResult = await executeLocalTool(result.content[0]);
// Continue conversation with tool result...
}**Key Points**:
- Server-side agentic behavior as first-class MCP feature
- Standard MCP primitives (no custom frameworks)
- Tool definitions follow same schema as
tools/listπ **Spec**: SEP-1577
---
## Cloudflare Service Tools
**D1 Database**:
server.registerTool('query-db', {
inputSchema: z.object({ query: z.string(), params: z.array(z.union([z.string(), z.number()])).optional() })
}, async ({ query, params }, env) => {
const result = await env.DB.prepare(query).bind(...(params || [])).all();
return { content: [{ type: 'text', text: JSON.stringify(result.results) }] };
});**KV, R2, Vectorize**: See
references/cloudflare-integration.md---
## Known Issues Prevention
This skill prevents 20 production issues documented in official MCP SDK and Cloudflare repos:
### Issue #1: Export Syntax Issues (CRITICAL)
**Error**:
"Cannot read properties of undefined (reading 'map')"**Source**: honojs/hono#3955, honojs/vite-plugins#237
**Why It Happens**: Incorrect export format with Vite build causes cryptic errors
**Prevention**:
// β WRONG - Causes cryptic build errors
export default { fetch: app.fetch };
// β
CORRECT - Direct export
export default app;### Issue #2: Unclosed Transport Connections
**Error**: Memory leaks, hanging connections
**Source**: Best practice from SDK maintainers
**Why It Happens**: Not closing StreamableHTTPServerTransport on request end
**Prevention**:
app.post('/mcp', async (c) => {
const transport = new StreamableHTTPServerTransport(/*...*/);
// CRITICAL: Always close on response end
c.res.raw.on('close', () => transport.close());
// ... handle request
});### Issue #3: Tool Schema Validation Failure
**Error**:
ListTools request handler fails to generate inputSchema**Source**: GitHub modelcontextprotocol/typescript-sdk#1028
**Why It Happens**: Zod schemas not properly converted to JSON Schema
**Prevention**:
// β
CORRECT - SDK handles Zod schema conversion automatically
server.registerTool(
'tool-name',
{
inputSchema: z.object({ a: z.number() })
},
handler
);
// No need for manual zodToJsonSchema() unless custom validation### Issue #4: Tool Arguments Not Passed to Handler
**Error**: Handler receives
undefined arguments**Source**: GitHub modelcontextprotocol/typescript-sdk#1026
**Why It Happens**: Schema type mismatch between registration and invocation
**Prevention**:
const schema = z.object({ a: z.number(), b: z.number() });
type Input = z.infer<typeof schema>;
server.registerTool(
'add',
{ inputSchema: schema },
async (args: Input) => {
// args.a and args.b properly typed and passed
return { content: [{ type: 'text', text: String(args.a + args.b) }] };
}
);### Issue #5: CORS Misconfiguration
**Error**: Browser clients can't connect to MCP server
**Source**: Common production issue
**Why It Happens**: Missing CORS headers for HTTP transport
**Prevention**:
import { cors } from 'hono/cors';
app.use('/mcp', cors({
origin: ['http://localhost:3000', 'https://your-app.com'],
allowMethods: ['POST', 'OPTIONS'],
allowHeaders: ['Content-Type', 'Authorization']
}));### Issue #6: Missing Rate Limiting
**Error**: API abuse, DDoS vulnerability
**Source**: Production security best practice
**Why It Happens**: No rate limiting on MCP endpoints
**Prevention**:
app.post('/mcp', async (c) => {
const ip = c.req.header('CF-Connecting-IP');
const rateLimitKey = ratelimit:${ip};
const count = await c.env.CACHE.get(rateLimitKey);
if (count && parseInt(count) > 100) {
return c.json({ error: 'Rate limit exceeded' }, 429);
}
await c.env.CACHE.put(
rateLimitKey,
String((parseInt(count || '0') + 1)),
{ expirationTtl: 60 }
);
// Continue...
});### Issue #7: TypeScript Compilation Memory Issues
**Error**:
Out of memory during tsc build**Source**: GitHub modelcontextprotocol/typescript-sdk#985
**Why It Happens**: Large dependency tree in MCP SDK
**Prevention**:
# Add to package.json scripts
"build": "NODE_OPTIONS='--max-old-space-size=4096' tsc && vite build"### Issue #8: UriTemplate ReDoS Vulnerability
**Error**: Server hangs on malicious URI patterns
**Source**: GitHub modelcontextprotocol/typescript-sdk#965 (Security)
**Why It Happens**: Regex denial-of-service in URI template parsing
**Prevention**: Update to SDK v1.20.2 or later (includes fix)
### Issue #9: Authentication Bypass
**Error**: Unauthenticated access to MCP tools
**Source**: Production security best practice
**Why It Happens**: Missing or improperly implemented authentication
**Prevention**: Always implement authentication for production servers (see Authentication Patterns section)
### Issue #10: Environment Variable Leakage
**Error**: Secrets exposed in error messages or logs
**Source**: Cloudflare Workers security best practice
**Why It Happens**: Environment variables logged or returned in responses
**Prevention**:
// β WRONG - Exposes secrets
console.log('Env:', JSON.stringify(env));
// β
CORRECT - Never log env objects
try {
// ... use env.SECRET_KEY
} catch (error) {
// Don't include env in error context
console.error('Operation failed:', error.message);
}### Issue #11: Server Instance Reuse Breaks Concurrent HTTP Sessions (CRITICAL)
**Error**:
AbortError: This operation was aborted**Source**: [GitHub Issue #1405](https://github.com/modelcontextprotocol/typescript-sdk/issues/1405)
**Why It Happens**: Calling
Server.connect(transport) silently overwrites the previous transport without warning, breaking all earlier connections**Prevention**:
// β
CORRECT - Create fresh McpServer per HTTP session
app.post('/mcp', async (c) => {
const server = new McpServer({ name: 'my-server', version: '1.0.0' });
// Register tools per request
server.registerTool('echo', { inputSchema: z.object({ text: z.string() }) },
async ({ text }) => ({ content: [{ type: 'text', text }] })
);
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined,
enableJsonResponse: true
});
transport.onerror = (error) => console.error('Transport error:', error);
c.res.raw.on('close', () => transport.close());
await server.connect(transport);
await transport.handleRequest(c.req.raw, c.res.raw, await c.req.json());
return c.body(null);
});
// β WRONG - Reusing server instance across sessions
const sharedServer = new McpServer({ name: 'my-server', version: '1.0.0' });
app.post('/mcp', async (c) => {
await sharedServer.connect(transport); // Breaks previous sessions!
});### Issue #12: sessionIdGenerator Type Error with TypeScript Strict Mode
**Error**:
Type 'undefined' is not assignable to type '() => string'**Source**: [GitHub Issue #1397](https://github.com/modelcontextprotocol/typescript-sdk/issues/1397)
**Why It Happens**: SDK 1.25.2 types break projects using
exactOptionalPropertyTypes: true in tsconfig.json**Prevention**:
// With exactOptionalPropertyTypes: true
// β
CORRECT - Omit the property instead of setting to undefined
const transport = new StreamableHTTPServerTransport({
enableJsonResponse: true
// sessionIdGenerator omitted entirely
});
// β WRONG - Setting to undefined causes type error in SDK 1.25.2
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined, // Type error!
enableJsonResponse: true
});
// Alternative: Provide a generator function
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: () => crypto.randomUUID(),
enableJsonResponse: true
});### Issue #13: Global fetch Pollution from Hono (SDK 1.25.0-1.25.2)
**Error**: Native Node.js fetch behavior breaks after importing SDK
**Source**: [GitHub Issue #1376](https://github.com/modelcontextprotocol/typescript-sdk/issues/1376)
**Why It Happens**: Hono's server code globally overwrites
global.fetch, breaking libraries expecting native behavior**Prevention**:
// FIXED in SDK v1.25.3 - Update to latest version
npm install @modelcontextprotocol/[email protected]
// Workaround for older versions (1.25.0-1.25.2):
const nativeFetch = global.fetch;
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
global.fetch = nativeFetch; // Restore if needed### Issue #14: Task Error Wrapping Masks Validation Errors
**Error**: Confusing error message hides actual validation failure
**Source**: [GitHub Issue #1385](https://github.com/modelcontextprotocol/typescript-sdk/issues/1385)
**Why It Happens**: When task-augmented tool call fails validation before task creation, SDK wraps error incorrectly
**Prevention**:
// Expected error for invalid input:
// "Invalid arguments: Too small: expected number to be >=500"
// Actual error (confusing):
// "Invalid task creation result: expected object, received undefined"
// WORKAROUND: Add explicit validation before task logic
server.experimental.tasks.registerToolTask(
'batch_process',
{
inputSchema: z.object({
itemCount: z.number().min(1).max(10),
processingTimeMs: z.number().min(500).max(5000).optional()
})
},
{
createTask: async (args, extra) => {
// SDK should fix this - currently no workaround
// Validation errors are masked by task wrapping
}
}
);### Issue #15: Tool Schema with All Optional Fields Causes InvalidParams
**Error**:
"expected": "object", "received": "undefined"**Source**: [GitHub Issue #400](https://github.com/modelcontextprotocol/typescript-sdk/issues/400)
**Why It Happens**: Some LLM clients omit
arguments field when all schema properties are optional**Prevention**:
// β WRONG - All optional fields may cause issues
server.registerTool('fetch-records', {
inputSchema: z.object({
limit: z.number().optional()
})
}, handler);
// β
CORRECT - Always include at least one required field
server.registerTool('fetch-records', {
inputSchema: z.object({
action: z.literal('fetch').default('fetch'), // Required
limit: z.number().optional()
})
}, handler);
// Alternative: Use empty object schema
server.registerTool('fetch-records', {
inputSchema: z.object({}).passthrough()
}, handler);### Issue #16: Bulk Tool Registration Triggers EventEmitter Memory Leak Warnings
**Error**:
MaxListenersExceededWarning: Possible EventEmitter memory leak detected**Source**: [GitHub Issue #842](https://github.com/modelcontextprotocol/typescript-sdk/issues/842)
**Why It Happens**: Registering 80+ tools in a loop overwhelms stdout buffer with rapid
sendToolListChanged() notifications**Prevention**:
// Workaround: Increase maxListeners before bulk registration
process.stdout.setMaxListeners(100);
const tools = [...]; // Array of 80+ tool definitions
for (const tool of tools) {
server.registerTool(tool.name, tool.schema, tool.handler);
}
// Future SDK may provide batch registration API### Issue #17: Silent Transport Errors Without onerror Handler
**Error**: Transport errors vanish without logs or exceptions
**Source**: [GitHub Issue #1395](https://github.com/modelcontextprotocol/typescript-sdk/issues/1395)
**Why It Happens**: SDK silently swallows transport errors if
onerror callback is not set**Prevention**:
// β
CORRECT - Always set onerror handler
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined,
enableJsonResponse: true
});
transport.onerror = (error) => {
console.error('Transport error:', error);
// Handle error appropriately
};
await server.connect(transport);### Issue #18: DoS via Query String Array Limit Bypass
**Error**: Memory exhaustion from malicious query parameters
**Source**: [GitHub Issue #1368](https://github.com/modelcontextprotocol/typescript-sdk/issues/1368)
**Why It Happens**: The
qs library's arrayLimit can be bypassed using bracket notation like ?foo[99999999]=bar**Prevention**:
// Validate query parameters to prevent DoS
app.post('/mcp', async (c) => {
const queryParams = c.req.query();
// Reject malicious patterns
if (Object.keys(queryParams).some(key => /\[\d{6,}\]/.test(key))) {
return c.json({ error: 'Invalid query parameters' }, 400);
}
// ... handle request
});### Issue #19: Request Handlers Not Cancelled on Transport Close
**Error**: Long-running handlers continue executing after client disconnect, wasting resources
**Source**: [GitHub Issue #611](https://github.com/modelcontextprotocol/typescript-sdk/issues/611)
**Why It Happens**: SDK doesn't automatically cancel request handlers when transport connection closes
**Prevention**:
// Workaround: Use AbortController pattern manually
server.registerTool(
'long-running-task',
{ inputSchema: z.object({ duration: z.number() }) },
async ({ duration }, extra) => {
const abortController = new AbortController();
// Listen for transport close
const transport = extra.transport;
if (transport) {
const originalOnClose = transport.onclose;
transport.onclose = () => {
abortController.abort();
if (originalOnClose) originalOnClose();
};
}
try {
await longRunningTask(duration, abortController.signal);
return { content: [{ type: 'text', text: 'Done' }] };
} catch (error) {
if (error.name === 'AbortError') {
return { content: [{ type: 'text', text: 'Cancelled' }], isError: true };
}
throw error;
}
}
);### Issue #20: $defs Schema References Failed in SDK 1.22.0-1.22.x
**Error**:
can't resolve reference #/$defs/...**Source**: [GitHub Issue #1175](https://github.com/modelcontextprotocol/typescript-sdk/issues/1175)
**Why It Happens**: SDK 1.22.0 regression in
cacheToolOutputSchemas broke listTools() with complex JSON Schema**Prevention**: Update to SDK v1.23.0 or later (fixed). If on 1.22.x, upgrade immediately.
---
## Deployment
# Local
wrangler dev # http://localhost:8787/mcp
# Production
wrangler deploy**Testing**:
npx @modelcontextprotocol/inspector (connect to http://localhost:8787/mcp)---
## Templates & References
**Templates**:
basic-mcp-server.ts, tool-server.ts, resource-server.ts, authenticated-server.ts, tasks-server.ts, wrangler.jsonc**References**:
tool-patterns.md, authentication-guide.md, testing-guide.md, cloudflare-integration.md, common-errors.md---
## Critical Rules
**Always**:
- β Create fresh
McpServer instance per HTTP request (never reuse across sessions)- β Set
transport.onerror handler to catch silent errors- β Close transport on response end (
c.res.raw.on('close', () => transport.close()))- β Use direct export (
export default app, NOT { fetch: app.fetch })- β Implement authentication for production
- β Update to SDK v1.25.3+ for security fixes, Tasks support, and fetch pollution fix
- β Include at least one required field in tool schemas (avoid all-optional)
- β Use
StreamableHTTPServerTransport for production (SSE is deprecated)**Never**:
- β Reuse
McpServer instance across concurrent HTTP sessions- β Export with object wrapper
- β Forget to close StreamableHTTPServerTransport
- β Omit
transport.onerror handler- β Log environment variables or secrets
- β Use outdated SDK versions (<1.23.0 has schema bugs, <1.25.3 has fetch pollution)
---
---
paths: "**/*.ts", "**/mcp*.ts", "**/server*.ts", "**/tools*.ts"
---
# TypeScript MCP Server Corrections
MCP (Model Context Protocol) is new (2024+). Claude's training may have limited or no MCP knowledge.
## SDK Import
/* β Wrong/outdated import */
import { Server } from 'mcp'
import { MCPServer } from '@modelcontextprotocol/server'
/* β
Correct import */
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'## Server Setup
/* β Incomplete setup */
const server = new McpServer()
/* β
Full setup with info */
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
const server = new McpServer({
name: 'my-server',
version: '1.0.0',
})
// Connect transport
const transport = new StdioServerTransport()
await server.connect(transport)## Tool Definition
/* β Wrong tool schema */
server.addTool({
name: 'my_tool',
description: 'Does something',
parameters: { type: 'object', properties: {...} },
})
/* β
Correct tool definition */
server.tool(
'my_tool',
'Does something useful',
{
input: z.object({
query: z.string().describe('The search query'),
}),
},
async ({ input }) => {
return {
content: [{ type: 'text', text: Result for: ${input.query} }],
}
}
)## Resource Definition
/* β Wrong resource pattern */
server.addResource({ uri: 'file://...', content: '...' })
/* β
Correct resource handler */
server.resource(
'config',
'config://settings',
async (uri) => ({
contents: [{
uri: uri.href,
mimeType: 'application/json',
text: JSON.stringify(config),
}],
})
)## Error Handling
/* β Throwing generic errors */
throw new Error('Something went wrong')
/* β
MCP error format */
return {
content: [{
type: 'text',
text: 'Error: Something went wrong',
}],
isError: true,
}## Cloudflare Workers Transport
/* β Using stdio in Workers */
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
/* β
Use SSE or custom transport for Workers */
// For Cloudflare Workers, use workers-mcp-server package
// or implement custom SSE transport
import { McpAgent } from 'workers-mcp-server'## Quick Fixes
| If Claude suggests... | Use instead... |
|----------------------|----------------|
|
import { Server } | import { McpServer } ||
server.addTool() | server.tool() ||
parameters: {...} | Zod schema: { input: z.object({...}) } ||
throw new Error() | Return { content: [...], isError: true } || stdio transport in Workers | SSE or workers-mcp-server |
|
@modelcontextprotocol/server | @modelcontextprotocol/sdk/server/mcp.js |How to Use This Skill Unit
Option A: Project-Specific (Recommended)
- Click "Download" above
- In your project, create the directory:
.agent/skills/typescript-mcp/ - Save the file as
SKILL.md - The agent will automatically discover the skill based on its description.
Option B: Global Installation (All Agents)
Save the file to these locations to make it available across all projects:
- Claude Code:
~/.claude/skills/jezweb/claude-skills/typescript-mcp/SKILL.md - Cursor:
~/.cursor/skills/jezweb/claude-skills/typescript-mcp/SKILL.md - Antigravity:
~/.gemini/antigravity/skills/jezweb/claude-skills/typescript-mcp/SKILL.md
π Install with CLI:npx skills add jezweb/claude-skills
