You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Breaking out item 3 of #335 ("optionally make catalog itself optional, so a headless/MCP-only config is just {"mcp_url": "…"}"), because the server-side blocker is now gone.
What changed on the server
mcp-data-server#346 / PR #348 makes an MCP head advertise the client-reachable URL of the catalog it reads, as structured data on a public endpoint:
No MCP session, no auth token./version is deliberately auth-exempt, so this works before mcp.connect() resolves and on token-gated heads.
Browser-reachable. Verified access-control-allow-origin: * on both heads today (duckdb-mcp.nrp-nautilus.io and duckdb-mcp.carlboettiger.info), so no proxy is needed.
Always public.stac_catalog_url is the client-facing URL even when the server itself reads an in-cluster address — that was the whole point of #346. Defaults to the server's own catalog URL, so heads on NRP prod already answer usefully.
Only public URLs are exposed there — the in-cluster address stays inside authenticated MCP responses.
Proposed change here
app/main.js already resolves mcpUrl at step 1c (app/main.js:64), before catalog.load(appConfig) at step 2+3, and DatasetCatalog.load reads appConfig.catalog at app/dataset-catalog.js:52. So the hook is small:
When appConfig.catalog is absent, derive it: GET <mcpUrl without trailing /mcp>/version → stac_catalog_url. A headless/MCP-only config becomes just {"mcp_url": "…"}.
A derived catalog is still not equivalent to the curated config: the app's collection list is what feeds list_datasets, get_schema, and the dataset paths in the assembled system prompt. Deriving the root URL doesn't change that — an MCP-only config still has collections: [] and still shifts agent behaviour onto the MCP STAC tools. Right for a smoke test or an outage, wrong for a benchmark meant to measure the production app.
Related: #335 (degrade instead of throwing; item 3 is this), #197 (source the catalog from MCP instead of walking STAC client-side), #287 (retry, shipped), mcp-data-server#346.
Breaking out item 3 of #335 ("optionally make
catalogitself optional, so a headless/MCP-only config is just{"mcp_url": "…"}"), because the server-side blocker is now gone.What changed on the server
mcp-data-server#346 / PR #348 makes an MCP head advertise the client-reachable URL of the catalog it reads, as structured data on a public endpoint:
$ curl -s https://duckdb-mcp.carlboettiger.info/version {"version":"main","git_sha":"…", "stac_catalog_url":"https://minio.carlboettiger.info/public-data/stac/catalog.json", "public_base_url":"https://duckdb-mcp.carlboettiger.info"}Properties that matter for this repo:
/versionis deliberately auth-exempt, so this works beforemcp.connect()resolves and on token-gated heads.access-control-allow-origin: *on both heads today (duckdb-mcp.nrp-nautilus.ioandduckdb-mcp.carlboettiger.info), so no proxy is needed.stac_catalog_urlis the client-facing URL even when the server itself reads an in-cluster address — that was the whole point of #346. Defaults to the server's own catalog URL, so heads on NRP prod already answer usefully.Proposed change here
app/main.jsalready resolvesmcpUrlat step 1c (app/main.js:64), beforecatalog.load(appConfig)at step 2+3, andDatasetCatalog.loadreadsappConfig.catalogatapp/dataset-catalog.js:52. So the hook is small:appConfig.catalogis absent, derive it:GET <mcpUrl without trailing /mcp>/version→stac_catalog_url. A headless/MCP-only config becomes just{"mcp_url": "…"}.catalogfetch fails after DatasetCatalog.load() still fatal after retry exhaustion (and fetches the root even with collections: []) — blocks a working MCP-only degraded mode #335's retry exhaustion, try the derived URL before degrading to an empty catalog — a head configured against a live mirror knows a reachable catalog even when the app's hardcoded one is down. That is exactly the case that cost the manual hunt in mcp-data-server#346./versionis unreachable or lacks the field (a head predating #346), fall through to DatasetCatalog.load() still fatal after retry exhaustion (and fetches the root even with collections: []) — blocks a working MCP-only degraded mode #335's degraded path. No new hard dependency on the boot critical path.Ordering note: this composes with #335 but doesn't need it — 1 is independent, 2 slots into whatever #335 lands as the post-retry branch.
Scope caveat carried over from #335
A derived catalog is still not equivalent to the curated config: the app's collection list is what feeds
list_datasets,get_schema, and the dataset paths in the assembled system prompt. Deriving the root URL doesn't change that — an MCP-only config still hascollections: []and still shifts agent behaviour onto the MCP STAC tools. Right for a smoke test or an outage, wrong for a benchmark meant to measure the production app.Related: #335 (degrade instead of throwing; item 3 is this), #197 (source the catalog from MCP instead of walking STAC client-side), #287 (retry, shipped), mcp-data-server#346.