# Deploying `ag-bids-mcp` behind MetaMCP This runs on the **MetaMCP host (`192.168.0.2`)** as its **own standalone docker-compose project** — independent from the MetaMCP/zerto-docs stack but joining the same `mcp-servers_mcp` Docker network so MetaMCP can proxy to it by container DNS name (`http://ag-bids-mcp:8000/mcp`). The deploy lives in `/home/justin/ag-bids-mcp/` on `.0.2`. Watchtower (already running on the host) auto-pulls a new image every 5 min whenever a fresh `git.jpaul.io/justin/ag-bids-mcp:latest` is pushed. **No in-container auth.** Port 8000 is never exposed outside the private `mcp-servers_mcp` Docker network — only MetaMCP can reach it. MetaMCP enforces auth at the gateway → MCP-client edge (bearer token in its UI), which is the right layer for it. ## One-time setup (already done — kept for re-runs) ### 1. Pull the deploy snippet `docker-compose.snippet.yml` in this directory is the ENTIRE compose file for the deployment. Copy it to `/home/justin/ag-bids-mcp/docker-compose.yml` on `.0.2`. ### 2. Write the `.env` Create `/home/justin/ag-bids-mcp/.env` (mode 600) on `.0.2` with: ```ini AG_BIDS_API_URL=https://agbids.paul.farm AG_BIDS_API_KEY= AG_BIDS_API_TIMEOUT_SECS=20 ``` ### 3. Build + push the image On any dev machine with the Gitea registry login: ```bash cd ~/github/ag-bids-mcp docker login git.jpaul.io # use your Gitea PAT docker build -t git.jpaul.io/justin/ag-bids-mcp:latest . docker push git.jpaul.io/justin/ag-bids-mcp:latest ``` ### 4. Start the container on .0.2 ```bash ssh justin@192.168.0.2 cd ~/ag-bids-mcp docker compose pull docker compose up -d docker compose logs -f ag-bids-mcp # expect "starting ag-bids MCP on streamable-http://0.0.0.0:8000" ``` ### 5. Register the namespace in MetaMCP In the MetaMCP web UI at `https://mcp.jpaul.io`: 1. **Create namespace** → name: `ag-bids` 2. **Add upstream MCP server** to that namespace: - **Transport:** Streamable HTTP - **URL:** `http://ag-bids-mcp:8000/mcp` - **Bearer token:** leave blank (the upstream has no auth; MetaMCP enforces at the user-facing endpoint instead) 3. Save. Public endpoint becomes: **`https://mcp.jpaul.io/metamcp/ag-bids/mcp`** ## Smoke test From inside the `mcp-servers_mcp` network the MCP should respond to a real MCP `initialize` handshake: ```bash ssh justin@192.168.0.2 'docker run --rm --network mcp-servers_mcp curlimages/curl:latest \ -s -H "content-type: application/json" \ -H "accept: application/json, text/event-stream" \ -X POST http://ag-bids-mcp:8000/mcp \ -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"smoke\",\"version\":\"1\"}}}"' # expect: event: message ... "serverInfo":{"name":"ag-bids", ...} ``` Then in a real MCP client (Claude Desktop / OpenWebUI / etc.) configured against `https://mcp.jpaul.io/metamcp/ag-bids/mcp`, try: - **"What's the best place to sell corn today?"** → calls `best_local_bid("corn")` - **"What's the current price of lime?"** → calls `current_lime_price()` - **"Are any sources down?"** → calls `source_health()` ## Rotating the upstream API key To rotate the upstream API key: change `BRIEF_API_KEY` in ag-monitor's `.env` on `.0.126` + restart `api` there, then update `AG_BIDS_API_KEY` in `~/ag-bids-mcp/.env` on `.0.2` + `docker compose up -d`. ## Observability - Per-tool-call usage logs: `/home/justin/ag-bids-mcp/ag-bids-mcp-logs/usage-YYYY-MM-DD.jsonl` - Container stdout: `docker compose logs ag-bids-mcp`