Inspiration
I love gardening, and coding with AI agents.
I've had conversations with ChatGPT and Gemini that start in a similar way: "what can I grow in my city?" (I know my hardiness zone because I've searched for it more than once) and the agent guesses from memory. The USDA Plant Hardiness Zone Map is the standard reference for what can survive where, but it lives in PDFs, a clunky ZIP lookup, and 300-dpi PNGs. Nothing an agent can call.
WebMCP made the fix obvious: put the authoritative data on a page, register it as tools, and let the human and the agent work from the same map. I also wanted a primitive, not just a demo. AGMCP is the first building block for a bigger garden-planning app I'm building next, where zones combine with hyper-local weather and sun position and regional, heirloom seeds.
What it does
AGMCP is the 2023 USDA Plant Hardiness Zone Map for all 40,502 US ZIP codes (50 states, DC, Puerto Rico), exposed three ways:
- For people: enter a ZIP (or use your location), see your half-zone with its temperature band and frost windows, browse 54 vegetables, herbs, peppers, and fruit rated
great/stretch/not recommendedfor that zone, and build a garden plan with a planting calendar. - For agents on the page: 18 WebMCP tools registered with
document.modelContext.registerTool(), plus a declarative form tool. Read tools likelookup_hardiness_zone,compare_locations,find_zone_by_coordinates,list_plants,get_planting_calendar. Write tools likeset_location,add_to_garden_plan, andfilter_plantschange what the human sees.clear_garden_planopens a confirmation dialog the user must accept;use_my_locationrequires the browser's geolocation permission. - For backend agents and other apps: a JSON API (
/api/v1/zone/{zip},/compare,/nearest,/plants,/calendar), an OpenAPI spec, andllms.txt.
Every tool call streams into an on-page Agent activity panel, so the human always sees what the agent did.
How we built it
- Data pipeline: PRISM Group's 2023 ZIP-to-zone CSVs (US, AK, HI, PR) plus US Census ZCTA centroids. A build script packs 100,000 possible ZIPs into a single 100 KB string (one character per ZIP indexing 26 half-zones) so lookups are O(1) in the browser and in the Worker. Coordinates load lazily for nearest-ZIP queries.
- Frontend: Vite + vanilla TypeScript, no framework. Modern CSS (oklch,
light-dark(), container queries, view transitions), native<dialog>for human-in-the-loop confirmation. - WebMCP: one tool module with JSON Schema inputs,
readOnlyHintannotations, and a wrapper that logs each call and converts app errors into MCP-styleisErrorresults instead of throwing. Feature-detectsdocument.modelContextwith anavigator.modelContextfallback for Chrome < 150. The UI buttons and the tools call the exact same functions, so there is no agent-only code path. - Backend: a Cloudflare Worker serves static assets and the JSON API from the same bundled data, deployed with Workers Builds on every push to
main. - Tooling: built with Cursor cloud agents; end-to-end tested in headless Chrome via
navigator.modelContextTesting.
Challenges we ran into
- Spec drift. Chrome 148 exposes WebMCP on
navigator.modelContext; the spec and newer Chrome usedocument.modelContext. ChatGPT's browser supports only imperative tools on the top-level page, so the declarative form is progressive enhancement. - Data size. Naive JSON for 40k ZIPs was megabytes; the 1-char-per-ZIP encoding brought core data to ~15 KB gzipped.
- Honesty about estimates. Frost dates and plant ranges are horticultural rules of thumb, not USDA data, so every tool output and UI label says so.
Accomplishments that we're proud of
- A real dataset as a real primitive: exact zones for every ZIP, callable by agents in-page and over HTTP.
- Genuine human-agent collaboration: shared state flows both ways, write tools change the visible page, and destructive actions wait for a click.
- Zero secrets, zero tracking, zero API keys. Fully open source, deployable with one command.
- Shipped, deployed, and passing an automated WebMCP end-to-end test on the live URL before the deadline.
What we learned
- WebMCP tools are best when they reuse the app's own actions. If a button and a tool call the same function, the agent and the human are always in sync.
- Tool descriptions are the UX for agents. Naming, enums, and "call
get_current_contextfirst" hints did more for reliability than any code. - Return enough for the agent to verify and warn:
add_to_garden_planreturns the plant's fit so the agent can say "habanero is a stretch in 6a." - Modern web platform features (dialog, view transitions,
light-dark()) covered everything a framework would have, with a 37 KB bundle.
What's next for AGMCP
- Pair it with hyper-local weather and sun-position tools to build the 3D garden planner it was designed to power: bed layout, succession planting, and season-aware recommendations for your exact zone.
- 2012 vs 2023 zone shift comparison ("did my zone change?").
- Richer plant data with varieties, companion planting, and community-contributed regional notes. This may involve parsing PDFs from Universities across the USA that have regional and local information. For example, UF has research papers dedicated to the Florida agriculture. I'll probably use a local model to running one a mini pc to keep costs low.
- Publish the tool set as a reusable module so any gardening site can register the same WebMCP tools.
Built With
- chatgpt
- chrome
- cloudflare
- css
- cursor
- github
- html
- javascript
- json
- node.js
- playwright
- typescript
- usda
- vite
- webmcp
- wrangler
Log in or sign up for Devpost to join the conversation.