fitbro-mcp-server
by simo21-ss
README.md
# fitbro-mcp-server
A [Model Context Protocol](https://modelcontextprotocol.io/) server giving Claude (and other MCP
clients) **read-only** access to a running FitBro local environment: Postgres, the app's logs,
WireMock's logs, the automation suite's logs — plus an on-demand Cucumber run.
Runs as a sidecar in the [FitBroLocal](../FitBroLocal) stack on port **8418**, serving
`http://localhost:8418/mcp`.
## What it exposes
| Tool | Purpose |
|---|---|
| `fitbro_pg_list_schemas` | List non-system schemas |
| `fitbro_pg_list_tables` | List tables in a schema |
| `fitbro_pg_describe_table` | Columns, types, constraints |
| `fitbro_pg_query` | Read-only SELECT (auto-LIMIT, `SET TRANSACTION READ ONLY`) |
| `fitbro_app_logs` | Spring app logs (Docker socket, host-file fallback for IDE runs) |
| `fitbro_wiremock_logs` | WireMock verbose logs — every request, match and response |
| `fitbro_postgres_logs` | Postgres container logs |
| `fitbro_tests_logs` | Automation suite logs (host file only) |
| `fitbro_liquibase_logs` | `fitbro_app_logs` filtered to lines mentioning `liquibase` |
| `fitbro_run_cucumber` | Run the automation suite in the test-runner container |
All log tools accept `tail`, `since` (ISO 8601), `until` and `grep` (case-insensitive substring).
Rotated archives (`*.YYYY-MM-DD.log.gz`) are decompressed and included when `since` reaches back.
## Running it
It is a service of the FitBroLocal stack, which builds this repo by path — the repos must sit side
by side:
```bash
cd ../FitBroLocal/docker && ./run.sh up
```
Then register it once with Claude Code:
```bash
claude mcp add --transport http fitbro-mcp-local http://localhost:8418/mcp
```
## Configuration
Everything is environment variables, set by FitBroLocal's compose file. The defaults assume that
stack.
| Variable | Default | Notes |
|---|---|---|
| `POSTGRES_HOST` / `PORT` / `USER` / `PASSWORD` / `DB` | `postgres` / `5432` / `fitbro_user` / `fitbro_password` / `fitbro` | Reached over the Compose network, so the *service* name |
| `FITBRO_APP_CONTAINER` | `fitbro-local-fitbro-1` | Container name, resolved through the Docker socket |
| `FITBRO_WIREMOCK_CONTAINER` | `fitbro-local-wiremock-1` | |
| `FITBRO_POSTGRES_CONTAINER` | `fitbro-local-postgres-1` | |
| `FITBRO_TEST_RUNNER` | `fitbro-local-fitbro-test-runner-1` | |
| `FITBRO_AUTOMATION_TASK` | `test` | Gradle task run in the test runner |
The container names are Compose-generated (`<project>-<service>-<n>`) rather than pinned, because a
bare `container_name: postgres` collides with every other stack on the machine. If you rename the
Compose project, these have to move with it.
## How logs reach it
The app and the suite write to `~/fitbro-logs/<app>/<app>.log` through their logback configs;
WireMock writes there too via the config FitBroLocal bind-mounts. This container gets `~/fitbro-logs`
mounted read-only at `/host-logs`, so each tool has two routes:
| Service | In Docker | On the host (IDE run) |
|---|---|---|
| Spring app | Docker socket | `~/fitbro-logs/fitbro-application/fitbro-application.log` |
| WireMock | Docker socket | `~/fitbro-logs/fitbro-wiremock-application/wiremock.log` |
| Automation suite | n/a — it runs on the host | `~/fitbro-logs/fitbro-tests-application/…` |
| Postgres | Docker socket | n/a |
## Implementation note
Built on the MCP Python SDK **2.x** (`MCPServer`). Tool schemas are derived from the function
signatures, and the SDK serves streamable HTTP itself — there is no Starlette or uvicorn wiring here.
## Scope
Local development only. It is read-only by construction — `fitbro_pg_query` opens a read-only
transaction and rolls back — but it exposes a database and a Docker socket, so it has no business
anywhere but a developer's machine. There is no auth on the endpoint.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing