Files
ag-bids-mcp/README.md
claude 3bd9bf38ee
CI / test (pull_request) Successful in 17s
CI / build-push (pull_request) Has been skipped
docs(README): document include_expired on the latest snapshot
Follow-up to the expired-month filter — the API/tool table didn't mention
the new default (current + future only) or the include_expired opt-in.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 22:36:17 -04:00

102 lines
5.1 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."
- "How is basis moving overall this week?"
- "What's the July corn futures price and how far has it moved since the open?"
- "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`, `/futures`, `/best`, `/inputs`,
`/sources`, `/deliveries`, `/price-trend`, `/price-series`, `/price-geographies`,
`/input-cost-trend`, `/input-cost-series`, `/input-cost-geographies`. 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, zip?, lat?, lng?, radius_miles?)` | Where to sell `corn`/`soy`/`wheat` for this month's delivery. Optional location (zip **or** lat/lng + `radius_miles`, default 50) restricts to nearby elevators and shows distance; out-of-range returns the nearest-source hint |
| `futures_quote(commodity, delivery?)` | CBOT futures price + change since open + change on the day. With a delivery month it resolves the listed contract; without it, the continuous nearby |
| `current_lime_price()` | Latest lime quotes across all manual-entry sources |
| `current_input_price(product?)` | MAP / Potash / Lime — all three or one (local DTN dealer feed) |
| `price_trend(commodity, geo?, years?)` | USDA NASS monthly price *received* ($/bu) + MoM/YoY change + seasonal context. `geo` = `US` or a state (corn back to 1908) |
| `price_series(commodity, geo?, start_year?, end_year?)` | Raw monthly price-received series for charting |
| `input_cost_trend(item, geo?, years?)` | Real input cost + change. `item` = `diesel` (U.S. `$/gal`, weekly, EIA) or a fertilizer `$/ton` (`urea`/`uan`/`anhydrous`/`dap`/`map`/`potash`, monthly, USDA AgTransport); `geo` selects the fertilizer region (default `Cornbelt`) |
| `input_cost_series(item, geo?)` | Raw historical series for an input cost (diesel `$/gal` or fertilizer `$/ton`, region-selectable) |
| `latest_prices(commodity?, source?, delivery?, kind?, zip?, lat?, lng?, radius_miles?, include_expired?)` | Live snapshot table; every filter optional (`kind` = `grain`/`fertilizer`). Current + future delivery months only by default; pass `include_expired=true` for past months (use only on an explicit historical request). Location filter (zip **or** lat/lng + `radius_miles`) keeps nearby sources, nearest-first, with distance |
| `price_history(commodity?, source?, delivery?, days?)` | Time series per (elevator, crop, delivery); **every filter optional** — omit `commodity` to span all crops. Shows bid + basis trend + futures |
| `basis_movement(commodity?, source?, delivery?, days?)` | Aggregated basis trend, one headline line per crop (the cheap overview) |
| `basis_detail(commodity?, source?, delivery?, days?)` | Per-(elevator, crop, delivery) basis first→last drill-down |
| `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 |
For the full per-release detail (signatures, conventions, example question → call
mappings), see [CHANGELOG.md](CHANGELOG.md).
Grain-marketing prompt library for the downstream Ag Advisor (planning +
monitoring, with the tools each prompt uses):
[examples/ag-advisor-prompts.md](examples/ag-advisor-prompts.md).