Introduction
Model Context Protocol (MCP) is the open standard AI clients use to call external tools. Connecting the Food Web server means Claude, ChatGPT, Gemini, Grok, Perplexity, Cursor and friends can search the map, build and save maps, file curation suggestions, and participate in the forum on your behalf — with exactly the permissions your account has, nothing more.
The model runs on the client side: the server performs no inference, it just executes tools. Anonymous access is allowed for public reads, so you can try it before minting a key.
Endpoint & transport
https://mcp.foodweb.network/accounthttps://mcp.foodweb.networkBoth are the same server with the same tools. The sign-in endpoint always requires a credential: called without one it answers 401 with a WWW-Authenticate challenge, which is what makes an assistant open the Food Web sign-in. The base endpoint also serves anonymous public reads.
Transport is Streamable HTTP in stateless mode: each JSON-RPC message is one POST, responses are plain JSON, and no session state is held between calls — ideal for serverless. GET/DELETE return 405. A raw exchange looks like:
# The endpoint speaks MCP Streamable HTTP (JSON responses).
curl -X POST https://mcp.foodweb.network \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer fw_YOUR_KEY" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{
"protocolVersion":"2025-06-18",
"capabilities":{},
"clientInfo":{"name":"curl","version":"0"}}}'Authentication
Three credentials, all resolving to your account:
- Sign in with Food Web (OAuth 2.1) — paste the sign-in endpoint into the assistant and approve on the Food Web consent screen. The assistant receives an hour-long access token plus a rotating refresh token, and you can disconnect it any time from the connect page. The only option for ChatGPT, and the standard one for Claude and Grok connectors.
- an API key (
fw_…) minted on the dashboard — long-lived, revocable, stored hashed. Send it asAuthorization: Bearer fw_…; a bare key inAuthorization(what assistant APIs’authorizationfields send) or anX-API-Keyheader also work. - a Firebase ID token — the same credential the REST API uses (expires hourly, so sign-in or a key is the better fit).
Roles are live
Building a client? Discovery is standard: protected-resource metadata (RFC 9728) at /.well-known/oauth-protected-resource/account, authorization-server metadata (RFC 8414) at /.well-known/oauth-authorization-server, authorization code with PKCE (S256 only), dynamic client registration (RFC 7591), and iss on every authorization response (RFC 9207). Clients that can’t self-register can use a client ID and secret created on the connect page.
OAuth access tokens work on the MCP server only. On /v1 REST, an API key reaches only the REST scopes chosen when it was minted.
Role tiers
The server registers tools per credential, so tools/list shows only what your account can actually call:
Tool catalog — asset map
24 tools across the map tiers.
Public reads (anonymous OK)
whoamiAuth status: method, uid, roles, unlocked capabilitiessearch_entitiesSearch the asset map by text, type, region, or bounding box (paginated)get_entityOne entity with its place and app linkslist_citiesMapped cities for a country + provinceSaved maps (any account)
list_saved_mapsYour saved maps, each with the rule config it was built from and its last pin countget_saved_mapOne map you own: full config, embed URL, share tokencreate_saved_mapSave a public map to your account and get its embed URL — counts against your planverify_saved_mapLoad a map exactly as readers see it: entity count and per-role breakdownupdate_saved_mapRename a map, or replace its rules and appearance — the embed URL keeps workingdelete_saved_mapPermanently delete a map. Needs confirm: true, and breaks any published embedMaps are saved to the connected account and bounded by its plan — the same saved-map quota and watermark rules as the map builder. Locality uses the stored forms: country CA, province NS, city Halifax; anything else yields an empty map, which verify_saved_map reports. A map that came out wrong is fixed with update_saved_map, which leaves the share token — and so every published embed — intact.
Contributor (verified email)
suggest_entityFile a map suggestion (create/edit/report-duplicate); curators can auto-applycheck_duplicatesDuplicate candidates near a coordinate before suggestingCurator / admin
list_suggestionsReview queue, filterable by status/typereview_suggestionApprove/apply, reject, or resolve as duplicateadmin_search_entitiesCuration search: hidden/duplicate rows, sort, UUID lookupentity_statsWhole-dataset counts and per-type breakdownupdate_entityEdit entity fields (status active|hidden, meta merge)update_placeEdit address/coordinates/status of a placemerge_entitiesMerge a duplicate entity into a canonical onemerge_placesMerge a duplicate place into a canonical onearchive_entitySoft-archive; admins may hard-deleteenrich_entityFill empty fields from Google Placesreingest_entityQueue re-ingestion from the entity website (single or bulk)link_entity_appConnect an entity to a Food Web app record (e.g. its kitchen listing)Forum tools
Reads follow the forum's visibility model (anonymous → public threads; signed-in → members threads and your private invites). Writes post as your account and require authentication.
forum_list_categoriesForum channels, in display orderforum_list_discussionsGlobal or per-category feed, visibility-filteredforum_get_discussionOne thread with messages and repliesforum_create_discussionStart a thread (public / members / private + invites)forum_post_messagePost a top-level messageforum_replyReply to a messageforum_voteLike/dislike a discussion, message, or replyAuditing & limits
- Every mutating tool call is recorded in an audit log — actor, key or connected app, tool, redacted arguments, affected ids, outcome. Reads are not logged.
- Requests are rate-limited to 120 calls/minute per account (per IP when anonymous); exceeding it returns an error with a retry hint.
whoamishows your remaining budget. - Suggestions are additionally limited to 20/hour per account, matching the REST API.
- Search pages are capped at 100 rows per call; use
cursorto paginate. - Up to 10 active API keys per account.
Connect a client
In ChatGPT, claude.ai, Claude Desktop or grok.com, add a custom connector with the sign-in endpoint https://mcp.foodweb.network/account and approve on Food Web. For Claude Code:
# Sign in through the browser (OAuth):
claude mcp add --transport http foodweb https://mcp.foodweb.network/account
# …or with an API key:
claude mcp add --transport http foodweb https://mcp.foodweb.network \
--header "Authorization: Bearer fw_YOUR_KEY"Step-by-step setup for Claude, ChatGPT, Gemini CLI, Grok, Perplexity, Cursor and the assistant APIs — plus client credentials and connected apps — is on the dashboard, pre-filled and copy-pastable.