Skip to content

Connect an AI tool

Mostly Right runs a Model Context Protocol server at https://mostlyright.md/api/mcp. It speaks Streamable HTTP, negotiates protocol revisions 2025-11-25, 2025-06-18, 2025-03-26 and 2024-11-05, and is stateless — no session id is issued, so every request stands alone.

Searching the catalogue, reading schemas and pulling sample rows need no account. Add the server, ask a question, and your agent can start answering immediately. Signing in is what unlocks querying whole tables (10,000 rows a page) and downloading a full Parquet snapshot. A paid workspace unlocks building: writing a recipe, running it, and publishing the table it produces.

Claude Code

Terminal window
claude mcp add --transport http mostlyright https://mostlyright.md/api/mcp

Claude Desktop — Settings → Connectors → Add custom connector, and paste https://mostlyright.md/api/mcp.

Cursor~/.cursor/mcp.json:

{
"mcpServers": {
"mostlyright": {
"url": "https://mostlyright.md/api/mcp"
}
}
}

VS Code.vscode/mcp.json:

{
"servers": {
"mostlyright": {
"type": "http",
"url": "https://mostlyright.md/api/mcp"
}
}
}

ChatGPT — Settings → Connectors → Add custom connector, and paste the same URL. ChatGPT’s connector contract requires two tools with exact names and shapes, and this server implements both: search, which takes a query and returns {results: [{id, title, url}]} with the dataset slug as the id, and fetch, which takes that id and returns {id, title, text, url, metadata} with the dataset as Markdown in text. Both are anonymous. From the OpenAI Responses API, pass the server as a tool: {"type": "mcp", "server_label": "mostlyright", "server_url": "https://mostlyright.md/api/mcp"}.

Anything else — the handshake by hand:

Terminal window
curl -sS https://mostlyright.md/api/mcp \
-H "content-type: application/json" \
-H "accept: application/json, text/event-stream" \
-H "mcp-protocol-version: 2025-06-18" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'
Tool What it answers
search The ChatGPT connector search: a query in, up to 20 {id, title, url} results out.
fetch The ChatGPT connector fetch: one dataset by slug, as Markdown, with its metadata.
search_datasets Full-text search over the public catalogue, with cursor pagination.
get_dataset One dataset: summary, publisher, licence, tables, column schemas, canonical URL.
list_tables Just the tables and their ids — the cheap call.
get_table_schema Columns, types, published profiles, and which capabilities the publisher enabled.
sample_rows The publisher’s materialized preview, up to 100 real rows. A sample, not a query.
get_download_instructions The exact URL, method and header for the full Parquet snapshot.
get_access_instructions What needs an account, the key classes, and the numbered steps to get one.

There is also a dataset://{slug} resource that returns one dataset as Markdown, a mostlyright://access resource explaining access, and three prompts — explore_dataset, find_dataset and build_dataset.

Tool What it does
query_table A bounded structured query: columns, filters, order, aggregates, up to 10,000 rows a page and offset to the end of the table. No SQL.
catalog_search Searches a sealed snapshot of public data sources for feeds that might answer a question. One provider — Data.gov — partially swept, so a hit is a lead to read and a miss proves nothing. Every ranked candidate comes back with its disposition, and nothing is scored. Each carries the catalogue’s own facts: a list of bounding boxes or null, and a record URL only where the entry is identified by one — about one in four are not, and none is invented. format is one lowercase token, sent once — the catalogue admits a single format filter per question and has no OR. It withholds nothing: it states the format the question requires, and an entry that does not declare it comes back refused, with filters_match: false, rather than being held back. The tool checks question, limit and format itself before calling, so a malformed argument is refused here; one that reached the catalogue another way can surface as its 422 rather than as CATALOG_SEARCH_INVALID.
list_connected_datasets The datasets this workspace has connected — exactly what query_table can read.
connect_dataset Connects a public dataset to the workspace. Owner, Admin or Editor, and an OAuth connection — see below.

Two ways to authenticate:

OAuth, no key pasted anywhere. Clients that speak OAuth 2.1 discover the authorization server from the WWW-Authenticate header the first refusal carries, register themselves, and open a browser where you sign in and pick one workspace. The client holds workspace-scoped credentials, never an API key, and membership is rechecked on every request. Manage or revoke these under Settings → Access.

A workspace key. Sign in and create an mr_use_… key under Settings → Access. Send it as Authorization: Bearer mr_use_…. The first query_table over a dataset connects it to your workspace. This is the route for scripted MCP clients that have no browser.

An mr_use_ key is read-only: it unlocks query_table over any public dataset and the workspace’s own tables, and list_connected_datasets. It never needs connect_dataset; its first query over a public dataset connects it. An OAuth connection is bounded by the scopes the person approved: datasets:read reads the datasets the workspace has already used, datasets:use lets the connection use new public datasets (on first query, or explicitly with connect_dataset), and datasets:build also reads the workspace’s own tables.

An mr_live_… key is a different credential: it authenticates the Hosted Table API for tables your own workspace publishes. The MCP server says so rather than refusing silently.

A paid workspace can use the same server to build a dataset rather than only read one. It costs $29 a month per workspace, and it needs three things at once: an OAuth connection that approved the datasets:build scope, the Owner, Admin or Editor role in that workspace, and an active subscription. An mr_use_ key cannot build — it is read-only, and every build tool refuses it by name and points at the OAuth route. A workspace with no subscription is refused with subscription_required and the billing URL.

The tools are grouped by what they act on rather than by the word “build”:

Tools What they do
create_dataset, update_dataset, list_my_datasets, get_my_dataset The dataset page: mint one, rename it, write its description, read its tables and their state.
register_recipe Send one recipe document. Answers with recipe_id, recipe_digest, dataset_id, table_id and source_ids.
start_run, confirm_run, cancel_run Start a run in sample, full, refresh or backfill mode with row and byte ceilings; settle a run held for a spend confirmation; stop one. A backfill covers one exact window and is refused without a window of {start, end}.
get_run, run_events, list_runs Read a run’s record, page its events until it is terminal, and find runs you did not start.
query_run One bounded read-only SQL statement over a finished run’s own table, where the relation is named run_table.
run_artifacts, get_artifact_download What the run sealed, and a signed URL for one artifact. Bytes never stream through MCP.
write_note One cell of the decision record, on the dataset or on the run.
promote_table, get_table Publish a table, and read what one is serving.
list_source_credentials The names of the secrets the workspace holds. Never a value.

The loop is: read the guide and the reference, propose sources, write a recipe with a description on every column and units on every numeric column, register_recipe, start_run in sample mode with ceilings, run_events until it is terminal, query_run to check the rows, write_note for each decision, then fix and register again. A full run happens only when the user asks for one, and promote_table only when they approve that exact table.

Credentials are pasted by a person, not by an agent. A source that needs an API key gets its value from Settings → Secrets in the dashboard, or from the Source credentials panel on the dataset’s own page, where it is stored under a name. The recipe references that name. No secret passes through MCP or through a chat message.

Four resources carry the rest:

  • mostlyright://build-guide — the whole loop with the exact tool names. Also published as an agent skill at /.well-known/agent-skills/mostlyright-build/SKILL.md.
  • mostlyright://recipe-reference — every member of the recipe document, every bound, every refusal.
  • mostlyright://recipe-connections — using a saved workspace connection instead of a named secret.
  • mostlyright://recipes/examples — six recipe documents that ran, each readable at mostlyright://recipes/examples/{name}.

The build_dataset prompt walks the same loop for a question you give it.

Every refusal carries what to do next. An anonymous caller reaching query_table gets a 401 whose body includes the signup URL, the header format and the numbered steps — the same content get_access_instructions returns. Clients that support OAuth turn that 401 into a sign-in prompt; clients that do not show the instructions to the model.

Bytes never stream through MCP. get_download_instructions returns the one request that fetches a complete Parquet snapshot, which you make yourself. For applications, scripts and notebooks, use the Public Dataset API directly.

  • /.well-known/oauth-protected-resource/api/mcp — the ratified protected-resource metadata.
  • /.well-known/mcp.json — a server card for registries and directory crawlers, listing the anonymous, authenticated and build tools.
  • /.well-known/agent-skills/index.json — the agent skills this deployment publishes.
  • /llms.txt and /llms-full.txt — the catalogue as plain text.
  • /datasets/{slug}/llms.txt — one dataset as Markdown.