Files
ag-bids-mcp/README.md
T
justin e78733d55e Drop in-container auth — MetaMCP guards the user-facing edge
The MCP's port 8000 isn't exposed outside the private mcp-servers_mcp
Docker network, so only the MetaMCP gateway can ever reach it. MetaMCP
itself enforces auth at the gateway → MCP-client edge (bearer token in
its UI), which is the right layer for it. In-container Basic/Bearer was
defense-in-depth that turned out to be friction-in-depth.

Removed:
  - ag_bids_mcp/auth.py (HTTP Basic middleware)
  - tests/test_auth.py (3 tests covering the middleware)
  - AG_BIDS_MCP_USER / AG_BIDS_MCP_PASS env vars from .env.example, README,
    docker-compose.snippet.yml, and deploy/README.md

Server.py simplified — direct `mcp.run(transport=...)` like zerto-docs-mcp,
no Starlette wrapping. 21 tests passing.

Live on 192.168.0.2: container recreated, real MCP initialize handshake
returns 200 + capability metadata over the mcp-servers_mcp network with
no auth header.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 16:05:41 -04:00

85 lines
2.8 KiB
Markdown

# ag-bids-mcp
Model Context Protocol server exposing live + historical commodity price data
collected by [ag-monitor](https://git.jpaul.io/justin/ag-bids). Sits behind
the user's MetaMCP gateway at `https://mcp.jpaul.io/metamcp/ag-bids/mcp`.
## What it does
Lets an LLM client (Claude Desktop, OpenWebUI, anything that speaks MCP) ask
plain-English questions like:
- "What's the best place to sell corn today?"
- "What's the current price of lime?"
- "Show me the corn basis trend at Andersons Greenville over the last 30 days."
- "Which sources are stale or failing?"
## How it talks to data
All data is read from ag-monitor over HTTPS:
```
ag-bids-mcp ── X-API-Key ─► https://agbids.paul.farm/api/data/*
```
Endpoints used: `/api/data/latest`, `/history`, `/best`, `/inputs`, `/sources`,
`/deliveries`. See the [ag-monitor source](https://git.jpaul.io/justin/ag-bids)
for the contract.
## Authentication
**No in-container auth.** The MCP's port 8000 is never exposed outside the
private `mcp-servers_mcp` Docker network on `.0.2`. The only client that
can reach it is MetaMCP, and MetaMCP enforces auth at the gateway → client
edge (bearer token / OAuth in its UI).
This matches the zerto-docs-mcp pattern.
## Local dev (stdio)
```bash
python3 -m venv venv && source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # fill in AG_BIDS_API_KEY + AG_BIDS_MCP_USER/PASS
MCP_TRANSPORT=stdio python -m ag_bids_mcp.server
```
Wire into Claude Desktop's `claude_desktop_config.json`:
```json
{
"mcpServers": {
"ag-bids": {
"command": "/path/to/venv/bin/python",
"args": ["-m", "ag_bids_mcp.server"],
"env": {
"MCP_TRANSPORT": "stdio",
"AG_BIDS_API_URL": "https://agbids.paul.farm",
"AG_BIDS_API_KEY": "..."
}
}
}
}
```
## Deploy (MetaMCP host)
See [deploy/README.md](deploy/README.md). Container image is pulled from
`git.jpaul.io/justin/ag-bids-mcp:latest`; Watchtower on the MetaMCP host
auto-updates it every 5 minutes.
## Tools exposed
| Tool | Returns |
|---|---|
| `best_local_bid(commodity)` | Where to sell `corn`, `soy`, or `wheat` for this month's delivery — markdown one-liner + table |
| `current_lime_price()` | Latest lime quotes across all manual-entry sources |
| `current_input_price(product?)` | MAP / Potash / Lime — all three or one |
| `latest_prices(commodity?, source?, delivery?)` | Snapshot table, optionally filtered |
| `price_history(commodity, source?, delivery?, days?)` | Compact time series |
| `list_sources()` | Active scrapers + last-success timestamps |
| `list_commodities()` | corn, soy, wheat, map, potash, lime |
| `list_deliveries(commodity)` | Posted delivery labels, chronological |
| `source_health()` | Stale / failing / healthy summary |
| `todays_summary()` | Same shape as the morning brief snapshot |