Repository navigation
MCP server, WebMCP tools and the map inside the chat - #28
Merged
Merged
Conversation
Search, filter and record shaping move out of app.js into
scripts/_lib/assets/query_core.mjs, a dependency-free ES module that
stage 04 inlines into app.js (export keywords stripped) and the coming
MCP server bundles unchanged, so both surfaces answer identically. The
omnisearch, tree filter and label helpers are aliases of the core
instance; the WebMCP tools become thin adapters over it.
- new WebMCP tool list_facets (countries, regions, styles, schemes with
counts, values that round-trip into filter_appellations)
- tool schemas hardened (limit bounds, country pattern, slug pattern,
maxLength) and shared as TOOL_DEFS; results carry structuredContent
- fix: a country-qualified scheme ("it:docg", "es:vino-de-pago") never
matched — the ':' was normalised away; "Vino de Pago" now matches too
- stage 04 writes wiki/data/mcp/<locale>.json, the query context the
server reads (QUERY_CONTEXT_KEYS / QUERY_CONTEXT_FORMAT)
- About dialog (4 locales) and llms.txt advertise
https://mcp.openwinemap.com/mcp
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mcp/ is a stateless MCP server (official @modelcontextprotocol/server 2.3.0, createMcpHandler) deployed as a Bunny standalone Edge Script at https://mcp.openwinemap.com/mcp. It serves protocol 2026-07-28 natively and 2025-era clients through the SDK's stateless fallback, with the query core's tools (search_appellations, filter_appellations, get_appellation, list_facets) plus a locale argument. - data: /data/mcp/<locale>.json from the site, cached per isolate and revalidated by ETag; get_appellation merges the panel JSON - MCP Tool Plausible event sent server-side (tool + locale only) - scripts/deploy_mcp.py: esbuild bundle -> Bunny compute API -> publish with the git SHA -> smoke test in all three protocol modes - tests: node --test (core anchors, protocol conformance per mode, context store), parity_webmcp.py (page WebMCP == server, headless), tests/test_mcp_query_context.py (stage 04 <-> context.js contract) - CI job builds the bundle and runs the tests - docs/plan-mcp-server.md: plan, decisions, spike results Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- deploy_mcp.py hostname HOST: attach the hostname to the script's pull zone, add the CNAME in the Bunny DNS zone, issue the free certificate, force SSL (idempotent; refuses to overwrite a different record) - deploy_mcp.py vars NAME=VALUE: set script environment variables - the smoke client sends X-OWM-Smoke; the edge script skips the `MCP Tool` Plausible event for it, so deploys don't inflate the counts Production: script owm-mcp (id 94571), https://mcp.openwinemap.com/mcp. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A smoke test right after publishing was answered by isolates still running the previous release (seen as test calls counted under the old, untracked code). The bundle now carries its git SHA as OWM_BUILD, the server reports it as version 1.0.0+<sha>, and deploy_mcp.py's smoke test polls until the endpoint reports that version before testing; a failed mode now fails the deploy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tor" The About dialog shows https://mcp.openwinemap.com/mcp in a code box with a Copy button (clipboard API, falls back to selecting the address); copies are counted as the `MCP Address Copied` Plausible event. Dutch wording "aangepaste connector" (a calque of "custom connector") becomes "eigen connector". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A `show_on_map` tool with an MCP Apps view (ui://open-wine-map/map): a MapLibre 4.7.1 map of the requested appellations drawn from the site's own pmtiles over the CARTO basemap, framed and highlighted, click for name + "Open on Open Wine Map", fullscreen, host light/dark theme. The text result stays Markdown map links for hosts without MCP Apps. - view/ → scripts/build-view.mjs → dist/view.html (one self-contained document, 1.46 MB; MapLibre's UMD build starts its worker from blob:), imported as text by the edge bundle (1.8 MB) - the resource declares its CSP (tile origin + *.basemaps.cartocdn.com); tile origin and CARTO key are injected at resources/read time, so one bundle serves the spike and production - optional TILE_PROXY: the script re-serves /map-data/*.pmtiles with CORS (no-store), for the spike, leaving the production site untouched - server instructions and the tool description ask the model to call show_on_map whenever it names appellations - test/apps_host_check.py: a local MCP Apps host (the SDK's AppBridge), the view on its own origin under the spec's reference CSP: draws with a Claude-like `worker-src blob:`, and — as expected — not under the literal spec CSP (blob: worker refused by script-src) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e 0 results Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"Does your browser already speak WebMCP? Every page of the map offers it the same tools. If that means nothing to you, never mind: the MCP server above is the one your AI assistant knows how to use." — in the four locales, WebMCP linked to Chrome's documentation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the same set Up to 10 appellations each get their own colour; the title opens a legend list (open by default for several). Hover a row or a polygon to light it, click a row to zoom to it (the site button becomes "<name> ↗"), the colour square hides it, "Show all" resets. A multi-appellation result links the set as /?aocs=a,b,c (≤ 50) in the text and the view; a hidden appellation drops out of that link. MapLibre's controls get dark styling. apps_host_check.py exercises the list, hover, hide, pin and the links. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…everal appellations
The landing IIFE opens the set as one panel stack, highlights all of it and
frames the map on the union of its boxes (unless the link carries a camera
hash). The query stays in the URL until the reader opens something else.
A set's header is the plain count ("2 appellations"), not "at this point",
and keeps it through a card pick. Docs: CLAUDE.md (map inside the chat),
mcp/README (show_on_map, view/, host check).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The site's pull zone already answers /map-data/*.pmtiles cross-origin (ranged GET and a Range preflight), so the view reads the tiles straight from the site. They are browser-cached for 30 days, so stage 04 writes the map's own fingerprinted URLs (?v=<sha8>) into the query context as `tiles`; show_on_map passes them on and the view uses them (bare paths only while the site predates the key; additive, format stays 1). llms.txt names show_on_map. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The 51 Alsace grands crus fell back to the homepage. 200 is show_on_map's own maximum; the worst case is under 10 KB of URL and the CDN takes 16 KB, so the homepage fallback goes. The site's ?aocs= landing reads up to 200. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Agents can query the map through two surfaces built on one query core (
scripts/_lib/assets/query_core.mjs, inlined into app.js):search_appellations,filter_appellations,get_appellation,list_facets,show_appellation, registered viadocument.modelContext(Chrome origin trial; token from.env).mcp/) serving the same four read tools plusshow_on_map, an MCP Apps view that draws the requested appellations from the site's pmtiles, with a legend and a link to the same set./?aocs=a,b,copens a set of up to 200 appellations in the panel, the linkshow_on_mapgives.wiki/data/mcp/<locale>.json(startup records + lookup tables) for the server;deploy_mcp.pybuilds, publishes and smoke-tests it.Already live in production. Plans and spike results:
docs/plan-mcp-server.md,docs/plan-mcp-apps.md.Deploy order when the context format changes:
deploy.shfirst, thendeploy_mcp.py deploy.🤖 Generated with Claude Code