api2ai 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +206 -0
  2. package/package.json +232 -0
package/README.md ADDED
@@ -0,0 +1,206 @@
1
+
2
+ <p align="center">
3
+ <img width="600px" src="https://i.imgur.com/TTJBLxo.png" />
4
+ </p>
5
+ <h3 align="center">
6
+ <a href="https://github.com/vtempest/GRAB-URL/tree/master/api2ai/example-petstore"> 🎯 Example MCP Server </a>
7
+ </h3>
8
+
9
+
10
+ <p align="center">
11
+ <a href="https://npmjs.org/package/grab-url"><img alt="NPM Version" src="https://img.shields.io/npm/v/grab-url" /></a><a href="https://github.com/vtempest/GRAB-URL/discussions"><img alt="GitHub Discussions"
12
+ src="https://img.shields.io/github/discussions/vtempest/GRAB-URL" /></a><a href="https://github.blog/developer-skills/github/beginners-guide-to-github-creating-a-pull-request/"><img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg" alt="PRs Welcome"/></a>
13
+ </p>
14
+
15
+
16
+ # API2AI: OpenAPI to MCP-Use Server
17
+
18
+ Generate production-ready MCP servers from any OpenAPI specification using the highly-used and convenient [mcp-use](https://mcp-use.com) framework (8k+ GitHub stars).
19
+
20
+ OpenAPI specs are easy to write and organize your code and have [100s of tools available](https://openapi.tools) such as the [OpenAPI Builder web UI](https://www.apibldr.com).
21
+
22
+ ## Features
23
+
24
+ - 🚀 **Modern Framework** - Uses mcp-use for clean, maintainable code
25
+ - 🔍 **Built-in Inspector** - Test tools immediately at `/inspector`
26
+ - 📡 **Multiple Transports** - HTTP, SSE, and Streamable HTTP support
27
+ - 🎨 **UI Widgets** - Compatible with ChatGPT Apps SDK and MCP-UI
28
+ - 🔐 **Auth Support** - Bearer tokens, API keys, custom headers
29
+ - ✨ **Zod Schemas** - Type-safe parameter validation
30
+ - 🐳 **Production Ready** - Docker, PM2, and Kubernetes ready
31
+
32
+ ## Quick Start
33
+
34
+ ```bash
35
+ # Generate a server from the Petstore API
36
+ npx api2ai \
37
+ https://petstore3.swagger.io/api/v3/openapi.json \
38
+ ./petstore-mcp \
39
+ --name petstore-api
40
+
41
+ # Install and run
42
+ cd petstore-mcp
43
+ npm install
44
+ npm start
45
+ ```
46
+
47
+ Open http://localhost:3000/inspector to test your tools!
48
+
49
+ ## Usage
50
+
51
+ ### CLI
52
+
53
+ ```bash
54
+ node generate-mcp-use-server.js <openapi-spec> [output-folder] [options]
55
+
56
+ Options:
57
+ --name <name> Server name (default: api-mcp-server)
58
+ --base-url <url> Override API base URL
59
+ --port <port> Server port (default: 3000)
60
+ --help Show help
61
+ ```
62
+
63
+ ### Examples
64
+
65
+ ```bash
66
+ # From remote URL
67
+ node generate-mcp-use-server.js \
68
+ https://api.example.com/openapi.json \
69
+ ./my-server \
70
+ --name my-api
71
+
72
+ # From local file
73
+ node generate-mcp-use-server.js \
74
+ ./specs/my-api.yaml \
75
+ ./my-mcp-server \
76
+ --port 8080
77
+
78
+ # With custom base URL
79
+ node generate-mcp-use-server.js \
80
+ ./petstore.json \
81
+ ./petstore \
82
+ --base-url https://petstore.example.com/v3
83
+ ```
84
+
85
+ ### Programmatic Usage
86
+
87
+ ```javascript
88
+ import { generateMcpServer, extractTools, loadOpenApiSpec } from './generate-mcp-use-server.js';
89
+
90
+ // Generate complete server
91
+ const result = await generateMcpServer(
92
+ 'https://api.example.com/openapi.json',
93
+ './output-folder',
94
+ {
95
+ serverName: 'my-api',
96
+ baseUrl: 'https://api.example.com/v1',
97
+ port: 3000,
98
+ }
99
+ );
100
+
101
+ console.log(`Generated ${result.toolCount} tools`);
102
+
103
+ // Or just extract tools for custom processing
104
+ const spec = await loadOpenApiSpec('./my-spec.json');
105
+ const tools = extractTools(spec, {
106
+ filterFn: (tool) => tool.method === 'get', // Only GET endpoints
107
+ excludeOperationIds: ['deleteUser'], // Exclude specific operations
108
+ });
109
+ ```
110
+
111
+ ## Generated Output
112
+
113
+ ```
114
+ my-mcp-server/
115
+ ├── .env # Environment config (gitignored)
116
+ ├── .env.example # Example environment file
117
+ ├── .gitignore
118
+ ├── package.json
119
+ ├── README.md # Generated documentation
120
+ └── src/
121
+ ├── index.js # Main server with tool registrations
122
+ ├── http-client.js # HTTP utilities
123
+ └── tools-config.js # Tool configurations
124
+ ```
125
+
126
+ ## Generated Server Features
127
+
128
+ ### Built-in Endpoints
129
+
130
+ | Endpoint | Description |
131
+ |----------|-------------|
132
+ | `GET /inspector` | Interactive tool testing UI |
133
+ | `POST /mcp` | MCP protocol endpoint |
134
+ | `GET /sse` | Server-Sent Events endpoint |
135
+ | `GET /health` | Health check |
136
+
137
+ ### Environment Variables
138
+
139
+ | Variable | Description |
140
+ |----------|-------------|
141
+ | `PORT` | Server port |
142
+ | `NODE_ENV` | development/production |
143
+ | `API_BASE_URL` | Base URL for API calls |
144
+ | `API_KEY` | Bearer token auth |
145
+ | `API_AUTH_HEADER` | Custom header (`Name:value`) |
146
+ | `MCP_URL` | Public URL for widgets |
147
+ | `ALLOWED_ORIGINS` | CORS origins (production) |
148
+
149
+
150
+ ### Connect to ChatGPT
151
+
152
+ The generated server supports the OpenAI Apps SDK out of the box.
153
+
154
+ ## Advanced Options
155
+
156
+ ### Filter Tools by Method
157
+
158
+ ```javascript
159
+ const result = await generateMcpServer(specUrl, outputDir, {
160
+ filterFn: (tool) => ['get', 'post'].includes(tool.method),
161
+ });
162
+ ```
163
+
164
+ ### Exclude Dangerous Operations
165
+
166
+ ```javascript
167
+ const result = await generateMcpServer(specUrl, outputDir, {
168
+ excludeOperationIds: [
169
+ 'deleteUser',
170
+ 'deleteAllData',
171
+ 'adminReset',
172
+ ],
173
+ });
174
+ ```
175
+
176
+ ### Filter by Path Pattern
177
+
178
+ ```javascript
179
+ const result = await generateMcpServer(specUrl, outputDir, {
180
+ filterFn: (tool) => tool.pathTemplate.startsWith('/api/v2/'),
181
+ });
182
+ ```
183
+
184
+ ### Combine Filters
185
+
186
+ ```javascript
187
+ const result = await generateMcpServer(specUrl, outputDir, {
188
+ excludeOperationIds: ['deleteUser'],
189
+ filterFn: (tool) =>
190
+ tool.method === 'get' &&
191
+ tool.pathTemplate.includes('/public/'),
192
+ });
193
+ ```
194
+
195
+
196
+
197
+ ## Comparison with Raw MCP SDK
198
+
199
+ | Feature | This Generator | Raw SDK |
200
+ |---------|---------------|---------|
201
+ | Code needed | ~50 lines | ~200+ lines |
202
+ | Inspector | ✅ Built-in | ❌ Manual |
203
+ | UI Widgets | ✅ Supported | ❌ Manual |
204
+ | Zod validation | ✅ Generated | ❌ Manual |
205
+ | Authentication | ✅ Configured | ❌ Manual |
206
+ | Production ready | ✅ Yes | ⚠️ Requires work |
package/package.json ADDED
@@ -0,0 +1,232 @@
1
+ {
2
+ "name": "api2ai",
3
+ "version": "0.2.1",
4
+ "description": "Generate production-ready MCP servers from any OpenAPI specification using the highly-used and convenient [mcp-use](https://mcp-use.com) framework",
5
+ "license": "rights.institute/prosper",
6
+ "author": "vtempest",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/OpenSourceAGI/appdemo-dev-tools/tree/master/packages/api2ai-mcp-generator"
10
+ },
11
+ "homepage": "https://github.com/OpenSourceAGI/appdemo-dev-tools/tree/master/packages/api2ai-mcp-generator",
12
+ "exports": {
13
+ ".": {
14
+ "import": "./dist/index.mjs",
15
+ "require": "./dist/index.js",
16
+ "types": "./dist/index.d.ts"
17
+ }
18
+ },
19
+ "main": "dist/index.js",
20
+ "module": "dist/index.mjs",
21
+ "types": "dist/index.d.ts",
22
+ "files": [
23
+ "dist"
24
+ ],
25
+ "scripts": {
26
+ "build": "next build",
27
+ "db:create": "npm create cloud-db",
28
+ "db:generate": "drizzle-kit generate",
29
+ "db:push": "drizzle-kit push",
30
+ "db:studio": "concurrently \"drizzle-kit studio\" \"wait-on https://local.drizzle.studio && opener https://local.drizzle.studio\"",
31
+ "dev": "concurrently \"next dev\" \"wait-on http://localhost:3000 && opener http://localhost:3000\"",
32
+ "docs:check": "fumadocs check",
33
+ "docs:generate": "fumadocs-mdx",
34
+ "postinstall": "fumadocs-mdx && drizzle-kit push",
35
+ "make": "concurrently \"next build && next start \" \"wait-on http://localhost:3000 && opener http://localhost:3000\"",
36
+ "start": "next start"
37
+ },
38
+ "dependencies": {
39
+ "@ai-sdk/react": "3.0.3",
40
+ "@aws-sdk/client-rds-data": "latest",
41
+ "@better-auth/core": "latest",
42
+ "@better-auth/stripe": "^1.4.7",
43
+ "@cloudflare/workers-types": "latest",
44
+ "@electric-sql/pglite": "latest",
45
+ "@emotion/is-prop-valid": "latest",
46
+ "@fumadocs/mdx-remote": "^1.4.3",
47
+ "@langchain/core": "^1.1.5",
48
+ "@langchain/groq": "^1.0.2",
49
+ "@langchain/openai": "^1.2.0",
50
+ "@libsql/client": "^0.15.15",
51
+ "@libsql/client-wasm": "latest",
52
+ "@lynx-js/react": "latest",
53
+ "@mixedbread/sdk": "latest",
54
+ "@neondatabase/serverless": "latest",
55
+ "@op-engineering/op-sqlite": "latest",
56
+ "@opentelemetry/api": "latest",
57
+ "@orama/core": "latest",
58
+ "@planetscale/database": "latest",
59
+ "@prisma/client": "latest",
60
+ "@radix-ui/react-accordion": "1.2.12",
61
+ "@radix-ui/react-alert-dialog": "1.1.15",
62
+ "@radix-ui/react-aspect-ratio": "1.1.8",
63
+ "@radix-ui/react-avatar": "^1.1.11",
64
+ "@radix-ui/react-checkbox": "1.3.3",
65
+ "@radix-ui/react-collapsible": "^1.1.12",
66
+ "@radix-ui/react-context-menu": "2.2.16",
67
+ "@radix-ui/react-dialog": "^1.1.15",
68
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
69
+ "@radix-ui/react-hover-card": "1.1.15",
70
+ "@radix-ui/react-label": "2.1.8",
71
+ "@radix-ui/react-menubar": "1.1.16",
72
+ "@radix-ui/react-navigation-menu": "1.2.14",
73
+ "@radix-ui/react-popover": "1.1.15",
74
+ "@radix-ui/react-presence": "1.1.5",
75
+ "@radix-ui/react-progress": "1.1.8",
76
+ "@radix-ui/react-radio-group": "^1.3.8",
77
+ "@radix-ui/react-scroll-area": "1.2.10",
78
+ "@radix-ui/react-select": "2.2.6",
79
+ "@radix-ui/react-separator": "^1.1.8",
80
+ "@radix-ui/react-slider": "1.3.6",
81
+ "@radix-ui/react-slot": "^1.2.4",
82
+ "@radix-ui/react-switch": "1.2.6",
83
+ "@radix-ui/react-tabs": "1.1.13",
84
+ "@radix-ui/react-toast": "1.2.15",
85
+ "@radix-ui/react-toggle": "1.1.10",
86
+ "@radix-ui/react-toggle-group": "1.1.11",
87
+ "@radix-ui/react-tooltip": "^1.2.8",
88
+ "@react-email/render": "latest",
89
+ "@react-three/drei": "^10.7.7",
90
+ "@react-three/fiber": "^9.4.2",
91
+ "@scalar/api-client-react": "latest",
92
+ "@scalar/api-reference": "^1.40.5",
93
+ "@scalar/api-reference-react": "^0.8.11",
94
+ "@shikijs/rehype": "^3.20.0",
95
+ "@shikijs/transformers": "^3.20.0",
96
+ "@silevis/reactgrid": "^4.1.17",
97
+ "@t3-oss/env-nextjs": "0.13.10",
98
+ "@tabler/icons-react": "^3.36.0",
99
+ "@tanstack/react-router": "latest",
100
+ "@tanstack/react-start": "latest",
101
+ "@tidbcloud/serverless": "latest",
102
+ "@types/better-sqlite3": "latest",
103
+ "@types/dompurify": "^3.2.0",
104
+ "@types/js-yaml": "^4.0.9",
105
+ "@types/marked": "^6.0.0",
106
+ "@types/pg": "latest",
107
+ "@types/sql.js": "latest",
108
+ "@upstash/redis": "latest",
109
+ "@vercel/analytics": "1.6.1",
110
+ "@vercel/postgres": "latest",
111
+ "@xata.io/client": "latest",
112
+ "ai": "6.0.3",
113
+ "algoliasearch": "latest",
114
+ "arktype": "latest",
115
+ "autoprefixer": "^10.4.22",
116
+ "axios": "^1.13.2",
117
+ "better-auth": "^1.4.7",
118
+ "better-sqlite3": "latest",
119
+ "bun-types": "latest",
120
+ "canvas": "latest",
121
+ "class-variance-authority": "^0.7.1",
122
+ "cli-highlight": "^2.1.11",
123
+ "clsx": "^2.1.1",
124
+ "cmdk": "^1.1.1",
125
+ "date-fns": "4.1.0",
126
+ "dompurify": "^3.3.1",
127
+ "dotenv": "^17.2.3",
128
+ "drizzle-orm": "^0.45.1",
129
+ "embla-carousel-react": "8.6.0",
130
+ "ethers": "^6.16.0",
131
+ "expo": "latest",
132
+ "expo-asset": "latest",
133
+ "expo-file-system": "latest",
134
+ "expo-gl": "latest",
135
+ "expo-sqlite": "latest",
136
+ "feed": "^5.1.0",
137
+ "fumadocs-core": "^16.2.5",
138
+ "fumadocs-mdx": "^14.1.1",
139
+ "fumadocs-openapi": "^10.1.4",
140
+ "fumadocs-twoslash": "^3.1.10",
141
+ "fumadocs-typescript": "^4.0.14",
142
+ "fumadocs-ui": "^16.2.5",
143
+ "gel": "latest",
144
+ "grab-url": "^1.0.15",
145
+ "hast-util-to-jsx-runtime": "2.3.6",
146
+ "highlight.js": "^11.11.1",
147
+ "jiti": "latest",
148
+ "js-yaml": "^4.1.1",
149
+ "jszip": "^3.10.1",
150
+ "katex": "^0.16.27",
151
+ "knex": "latest",
152
+ "kysely": "latest",
153
+ "langchain": "^1.2.0",
154
+ "less": "latest",
155
+ "lightningcss": "latest",
156
+ "linkedom": "^0.18.12",
157
+ "lucide-react": "^0.561.0",
158
+ "marked": "^17.0.1",
159
+ "mermaid": "^11.12.2",
160
+ "mongodb": "latest",
161
+ "motion": "^12.23.26",
162
+ "mysql2": "latest",
163
+ "next": "16.0.10",
164
+ "next-themes": "^0.4.6",
165
+ "pg": "latest",
166
+ "pinets": "^0.5.0",
167
+ "postgres": "latest",
168
+ "prisma": "latest",
169
+ "react": "19.2.3",
170
+ "react-day-picker": "9.12.0",
171
+ "react-dom": "19.2.3",
172
+ "react-hook-form": "^7.68.0",
173
+ "react-is": "^19.2.3",
174
+ "react-native": "latest",
175
+ "react-resizable-panels": "^3.0.6",
176
+ "react-router": "latest",
177
+ "rehype-katex": "^7.0.1",
178
+ "remark": "15.0.1",
179
+ "remark-gfm": "4.0.1",
180
+ "remark-math": "^6.0.0",
181
+ "remark-rehype": "11.1.2",
182
+ "resend": "^6.6.0",
183
+ "sass": "latest",
184
+ "sass-embedded": "latest",
185
+ "simplex-noise": "^4.0.3",
186
+ "siwe": "^3.0.0",
187
+ "solid-js": "latest",
188
+ "sonner": "^2.0.7",
189
+ "sql.js": "latest",
190
+ "sqlite3": "latest",
191
+ "stripe": "^20.0.0",
192
+ "stylus": "latest",
193
+ "sugarss": "latest",
194
+ "tailwind-merge": "^3.4.0",
195
+ "tailwindcss-animate": "^1.0.7",
196
+ "tavily": "^1.0.2",
197
+ "terser": "^5.44.1",
198
+ "three": "^0.182.0",
199
+ "three-globe": "^2.45.0",
200
+ "tsx": "latest",
201
+ "unist-util-visit": "5.0.0",
202
+ "valibot": "latest",
203
+ "vaul": "^1.1.2",
204
+ "viem": "^2.42.0",
205
+ "vitest": "latest",
206
+ "waku": "latest",
207
+ "yaml": "latest",
208
+ "zod": "4.1.13"
209
+ },
210
+ "devDependencies": {
211
+ "@fumadocs/cli": "^1.1.0",
212
+ "@tailwindcss/postcss": "^4.1.18",
213
+ "@types/node": "^25.0.2",
214
+ "@types/react": "^19.2.7",
215
+ "@types/react-dom": "^19.2.3",
216
+ "@types/three": "^0.182.0",
217
+ "concurrently": "^9.2.1",
218
+ "drizzle-kit": "^0.31.8",
219
+ "opener": "^1.5.2",
220
+ "postcss": "^8.5.6",
221
+ "tailwindcss": "^4.1.18",
222
+ "tw-animate-css": "1.4.0",
223
+ "typescript": "^5.9.3",
224
+ "vite": "^7.3.0",
225
+ "vite-plugin-dts": "^4.5.4",
226
+ "wait-on": "^9.0.3"
227
+ },
228
+ "data": "dist/index.d.ts",
229
+ "trustedDependencies": [
230
+ "pg-native"
231
+ ]
232
+ }