Receber por email
← Voltar para o catálogo

typescript-mcp

Use this skill when building MCP (Model Context Protocol) servers with TypeScript on Cloudflare Workers. This skill provides production-tested patterns for implementing tools, resources, and prompts using the official @modelcontextprotocol/sdk. It prevents 10+ common errors including export syntax issues, schema validation failures, memory leaks from unclosed transports, CORS misconfigurations, an

15estrelas
Atualizado há 11 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add jackspace/ClaudeSkillz

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/typescript-mcp/svg)](https://www.skillteca.com.br/skills/typescript-mcp)

Skills relacionadas

Ver todas de DevOps e Infra →

Alerta por categoria

Receba novas skills de DevOps e Infra toda segunda

1 email curto, só com as skills novas de DevOps e Infra. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

TypeScript MCP Server on Cloudflare Workers

Build production-ready Model Context Protocol (MCP) servers using TypeScript and deploy them on Cloudflare Workers. This skill covers the official @modelcontextprotocol/sdk, HTTP transport setup, authentication patterns, Cloudflare service integrations, and comprehensive error prevention.

When to Use This Skill

Use this skill when:

  • Building MCP servers to expose APIs, tools, or data to LLMs
  • Deploying serverless MCP endpoints on Cloudflare Workers
  • Integrating external APIs as MCP tools (REST, GraphQL, databases)
  • Creating stateless MCP servers for edge deployment
  • Exposing Cloudflare services (D1, KV, R2, Vectorize) via MCP protocol
  • Implementing authenticated MCP servers with API keys, OAuth, or Zero Trust
  • Building multi-tool MCP servers with resources and prompts
  • Needing production-ready templates that prevent common MCP errors

Do NOT use this skill when:

  • Building Python MCP servers (use FastMCP skill instead)
  • Needing stateful agents with WebSockets (use Cloudflare Agents SDK)
  • Wanting long-running persistent agents with SQLite storage (use Durable Objects)
  • Building local CLI tools (use stdio transport, not HTTP)

Core Concepts

MCP Protocol Components

1. Tools - Functions LLMs can invoke

  • Input/output schemas defined with Zod
  • Async handlers return structured content
  • Can call external APIs, databases, or computations

2. Resources - Static or dynamic data exposure

  • URI-based addressing (e.g., config://app/settings)
  • Templates support parameters (e.g., user://{userId})
  • Return text, JSON, or binary data

3. Prompts - Pre-configured prompt templates

  • Provide reusable conversation starters
  • Can include placeholders and dynamic content
  • Help standardize LLM interactions

4. Completions (Optional) - Argument auto-complete

  • Suggest valid values for tool arguments
  • Improve developer experience

Quick Start

1. Basic MCP Server Template

Use the basic-mcp-server.ts template for a minimal working server:

// See templates/basic-mcp-server.ts
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'
});

// Register a simple tool
server.registerTool(
  'echo',
  {
    description: 'Echoes back the input text',
    inputSchema: z.object({
      text: z.string().describe('Text to echo back')
    })
  },
  async ({ text }) => ({
    content: [{ type: 'text', text }]
  })
);

// HTTP endpoint setup
const app = new Hono();

app.post('/mcp', async (c) => {
  const transport = new StreamableHTTPServerTransport({
    sessionIdGenerator: undefined,
    enableJsonResponse: true
  });

  // CRITICAL: Close transport on response end 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;

Install dependencies:

npm install @modelcontextprotocol/sdk hono zod
npm install -D @cloudflare/workers-types wrangler typescript

Deploy:

wrangler deploy

2. Tool-Server Template

Use tool-server.ts for exposing multiple tools (API integrations, calculations):

// Example: Weather API tool
server.registerTool(
  'get-weather',
  {
    description: 'Fetches current weather for a city',
    inputSchema: z.object({
      city: z.string().describe('City name'),
      units: z.enum(['metric', 'imperial']).default('metric')
    })
  },
  async ({ city, units }, env) => {
    const response = await fetch(
      `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=${units}&appid=${env.WEATHER_API_KEY}`
    );
    const data = await response.json();

    return {
      content: [{
        type: 'text',
        text: `Temperature in ${city}: ${data.main.temp}°${units === 'metric' ? 'C' : 'F'}`
      }]
    };
  }
);

3. Resource-Server Template

Use resource-server.ts for exposing data:

import { ResourceTemplate } from '@modelcontextprotocol/sdk/types.js';

// Static resource
server.registerResource(
  'config',
  new ResourceTemplate('config://app', { list: undefined }),
  { description: 'Application configuration' },
  async (uri) => ({
    contents: [{
      uri: uri.href,
      mimeType: 'application/json',
      text: JSON.stringify({ version: '1.0.0', features: ['tool1', 'tool2'] })
    }]
  })
);

// Dynamic resource with parameter
server.registerResource(
  'user-profile',
  new ResourceTemplate('user://{userId}', { list: undefined }),
  { description: 'User profile data' },
  async (uri, { userId }, env) => {
    const user = await env.DB.prepare('SELECT * FROM users WHERE id = ?').bind(userId).first();

    return {
      contents: [{
        uri: uri.href,
        mimeType: 'application/json',
        text: JSON.stringify(user)
      }]
    };
  }
);

4. Authenticated Server Template

Use authenticated-server.ts for production security:

import { Hono } from 'hono';

const app = new Hono();

// API Key authentication middleware
app.use('/mcp', async (c, next) => {
  const authHeader = c.req.header('Authorization');
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return c.json({ error: 'Unauthorized' }, 401);
  }

  const apiKey = authHeader.replace('Bearer ', '');
  const isValid = await c.env.MCP_API_KEYS.get(`key:${apiKey}`);

  if (!isValid) {
    return c.json({ error: 'Invalid API key' }, 403);
  }

  await next();
});

app.post('/mcp', async (c) => {
  // MCP server logic (user is authenticated)
  // ... transport setup and handling
});

Authentication Patterns

Pattern 1: API Key (Recommended for Most Cases)

Setup:

  1. Create KV namespace: wrangler kv namespace create MCP_API_KEYS
  2. Add to wrangler.jsonc:
{
  "kv_namespaces": [
    { "binding": "MCP_API_KEYS", "id": "YOUR_NAMESPACE_ID" }
  ]
}

Implementation:

async function verifyApiKey(key: string, env: Env): Promise<boolean> {
  const storedKey = await env.MCP_API_KEYS.get(`key:${key}`);
  return storedKey !== null;
}

Manage keys:

# Add key
wrangler kv key put --binding=MCP_API_KEYS "key:abc123" "true"

# Revoke key
wrangler kv key delete --binding=MCP_API_KEYS "key:abc123"

Pattern 2: Cloudflare Zero Trust Access

import { verifyJWT } from '@cloudflare/workers-jwt';

const jwt = c.req.header('Cf-Access-Jwt-Assertion');
if (!jwt) {
  return c.json({ error: 'Access denied' }, 403);
}

const payload = await verifyJWT(jwt, c.env.CF_ACCESS_TEAM_DOMAIN);
// User authenticated via Cloudflare Access

Pattern 3: OAuth 2.0

See references/authentication-guide.md for complete OAuth implementation.

Cloudflare Service Integration

D1 Database Tool Example

server.registerTool(
  'query-database',
  {
    description: 'Executes SQL query on D1 database',
    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, null, 2)
      }]
    };
  }
);

Wrangler config:

{
  "d1_databases": [
    { "binding": "DB", "database_name": "my-db", "database_id": "..." }
  ]
}

KV Storage Tool Example

server.registerTool(
  'get-cache',
  {
    description: 'Retrieves cached value by key',
    inputSchema: z.object({ key: z.string() })
  },
  as
Compartilhar X LinkedIn