openapi-mcp-bridge
by ephrin
README.md
# OpenAPI MCP Bridge
[](https://www.npmjs.com/package/openapi-mcp-bridge)
[](https://www.typescriptlang.org/)
[](https://opensource.org/licenses/MIT)
Transform OpenAPI definitions into MCP (Model Context Protocol) tools for seamless LLM-API integration.
## What is MCP?
**Model Context Protocol (MCP)** is a standard protocol that allows AI models to interact with external tools and data sources. Unlike REST APIs that use HTTP requests, MCP uses JSON-RPC messages over stdio or WebSocket connections.
**Key Differences:**
- **REST API**: HTTP requests → JSON responses
- **MCP**: JSON-RPC messages → Tool calls and responses
- **Purpose**: MCP bridges AI models with external systems safely and efficiently
**Why OpenAPI → MCP?**
- Your APIs are already documented in OpenAPI format
- AI models can't directly call REST APIs
- MCP provides a secure, standardized way to expose API functionality to AI
## Quick Start (30 seconds)
### 1. Install and Run
```bash
npm install -g openapi-mcp-bridge
mkdir my-api && cd my-api
```
### 2. Create OpenAPI Definition
```bash
cat > museum-api.yaml << 'EOF'
openapi: 3.1.0
info:
title: Museum API
version: 1.0.0
servers:
- url: https://redocly.com/_mock/demo/openapi/museum-api
paths:
/museum-hours:
get:
summary: Get museum hours
operationId: getMuseumHours
parameters:
- name: date
in: query
schema:
type: string
format: date
components:
securitySchemes:
BasicAuth:
type: http
scheme: basic
EOF
```
### 3. Test with MCP Inspector
```bash
# Terminal 1: Start MCP server
openapi-mcp-bridge --definitions .
# Terminal 2: Test with inspector
npm install -g @modelcontextprotocol/inspector
mcp-inspector npx openapi-mcp-bridge --definitions .
```
**Result**: You'll see `getMuseumHours` tool available in the MCP Inspector interface.
## Integration Examples
### Claude Desktop Integration
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):
```json
{
"mcpServers": {
"museum-api": {
"command": "npx",
"args": ["openapi-mcp-bridge", "--definitions", "/path/to/your/api-definitions"]
}
}
}
```
**Usage**: Ask Claude "What are the museum hours?" and it will automatically call your API.
### Claude Code Integration
1. Create `.claude-code-mcp.json` in your project:
```json
{
"mcpServers": {
"my-api": {
"command": "npx",
"args": ["openapi-mcp-bridge", "--definitions", "./api-definitions"]
}
}
}
```
2. Claude Code will automatically detect and use your API tools.
### Custom MCP Client
```typescript
// TypeScript example with proper ES module setup
import { spawn } from 'child_process';
import { MCPClient } from '@modelcontextprotocol/client';
const serverProcess = spawn('npx', ['openapi-mcp-bridge', '--definitions', './api-definitions']);
const client = new MCPClient();
await client.connect({
stdio: {
stdin: serverProcess.stdin,
stdout: serverProcess.stdout
}
});
// List available tools
const tools = await client.listTools();
console.log('Available tools:', tools);
// Call a tool
const result = await client.callTool('getMuseumHours', { date: '2024-01-15' });
console.log('Result:', result);
```
## Usage Patterns
### When to Use Each Approach
| Use Case | Approach | Best For |
|----------|----------|----------|
| **AI Model Integration** | CLI (`openapi-mcp-bridge`) | Claude Desktop, Claude Code, custom MCP clients |
| **Web Application** | Express/Fastify middleware | Adding MCP endpoints to existing web apps |
| **Microservice** | Standalone server | Dedicated MCP service, Docker deployments |
| **Development/Testing** | MCP Inspector | Testing and debugging MCP tools |
### Decision Tree
```
Do you want to integrate with an AI model?
├── Yes → Use CLI approach
│ ├── Claude Desktop → Update claude_desktop_config.json
│ ├── Claude Code → Use `claude mcp add` command
│ └── Custom client → Use stdio connection
└── No → Use HTTP approach
├── Existing Express app → Use Express middleware
├── New microservice → Use standalone server
└── Testing → Use MCP Inspector
```
### Transport Mode Decision Matrix
| Transport | Use Case | Pros | Cons | Best For |
|-----------|----------|------|------|----------|
| **stdio** | AI model integration | Simple, secure, no network config | Single process, local only | Claude Desktop, Claude Code, development |
| **HTTP** | Web applications | Multi-user, remote access, familiar | Network setup, security concerns | Production APIs, microservices |
| **WebSocket** | Real-time updates | Bi-directional, low latency | Complex setup, connection management | Streaming, live data |
**stdio** is the recommended transport for AI model integration because:
- ✅ **Security**: No network exposure or authentication needed
- ✅ **Simplicity**: Direct process communication
- ✅ **Performance**: Lower overhead than HTTP
- ✅ **Reliability**: No network connectivity issues
- ✅ **Lifecycle**: Automatic process management
## Troubleshooting
### Common Issues
#### 1. Import Path Errors
```bash
# ❌ Error: Cannot find module 'openapi-mcp-bridge/express'
import { createExpressMiddleware } from 'openapi-mcp-bridge/express';
# ✅ Solution: Use the correct package exports
import { createExpressMiddleware } from 'openapi-mcp-bridge/express';
```
**Root Cause**: Package uses ES modules. Ensure your `package.json` has `"type": "module"`.
#### 2. "Cannot POST /mcp" Error
```bash
# ❌ Wrong: Trying to make HTTP requests to MCP endpoint
curl -X POST http://localhost:3000/mcp
# ✅ Right: Use MCP Inspector or MCP client
mcp-inspector http://localhost:3000/mcp
```
**Root Cause**: MCP is not a REST API. It uses JSON-RPC over stdio/WebSocket.
#### 3. Port Conflicts
```bash
# ❌ Error: EADDRINUSE: address already in use :::3000
npm start
# ✅ Solution: Use a different port
PORT=3001 npm start
# or
npx openapi-mcp-bridge --definitions . --port 3001
```
#### 4. CLI Warnings
```bash
# ❌ Warning: --port is not yet implemented in stdio mode
openapi-mcp-bridge --definitions . --port 3000
# ✅ Solution: Don't use --port with CLI (stdio mode)
openapi-mcp-bridge --definitions .
```
**Root Cause**: CLI runs in stdio mode for MCP clients. Use standalone server for HTTP mode.
#### 5. Module Import Issues
```typescript
// ❌ CommonJS in ES module project
const { createExpressMiddleware } = require('openapi-mcp-bridge/express');
// ✅ ES modules syntax
import { createExpressMiddleware } from 'openapi-mcp-bridge/express';
```
**Setup for TypeScript projects**:
```json
// package.json
{
"type": "module",
"scripts": {
"start": "tsx src/server.ts"
}
}
```
```json
// tsconfig.json
{
"compilerOptions": {
"module": "ES2022",
"moduleResolution": "node",
"target": "ES2022",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
}
}
```
### Debug Mode
Enable detailed logging:
```bash
# CLI
openapi-mcp-bridge --definitions . --debug
# Environment variable
DEBUG=true openapi-mcp-bridge --definitions .
# Programmatic
const config = {
logging: { consoleFallback: true },
debug: true
};
```
### Validation Issues
```bash
# Check if OpenAPI file is valid
npx @redocly/cli lint your-api.yaml
# Force cache regeneration
OPENAPI_FORCE_REGEN=true openapi-mcp-bridge --definitions .
# Test tool generation
mcp-inspector npx openapi-mcp-bridge --definitions .
```
## Advanced Usage
### Express Integration
```typescript
// server.ts
import express from 'express';
import { createExpressMiddleware } from 'openapi-mcp-bridge/express';
const app = express();
// Add MCP endpoint
app.use('/mcp', createExpressMiddleware({
definitionsDirectory: './api-definitions',
defaultCredentials: {
username: process.env.API_USERNAME,
password: process.env.API_PASSWORD
}
}));
// Add health check
app.get('/health', (req, res) => {
res.json({ status: 'healthy' });
});
app.listen(3000, () => {
console.log('MCP server: http://localhost:3000/mcp');
});
```
### Standalone Server
```typescript
import { MCPServer } from 'openapi-mcp-bridge';
const server = new MCPServer({
definitionsDirectory: './api-definitions',
port: 3000,
mountPath: '/mcp',
defaultCredentials: {
username: process.env.API_USERNAME,
password: process.env.API_PASSWORD
}
});
await server.start();
console.log('MCP server running on http://localhost:3000/mcp');
```
### Configuration
```typescript
interface Config {
definitionsDirectory: string;
cacheDirectory?: string;
defaultCredentials?: {
username?: string;
password?: string;
token?: string;
apiKey?: string;
};
logging?: {
winston?: any;
pino?: any;
consoleFallback?: boolean;
};
mcpOptions?: {
serverName?: string;
serverVersion?: string;
};
}
```
## 🏷️ Tool Naming & Discoverability
### Naming Patterns
The library generates predictable tool names from OpenAPI operations:
| OpenAPI Operation | Generated Tool Name | Rule |
|-------------------|-------------------|------|
| `GET /museum-hours` with `operationId: getMuseumHours` | `getMuseumHours` | Uses operationId when available |
| `POST /special-events` with `operationId: createSpecialEvent` | `createSpecialEvent` | Uses operationId when available |
| `GET /events/{eventId}` | `get-events-by-eventId` | Auto-generated: `{method}-{path}-by-{param}` |
| `DELETE /tickets/{ticketId}` | `delete-tickets-by-ticketId` | Auto-generated: `{method}-{path}-by-{param}` |
| `PATCH /users/{userId}/profile` | `patch-users-by-userId-profile` | Auto-generated: handles nested paths |
### Custom Tool Names
Override generated names using customization:
```yaml
# museum-api.custom.yaml
toolAliases:
"getMuseumHours": "get-hours"
"createSpecialEvent": "create-event"
"get-events-by-eventId": "get-event-details"
```
### Tool Discovery
List available tools programmatically:
```bash
# Using MCP Inspector
mcp-inspector npx openapi-mcp-bridge --definitions ./api-definitions
# In Claude Code
"What tools are available?"
# In Claude Desktop
"List all museum API tools"
```
## 📁 Project Structure
```
your-project/
├── api-definitions/
│ ├── museum-api.yaml # OpenAPI specification
│ ├── museum-api.custom.yaml # Optional customization
│ └── .cache/ # Auto-generated cache
├── src/
│ └── server.ts # Your server code
├── package.json # {"type": "module"}
└── tsconfig.json # ES2022 modules
```
## 🔐 Authentication
Supports HTTP Basic, Bearer tokens, and API keys:
```yaml
# museum-api.custom.yaml
authenticationOverrides:
- endpoint: "*"
credentials:
username: "${API_USERNAME}"
password: "${API_PASSWORD}"
```
## 🧪 Testing
```bash
# Test tool generation
npm install -g @modelcontextprotocol/inspector
mcp-inspector npx openapi-mcp-bridge --definitions ./api-definitions
# Validate OpenAPI specs
npx @redocly/cli lint api-definitions/*.yaml
# Test with real API calls
node -e "
import { MCPClient } from '@modelcontextprotocol/client';
// ... client code
"
```
## 📝 Examples
- [Express Integration](examples/express-integration/)
- [Standalone Server](examples/standalone-server/)
- [CLI Usage](examples/cli-usage/)
- [Claude Desktop Setup](examples/claude-desktop/)
- [Claude Code Integration](examples/claude-code/)
- [Complete Museum API](examples/museum-api/)
## 🤝 Contributing
1. Fork the repository
2. Create a feature branch
3. Add tests for new functionality
4. Ensure all tests pass
5. Submit a pull request
## 📄 License
MIT License - see [LICENSE](LICENSE) file for details.
## 🙏 Acknowledgments
- [Model Context Protocol](https://modelcontextprotocol.io) for the MCP specification
- [OpenAPI Initiative](https://www.openapis.org/) for the OpenAPI specification
- [ReadMe OpenAPI Parser](https://github.com/readmeio/oas) for robust OpenAPI parsing
---
**Need help?** Check our [troubleshooting guide](#troubleshooting) or [open an issue](https://github.com/ephrin/openapi-mcp-bridge/issues).TDQS
B3.1/5.0
Scored across 8 tools
Disambiguation5/5
Each tool targets a distinct function: CRUD for events, listing hours, and ticket operations. No overlap between tools.
Naming Consistency5/5
All tool names follow a consistent verb_noun pattern with underscores, e.g., update-event, list-museum-hours, buy-tickets.
Tool Count5/5
8 tools is well-scoped for a museum domain covering events, hours, and ticket purchase/QR retrieval.
Completeness4/5
Events have full CRUD, museum hours listed, tickets covered for purchase and QR. Missing cancellation or history of tickets, but core is complete.
Maintenance
ActivityInactive
ResponsivenessNo issues