ClinicMarketIQ public MCP Worker
Minimal stateless, read-only remote MCP server for discovery of ClinicMarketIQ public datasets. It exposes Streamable HTTP at /mcp and a process-only health response at /healthz.
This directory is intentionally self-contained. The reviewed build is deployed at https://clinicmarketiq-public-mcp.rotgar-fizkl.workers.dev/mcp; the canonical setup page is https://clinicmarketiq.com/mcp/. External MCP Registry publication is tracked by server.json.
| Tool | Purpose |
|---|
list_datasets | Page through compact public catalog summaries. |
search_datasets | Search dataset ID, slug, name, and publisher. |
get_dataset_metadata | Fetch a dataset's canonical public machine index. |
get_schema | Follow the immutable manifest and return its declared JSON schema(s). |
get_download_url | Return direct immutable artifact URLs, sizes, formats, and SHA-256 values; never proxy file bytes. |
verify_checksum | Compare a caller-provided SHA-256 value with the digest declared in canonical metadata. It does not re-download and hash large artifacts. |
The Worker proxies small canonical JSON documents from https://clinicmarketiq.com rather than copying release metadata into the server bundle. Every derived URL is restricted to that exact origin and an allowlisted public path. Dataset bytes are never fetched by the MCP server.
Local verification
Requires Node.js 22.18+ or 24.11+ (odd-numbered Node releases are not supported by the pinned Vitest toolchain).
npm install
npm run types
npm run check
npm test
npm run dry-run
Start locally with npm run dev, then connect an MCP client or the MCP Inspector to http://localhost:8787/mcp. npm run dry-run bundles and validates the Worker but does not deploy it.
Security and operational boundaries
- All six tools are annotated read-only, non-destructive, and idempotent.
- The server uses Cloudflare's stateless
createMcpHandler; there is no Durable Object, KV, D1, session store, or write-capable binding.
- Upstream fetches use a fixed origin, reject redirects, require JSON, have an 8-second timeout, and stream into bounded buffers. Catalog, index, manifest, and schema documents have separate size ceilings.
- Catalog routes, release IDs, dataset IDs, slugs, manifest URLs, schema names, download URLs, encodings, and SHA-256 values are validated before being returned or followed.
- MCP request bodies are streamed into a bounded 64 KiB buffer and rejected above that limit, including chunked requests without
Content-Length. A matching Cloudflare WAF body-size rule should reject abuse before Worker CPU is consumed.
- Browser
Origin and endpoint Host validation are provided by the MCP handler. Before adding a custom domain, configure exact allowedHostnames, allowedOriginHostnames, and CORS origins; do not use wildcard origin bypasses for the public unauthenticated route.
- No authentication is required because every exposed action reads already-public metadata. If tools later expose non-public data or costly computation, add OAuth/Cloudflare Access and per-tool authorization before release.
- No request bodies, dataset queries, artifact URLs, or auth tokens are logged. Structured error logs contain only method, path, and a bounded error message.
Rate limiting
This Worker is stateless, so it does not pretend to enforce a reliable per-client counter in isolate memory. Before external registration, attach a Cloudflare rate-limiting rule to the exact /mcp route (for example, by verified client identity when OAuth exists, otherwise IP plus a conservative burst/window), and add a WAF rule for malformed or oversized requests. Monitor 429 rate, upstream error rate, CPU time, and subrequest volume before increasing limits.
The public metadata origin should also retain its own cache and abuse controls. Do not turn get_download_url into a byte proxy: clients should download immutable artifacts directly from ClinicMarketIQ so CDN controls and checksums remain authoritative.
Deployment and registration gate
Before changing, redeploying, or registering a new version of this server externally:
- Re-run
npm run types, npm run check, npm test, and npm run dry-run from a clean checkout.
- Confirm the current
https://clinicmarketiq.com/catalog.json and at least one dataset machine index, immutable manifest, schema, and download URL return the expected content types and release ID.
- Choose the final Worker/custom-domain hostname and configure exact MCP Host/Origin policy.
- Add route-level WAF and rate-limiting rules, then test 413/429 behavior.
- Perform an independent YMYL/privacy/rights review. This server is discovery infrastructure and must not imply that metadata is clinical advice, all-payer coverage, or permission to reuse third-party data.
- Deploy to a non-production environment, validate with the MCP Inspector, and only then decide whether to register the endpoint with external clients.
References