返回市场
开放API到MCP转换器

开放API到MCP转换器

作者:zxypro14 星标更新:2025-05-09

项目介绍

OpenAPI 到 MCP 服务器转换器

Node.js 版本 TypeScript 版本 许可证: MIT

一个自动将 OpenAPI 规范转换为模型上下文协议 (MCP) 服务器实例的工具

功能

  • 🚀 自动化转换: 自动解析 OpenAPI 3.0 规范
  • 🛠 类型安全: 基于 TypeScript 的强类型验证
  • 🔄 请求代理: 自动处理工具调用参数映射

快速开始

预备条件

  • Node.js 18+
  • TypeScript 5.x

基本用法

安装包:

npm install openapi-mcp-converter

创建服务器实例:

import fs from 'fs';
import { OpenApiMCPSeverConverter } from '../index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import path from 'path';
import { fileURLToPath } from 'url';

const openApiDoc = JSON.parse(fs.readFileSync(path.join(path.dirname(fileURLToPath(import.meta.url)), 'openapi.json'), 'utf8'));

const converter = new OpenApiMCPSeverConverter(openApiDoc, { timeout: 100000, security: { apiKey: 'my-api-key' } });
const server = converter.getServer();

运行本地 stdio MCP 服务器:

async function runServer() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.log("GitHub MCP 服务器正在通过 stdio 运行");
}

runServer().catch((error) => {
  console.error("主函数中致命错误:", error);
  process.exit(1);
});

运行本地 SSE 服务器:

const app = express();
let transport = null;

app.get("/sse", async (req, res) => {
  console.log("SSE 连接已打开");
  console.log("请求头:", req?.headers);
  console.log("请求查询:", req?.query);
  server.onclose = async () => {
    await server.close();
  };
  transport = new SSEServerTransport("/messages", res);
  await server.connect(transport);
  return;
});

app.post("/messages", async (req, res) => {
  const sessionId = req.query.sessionId as string;
  if (!sessionId) {
      throw new Error("需要 sessionId 查询参数");
  }
  await transport.handlePostMessage(req, res);
  return;
});

app.listen(8080, () => {
  console.log('MCP 服务器正在 8080 端口运行');
});

运行本地流式 HTTP 服务器:

const app = express();
app.use(express.json());

const transports: { [sessionId: string]: StreamableHTTPServerTransport } = {};

app.post('/mcp', async (req, res) => {
  const sessionId = req.headers['mcp-session-id'] as string | undefined;
  let transport: StreamableHTTPServerTransport;

  if (sessionId && transports[sessionId]) {
    transport = transports[sessionId];
  } else if (!sessionId && isInitializeRequest(req.body)) {
    transport = new StreamableHTTPServerTransport({
      sessionIdGenerator: () => randomUUID(),
      onsessioninitialized: (sessionId) => {
        transports[sessionId] = transport;
      }
    });
    transport.onclose = () => {
      if (transport.sessionId) {
        delete transports[transport.sessionId];
      }
    };
    await server.connect(transport);
  } else {
    res.status(400).json({
      jsonrpc: '2.0',
      error: {
        code: -32000,
        message: '无效请求: 没有提供有效的会话ID',
      },
      id: null,
    });
    return;
  }

  await transport.handleRequest(req, res, req.body);
});

const handleSessionRequest = async (req: express.Request, res: express.Response) => {
  const sessionId = req.headers['mcp-session-id'] as string | undefined;
  if (!sessionId || !transports[sessionId]) {
    res.status(400).send('无效或缺少会话ID');
    return;
  }
  
  const transport = transports[sessionId];
  await transport.handleRequest(req, res);
};

app.get('/mcp', handleSessionRequest);

app.delete('/mcp', handleSessionRequest);

app.listen(3000);

运行示例

npm run test  # 执行示例测试用例

开发指南

项目结构

/openapi-to-mcp
├── dist/            # 编译输出
├── src/             # 源代码
│   ├── example/     # 示例配置
│   └── index.ts     # 核心实现
├── package.json
└── tsconfig.json

构建命令

npm run build    # 生产构建
npm run watch    # 开发模式监视