# 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
