一个自动将 OpenAPI 规范转换为模型上下文协议 (MCP) 服务器实例的工具
安装包:
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 # 开发模式监视