Files
ag-bids-mcp/CHANGELOG.md
T
justin 7b6661e3d9
CI / test (push) Failing after 1s
CI / build-push (push) Has been skipped
Changelog: source geo + many more elevator locations
Document the per-source geo on /api/data/sources + list_sources, and the new
Heritage Cooperative (23 locations), expanded Mercer Landmark (16, with two
source renames), and Bambauer Pemberton sources.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 11:15:59 -04:00

140 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Changelog
Notes for clients/agents that consume the ag-bids MCP tools and the underlying
`ag-monitor` `/api/data/*` HTTP API. Newest first.
## 2026-05-30 — Source geo + many more locations
### Per-source geo (API + MCP)
- **`GET /api/data/sources`** now returns location geo on every source:
`city, state, zip, county, latitude, longitude` (any may be `null`). The
AgriCharts-fed elevators carry exact coordinates; smaller sites carry
city/state/zip.
- **MCP `list_sources`** gained a **Location** column (`City, ST ZIP`).
`source_health` is unchanged in shape.
- Sources that are national or non-physical (CBOT futures, USDA AMS, DTN
fertilizer, hedge-to-arrive / "Direct" bid buckets) legitimately have `null`
geo. ~43 of ~51 sources are geo-tagged.
### Many more elevator locations
These flow through every data tool/endpoint automatically (`latest`, `history`,
`best`, `basis_movement`/`basis_detail`, `sources`, `deliveries`). No tool
signatures changed — just far more sources, all named `"<Co-op> — <Location>"`:
- **Heritage Cooperative** — new co-op, **23 central/eastern-Ohio locations**
(corn/soy/wheat).
- **Mercer Landmark** — expanded from 2 to **all ~16 locations**. Note: the two
old source names were renamed for continuity — `"Mercer Landmark — St Henry"`
`"Mercer Landmark — MPS St Henry"`, `"Mercer Landmark — Minster"`
`"Mercer Landmark — Heartland Minster"`.
- **Bambauer** — now both locations incl. **Pemberton**
(`"Bambauer — Jackson Center / New Knoxville"`, `"Bambauer — Pemberton"`);
the old `"Bambauer Jackson Center / New Knoxville, OH"` source was renamed to
the first of those.
If you cache source names, refresh them — several changed and many were added.
## 2026-05-29 — Futures price + change tool
### New MCP tool
- **`futures_quote(commodity, delivery?)`** — CBOT futures price and change for a
grain. Reports the latest price, today's **session open**, the prior day's
close, and **both** moves: **change since open** and **change on the day**
(vs the previous settle). With `delivery` (e.g. `"Jul 2026"`) it resolves the
listed contract that month prices against (e.g. `ZCN26`); without it, the
continuous nearby.
### API changes (`ag-monitor`)
- **`GET /api/data/futures?commodity=<grain>&delivery=<label?>`** — new endpoint.
Returns `{ commodity, delivery, contract, symbol, quote }` where `quote` is
`{ settle_date, open_cents, last_cents, prev_close_cents,
change_since_open_cents, change_on_day_cents, fetched_at }` (or `null` if no
data yet for that contract). `commodity` must be `corn`/`soy`/`wheat`.
- **`futures_quotes` table** gained an `open_cents` column; the futures scraper
now stores the session **Open** alongside the close. Rows captured before this
change have `open_cents = NULL`, so `change_since_open_cents` is `null` for
those until the next session is scraped.
- Futures now also pull at **:30 during the CBOT day session** (on top of the
hourly :00), so `last` and the changes track the session every ~30 min.
### Example questions → tool calls
| Ask | Call |
|---|---|
| Corn Jul futures and how far it's moved today | `futures_quote(commodity="corn", delivery="Jul 2026")` |
| Soy nearby futures, change on the day | `futures_quote(commodity="soy")` |
## 2026-05-29 — Flexible history + basis movement
### New MCP tools
- **`basis_movement(commodity?, source?, delivery?, days=30)`** — aggregated
basis trend, **one headline line per crop**. Averages every matching
(elevator × delivery) series to `avg basis first → last` over the window and
reports how far it moved. This is the cheap "how is basis moving overall"
view. All filters optional; `commodity` (if given) must be `corn`/`soy`/`wheat`.
- Positive move = **cash strengthened** vs futures (basis up); negative = weaker.
- Aggregation is intentional: divergent elevators can net to "flat". When the
aggregate looks flat or surprising, call `basis_detail` to see per-elevator
splits.
- **`basis_detail(commodity?, source?, delivery?, days=30)`** — the drill-down
for `basis_movement`. **One row per (elevator, crop, delivery)** series with
basis `first → last` and the move. Same optional filters.
Both tools do the aggregation **server-side (in the MCP)** and return compact
markdown — they do not dump every raw sample — to keep token usage low. Pattern:
call `basis_movement` first, then `basis_detail` (optionally filtered) only when
you need the breakdown.
### Changed MCP tools
- **`price_history`** — `commodity` is now **optional** (was required). Omit it
to span every crop. Output now groups by **(elevator, crop, delivery)**,
surfaces **basis first → last** in each series summary, and adds a **Futures**
column to the raw points table. Every filter (`commodity`, `source`,
`delivery`, `days`) is optional and AND'd — pivot per elevator, per crop, per
delivery, or any combination.
- Raw per-row points are still only included when the window has ≤ ~60 samples;
wider queries return the per-series summaries only.
- **`latest_prices`** — added the **`kind`** filter (`grain` | `fertilizer`) for
parity with the API. `commodity`, `source`, `delivery`, `kind` all optional.
### API changes (`ag-monitor`)
- **`GET /api/data/history`** — `commodity` query param is now **optional**.
When omitted, returns history across all crops. `source_id`, `delivery`, and
`days` (1730, default 30) remain optional. Response shape is unchanged:
`{ "commodity": <str|null>, "days": <int>, "rows": [...] }`. Each row carries
`fetched_at, source_id, source_name, commodity, delivery, bid_cents,
basis_cents, futures_cents` so callers can pivot client-side.
- `GET /api/data/latest` already supported optional `commodity`, `source`,
`delivery`, `kind` — unchanged.
### Conventions / gotchas
- All money fields are **integer cents**. `bid_cents`/`futures_cents` render as
`$/bu` (4 dp) for grain and `$/ton` (2 dp) for fertilizer; `basis_cents`
renders as a signed dollar value (2 dp), e.g. `-0.14`.
- Basis is only meaningful for grain — the basis tools skip non-grain rows and
any series with no basis on file.
- `source` filtering is by **exact** elevator display name (e.g.
`"Mercer Landmark — Minster"`). Use `list_sources` to get exact names.
### Example questions → tool calls
| Ask | Call |
|---|---|
| Basis movement overall, last 7 days | `basis_movement(days=7)` |
| Corn basis movement across all elevators | `basis_movement(commodity="corn")` |
| Basis movement at one elevator | `basis_movement(source="Mercer Landmark — Minster")` |
| Per-elevator basis breakdown for corn | `basis_detail(commodity="corn")` |
| Last 7 days of history from elevator X for corn | `price_history(commodity="corn", source="…", days=7)` |
| All-crop price history at one elevator | `price_history(source="…")` |
| Latest grain bids only | `latest_prices(kind="grain")` |