Mostly Right
Search, sample and query open reproducible datasets published as immutable Parquet with schemas.
Connect it
Settings → Connectors → Add custom connector
URL: https://mostlyright.md/api/mcpSettings → Apps & Connectors → Advanced → Developer mode
Create connector with URL: https://mostlyright.md/api/mcp{
"mcpServers": {
"datasets": {
"url": "https://mostlyright.md/api/mcp"
}
}
}claude mcp add --transport http datasets https://mostlyright.md/api/mcp{
"servers": {
"datasets": {
"type": "http",
"url": "https://mostlyright.md/api/mcp"
}
}
}54 tools, verified live
search_datasetsread-onlyFull-text search over every public dataset on Mostly Right. No account needed. Example: {"query": "hourly airport weather observations", "limit": 10}. Returns {datasets: [{id, slug, title, summary, topics, publisher, published_at, canonical_url}], next_cursor}. publisher is the ACCOUNT that published the dataset here, never the organisation that publishes the data it was built from — those are nam
get_datasetread-onlyOne dataset's overview: title, summary, topics, publisher, publication and update dates, canonical page URL, star and table counts, and every table with its id, title, license, immutable version_id, column count, column names and the capabilities the publisher enabled. Here and everywhere in this tool, publisher means the ACCOUNT that published the dataset — not the organisation the data was gathe
list_tablesread-onlyThe tables in one dataset, without the full column schemas — the cheap call when you only need table ids and titles. Example: {"dataset_slug": "kden-metar-hourly"}. Returns {dataset_slug, tables: [{id, slug, title, license, version_id, capabilities}]}. Use get_dataset instead when you also want columns.
get_table_schemaread-onlyOne public table's columns (name, type, and any published profile such as null counts, distinct counts or ranges), its immutable version_id, and its capabilities: whether anonymous sampling, keyed querying and Parquet download are enabled, and, when the publisher declared text search, capabilities.search (spec_digest and keyword_columns for query_table's search). Private workspace tables are not a
sample_rowsread-onlyThe publisher's materialized preview of a public table — real rows, no account, no query cost. Private workspace tables are not available here; use query_run on a successful build instead. To sample a source before anything is built, use probe_source (kind sample_rows). 20 rows by default, 100 at most, and they are always the same rows: this is a sample for understanding shape and values, NOT a qu
get_download_instructionsread-onlyThe exact URL, HTTP method and header for downloading one table's current immutable Parquet snapshot, plus whether the publisher enabled it. Example: {"table_id": "0f2f6bfa-4a63-4f75-9a0b-1a7d9c5b2e10"}. Bytes are never streamed through MCP: this returns the request to make yourself. Downloading needs an mr_use_ workspace key; the result includes how to get one. Prefer this over paging a whole tab
get_access_instructionsread-onlyWhat this server does anonymously, what needs an account, the two API key classes and what each unlocks, the OAuth option, the signup URL, and the numbered steps from 'no account' to 'querying rows'. Optionally pass {"dataset_slug": "kden-metar-hourly"} to get the link to that dataset's page, which is where a key is minted. Call this whenever a tool refuses for want of authentication, or before te
searchread-onlySearch every public dataset on Mostly Right and return up to 20 matches as {results: [{id, title, url}]}, where `id` is the dataset slug and `url` its canonical page. No account needed. Example: {"query": "hourly airport weather observations"}. Pass a result's `id` straight to fetch for the full dataset document. This is the plain search-and-fetch pair; search_datasets is the richer, paged version
fetchread-onlyThe full public document for one dataset as Markdown: summary, facts, access instructions, and every table with its columns, types, descriptions and units. No account needed. Example: {"id": "kden-metar-hourly"} — the `id` is a slug from search, and a canonical dataset URL works too. Returns {id, title, text, url, metadata: {slug, publisher, published_at, table_count, topics}}. publisher is the ac
query_tableread-onlyA bounded, structured query over one table's current version. NO SQL: send columns, filters, order_by, aggregates, group_by and limit as JSON. Example: {"table_id": "0f2f...", "columns": ["observed_at", "air_temp_f"], "filters": [{"column": "air_temp_f", "operator": "gte", "value": 80}], "order_by": [{"column": "observed_at", "direction": "desc"}], "limit": 50}. Ceilings: 64 columns, 8 filters, 2
catalog_searchread-onlySearch a sealed snapshot of public data sources for feeds that might answer a question — the first move when you need a source and do not already know one. Example: {"question": "county unemployment rate monthly", "limit": 10, "format": "csv"}. READ THIS BEFORE YOU TRUST A RESULT. The snapshot indexes ONE provider, Data.gov, and only part of it: about 22,000 records were catalogued out of the ~550
list_connected_datasetsread-onlyThe public datasets the authenticated workspace has used so far. Takes no arguments. query_table is not limited to this list: a key reads any public dataset (connecting it on first use) and the workspace's own tables; an OAuth connection reads any public dataset it has datasets:use for, or connect_dataset first. Returns {workspace_id, datasets: [{slug, title, use_id, connected_at, canonical_url}]}
connect_datasetConnects one public dataset to the authenticated workspace so its tables become queryable and downloadable. This is the gate every keyed read passes. Example: {"dataset_slug": "kden-metar-hourly"}. Idempotent: connecting an already-connected dataset succeeds and reports already_connected. Requires the Owner, Admin or Editor role. This is the one tool an mr_use_ key CANNOT call — that key class is
create_datasetCreates an empty dataset in your workspace and returns its ids. A dataset is the container a recipe binds to; it exists before it has a description, a recipe or a single row, which is the point — the page opens on it and fills in. The name leads with the subject a searcher would type and then the place, never with a grain word, a mechanism, a publisher or a station code. When this creates a datase
update_datasetA changed nonblank description generates a factual dataset name and topic tags, except a name or tags someone chose in an earlier update, which stay. The name given at create_dataset is a working title and does not count as chosen. Send name with the description to keep a title you want; it then stays until someone sends another. Drafts and unchanged descriptions do not generate metadata. Changes
generate_coverGenerates the dataset's branded 1200×630 cover and attaches it: the page, the Community tile and the share card all wear it. Every dataset gets exactly one, generated once its description is written. Call it only for a dataset that has no cover (get_my_dataset says has_cover). A dataset that already has one is refused cover_exists, because a new cover REPLACES the current one everywhere, including
set_dataset_visibilitycan modifyChanges who can read a dataset: private (this workspace only), link (anyone holding an unlisted address, which this returns) or public (listed on Mostly Right for anyone). The same change as Share on the dataset's page and `mr-data dataset publish`, with the same checks and audit record. Owner or Admin only. Making a dataset link or public PUBLISHES it: readers outside the workspace see its live t
archive_datasetcan modifyRetires a whole dataset: every reader loses access, its public page and unlisted link are withdrawn, and its name is free for a new dataset. Nothing it built is deleted, but ONLY Mostly Right support can restore it. The same act as the settings page's delete and `mr-data dataset archive`; the service confirms it against the dataset's stored name itself. Example: {"dataset_id": "…", "confirm": true
list_my_datasetsread-onlyEvery dataset this workspace owns, most recently updated first — not the public catalog. Use it to find the dataset_id for a dataset you or a colleague created earlier. Example: {"limit": 25}. Returns {workspace_id, datasets: [{dataset_id, cloud_dataset_id, name, description, updated_at, dashboard_url}], count}. Cheap: a database read, no backend call. Next: get_my_dataset for one dataset's tables
get_my_datasetread-onlyOne workspace dataset in build terms: name, description, status, each table with its build state, promotion state and live version, the latest run, and any run held waiting for a confirmation. Example: {"dataset_id": "…"}. Returns {dataset_id, name, description, status, version, has_cover, visibility (private, link or public: who can see it), tables: [{table_id, name, status, promotion_status, liv
register_recipeRegisters the JSON recipe that says where the data comes from, how it is shaped and what must be true of it. The server canonicalizes the document and computes its digest — you cannot and must not state one. Identical bytes register once: a repeat returns the same ids. Example: {"recipe": { …the whole recipe document… }}. Read the mostlyright://recipe-reference resource before writing one, and mos
explain_reciperead-onlyChecks a recipe document without registering, writing or running anything — the same evaluator that admits refreshes, plus the fast-path features the harness's `recipe explain` reports. Example: {"recipe": { …the whole recipe document… }}. Returns {refresh_ready, first_blocker, action_plan, rebuild, capabilities, findings, fast_features}. Every finding names a rule_code, the sources it is about, a
forecast_reciperead-onlySays what one full or refresh run of a registered recipe would ask of its sources, before anything is started: per-source request ceilings, runtime at the ceiling, platform spend, and the projected bytes and cost. Warnings name what would slow or block the run. Example: {"recipe_id": "…", "recipe_digest": "…", "mode": "full"}. Returns {recipe_id, recipe_digest, mode, sources, totals, warnings}. St
test_recipeStarts a recipe preflight: a bounded rehearsal of a full run that fetches at most max_pages_per_source pages of each listing (default 1, max 5) and max_upstream_rows rows of each per-row source (default 25), runs the transform and the checks a slice can answer, and reports. Sources that present a paid or stored credential are skipped and reported skipped_paid. It never seals a version and never be
propose_revisionRegisters a proposed revision and returns its immutable recipe coordinates plus a review link. It then starts EXACTLY ONE run: a replay of the named successful run's retained inputs, which reads no upstream source and never becomes live. Nothing else runs — it confirms no run, promotes no table and approves no repair. Example: {"recipe": { …the whole revision document… }, "sources_from_run": "…"}.
replay_runRuns a registered recipe revision against the retained raw inputs of a named successful run of the same table. No upstream acquisition is performed. Replay must be enabled and the inputs must still be retained. Returns {run_id, status, mode, version, dashboard_url}. Replay never becomes live and does not approve a repair. Follow the run's dashboard_url to inspect its comparison; a person approves
start_runRuns a registered recipe. THIS IS THE TOOL THAT DOES THE REAL WORK: it reads the sources and can run for a long time. Start builds in full mode: full runs use one progressive acquisition with an inspection checkpoint after about five minutes and continue automatically. The checkpoint is not an approval gate or a second run. Four modes: full (the whole build), sample (an explicitly requested bounde
confirm_runAuthorizes a held run and starts it. The numbers are the ones already stored on the run — you cannot restate them, which is the point: what is authorized is the server's own projection. Example: {"run_id": "…", "expected_version": 3}. Pass expected_version from the get_run that showed you the projection, so a projection that moved in between is refused rather than silently authorized. Returns the
approve_full_runCompatibility for an existing legacy full run paired with a bounded preview, in awaiting_sample_approval. New full builds use progressive acquisition and never need this tool for their inspection checkpoint. Call it ONLY once the legacy preview has sealed a table you have checked and the user has said to build the whole thing, or on a delegation you recorded with write_note. Example: {"run_id": "…
cancel_runStops a run that is queued, held at the confirmation gate, or running. A run cancelled at the gate never ran. Example: {"run_id": "…"}. Returns the run receipt with status cancelled. A run that already finished cannot be cancelled and says so — read get_run rather than retrying.
get_runread-onlyOne run's current state: status, mode, the clamps it ran under, rows delivered and whether a clamp truncated them, how many pages a many-page source reached, the table and table version it sealed, the failure code and stage when it failed, and the version number a confirm or cancel should send. Provider-derived detail is also labelled under untrusted_provider_content, a list of {source, text?} — t
run_eventsread-onlyOpens the run's event stream, collects up to max_events, and returns as soon as the run reaches a terminal event or wait_seconds elapses — whichever comes first. This is how you watch a build without polling. Example: {"run_id": "…", "from_seq": 0, "max_events": 50, "wait_seconds": 5}. Returns {events: [{seq, type, at, stage, message, rows, bytes, failure_code}], next_from_seq, run_status, termina
list_runsread-onlyThe workspace's own runs, newest first, optionally narrowed to one dataset, one status or one mode. Example: {"dataset_id": "…", "status": "failed", "limit": 20}. Returns {runs: [{run_id, status, mode, dataset_id, table_id, created_at, completed_at, failure_code}], count, complete}. complete false means the walk stopped at its page cap and there are older runs it did not see. ALWAYS pass dataset_i
compare_runsread-onlyReads two runs and says what changed between them: status, mode, rows, bytes, truncated, covered_window, table_version_id, outcome, failure code and stage, created and completed times, and each declared check whose result moved. Use it to tell whether a revision or a refresh delivered more, less or different data than the run before it. Example: {"run_id": "…", "other_run_id": "…"}. Returns {run_i
query_runread-onlyRuns one read-only SQL statement over the parquet a run sealed, available as the relation run_table (not the recipe table name), and waits for the answer. THIS IS HOW YOU CHECK THE DATA IS RIGHT after a successful run: count the rows, look at the range, find the nulls. Example: {"run_id": "…", "sql": "SELECT count(*) AS rows, min(observed_at) AS first, max(observed_at) AS last FROM run_table", "ma
run_artifactsread-onlyThe files a run sealed: the parquet, the column profile, the receipt, the preview. Works on a running, succeeded or failed run — a failed run's partial output is listed too. Example: {"run_id": "…"}. Returns {artifacts: [{artifact_id, kind, size_bytes, digest, media_type}], more}. Bytes are never streamed through this server. Next: get_artifact_download for a URL to fetch yourself.
get_artifact_downloadread-onlyMints a short-lived signed URL for one sealed artifact. Fetch it yourself with a plain GET and no headers; it expires. Example: {"run_id": "…", "artifact_id": "…"}. Returns {url, expires_at, media_type, digest, size_bytes, kind}. Cite the digest. Artifact ids come from run_artifacts. Do not use this to read a few rows — query_run is the cheaper answer. Reads past the free sample (the first 500 row
write_noteAppends one cell to a run's or a dataset's decision record — why a source was chosen, what a check found, what you changed and why. The record is append-only and is what a reader sees beside the data. Write one for every decision worth explaining. Example: {"run_id": "…", "heading": "Dropped the 2019 station file", "markdown": "The 2019 export repeats each hour twice; the API covers the same range
list_notesread-onlyLists the cells of a run's or a dataset's decision record, newest first: the heading, the body, the phase, any typed blocks (source, decision, clarification) and whether a later revision superseded it. Read it before writing a note, so a decision already recorded is revised rather than repeated, and to learn what an earlier build decided and why. Example: {"dataset_id": "…"}. Exactly one of run_id
list_table_partsread-onlyLists the parts (parquet files) one table version is made of: each part's index, part_id (its content digest), artifact_id, the run that sealed it, its row count, its size, its partition, and the lowest and highest value it holds per field (lower_bounds, upper_bounds, keyed by field name). This is what a training loader shards: give worker k of N the parts whose index % N == k. Nothing is download
verify_runread-onlyChecks the table one succeeded run sealed against its own manifest. Without deep it reads the manifest, checks it hashes to the digest it was sealed with and names this run's table version, and checks every part the run sealed is among the parts the run lists; no part is fetched. With deep: true it also re-hashes every part this run sealed against the digest the manifest states. Example: {"run_id"
promote_tablePromotion makes the table's newest passing version the version everyone reads, and starts the recurring refresh that keeps it current. Example: {"table_id": "…", "confirm": true}. It refuses without confirm: true. Only call it when the person you are working for has said to. Check the data with query_run first. Returns {table_id, promotion_status, live_version_id, cadence, dashboard_url}. The prom
reschedule_tableSets a live table's refresh schedule, or replaces the one it has, without starting a run or fetching anything. A table that went live on its first run has NO schedule yet (get_table shows schedule null, the chat shows "No refresh schedule"): this is the tool that gives it one. When the table's recipe cannot refresh yet, the schedule is HELD rather than applied and the answer carries schedule null:
demote_tablecan modifyWithdraws a table's live pointer and detaches its refresh schedule: readers stop being served it and it stops refreshing. Nothing built is deleted, and promote_table later revives the same table. A live table must be demoted before archive_table will retire it. Example: {"table_id": "…", "expected_version": 4}. Pass expected_version from get_table so a table that moved in between is refused rather
archive_tablecan modifyRetires one table from its dataset: it leaves the dataset's table list and frees its name for a new table. The versions it built are not deleted. The service confirms the archive with the table's current stored name itself, so you never send one. Example: {"table_id": "…"}. A live table is refused — call demote_table first. A table with a run still queued, held or running is refused too: cancel_ru
rename_tableChanges one table's name within its dataset. Nothing is rebuilt, re-served or republished, and the table keeps its id, versions and schedule; every reader of the dataset sees the new name. The old name is released, so another table may take it, and a later recipe revision must name the table by its new name. A name is lowercase letters, digits and underscores, starting with a letter, at most 63 ch
get_tableread-onlyOne table as the builder sees it: whether it is promoted, which version is live, the refresh schedule and what the platform has learned about its rhythm, when it last refreshed and why it last failed. Example: {"table_id": "…"}. Returns {table_id, dataset_id, promotion_status, live_version_id, schedule, last_refresh, last_failure, provider_wait, promoted_at, version, untrusted_provider_content}. l
diagnose_tableread-onlyReads one table's current promotion pointers and latest recorded failure. When that failure names a run, it also reads that run and its declared recipe sources, so the diagnosis still works when a failed run never sealed a version. Example: {"table_id": "…"}. Returns {table, latest_failure, failed_run, latest_passing_run, live_version_evidence, raw_and_preview_pointers, schema_difference, diagnosi
list_source_credentialsread-onlyLists named secret metadata and saved workspace connections without secret values. Pass dataset_id to check dataset grants. Follow connections.next_offset with connection_offset to read another bounded page. Returns credentials, connections (status, safe items, grants_status), and a structured source_credentials setup request for the chat UI. Stored or active means enrolled, not a verified provide
normalize_reader_optionsread-onlyResolves the certified Reader family and version and returns default-filled canonical decode options. Validates options only; it does not acquire or decode bytes. Returns family_id, family_version, decode_options and decode_options_json for the recipe.
start_source_inspectionread-onlyPrepares an HTTPS source, opens a bounded research session and queues a source_inspect probe. Supply rights_claim.claim_note with the actual rights evidence or operator assertion; the service hashes its trimmed UTF-8 bytes and returns rights_claim with the real digest. Alternatively supply an already computed claim_evidence_digest; never fabricate a hash. A digest records the claim, not legal veri
get_source_inspectionread-onlyReads one source inspection by session_id and probe_id, waiting up to wait_seconds (default 20) for a queued inspection to settle. Returns bounded evidence with status queued, complete, truncated or failed. A worker can take a few minutes to start, so while it is queued, call again with the same ids without asking the person; an inspection that will never run reads as failed. After about 10 minute
probe_sourceread-onlyQueues one bounded probe of a source start_source_inspection prepared, and returns its coordinates. It reads the SOURCE, before anything is built; the sample_rows tool reads a published table instead. Four kinds: source_inspect (the columns and their inferred types; no cell values), sample_rows (up to limit rows from offset, optionally only some columns), profile_columns (per column: inferred type
get_source_proberead-onlyReads one probe_source probe, waiting up to wait_seconds (default 20) for a queued probe to settle. Returns {session_id, probe_id, probe_kind, state, source_id, failure_code, untrusted_provider_content}. state is queued or claimed while it runs, then succeeded, failed, expired or cancelled. A succeeded probe's answer -- the source's own columns and values -- is labelled under untrusted_provider_co
Alternatives in Search & Research
Compare →
Bitbybit CAD MCPA
Bitbybit 3D parametric CAD API, version-exact, for coding agents: search, describe, examples, guide
beehiivOfficialA
Manage beehiiv newsletters, posts, podcasts, community, subscribers, and analytics.
ARAtlassian Rovo MCP ServerOfficialA
Connect to Atlassian Jira, Confluence, Loom, and more to search, create, and manage your work.
ZOZoomInfoOfficialA
Official ZoomInfo MCP server. Search and enrich companies, contacts, and buyer intent signals.
CACloudinary Asset ManagementOfficialA
Upload, organize, search, and transform images, videos, and files with AI-powered tools.
MAMapboxOfficialA
Geospatial intelligence with Mapbox APIs like geocoding, POI search, directions, isochrones, etc.