IndexPackages

api2ai

Generate production-ready MCP servers from any OpenAPI specification using the highly-used and convenient mcp-use framework

DocumentationOpen in StackBlitz
NPM Monthly Downloadsnpm versionNPM Total DownloadsTypeScript typesInstall size

🤖 Agent skillnpx skills@latest add https://github.com/OpenSourceAGI/dev-tools-starter-agent --skill api2ai (what it covers)

🌐 Live Site  |  🎯 Example MCP Server

Generate production-ready MCP servers from any OpenAPI specification using the highly-used and convenient mcp-use framework (8k+ GitHub stars).

OpenAPI specs are easy to write and organize your code and have 100s of tools available such as the OpenAPI Builder web UI.

Try it in the browser at api-2-ai.vercel.app — the hosted site lets you design and validate OpenAPI specs visually, browse the docs, and see generated-server examples without installing anything.

Features

  • 🚀 Modern Framework - Uses mcp-use for clean, maintainable code
  • 🔍 Built-in Inspector - Test tools immediately at /inspector
  • 📡 Multiple Transports - HTTP, SSE, and Streamable HTTP support
  • 🎨 UI Widgets - Compatible with ChatGPT Apps SDK and MCP-UI
  • 🔐 Auth Support - Bearer tokens, API keys, custom headers
  • Zod Schemas - Type-safe parameter validation
  • 🛡️ Security Hardening - Risk classification, policy enforcement, HTTP guardrails
  • 🐳 Production Ready - Docker, PM2, and Kubernetes ready

Quick Start

# Generate a server from the Petstore API
npx api2ai \
  https://petstore3.swagger.io/api/v3/openapi.json \
  ./petstore-mcp \
  --name petstore-api

# Install and run
cd petstore-mcp
npm install
npm start

Open http://localhost:3000/inspector to test your tools!

Usage

CLI

node generate-mcp-use-server.js <openapi-spec> [output-folder] [options]

Options:
  --name <name>            Server name (default: api-mcp-server)
  --base-url <url>         Override API base URL
  --port <port>            Server port (default: 3000)
  --allow-mutations        Enable POST/PUT/PATCH/DELETE tools by default
  --include-tags <tags>    Only include tools with these tags (comma-separated)
  --exclude-tags <tags>    Exclude tools with these tags (comma-separated)
  --approve-writes         Disable approval requirement for restricted tools
  --help                   Show help

Examples

# From remote URL
node generate-mcp-use-server.js \
  https://api.example.com/openapi.json \
  ./my-server \
  --name my-api

# From local file
node generate-mcp-use-server.js \
  ./specs/my-api.yaml \
  ./my-mcp-server \
  --port 8080

# With custom base URL
node generate-mcp-use-server.js \
  ./petstore.json \
  ./petstore \
  --base-url https://petstore.example.com/v3

# Include only read-only tools tagged "public"
node generate-mcp-use-server.js \
  ./api.json \
  ./readonly-server \
  --include-tags public \
  --exclude-tags admin,internal

# Enable writes (mutations) explicitly
node generate-mcp-use-server.js \
  ./api.json \
  ./full-server \
  --allow-mutations \
  --approve-writes

Programmatic Usage

import { generateMcpServer, extractTools, loadOpenApiSpec } from './generate-mcp-use-server.js';

// Generate complete server
const result = await generateMcpServer(
  'https://api.example.com/openapi.json',
  './output-folder',
  {
    serverName: 'my-api',
    baseUrl: 'https://api.example.com/v1',
    port: 3000,
    allowMutations: false,       // block POST/PUT/PATCH/DELETE by default
    includeTags: ['public'],     // only include tools tagged "public"
    excludeTags: ['admin'],      // exclude tools tagged "admin"
  }
);

console.log(`Generated ${result.toolCount} tools`);

// Or just extract tools for custom processing
const spec = await loadOpenApiSpec('./my-spec.json');
const tools = extractTools(spec, {
  filterFn: (tool) => tool.riskLevel === 'low',  // only safe read-only tools
  excludeOperationIds: ['deleteUser'],
});

Security

The generator enforces a three-layer security model in every generated server.

Layer 1 — Generation-time risk classification

Every tool is classified during generation and the result is baked into src/tools-config.js:

Risk levelWhen assignedDefault behavior
lowGET, HEAD, OPTIONS with no dangerous keywordsEnabled, no approval required
mediumAny mutating method (POST, PUT, PATCH, DELETE)Blocked unless ALLOW_RESTRICTED_TOOLS=true
highAny operation matching admin, auth, billing, payments, tokens, secrets, user management patternsBlocked, approval required

Use --allow-mutations at generation time to promote medium-risk tools to enabled-by-default, or override at runtime with env vars.

Layer 2 — Runtime policy enforcement

checkToolPolicy() runs before every outbound API call, reading env vars at call-time so you can change policy without regenerating:

ALLOW_RESTRICTED_TOOLS=true    # unlock medium/high-risk tools
REQUIRE_APPROVALS=false        # bypass per-call approval gate

Layer 3 — HTTP hardening

The generated HTTP client enforces these on every request:

  • Timeouts — configurable via REQUEST_TIMEOUT_MS (default 30 s)
  • Response size cap — configurable via MAX_RESPONSE_BYTES (default 10 MB)
  • No redirectsredirect: 'error' prevents host-pivot attacks
  • Credential header protection — tool arguments cannot override Authorization, Cookie, X-API-Key, or other credential headers; env-configured auth always wins
  • Host allowlistALLOWED_API_HOSTS restricts outbound calls to specific hostnames

Inspector note: The built-in inspector at /inspector exposes all registered tools. In production, restrict access using a reverse proxy or firewall rule.

Generated Output

my-mcp-server/
├── .env              # Environment config (gitignored)
├── .env.example      # Example environment file
├── .gitignore
├── package.json
├── README.md         # Generated documentation
└── src/
    ├── index.js        # Main server with tool registrations
    ├── http-client.js  # Hardened HTTP client
    ├── tools-config.js # Tool configurations with risk metadata
    └── policy.js       # Runtime security policy

Generated Server Features

Built-in Endpoints

EndpointDescription
GET /inspectorInteractive tool testing UI
POST /mcpMCP protocol endpoint
GET /sseServer-Sent Events endpoint
GET /healthHealth check

Environment Variables

VariableDescriptionDefault
PORTServer port3000
NODE_ENVdevelopment / productiondevelopment
API_BASE_URLBase URL for API callsFrom spec
API_KEYBearer token auth
API_AUTH_HEADERCustom header (Name:value)
MCP_URLPublic URL for widgets
ALLOWED_ORIGINSCORS origins (production)
ALLOW_RESTRICTED_TOOLSAllow medium/high-risk toolsfalse
REQUIRE_APPROVALSRequire approval for restricted toolstrue
ALLOWED_API_HOSTSComma-separated allowed API hostnames(spec's host)
REQUEST_TIMEOUT_MSOutbound request timeout in ms30000
MAX_RESPONSE_BYTESMaximum response body size in bytes10485760

Connect to Claude Desktop

{
  "mcpServers": {
    "my-api": {
      "url": "http://localhost:3000/mcp"
    }
  }
}

Connect to ChatGPT

The generated server supports the OpenAI Apps SDK out of the box.

Advanced Options

Filter by risk level

const result = await generateMcpServer(specUrl, outputDir, {
  filterFn: (tool) => tool.riskLevel === 'low',
});

Filter Tools by Method

const result = await generateMcpServer(specUrl, outputDir, {
  filterFn: (tool) => ['get', 'post'].includes(tool.method),
});

Exclude Dangerous Operations

const result = await generateMcpServer(specUrl, outputDir, {
  excludeOperationIds: [
    'deleteUser',
    'deleteAllData', 
    'adminReset',
  ],
});

Filter by Path Pattern

const result = await generateMcpServer(specUrl, outputDir, {
  filterFn: (tool) => tool.pathTemplate.startsWith('/api/v2/'),
});

Combine Filters

const result = await generateMcpServer(specUrl, outputDir, {
  excludeOperationIds: ['deleteUser'],
  allowMutations: false,
  filterFn: (tool) => 
    tool.riskLevel === 'low' && 
    tool.pathTemplate.includes('/public/'),
});

Comparison with Raw MCP SDK

FeatureThis GeneratorRaw SDK
Code needed~50 lines~200+ lines
Inspector✅ Built-in❌ Manual
UI Widgets✅ Supported❌ Manual
Zod validation✅ Generated❌ Manual
Authentication✅ Configured❌ Manual
Risk classification✅ Automatic❌ Manual
Runtime policy✅ Generated❌ Manual
HTTP hardening✅ Built-in❌ Manual
Production ready✅ Yes⚠️ Requires work

PRs Welcome

Please star this repo for updates! 🌟


Source: packages/api2ai-mcp-generator/README.md

Last updated on

On this page