Public API MCP Server
by ampeco
README.md
# Public API MCP Server
An MCP (Model Context Protocol) server that dynamically exposes a public API defined by an OpenAPI 3 specification.
## Quick Start
### Development (Stdio Mode)
```bash
# One-liner to add dev server (with hot reload)
claude mcp add --transport stdio ampeco-api-dev \
--env AMPECO_BEARER_TOKEN=your-token-here \
-- bash -c "cd /absolute/path/to/public-api-mcp && npm run dev:stdio"
```
### Production (via NPX)
```bash
# One-liner to add production server
claude mcp add --transport stdio ampeco-api \
--env AMPECO_BEARER_TOKEN=your-token-here \
-- npx -y @ampeco/public-api-mcp --stdio --hostname https://api.example.com
```
### HTTP Mode (Remote Server)
```bash
# Start the server first
PORT=3001 npm run dev:http
# Then add to Claude Code
claude mcp add --transport http ampeco-api \
http://localhost:3001/api.example.com \
--header "Authorization: Bearer your-token-here"
```
See [Setting Up with Claude Code](#setting-up-with-claude-code) for detailed instructions and troubleshooting.
## Overview
This project transforms OpenAPI specifications into optimized, self-contained API definitions that can be served through the Model Context Protocol. It features a sophisticated build pipeline that processes OpenAPI specs at build time to minimize runtime overhead and reduce token usage.
## Usage
### Running the Build Pipeline
```bash
# Install dependencies
npm install
# Run the build pipeline with default path
npm run build
# Run the build pipeline with custom OpenAPI spec path
OPENAPI_SPEC_PATH=/path/to/your/openapi.yaml npm run build
# Or set it as an environment variable for multiple commands
export OPENAPI_SPEC_PATH=/path/to/your/openapi.yaml
npm run build
npm run dev
```
The build script:
1. Parses the OpenAPI spec from the specified path
2. Processes all endpoints through the optimization pipeline
3. Generates Zod schemas for runtime validation
4. Outputs optimized artifacts to `src/generated/`
**Configuration Options:**
- **`OPENAPI_SPEC_PATH`**: Path to the OpenAPI YAML/JSON file (relative or absolute)
- Can be set as an environment variable or passed directly to npm commands
- Used by both `npm run build` and `npm run dev`
### Development
```bash
# Type check without building
npm run type-check
# Run in development mode (build + start server)
npm run dev
```
## Architecture
### Build-Time Pipeline
```
OpenAPI Spec
↓
[Parser] Bundle & Resolve References
↓
[Extractor] Extract Endpoints & Security
↓
[Flattener] Flatten Schemas (allOf, nested objects)
↓
[Optimizer] Minify & Optimize
↓
[Zod Generator] Generate Validation Schemas
↓
Generated Artifacts (endpoints.json, schemas.ts)
```
### MCP Server
The server provides a complete MCP implementation for accessing your OpenAPI-defined API:
- **Dual Transport Support**: Both Stdio (local) and HTTP (remote) transports
- **Flexible Resource Mode**: Native MCP resources OR tool-based emulation for Claude Desktop compatibility
- **Dynamic Resources**: All API endpoints exposed as MCP resources with full schema details
- **API Request Tool**: Fully typed `api_request` tool with automatic authentication and parameter validation
- **Stateless Architecture**: No session state required - all parameters provided per request
- **Zero Configuration**: Pre-processed data loads instantly, no config files needed
- **MCP Protocol Compliance**: Full implementation of MCP Streamable HTTP transport specification
#### Resource Modes
The server supports two modes for exposing API endpoints:
1. **Native Resources Mode** (Default): Uses native MCP resources for endpoint discovery
- Best for: MCP clients that fully support the resources capability
- Features: Hierarchical 3-tier navigation (tags → endpoints → details)
2. **Tool Emulation Mode**: Exposes resources through tools (`list_resources`, `read_resource`)
- **Required for Claude Desktop** (does not support native MCP resources)
- Provides identical functionality through tool-based interface
- Enable with `--emulate-resources-via-tools` flag
### Running the Server
```bash
# Development mode (rebuild + start server)
npm run dev
# Production mode
npm run build # First time only
npm start
# Custom port
PORT=3001 npm run dev
```
### Server Endpoints
The server uses a hostname-based routing structure where the target API hostname is embedded in the URL path:
- **`GET /health`**: Health check and server statistics
- **`POST /{hostname}[/{protocol}]`**: MCP protocol endpoint with hostname routing
- `{hostname}`: Target API hostname (e.g., `api.example.com`)
- `{protocol}`: Optional protocol (`http` or `https`, defaults to `https`)
**Examples:**
- `POST /api.example.com` → Routes to `https://api.example.com`
- `POST /api.example.com/https` → Routes to `https://api.example.com`
- `POST /api.example.com/http` → Routes to `http://api.example.com`
- `POST /internal.api.company.com/http` → Routes to `http://internal.api.company.com`
## Setting Up with Claude Desktop
**IMPORTANT**: Claude Desktop **does not support native MCP resources**. You **MUST** use the `--emulate-resources-via-tools` flag for Claude Desktop.
### Installation via Desktop Extension (.mcpb)
The easiest way to install this MCP server in Claude Desktop is using the Desktop Extension bundle:
#### Option 1: From Official Directory (Recommended)
1. Open Claude Desktop
2. Go to **Settings** → **Extensions**
3. Click **"Browse extensions"**
4. Search for **"AMPECO Public API"**
5. Click **Install** and follow the configuration prompts
#### Option 2: Manual Installation
1. Download the latest `.mcpb` file from the [releases page](https://github.com/ampeco/public-api-mcp/releases)
2. Open Claude Desktop
3. Go to **Settings** → **Extensions**
4. Click **"Install Extension..."**
5. Select the downloaded `.mcpb` file
6. Configure the required settings:
- **API Hostname**: Your AMPECO API server (e.g., `https://api.example.com`)
- **Bearer Token**: Your AMPECO API authentication token
The extension will automatically operate in resource emulation mode for Claude Desktop compatibility.
### Manual Configuration (Advanced)
If you prefer manual configuration or want to customize the setup:
### Claude Desktop Configuration
Claude Desktop uses a configuration file called `claude_desktop_config.json` located at:
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
You can also access this file through Claude Desktop: **Settings** → **Developer** → **Edit Config**
### Configuration Example
Add this to your `claude_desktop_config.json`:
```json
{
"mcpServers": {
"ampeco-api": {
"command": "npx",
"args": [
"-y",
"@ampeco/public-api-mcp",
"--stdio",
"--hostname",
"https://api.example.com",
"--emulate-resources-via-tools"
],
"env": {
"AMPECO_BEARER_TOKEN": "your-token-here"
}
}
}
}
```
**Replace**:
- `https://api.example.com` with your actual API hostname
- `your-token-here` with your bearer token
**After editing the file**, restart Claude Desktop for changes to take effect
### What is Tool Emulation Mode?
When `--emulate-resources-via-tools` is enabled, the server provides two additional tools:
1. **`list_resources`**: Discover available API tags (e.g., Users, ChargingSessions)
- No parameters required
- Returns list of tags that group related endpoints
2. **`read_resource`**: Read endpoint definitions by URI
- Parameter: `uri` (e.g., `tag://Users` or `api://GET/users/{id}`)
- Returns full endpoint specification
These tools provide **identical functionality** to native MCP resources but work through the tools interface that Claude Desktop supports.
### Tool Schemas (Emulation Mode)
When `--emulate-resources-via-tools` is enabled, the following tools are available:
#### `list_resources` Tool
**Description**: List all available API tags. This emulates the native MCP resources/list functionality. Returns a list of tags that group related endpoints together (e.g., Users, ChargingSessions, Connectors). Each tag can then be read using the read_resource tool with tag:// URIs.
**Parameters**: None
**Returns**: JSON object with `resources` array containing:
```json
{
"resources": [
{
"uri": "tag://Users",
"name": "Users",
"description": "15 endpoints tagged with 'Users'",
"mimeType": "application/json"
},
{
"uri": "tag://ChargingSessions",
"name": "ChargingSessions",
"description": "8 endpoints tagged with 'ChargingSessions'",
"mimeType": "application/json"
}
]
}
```
**Example Usage**:
```
Call list_resources tool → Get list of all API tags
```
#### `read_resource` Tool
**Description**: Read a specific resource by URI. This emulates the native MCP resources/read functionality. Supports two URI formats: tag://{TagName} to read all endpoints within a tag, and api://{METHOD}{path} to read detailed endpoint specifications. You MUST use this tool to read endpoint definitions before calling api_request.
**Parameters**:
- `uri` (string, required): The resource URI to read
- Format: `tag://{TagName}` or `api://{METHOD}{path}`
- Examples: `"tag://Users"`, `"api://GET/users/{id}"`, `"api://POST/charging-sessions"`
**Returns** (for tag URIs):
```json
{
"tag": "Users",
"count": 15,
"endpoints": [
{
"uri": "api://GET/users/{id}",
"method": "GET",
"path": "/users/{id}",
"summary": "Get user by ID",
"operationId": "getUser"
}
]
}
```
**Returns** (for api URIs):
```json
{
"path": "/users/{id}",
"method": "GET",
"operationId": "getUser",
"summary": "Get user by ID",
"description": "Retrieves detailed information about a specific user",
"parameters": [...],
"requestBody": {...},
"responses": {...},
"security": "Include token in Authorization header as: Authorization: Bearer <token>"
}
```
**Example Usage**:
```
1. Call read_resource with uri="tag://Users" → Get all endpoints in Users tag
2. Call read_resource with uri="api://GET/users/{id}" → Get full endpoint specification
3. Call api_request with correct parameters → Make the actual API call
```
### When to Use Each Mode
| Mode | Use For | Clients |
|------|---------|---------|
| **Native Resources** (default) | MCP clients that fully support resources | **Claude Code**, MCP Inspector |
| **Tool Emulation** (`--emulate-resources-via-tools`) | Clients without resource support | **Claude Desktop** |
**Important Distinction**:
- **Claude Code** (the CLI tool): Supports native MCP resources - use **default mode**
- **Claude Desktop** (the desktop app): Does NOT support resources - use **`--emulate-resources-via-tools`**
**Rule of thumb**: If you're using **Claude Desktop**, always add `--emulate-resources-via-tools`. If using **Claude Code**, use default mode.
## Setting Up with Claude Code
The MCP server supports two transport modes:
1. **Stdio Mode (Recommended)**: Direct process communication for local development and production
2. **HTTP Mode**: Remote server access via HTTP transport
### Stdio Mode (Local Development)
For development with hot reloading and build integration:
#### Option 1: One-Liner (Recommended)
```bash
# Add dev server with a single command
claude mcp add --transport stdio ampeco-api-dev \
--env AMPECO_BEARER_TOKEN=your-token-here \
-- bash -c "cd /absolute/path/to/public-api-mcp && npm run dev:stdio"
```
**Replace**:
- `/absolute/path/to/public-api-mcp` with your actual project path
- `your-token-here` with your API token
**Features**:
- Automatically creates `.mcp.json` configuration
- Rebuilds on each start for hot reloading
- All build output redirected to stderr (clean protocol)
#### Option 2: Manual Configuration
If you prefer to manually edit configuration files:
1. **Set environment variable** (optional, for substitution):
```bash
export AMPECO_BEARER_TOKEN="your-token-here"
source ~/.bashrc # or ~/.zshrc
```
2. **Create `.mcp.json` in project root**:
```json
{
"mcpServers": {
"ampeco-api-dev": {
"type": "stdio",
"command": "bash",
"args": ["-c", "cd /absolute/path/to/public-api-mcp && npm run dev:stdio"],
"env": {"AMPECO_BEARER_TOKEN": "${AMPECO_BEARER_TOKEN}"}
}
}
}
```
3. **Reload**: Claude Code will auto-detect the configuration
### Stdio Mode (Production via NPX)
For production use without needing the source code:
#### Option 1: One-Liner (Recommended)
```bash
# Add production server with a single command (native resources)
claude mcp add --transport stdio ampeco-api \
--env AMPECO_BEARER_TOKEN=your-token-here \
-- npx -y @ampeco/public-api-mcp --stdio --hostname https://api.example.com
# With tool emulation mode (if client doesn't support resources)
claude mcp add --transport stdio ampeco-api \
--env AMPECO_BEARER_TOKEN=your-token-here \
-- npx -y @ampeco/public-api-mcp --stdio --hostname https://api.example.com --emulate-resources-via-tools
```
**Replace**:
- `your-token-here` with your API token
- `https://api.example.com` with your target API hostname
**Features**:
- NPX downloads and caches the package automatically
- No source code or build required
- Works from any directory
- Add `--emulate-resources-via-tools` for Claude Desktop compatibility
#### Option 2: Manual Configuration
Create `.mcp.json` in your project or home directory:
**Native Resources Mode**:
```json
{
"mcpServers": {
"ampeco-api": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@ampeco/public-api-mcp",
"--stdio",
"--hostname",
"https://api.example.com"
],
"env": {
"AMPECO_BEARER_TOKEN": "your-token-here"
}
}
}
}
```
**Tool Emulation Mode** (for Claude Desktop):
```json
{
"mcpServers": {
"ampeco-api": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@ampeco/public-api-mcp",
"--stdio",
"--hostname",
"https://api.example.com",
"--emulate-resources-via-tools"
],
"env": {
"AMPECO_BEARER_TOKEN": "your-token-here"
}
}
}
}
```
**Using environment variables** (more secure):
```bash
export AMPECO_BEARER_TOKEN="your-token-here"
```
Then use `"${AMPECO_BEARER_TOKEN}"` in the JSON config.
### Stdio Mode (Production via Global Install)
For faster startup without NPX overhead:
#### 1. Install Globally
```bash
npm install -g @ampeco/public-api-mcp
```
#### 2. Add to Claude Code (One-Liner)
```bash
# Add globally installed server (native resources)
claude mcp add --transport stdio ampeco-api \
--env AMPECO_BEARER_TOKEN=your-token-here \
-- ampeco-api-mcp --stdio --hostname https://api.example.com
# With tool emulation mode (for Claude Desktop)
claude mcp add --transport stdio ampeco-api \
--env AMPECO_BEARER_TOKEN=your-token-here \
-- ampeco-api-mcp --stdio --hostname https://api.example.com --emulate-resources-via-tools
```
**Or manual configuration** in `.mcp.json`:
**Native Resources Mode**:
```json
{
"mcpServers": {
"ampeco-api": {
"type": "stdio",
"command": "ampeco-api-mcp",
"args": ["--stdio", "--hostname", "https://api.example.com"],
"env": {"AMPECO_BEARER_TOKEN": "your-token-here"}
}
}
}
```
**Tool Emulation Mode** (for Claude Desktop):
```json
{
"mcpServers": {
"ampeco-api": {
"type": "stdio",
"command": "ampeco-api-mcp",
"args": [
"--stdio",
"--hostname",
"https://api.example.com",
"--emulate-resources-via-tools"
],
"env": {"AMPECO_BEARER_TOKEN": "your-token-here"}
}
}
}
```
### HTTP Mode (Remote Server)
For shared server access or when multiple clients need to connect:
#### 1. Start the Server
```bash
# Development mode (native resources)
PORT=3001 npm run dev:http
# Development mode (tool emulation)
PORT=3001 npm start -- --http --port 3001 --emulate-resources-via-tools
# Production mode (native resources)
npm run build # First time only
PORT=3001 npm start -- --http --port 3001
# Production mode (tool emulation)
npm run build # First time only
PORT=3001 npm start -- --http --port 3001 --emulate-resources-via-tools
```
#### 2. Add to Claude Code (One-Liner)
```bash
# Add HTTP server with a single command
claude mcp add --transport http ampeco-api \
http://localhost:3001/api.example.com \
--header "Authorization: Bearer your-token-here"
```
**With protocol override** (use HTTP for target API instead of HTTPS):
```bash
claude mcp add --transport http ampeco-api \
http://localhost:3001/api.example.com/http \
--header "Authorization: Bearer your-token-here"
```
**Or manual configuration** in `.mcp.json`:
```json
{
"mcpServers": {
"ampeco-api-http": {
"type": "http",
"url": "http://localhost:3001/api.example.com",
"headers": {"Authorization": "Bearer your-token-here"}
}
}
}
```
**Notes:**
- Server must be running before connecting
- Target API hostname is in the URL path
- Optional `/http` or `/https` suffix controls target API protocol
- Defaults to HTTPS if not specified
### Comparison: Stdio vs HTTP Mode
| Feature | Stdio Mode | HTTP Mode |
|---------|-----------|-----------|
| **Use Case** | Local development, single user | Remote access, multiple clients |
| **Setup Complexity** | Simple (just config file) | Requires running server |
| **Performance** | Faster (no HTTP overhead) | Slightly slower (HTTP latency) |
| **Security** | More secure (local only) | Network exposure (use HTTPS in prod) |
| **Hot Reload** | Yes (dev mode) | Requires server restart |
| **Multi-Client** | No (one client at a time) | Yes (concurrent clients) |
| **Memory Usage** | Lower (~30MB per instance) | Higher (~50MB + per-request) |
**Recommendation**: Use **stdio mode** for development and single-user production. Use **HTTP mode** for shared servers or when multiple clients need concurrent access.
### Troubleshooting
#### Stdio Mode Issues
**Problem**: Server not starting or connection fails
```bash
# List configured MCP servers
claude mcp list
# Check status
claude mcp status ampeco-api-dev
# Remove and re-add the server
claude mcp remove ampeco-api-dev
claude mcp add --transport stdio ampeco-api-dev \
--env AMPECO_BEARER_TOKEN=your-token \
-- bash -c "cd /path/to/public-api-mcp && npm run dev:stdio"
# Verify the command works standalone
cd /path/to/public-api-mcp
AMPECO_BEARER_TOKEN=your-token npm run dev:stdio
```
**Problem**: Build output interfering with protocol
- This is fixed in `dev:stdio` script which redirects build output to stderr
- For production, run `npm run build` first, then use the compiled CLI
**Problem**: Environment variables not loading
```bash
# Verify environment variable is set
echo $AMPECO_BEARER_TOKEN
# Reload shell configuration
source ~/.bashrc # or ~/.zshrc
```
#### HTTP Mode Issues
**Problem**: Server not accessible
```bash
# Test server health
curl http://localhost:3001/health
# Check if port is in use
lsof -i :3001
# Try a different port
PORT=3002 npm run dev:http
```
**Problem**: CORS errors
- The server has CORS enabled for all origins
- Check browser console for specific error messages
#### General Issues
**Problem**: Endpoints not loading
```bash
# Verify build artifacts exist
ls -la src/generated/
# Rebuild if needed
npm run build
```
**Problem**: Authentication errors
- Verify your `AMPECO_BEARER_TOKEN` is correct
- Check the token has proper permissions for the API
- Test the token directly with the API:
```bash
curl -H "Authorization: Bearer your-token" \
https://api.example.com/health
```
## Building Desktop Extension (.mcpb)
To package this MCP server as a Desktop Extension for distribution:
```bash
# Build and package as .mcpb
npm run package:mcpb
```
This creates a `.mcpb` file (e.g., `ampeco-api-mcp-0.3.0.mcpb`) that can be:
- Distributed to users for manual installation
- Submitted to the official Claude Desktop extensions directory
- Shared within your organization
The `.mcpb` file is a self-contained bundle including:
- Compiled server code (`dist/`)
- All dependencies (via `package.json`)
- Extension metadata (`manifest.json`)
- Documentation (`README.md`)
### What's Included in the Bundle
The Desktop Extension bundle operates in **resource emulation mode** by default, which means:
- Full compatibility with Claude Desktop (no native resource support needed)
- `list_resources` and `read_resource` tools for endpoint discovery
- `api_request` tool for making authenticated API calls
- Automatic token management via environment variables
Users only need to provide two configuration values during installation:
1. **API Hostname**: The AMPECO API server URL
2. **Bearer Token**: Their authentication token
## Technology Stack
### Runtime
- **Language**: TypeScript / Node.js (ES2022 modules)
- **Server**: Express
- **MCP SDK**: `@modelcontextprotocol/sdk`
- **HTTP Client**: `node-fetch`
- **Validation**: `zod`
### Build-Time
- **OpenAPI Parser**: `@readme/openapi-parser`
- **Build Tools**: tsx, TypeScript compiler
### Development
- **Type Checking**: TypeScript (strict mode)
- **Testing**: Vitest (planned)
## License
MIT
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessSyncing