input_cost_trend/input_cost_series now accept six fertilizers (urea, uan, anhydrous, dap, map, potash) alongside diesel, with an optional `geo` region (default Cornbelt). Real $/ton + MoM/YoY change + seasonal context. - client: pass geo through; add input_cost_geographies - server: expand VALID_INPUTS; geo param + docstrings - format already unit-aware ($/ton) and geo-aware - README tools table now lists the reference/trend + input-cost tools - CHANGELOG: regional fertilizer input-cost release notes - tests: fertilizer $/ton + region formatting Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
11 KiB
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 — Regional fertilizer input costs (real $/ton + change)
Real U.S. regional retail fertilizer prices now feed the input-cost tools,
so the advisor can reason about fertilizer the same way it does diesel and grain
— actual dollars and the move, not an index. Source: USDA AgTransport
(monthly, $/ton, history back to 2023).
Changed MCP tools (fertilizer added to the existing input-cost tools)
input_cost_trend(item, geo?, years=10)—itemnow accepts six fertilizers in addition todiesel:urea,uan,anhydrous(anhydrous ammonia),dap,map,potash. Returns the latest real$/ton, month-over-month and year-over-year change ($ and %), and seasonal context.- New optional
geo= AgTransport region; defaults toCornbelt. Other regions:U.S. Gulf NOLA,Northern Plains,Southern Plains,Southeast,Northeast,California,Pacific Northwest,South Central,Central Florida,Tampa(not every product is published for every region). dieselis unchanged — national U.S.$/gal, weekly;geois ignored for it.
- New optional
input_cost_series(item, geo?)— raw monthly$/tonseries for any fertilizer (or the diesel$/galweekly series), region-selectable.
Seasonal percentile for fertilizer is computed over a short history (2023+), so it deepens over time; the price and YoY/MoM change are solid now.
API
GET /api/data/input-cost-trend?item=&geo=&years=—geoadded.GET /api/data/input-cost-series?item=&geo=—geoadded.GET /api/data/input-cost-geographies?item=— new: lists the regions a given input has data for (plus itsdefault_geo).
Example questions → tool calls
| Ask | Call |
|---|---|
| Cornbelt urea price and how it's moved | input_cost_trend(item="urea") |
| Anhydrous ammonia in the Southern Plains | input_cost_trend(item="anhydrous", geo="Southern Plains") |
| Potash $/ton history | input_cost_series(item="potash") |
| Which regions have DAP prices | (API) GET /api/data/input-cost-geographies?item=dap |
2026-05-30 — Grain price-received trends (real $ + change + seasonal)
New national/seasonal reference layer (USDA NASS, corn back to 1908) — the macro benchmark to compare local cash bids against. Real prices and the change, not an index.
New MCP tools
price_trend(commodity, geo="US", years=10)— monthly price received by farmers ($/bu) with the move: latest real price, month-over-month and year-over-year change ($ and %), and seasonal context (percentile vs the same month over the last N years, normal, and range).geoisUSor any 2-letter state. Conclusions, not rows.price_series(commodity, geo="US", start_year?, end_year?)— raw monthly series ($/bu) for charting/drill-down (defaults to the recent window).
API
GET /api/data/price-trend?commodity=&geo=&years=— computed trend (cents +change_cents/change_pct/yoy_*+seasonal).GET /api/data/price-series?commodity=&geo=&start_year=&end_year=— raw series.GET /api/data/price-geographies?commodity=— which geos (US + states) exist.
All grain: corn/soy/wheat, all 50 states + US.
Input-cost tools (real $ + change)
input_cost_trend(item, years=10)— real input price with the move. Currentlyitem="diesel"(EIA U.S. retail $/gal, weekly, back to 1994): latest price + week-over-week and year-over-year change + seasonal percentile/range. (For current fertilizer $/ton,current_input_price(DTN) still applies; more inputs extend this same tool.)input_cost_series(item)— raw historical series for an input.- API:
GET /api/data/input-cost-trend?item=&years=,GET /api/data/input-cost-series?item=.
USDA stopped publishing dollar input prices in 2014, so these use real-dollar sources (EIA) rather than an index.
2026-05-30 — Source geo + many more locations
Per-source geo (API + MCP)
GET /api/data/sourcesnow returns location geo on every source:city, state, zip, county, latitude, longitude(any may benull). The AgriCharts-fed elevators carry exact coordinates; smaller sites carry city/state/zip.- MCP
list_sourcesgained a Location column (City, ST ZIP).source_healthis unchanged in shape. - Sources that are national or non-physical (CBOT futures, USDA AMS, DTN
fertilizer, hedge-to-arrive / "Direct" bid buckets) legitimately have
nullgeo. ~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). Withdelivery(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 }wherequoteis{ settle_date, open_cents, last_cents, prev_close_cents, change_since_open_cents, change_on_day_cents, fetched_at }(ornullif no data yet for that contract).commoditymust becorn/soy/wheat.futures_quotestable gained anopen_centscolumn; the futures scraper now stores the session Open alongside the close. Rows captured before this change haveopen_cents = NULL, sochange_since_open_centsisnullfor 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
lastand 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 toavg basis first → lastover 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 becorn/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_detailto see per-elevator splits.
-
basis_detail(commodity?, source?, delivery?, days=30)— the drill-down forbasis_movement. One row per (elevator, crop, delivery) series with basisfirst → lastand 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—commodityis 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 thekindfilter (grain|fertilizer) for parity with the API.commodity,source,delivery,kindall optional.
API changes (ag-monitor)
GET /api/data/history—commodityquery param is now optional. When omitted, returns history across all crops.source_id,delivery, anddays(1–730, default 30) remain optional. Response shape is unchanged:{ "commodity": <str|null>, "days": <int>, "rows": [...] }. Each row carriesfetched_at, source_id, source_name, commodity, delivery, bid_cents, basis_cents, futures_centsso callers can pivot client-side.GET /api/data/latestalready supported optionalcommodity,source,delivery,kind— unchanged.
Conventions / gotchas
- All money fields are integer cents.
bid_cents/futures_centsrender as$/bu(4 dp) for grain and$/ton(2 dp) for fertilizer;basis_centsrenders 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.
sourcefiltering is by exact elevator display name (e.g."Mercer Landmark — Minster"). Uselist_sourcesto 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") |