https://github.com/serverless-devs/openapi-mcp-converter
Automatically convert OpenAPI specifications into Model Context Protocol (MCP) service instances
https://github.com/serverless-devs/openapi-mcp-converter
Last synced: 7 months ago
JSON representation
Automatically convert OpenAPI specifications into Model Context Protocol (MCP) service instances
- Host: GitHub
- URL: https://github.com/serverless-devs/openapi-mcp-converter
- Owner: Serverless-Devs
- License: mit
- Created: 2025-05-11T14:16:52.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2025-05-11T14:43:22.000Z (11 months ago)
- Last Synced: 2025-05-11T15:32:43.395Z (11 months ago)
- Language: TypeScript
- Size: 18.6 KB
- Stars: 0
- Watchers: 6
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
- License: LICENSE
Awesome Lists containing this project
README
# OpenAPI to MCP Server Converter
[](https://nodejs.org/)
[](https://www.typescriptlang.org/)
[](https://opensource.org/licenses/MIT)
将 OpenAPI 规范自动转换为 Model Context Protocol(MCP)服务实例
## 功能特性
- 🚀 **自动化转换**:自动解析 OpenAPI 3.0 规范
- 🛠 **类型安全**:基于 TypeScript 的强类型校验
- 🔄 **请求代理**:自动处理工具调用参数映射
## 快速开始
### 前置条件
- Node.js 18+
- TypeScript 5.x
### 基础用法
引入依赖:
```bash
npm install @serverless-devs/openapi-mcp-converter
```
创建一个 Server 实例:
```typescript
import fs from 'fs';
import { OpenApiMCPSeverConverter } from '@serverless-devs/openapi-mcp-converter';
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 Server:
```typescript
async function runServer() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.log("GitHub MCP Server running on stdio");
}
runServer().catch((error) => {
console.error("Fatal error in main():", error);
process.exit(1);
});
```
运行一个本地 SSE Server:
```typescript
import fs from 'fs';
import { OpenApiMCPSeverConverter } from '../index.js';
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
import path from 'path';
import { fileURLToPath } from 'url';
import express from 'express';
const openApiDoc = JSON.parse(fs.readFileSync(path.join(path.dirname(fileURLToPath(import.meta.url)), 'openapi.json'), 'utf8'));
const converter = new OpenApiMCPSeverConverter(openApiDoc, { timeout: 100000 });
const server = converter.getServer();
console.log(JSON.stringify(converter.getMcpTools(), null, 2));
console.log(JSON.stringify(converter.getTools(), null, 2));
const app = express();
let transport: SSEServerTransport;
app.get("/sse", async (req, res) => {
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 query parameter is required");
}
await transport.handlePostMessage(req, res);
return;
});
app.listen(8080, () => {
console.log('MCP Server running on port 8080');
});
```
运行一个本地 Streamable HTTP Server:
```typescript
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: 'Bad Request: No valid session ID provided',
},
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('Invalid or missing session ID');
return;
}
const transport = transports[sessionId];
await transport.handleRequest(req, res);
};
app.get('/mcp', handleSessionRequest);
app.delete('/mcp', handleSessionRequest);
app.listen(3000);
```
## 开发指南
### 项目结构
```
/openapi-to-mcp
├── dist/ # 编译输出
├── src/ # 源代码
│ ├── example/ # 示例配置
│ └── index.ts # 核心实现
├── package.json
└── tsconfig.json
```
### 构建命令
```bash
npm run build # 生产环境构建
npm run watch # 开发模式监听
```