Skip to main content
Glama
README.md
# internal-tools MCP server (MVP)

One hosted MCP server that maps internal API endpoints to agent tools, generated
from OpenAPI specs via [FastMCP](https://gofastmcp.com) `from_openapi()`. No
per-agent tool wrappers, no duplicated work across repos.

For the MVP it fronts a mock "build-metrics" FastAPI service in this repo; swap
`API_BASE_URL` to point at a real internal service.

## Run

```bash
uv sync

# terminal 1 — mock backend (port 8000)
uv run uvicorn mock_api.main:app --port 8000

# terminal 2 — MCP server (port 8001)
uv run python mcp_server/server.py
```

The MCP endpoint is `http://localhost:8001/mcp` (streamable HTTP).

## Connect an agent

Claude Code (this repo already has `.mcp.json`):

```json
{
  "mcpServers": {
    "internal-tools": { "type": "http", "url": "http://localhost:8001/mcp" }
  }
}
```

For a team deployment, host `mcp_server/server.py` on an internal box and point
the URL there — every agent gets the same toolset from one place.

## Point at a real service

```bash
API_BASE_URL=https://your-service.internal uv run python mcp_server/server.py
```

Requirements on the backend:
- serves its OpenAPI spec at `/openapi.json` (FastAPI does this out of the box;
  for non-FastAPI services, hand-write a minimal spec and load it from a file)
- good `operation_id`s and endpoint docstrings — they become tool names and
  descriptions, which is what the agent reasons over

Auth: add headers to the httpx client in `mcp_server/server.py`, e.g.
`httpx.AsyncClient(base_url=..., headers={"Authorization": f"Bearer {token}"})`.

## Curating the toolset

`route_maps` in `mcp_server/server.py` controls what gets exposed. The MVP
excludes `/admin/*` and anything tagged `internal`; everything else becomes a
tool. Add `RouteMap` entries (regex, HTTP method, or tag based) to include or
exclude endpoints as the toolset grows.

## Adding more backends later

The goal is one server, many services: fetch each service's spec, build a
`FastMCP.from_openapi()` server for it, and `mcp.mount(other, prefix="svc")`
them onto the main server so tools stay namespaced.

Maintenance

ActivityStale
ResponsivenessNo issues