proratia-mcp
by d3bn
README.md
# Proratia MCP Server (FastMCP + Docker)
A high-performance, containerized Model Context Protocol (MCP) server built with **FastMCP** (Python).
This server is a generic, bare-minimum MCP boilerplate for giving agents access to a locally running API's OpenAPI/Swagger spec, completely inside a Docker container. It is not tied to any specific backend—it auto-discovers whatever API is running locally, or repoint it via `.env` configuration, no code changes required.
No local runtimes (Python, Node, etc.) are required on the host machine—only Docker is required.
---
## Features
- **OpenAPI Spec Fetcher (`get_openapi_spec`)**: Fetches the Swagger/OpenAPI JSON spec from a locally running API. Requires no configuration or arguments—auto-discovers the API by probing common hosts/ports/paths.
- **Manual URL Override (`set_api_url`)**: If auto-discovery can't find the right API, save its spec URL directly. Persisted on a volume until you change or clear it.
- **Interactive Fallback**: On clients that support MCP elicitation, `get_openapi_spec` asks the user for the URL directly when discovery fails, and saves the answer automatically—no separate `set_api_url` call needed.
---
## Directory Structure
```text
proratia-mcp/
├── Dockerfile # Container configuration with unbuffered I/O
├── docker-compose.yml # Service compose definition for network (SSE) mode
├── .dockerignore # Build-context exclusions
├── .env.example # Template for local environment configuration
├── requirements.txt # Python dependencies (fastmcp, httpx, python-dotenv)
├── server.py # Main FastMCP server implementation
└── README.md # This guide
```
---
## 1. Quick Start: Build the Docker Image
Build the docker image locally using the terminal. Open a terminal in the `proratia-mcp` directory and run:
```bash
docker build -t proratia-mcp:latest .
```
### Configure the environment
Copy `.env.example` to `.env`:
```bash
cp .env.example .env
```
```env
MCP_PORT=8000
```
`MCP_PORT` is the only setting needed to get started—it controls which port the server listens on (and publishes) in SSE mode via `docker-compose`.
No API configuration is required: `get_openapi_spec` takes no arguments and auto-discovers a locally running API by probing common hosts/ports/paths. If you want to skip the scan for a faster/more reliable lookup, `.env.example` has commented-out variables (`API_BASE_URL`, `OPENAPI_PATH`, `API_HOST_HEADER`, and the `DISCOVERY_*` candidate-list overrides) you can uncomment as needed.
---
## 2. How to Use the MCP
Add this to your MCP client's `mcpServers` configuration (see [STDIO](#3-integration-with-llm-clients-stdio-mode) or [SSE](#4-running-as-a-network-service-sse-mode) below for client-specific instructions and options):
```json
{
"mcpServers": {
"proratia-mcp": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"--env-file",
"/absolute/path/to/proratia-mcp/.env",
"-v",
"proratia-mcp-data:/app/data",
"proratia-mcp:latest"
]
}
}
}
```
Once the server is connected to your client (STDIO or SSE—see the sections below), two tools are exposed: `get_openapi_spec` and `set_api_url`. Just ask your agent to fetch the API spec in plain language, e.g.:
> "Get the OpenAPI spec for the API running locally."
If auto-discovery can't find it, your client may prompt you for the URL directly (if it supports MCP elicitation)—just answer and it's remembered automatically. Otherwise, tell your agent the URL directly and it'll save it for you:
> "The API spec is at http://localhost:4000/swagger.json, use that from now on."
Example manual invocations (e.g. via [MCP Inspector](#5-testing-changes-with-mcp-inspector)):
```json
{
"tool": "get_openapi_spec",
"arguments": {}
}
```
```json
{
"tool": "set_api_url",
"arguments": { "url": "http://localhost:4000/swagger.json" }
}
```
See [Available Tools](#available-tools) below for details on how discovery works, how to hint it via `.env`, and how the saved URL persists.
---
## 3. Integration with LLM Clients (STDIO Mode)
In STDIO mode, the LLM client (e.g., Claude Desktop, Cursor, Cline, Agy, Windsurf, or any other MCP-compatible agent) launches the Docker container as a subprocess and communicates with it using `stdin` and `stdout`.
### A. Standard `mcpServers` JSON Configuration
Most MCP clients share the same `mcpServers` JSON schema, just in a client-specific config file. Add `proratia-mcp` there, making sure to pass the `-i` (interactive) flag so stdio streams stay open, and `--env-file` to load your `.env` configuration:
```json
{
"mcpServers": {
"proratia-mcp": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"--env-file",
"/absolute/path/to/proratia-mcp/.env",
"-v",
"proratia-mcp-data:/app/data",
"proratia-mcp:latest"
]
}
}
}
```
Common config file locations:
- **Claude Desktop (macOS)**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Claude Desktop (Windows)**: `%APPDATA%\Claude\claude_desktop_config.json`
- **Cursor**: `.cursor/mcp.json` (project-level) or global MCP settings
- **Other clients** (Agy, Cline, Windsurf, etc.): check that client's MCP documentation for its config file location—the `mcpServers` block itself is portable across all of them.
After saving, restart your client (or reload its MCP connections) to pick up the new server.
### B. GUI-Based Configuration
Some clients offer a settings UI instead of hand-editing JSON (e.g. Cursor):
1. Go to **Settings > Features > MCP** (or the equivalent in your client).
2. Click **+ Add New MCP Server**.
3. Fill out the fields:
- **Name**: `proratia-mcp`
- **Type**: `command`
- **Command**: `docker run -i --rm --env-file /absolute/path/to/proratia-mcp/.env -v proratia-mcp-data:/app/data proratia-mcp:latest`
4. Save and wait for the status indicator to turn green.
---
## 4. Running as a Network Service (SSE Mode)
If you prefer to run the server as a background service that clients connect to over HTTP (Server-Sent Events), you can use Docker Compose.
1. Start the service:
```bash
docker-compose up -d
```
2. The server will spin up and listen on the port set by `MCP_PORT` in your `.env` file (defaults to `8000`). You can configure your MCP clients to connect to `http://localhost:${MCP_PORT}/sse`.
To stop the service:
```bash
docker-compose down
```
---
## 5. Testing Changes with MCP Inspector
After modifying `server.py`, rebuild the image (`docker build -t proratia-mcp:latest .`) and use the official [MCP Inspector](https://github.com/modelcontextprotocol/inspector) to interactively call the tool and verify it behaves as expected before wiring it into an LLM client:
```bash
npx @modelcontextprotocol/inspector docker run -i --rm --env-file .env -v proratia-mcp-data:/app/data proratia-mcp:latest
```
This opens a local web UI where you can invoke `get_openapi_spec` (no arguments needed) or `set_api_url` and inspect the raw response.
---
## Available Tools
### 1. `get_openapi_spec`
Fetches the Swagger/OpenAPI JSON spec from a locally running API. Takes **no parameters**.
Tries, in order:
1. A URL saved via `set_api_url` (or a previous elicitation answer), if one was set.
2. `API_BASE_URL` (+ `OPENAPI_PATH`, `API_HOST_HEADER`), if set in `.env`, as a fast-path hint.
3. Full auto-discovery—probing combinations of `DISCOVERY_HOSTS`, `DISCOVERY_PORTS`, `DISCOVERY_PATHS`, and `DISCOVERY_HOST_HEADERS` (all with sane defaults, overridable in `.env`) and returning the first response containing an `openapi` or `swagger` key.
4. If the client supports [MCP elicitation](https://modelcontextprotocol.io/), asking the user for the URL directly and saving their answer for next time (same storage as `set_api_url`).
`API_HOST_HEADER` / `DISCOVERY_HOST_HEADERS` override the HTTP `Host` header independently of the connection address. Needed when the target sits behind a reverse proxy (e.g. Caddy, Nginx) that routes by virtual host.
### 2. `set_api_url`
Manually sets the OpenAPI/Swagger spec URL for `get_openapi_spec` to use, for when auto-discovery can't find the right API.
- **Parameters**:
- `url` (string, required): The full URL to the spec document, e.g. `"http://localhost:4000/openapi.json"`. Pass an empty string to clear the saved URL and revert to the `.env` hint / auto-discovery.
The value is written to `/app/data` inside the container and **persists across restarts** until changed or cleared again—see [Persisting the saved URL](#persisting-the-saved-url) below for the volume mount required to make this durable.
---
## Persisting the Saved URL
`set_api_url` writes to `/app/data/url.txt` inside the container. Without a mounted volume, this is lost the moment the container is removed (which happens on every call in STDIO mode, since it runs with `--rm`). To make it durable, mount a named volume at that path:
```bash
-v proratia-mcp-data:/app/data
```
This is already included in the `mcpServers` config examples and the Inspector command above, and in `docker-compose.yml` for SSE mode. Docker creates the named volume automatically on first use—no manual setup needed.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues