Token导航 LogoToken导航TokenDH.com
MCP Express Adapter logo
AI代理stdio官方级别未说明来源级核验

MCP Express Adapter

MCP Server

mcp-express-adapter@latest

一个轻量级的适配器,用于在Express.js服务器上创建和管理MCP(Model Context Protocol)服务,支持多工具集成和SSE通信。

工具数

0

提示词数

0

GitHub Stars

12

资源数

0
中间件TypeScriptClaude工具集成Claude

安装说明

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

作者 / 组织

Moe03

提供方

Moe03

最后核验

2026/5/17 20:21

运行时

Node.js

快速接入

先看主来源和安装命令,再打开仓库或文档;下面只保留这个条目的关键接入事实。

命令预览

npx mcp-express-adapter@latest --host http://localhost:3000/mcp/sse --header "Authorization: Bearer 000000"

详细介绍

用于Express服务器的MCP中间件适配器

  • 赞助https://tixaeagents.ai在几秒钟内创建与MCP服务器兼容的文本/语音AI代理。

检查表:

  • \[x\] 快速中间件集成SSE支持
  • \[\]Websocket集成支持(很快,但SSE工作得很好)
  • \[x\] 支持TypeScript的工具实现
  • \[x\] 基于标头的授权支持
  • \[x\] 不同端点上的多个MCP客户端
  • \[\]提示支持(只要有点不必要)

为什么

  • 如果你有100个人在一台服务器上直接使用npx打开剧作家、勇敢者等MCP,那么你就不能从托管聊天的主要LLM服务中单独放大或缩小你的MCP客户端(如果它们都很轻,就把一些客户端组合在一起),这很容易消耗大量内存和瓶颈性能。
  • 部署、更新和维护许多MCP服务器的默认方式很烦人,这是为了简化它。

安装

npm install mcp-express-adapter@latest
# or
yarn add mcp-express-adapter@latest
# or
pnpm add mcp-express-adapter@latest

注意:如果从私有存储库安装,您需要对GitHub软件包进行身份验证。看 了解更多详情。

开始使用

在express服务器上创建MCP客户端(示例)

// examples/with-express/src/super-simple.ts
import express from 'express'
import cors from 'cors'
import { MCPClient, mcpTool } from 'mcp-express-adapter'
import { z } from 'zod'

// Create Express app
const app = express()
app.use(cors())

// Define a super simple weather tool
const weatherTool = mcpTool({
  name: 'get_weather',
  description: 'Get weather for a location',
  // Define input schema
  schema: z.object({
    location: z.string().describe('The city to get weather for'),
  }),
  // No output schema needed for simple string responses
  handler: async (args) => {
    // Just return a string - mcpTool handles the formatting
    return `Weather for ${args.location}: ☀️ Sunny and 72°F`
  },
})

// Create MCP client
const mcpClient = new MCPClient({
  endpoint: '/mcp',
  tools: [weatherTool],
  serverName: 'demo-server',
  serverVersion: '1.0.0',
})

// Mount MCP router
app.use('/mcp', mcpClient.middleware())

// Apply JSON parser for other routes
app.use(express.json())

// Start the server
const PORT = process.env.PORT || 3000
app.listen(PORT, () => {
  console.log(`✨ Super Simple MCP Server running!`)
  console.log(`🔗 Connect at: http://localhost:${PORT}/mcp/sse`)
})

在终端中,确保服务器正在运行:

MCP Client created with the following configuration:
- Endpoint: /mcp
- Server: my-mcp-server v1.0.0
- Tools: get_weather, calculator, generate_list, greeting
MCP Server running on port 3000
Connect at: http://localhost:3000/mcp/sse
Debug mode: enabled will show debug logs, to disable set NODE_ENV=production

现在,您可以在Claude桌面中测试MCP服务器

  • 设置>开发人员>将配置文件编辑为:
{
  "mcpServers": {
    "localMcpServer": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-express-adapter",
        "--host",
        "http://localhost:3000/mcp/sse"
      ]
    }
  }
}

然后 重启 Claude桌面,您将能够在几秒钟内看到MCP工具 Image Image

同一Express服务器上的多个MCP客户端。

// examples/with-express/src/multiple-mcp-clients.ts
import express from 'express'
import cors from 'cors'
import { MCPClient, mcpTool } from 'mcp-express-adapter'
import { z } from 'zod'

// Create Express app
const app = express()
app.use(cors())

// Define weather tool using mcpTool helper
const weatherTool = mcpTool({
  name: 'get_weather',
  description: 'Get the current weather for a location',
  schema: z.object({
    location: z.string().describe('The location to get weather for'),
  }),
  // you can define typesafe output schema..
  outputSchema: z.object({
    farenheight: z.number().describe('The temperature in farenheight'),
    celsius: z.number().describe('The temperature in celsius'),
  }),
  handler: async (args) => {
    return {
      farenheight: 72,
      celsius: 22,
    }
  },
})

// Define calculator tool using mcpTool helper
const calculatorTool = mcpTool({
  name: 'calculate',
  description: 'Calculate the result of a mathematical expression',
  schema: z.object({
    expression: z.string().describe('The mathematical expression to evaluate'),
  }),
  handler: async (args) => {
    return `Result: ${eval(args.expression)}`
  },
})

// Define time tool using mcpTool helper
const timeTool = mcpTool({
  name: 'get_time',
  description: 'Get the current time, optionally for a specific timezone',
  schema: z.object({
    timezone: z
      .string()
      .optional()
      .describe('The timezone to get time for (optional)'),
  }),
  handler: async (args) => {
    return `Current time${args.timezone ? ` in ${args.timezone}` : ''}: ${new Date().toLocaleString()}`
  },
})

// Create first MCP client with weather tool
const weatherClient = new MCPClient({
  endpoint: '/weather-mcp',
  tools: [weatherTool],
  serverName: 'weather-mcp-server',
  serverVersion: '1.0.0',
})

// Create second MCP client with calculator tool
const calculatorClient = new MCPClient({
  endpoint: '/calculator-mcp',
  tools: [calculatorTool],
  serverName: 'calculator-mcp-server',
  serverVersion: '1.0.0',
})

// Create third MCP client with time tool
const timeClient = new MCPClient({
  endpoint: '/time-mcp',
  tools: [timeTool],
  serverName: 'time-mcp-server',
  serverVersion: '1.0.0',
})

// Mount MCP routers BEFORE global JSON parser
app.use('/weather-mcp', weatherClient.middleware())
app.use('/calculator-mcp', calculatorClient.middleware())
app.use('/time-mcp', timeClient.middleware())

// Apply global JSON parser AFTER agent routes
app.use(express.json())

// Start the server
const PORT = process.env.PORT ? parseInt(process.env.PORT) : 3000
app.listen(PORT, () => {
  console.log(`Multiple MCP Servers running on port ${PORT}`)
  console.log(`Weather MCP: http://localhost:${PORT}/weather-mcp/sse`)
  console.log(`Calculator MCP: http://localhost:${PORT}/calculator-mcp/sse`)
  console.log(`Time MCP: http://localhost:${PORT}/time-mcp/sse`)
})

使用Langchain+Langgraph

  • 借助@langchain/mcp适配器https://github.com/langchain-ai/langchainjs-mcp-adapters
// examples/with-langchain/src/index.ts
import { MultiServerMCPClient } from '@langchain/mcp-adapters'
import { ChatAnthropic } from '@langchain/anthropic'
import { createReactAgent } from '@langchain/langgraph/prebuilt' // Incorrect
import dotenv from 'dotenv'

dotenv.config()

async function runLangchainMcpExample() {
  console.log('Initializing LangChain with MCP Adapters...')

  const model = new ChatAnthropic({
    model: 'claude-3-5-sonnet-20240620',
    temperature: 0,
    anthropicApiKey: process.env.ANTHROPIC_API_KEY,
  })

  // Keep constructor with only mcpServers map
  const mcpClient = new MultiServerMCPClient({
    googleMapsServer: {
      // The server map directly
      transport: 'sse',
      url: 'http://localhost:3000/mcp/sse',
      useNodeEventSource: true,
      reconnect: {
        enabled: true,
        maxAttempts: 3,
        delayMs: 1000,
      },
    },
  })

  console.log('Loading tools from MCP server via express adapter...')
  // Keep getTools call with options
  const tools = (await Promise.race([
    mcpClient.getTools(),
    new Promise((_, reject) =>
      setTimeout(
        () =>
          reject(new Error('Timeout: Failed to load tools within 15 seconds')),
        15000,
      ),
    ),
  ])) as Awaited>

  if (tools.length === 0) {
    console.error('No tools were loaded...')
    await mcpClient.close()
    return
  }

  console.log(
    `Loaded ${tools.length} tools:`,
    tools.map((t) => t.name).join(', '),
  )

  const agent = await createReactAgent({
    llm: model,
    tools,
  })

  const messages = [
    {
      role: 'system',
      content:
        'You are a helpful assistant. Use tools to answer user questions.',
    },
    {
      role: 'user',
      content: `What is the current weather in San Francisco?`,
    },
  ]
  let inputs = { messages }
  // console.log(`ALL GOOD NOW TART EVEN STREAMM>>!: `, inputs);
  // await new Promise((resolve) => setImmediate(resolve));
  const eventStream = await agent.streamEvents(inputs, {
    version: 'v2',
    //  signal: localController.signal, //  {
    console.log(`[WeatherTool] Called with location: ${args.location}`)
    // Return an object matching our output schema
    return {
      temperature: 72,
      condition: 'Sunny',
      humidity: 45,
      location: args.location,
    }
  },
})

// Add a calculator tool with a simple numeric output
const calculatorTool = mcpTool({
  name: 'calculator',
  description: 'Calculate the sum of two numbers',
  schema: z.object({
    a: z.number().describe('First number'),
    b: z.number().describe('Second number'),
  }),
  // Output is just a number
  outputSchema: z.number().describe('The sum of the two input numbers'),
  // Simply return the sum - no need to format for MCP
  handler: async (args) => {
    console.log(`[CalculatorTool] Called with: ${args.a}, ${args.b}`)
    return args.a + args.b
  },
})

// Add a tool that returns an array
const listTool = mcpTool({
  name: 'generate_list',
  description: 'Generate a list of items based on a category',
  schema: z.object({
    category: z
      .string()
      .describe('Category to generate items for (e.g., fruits, colors)'),
    count: z
      .number()
      .optional()
      .describe('Number of items to generate (default: 3)'),
  }),
  // Output is an array of strings
  outputSchema: z
    .array(z.string())
    .describe('List of generated items in the category'),
  handler: async (args) => {
    const count = args.count || 3
    console.log(
      `[ListTool] Generating ${count} items for category: ${args.category}`,
    )

    // Sample data based on category
    const items: Record = {
      fruits: ['apple', 'banana', 'orange', 'grape', 'strawberry'],
      colors: ['red', 'blue', 'green', 'yellow', 'purple'],
      animals: ['dog', 'cat', 'elephant', 'tiger', 'penguin'],
    }

    const categoryItems = items[args.category.toLowerCase()] || [
      'item1',
      'item2',
      'item3',
      'item4',
      'item5',
    ]
    return categoryItems.slice(0, count)
  },
})

// Add a tool that doesn't specify an outputSchema (will expect string return)
const greetingTool = mcpTool({
  name: 'greeting',
  description: 'Get a personalized greeting',
  schema: z.object({
    name: z.string().describe('The name to greet'),
    formal: z.boolean().optional().describe('Whether to use formal language'),
  }),
  // No outputSchema needed, just return a string
  handler: async (args) => {
    const greeting = args.formal
      ? `Good day, ${args.name}. How may I be of service?`
      : `Hey ${args.name}! How's it going?`

    console.log(
      `[GreetingTool] Generated greeting for ${args.name} (formal: ${args.formal || false})`,
    )
    return greeting
  },
})

// Add a protected tool that checks for authentication
const protectedTool = mcpTool({
  name: 'get_passcode',
  description: 'Get the passcode for the user',
  schema: z.object({
    name: z.string().describe('The name of the user'),
  }),
  // Implement authentication check in the handler
  handler: async (args, context) => {
    console.log(`[ProtectedTool] Called with name: ${args.name}`)

    // Check for authorization header
    const authHeader = context?.headers?.authorization || ''
    console.log(context)
    console.log(`[ProtectedTool] Auth header: ${authHeader}`)

    // Check for bearer token that matches "000000"
    const validToken = 'Bearer 000000'
    if (!authHeader || authHeader !== validToken) {
      // Return error for unauthorized access
      throw new Error('Unauthorized: Invalid or missing authentication token')
    }

    // If authorized, return the protected data
    return `Protected data for ID: ${args.name}`
  },
})

// if true will show debug logs, to disable set NODE_ENV=production
const debugMode = process.env.NODE_ENV === 'development'

// Create MCP client
const mcpClient = new MCPClient({
  endpoint: '/mcp',
  tools: [weatherTool, calculatorTool, listTool, greetingTool, protectedTool],
  serverName: 'my-mcp-server',
  serverVersion: '1.0.0',
  debug: debugMode, // Enable debug logs only when --debug flag is passed
})

// Show metadata about the client
const metadata = mcpClient.getMetadata()
console.log('MCP Client created with the following configuration:')
console.log(`- Endpoint: ${metadata.endpoint}`)
console.log(`- Server: ${metadata.serverName} v${metadata.serverVersion}`)
console.log(`- Tools: ${metadata.tools.map((tool) => tool.name).join(', ')}`)

// Mount MCP router
app.use('/mcp', mcpClient.middleware())

// Apply JSON parser for other routes
app.use(express.json())

app.get('/', (req, res) => {
  res.send(`Hello World MCP Express Adapter.`)
})

// Start the server
const PORT = process.env.PORT ? parseInt(process.env.PORT) : 3000
app.listen(PORT, () => {
  const baseUrl = `http://localhost:${PORT}`

  // Get the SSE endpoint URL using the helper method
  const sseEndpoint = mcpClient.getSSEEndpoint(baseUrl)
  console.log(`MCP Client SSE Endpoint: ${sseEndpoint}`)

  console.log(
    `Debug mode: ${debugMode ? 'enabled will show debug logs, to disable set NODE_ENV=production' : 'disabled will not log anything.'}`,
  )
})

您可以使用以下命令运行此示例:

# From the root of the repo
pnpm install
pnpm test-express

工具实施示例

以下是如何使用创建一个简单的工具 mcpTool 帮手:

// examples/with-express/src/tool-example.ts
import { mcpTool } from 'mcp-express-adapter'
import { z } from 'zod'

/**
 * Example 1: Tool with an output schema for complex data
 *
 * Use this approach when your tool returns structured data that
 * needs strong type checking.
 */
const weatherTool = mcpTool({
  name: 'get_weather',
  description: 'Get the current weather for a location',
  schema: z.object({
    location: z.string().describe('The location to get weather for'),
  }),
  // Define the output schema for structured data
  outputSchema: z
    .object({
      temperature: z.number().describe('Current temperature in °F'),
      condition: z.string().describe('Weather condition (e.g., Sunny, Rainy)'),
      humidity: z.number().describe('Humidity percentage'),
      location: z.string().describe('The location this weather is for'),
    })
    .describe('Weather information for the requested location'),
  handler: async (args) => {
    // args.location is fully typed as string
    return {
      temperature: 72,
      condition: 'Sunny',
      humidity: 45,
      location: args.location,
    }
  },
})

/**
 * Example 2: Tool without an output schema for simple string responses
 *
 * Use this approach when your tool returns simple text responses
 * that don't need complex structure or validation.
 */
const greetingTool = mcpTool({
  name: 'greeting',
  description: 'Get a personalized greeting',
  schema: z.object({
    name: z.string().describe('The name to greet'),
    formal: z.boolean().optional().describe('Whether to use formal language'),
  }),
  // No outputSchema needed for simple string responses
  handler: async (args) => {
    // When no outputSchema is provided, you must return a string
    return args.formal
      ? `Good day, ${args.name}. How may I be of service?`
      : `Hey ${args.name}! How's it going?`
  },
})

// non typesafe tool:
// javascript ready
const nonTypesafeTool = {
  name: 'search_web',
  description: 'Search the web for information',
  inputSchema: {
    type: 'object',
    properties: {
      query: { type: 'string', description: 'The search query' },
      limit: {
        type: 'number',
        description: 'Maximum number of results to return',
      },
    },
    required: ['query'],
  },
  handler: async (args) => ({
    content: [
      {
        type: 'text',
        text: `Search results for "${args.query}": Results here...`,
      },
    ],
    isError: false,
  }),
}

export { weatherTool, greetingTool, nonTypesafeTool }

api参考

MCP客户端

在Express服务器上创建MCP端点的主类。

构建器选项

interface MCPClientOptions {
  endpoint: string // The base path for the MCP endpoints
  tools: ToolImpl[] // Array of tool implementations
  serverName?: string // Optional server name (default: 'mcp-server')
  serverVersion?: string // Optional server version (default: '1.0.0')
}

工具实施

interface ToolImpl {
  name: string // Tool name
  description: string // Tool description
  inputSchema: {
    // JSON Schema for the tool's input
    type: 'object'
    properties: Record
    required?: string[]
  }
  handler: (
    args: T,
    context?: {
      headers?: Record // Request headers accessible here
      [key: string]: any
    },
  ) => Promise
    isError?: boolean
  }>
}

工具中的标题访问

您可以通过以下方式访问工具处理程序函数中的请求头 context.headers 对象。这对于实现身份验证、传递自定义元数据或其他基于标头的逻辑非常有用。

客户端发送的标头(例如,使用 mcp-express-adapter CLI与 --header--headers 标志)在 context.

示例:通过CLI传递授权标头

调用一个受保护的工具,该工具需要 Authorization: Bearer header,您可以这样使用CLI适配器:

# Using --header
npx mcp-express-adapter@latest --host http://localhost:3000/mcp/sse --header "Authorization: Bearer 000000"

# Using --headers (if passing multiple)
npx mcp-express-adapter@latest --host http://localhost:3000/mcp/sse --headers "Authorization: Bearer 000000, X-Custom: my-value"

示例:工具读取授权标头

这是 protectedTool 示例(来自 examples/with-express/src/index.ts)演示如何阅读 Authorization 标题来自 context:

// Protected tool example with authentication
const protectedTool = mcpTool({
  name: 'get_passcode', // or 'protected_data' depending on your example version
  description: 'Get protected data (requires authentication)',
  schema: z.object({
    // ... input schema properties
    name: z.string().describe('The name of the user'), // Example property
  }),
  handler: async (args, context) => {
    // Access the headers from the context object
    // Node.js automatically lowercases header names
    const authHeader = context?.headers?.authorization || ''
    console.log(`[ProtectedTool] Auth header received: ${authHeader}`)

    // Validate the token (e.g., check for a specific Bearer token)
    const validToken = 'Bearer 000000'
    if (authHeader !== validToken) {
      throw new Error('Unauthorized: Invalid or missing authentication token')
    }

    // If authorized, proceed with tool logic
    console.log(`[ProtectedTool] Authorized access for user: ${args.name}`)
    return `Protected passcode for ${args.name}: 123456` // Return the protected data
  },
})

高级示例

以下是一个更高级的示例,其中包含多个工具和端点:

import express from 'express'
import cors from 'cors'
import { MCPClient } from 'mcp-express-adapter'

const app = express()
app.use(cors())

// Define multiple tools
const weatherTool = {
  name: 'get_weather',
  description: 'Get the current weather for a location',
  inputSchema: {
    type: 'object',
    properties: {
      location: { type: 'string', description: 'The location' },
    },
    required: ['location'],
  },
  handler: async (args) => ({
    content: [
      { type: 'text', text: `Weather for ${args.location}: Sunny, 72°F` },
    ],
    isError: false,
  }),
}

const searchTool = {
  name: 'search_web',
  description: 'Search the web for information',
  inputSchema: {
    type: 'object',
    properties: {
      query: { type: 'string', description: 'The search query' },
    },
    required: ['query'],
  },
  handler: async (args) => ({
    content: [
      {
        type: 'text',
        text: `Search results for "${args.query}": Results here...`,
      },
    ],
    isError: false,
  }),
}

// Set up multiple MCP Clients on different endpoints
const agent1 = new MCPClient({
  endpoint: '/agent-1',
  tools: [weatherTool, searchTool],
  serverName: 'mcp-server-agent-1',
  serverVersion: '1.0.0',
})

const agent2 = new MCPClient({
  endpoint: '/agent-2',
  tools: [weatherTool], // This agent only has weather tool
  serverName: 'mcp-server-agent-2',
  serverVersion: '1.0.0',
})

// Mount agent routers BEFORE global JSON parser
app.use('/agent-1', agent1.middleware())
app.use('/agent-2', agent2.middleware())

// Apply global JSON parser AFTER agent routes
app.use(express.json())

// Start the server
const PORT = 3000
app.listen(PORT, () => {
  console.log(`MCP Server running on port ${PORT}`)
  console.log(`Agent 1: http://localhost:${PORT}/agent-1/sse`)
  console.log(`Agent 2: http://localhost:${PORT}/agent-2/sse`)
})

测试您的MCP服务器

您可以使用以下命令测试MCP服务器 curl 要连接到SSE端点:

curl -N http://localhost:3000/mcp/sse

或者使用MCP命令行客户端:

# Basic usage
npx mcp-express-adapter --host http://localhost:3000/mcp/sse

# With a single header
npx mcp-express-adapter --host http://localhost:3000/mcp/sse --header "Authorization: Bearer token123"

# With multiple headers (option 1: repeating --header)
npx mcp-express-adapter --host http://localhost:3000/mcp/sse --header "Authorization: Bearer token123" --header "X-Custom: Value"

# With multiple headers (option 2: comma-separated list)
npx mcp-express-adapter --host http://localhost:3000/mcp/sse --headers "Authorization: Bearer token123, X-Custom: Value"

常见问题

  • 确保在应用程序之后应用exress.json()。使用MCP中间件
  • 网络集市还没有经过足够的测试。

贡献者

  • Moe03 -主要贡献者和维护者

如何做出贡献

有兴趣贡献吗?请在 您的功能请求或错误报告。

许可证

麻省理工学院

目录标签

目录标签

中间件TypeScriptClaude工具集成本地部署MCP协议Express.jsSSE

支持客户端

Claude

接入字段

传输方式(transport,传输协议)

stdio

鉴权方式(authType,认证方式)

token

运行时(runtime,运行环境)

Node.js

来源包(packageName,安装包名)

mcp-express-adapter@latest

工具数量(toolCount,工具数)

0

资源数量(resourceCount,资源数)

0

提示词数量(promptCount,提示词数)

0

权限和风险

stdiotoken部署方式未说明

接入前请确认传输方式、认证方式和部署位置,并根据实际工具能力限制访问范围。

安装前确认

不要直接授予不必要的文件、网络或账号权限;先核对安装命令和配置内容。

来源信息

继续浏览同类 MCP