# Berlin Transport MCP Server

An MCP server that provides access to Berlin's public transport data through the VBB (Verkehrsverbund Berlin-Brandenburg) API. This server wraps the [v6.vbb.transport.rest](https://v6.vbb.transport.rest/) API.

This server uses [Code Mode](https://developers.cloudflare.com/agents/tools/codemode/): instead of exposing one MCP tool per API operation, the VBB API is described as an OpenAPI spec and the server exposes exactly two tools, `search` and `execute`. The model reads the spec, then writes and runs a short JavaScript snippet in a sandboxed [Dynamic Worker](https://developers.cloudflare.com/dynamic-workers/) to call the API — which scales far better than dumping every tool schema into the model's context window, and lets it chain multiple calls (e.g. search a stop, then fetch its departures) in a single sandbox run.

## Get started

```bash
npm install
npm run dev
```

This starts a local server at `http://localhost:8787/mcp`.

```bash
npm run deploy
```

This deploys the Worker to a URL like: `berlin-transport-mcp.<your-account>.workers.dev/mcp`.

## Available Tools

- **`search`** — Search the OpenAPI spec (`codemode.spec()`) to discover available operations, parameters, and response shapes before calling the API.
- **`execute`** — Run a short async JavaScript snippet that calls `codemode.request({ method, path, query })` against the VBB API. The host proxies the actual HTTP request; the sandbox has no direct network access.

### Underlying API operations

The OpenAPI spec exposed to the model covers:

- **`getLocations`** (`GET /locations`) — search for stops, stations, addresses, and points of interest.
- **`getDepartures`** (`GET /stops/{id}/departures`) — upcoming departures for a stop.
- **`getJourneys`** (`GET /journeys`) — journey options between an origin and a destination.

For more details about the underlying API, visit [v6.vbb.transport.rest/getting-started.html](https://v6.vbb.transport.rest/getting-started.html).

## Customizing your MCP Server

The OpenAPI spec passed to `openApiMcpServer` and the `request` proxy function both live in `src/index.ts`. To wrap a different API:

1. Update `API_ORIGIN` and `openApiSpec` with the new API's paths/operations.
2. Adjust the `request` function if the upstream API needs different methods, auth headers, or response handling.

## Connect to Cloudflare AI Playground

You can connect to your MCP server from the Cloudflare AI Playground, which is a remote MCP client:

1. Go to https://playground.ai.cloudflare.com/
2. Enter your deployed MCP server URL (`berlin-transport-mcp.<your-account>.workers.dev/mcp`)
3. You can now use the `search` and `execute` tools directly from the playground!

## Connect Claude Desktop to your MCP server

You can also connect to your remote MCP server from local MCP clients, by using the [mcp-remote proxy](https://www.npmjs.com/package/mcp-remote).

To connect to your MCP server from Claude Desktop, follow [Anthropic's Quickstart](https://modelcontextprotocol.io/quickstart/user) and within Claude Desktop go to Settings > Developer > Edit Config.

Update with this configuration:

```json
{
  "mcpServers": {
    "berlin-transport": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://berlin-transport.mcp-tools.app/mcp"  // or if local http://localhost:8787/mcp
      ]
    }
  }
}
```

Restart Claude and you should see the `search` and `execute` tools become available.
