/mcp surface, so reading your own uploaded tables needs no second connection. They are also what widget pipelines point at.
list_datasets
Read-only
List the datasets in the workspaces you belong to — tables extracted from files uploaded to chats and discussions (CSV, spreadsheets, JSON, and tables found in PDFs/screenshots). Returns {id, workspaceId, name, columns, rowCount, updatedAt, deleted} per dataset. THE DISCOVERY CALL: dataset ids are opaque and never guessable, so start here (or take the id the user’s attached file gave you) before describe_dataset / read_dataset. deleted: true means the source file was deleted — the columns still describe what it held, but reading it fails; wire a chart to a live dataset instead. Pass workspaceId to narrow to one workspace; a workspace this connection was not granted is refused, not silently empty. Carry the workspaceId a dataset comes back with into describe_dataset / read_dataset — that is the workspace the call is billed to.
describe_dataset
Read-only
Inspect one dataset before charting it: its column names and inferred types (string | number | date | boolean), its row count, and a 5-row SAMPLE of the actual data. Call this between list_datasets and read_dataset — the sample is what tells you whether a column labelled date really holds dates, which column is the measure, and what the category values look like, so read_dataset’s columns/where/orderBy can be written once instead of guessed at. Cheap: it reads only the head of the file. Pass the workspaceId list_datasets reported for this dataset: it is the workspace the call is billed to, and without it a connection covering several workspaces bills the first one you consented to.
read_dataset
Read-only
Read rows from a dataset — the tool a WIDGET is wired to. Returns {columns, rows, total}: rows are objects keyed by column name with values already coerced to the column’s type (numbers as numbers, dates as ISO strings, empty cells as null), and total is how many rows matched before limit. Narrow server-side rather than client-side: columns picks the fields to return, where filters (an AND of {column, op, value} with op eq | neq | gt | gte | lt | lte | in | contains — in takes an array, contains is a case-insensitive substring test on the text form), orderBy sorts ({column, dir}), and limit caps the result (default 5000). When building a chart, point the widget’s pipeline at THIS tool with the filters it needs — never paste rows into the widget’s config, or the chart freezes at today’s data and stops following the file. If the source file was deleted the call fails with dataset_deleted, naming the file and who removed it; the fix is a re-upload, not a retry. Pass the workspaceId list_datasets reported for this dataset: it is the workspace the call is billed to, and without it a connection covering several workspaces bills the first one you consented to.