Token导航 LogoToken导航TokenDH.com
开发敏感数据github未标认证来源可访问clear审计提醒

typescript-mcpTypeScript MCP 命令行

Agent Skill

typescript-mcp 用于记录任务执行中的错误、用户纠正、经验和能力缺口,适合在 Codex、Claude、Cursor、Gemini CLI 中希望让 Agent 持续沉淀问题、修正和最佳实践时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

8,380

周安装

339

GitHub Stars

750

下载量

2,631
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:typescript-mcp(TypeScript MCP 命令行)
来源仓库:https://github.com/jezweb/claude-skills
仓库路径:skills/typescript-mcp
安装命令:
npx skills add https://github.com/jezweb/claude-skills --skill typescript-mcp
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/jezweb/claude-skills --skill typescript-mcp

简介

在 Cloudflare Workers 上使用 TypeScript 构建 MCP 服务器,防止 20 个已记录的生产问题。

  • 通过内置 Cloudflare 服务集成(D1、KV、R2、Vectorize)支持工具、资源、提示、任务和三种身份验证模式(API 密钥、OAuth、零信任)
  • 需要新的 McpServer
  • 每个 HTTP 请求和 StreamableHTTPServerTransport 的实例
  • 用于生产; SSE 传输已弃用
  • 防止严重问题,包括服务器实例重用破坏并发会话、未关闭的传输内存泄漏、导出语法错误、CORS 错误配置和任务验证失败
  • 任务通过轮询启用长时间运行的操作;使用工具采样可以使用标准 MCP 原语实现服务器端代理行为

SKILL.md

TypeScript MCP on Cloudflare Workers

Last Updated: 2026-01-21 Versions: @modelcontextprotocol/sdk@1.25.3, hono@4.11.3, zod@4.3.5 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: workinginput_requiredcompleted / 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 taskId
  2. Client polls via tasks/get with taskId
  3. When status is completed, client calls tasks/result to get output
  4. 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 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 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 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/sdk@1.25.3

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

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Claude Code

30.14%
按下载量换算793

Cursor

24.93%
按下载量换算656

Gemini CLI

16.58%
按下载量换算436

Antigravity

13.63%
按下载量换算359

OpenCode

7.44%
按下载量换算196

Codex

3.24%
按下载量换算85

安全审计

Gen Agent Trust Hub

可疑

Socket

通过

Snyk

可疑

权限和风险

敏感数据

该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在 warning/failed 结果,不能写成本站确认安全。

来源信息

继续浏览同类 Skills