AI access to Quadratic spreadsheets: open files, run Python/SQL, query connected databases.
The io.github.quadratichq/quadratic-mcp MCP server provides AI access to Quadratic spreadsheets. It supports opening files, running Python/SQL, and querying connected databases. The repository packages the hosted Quadratic MCP server for use as a Cursor plugin via a production streamable HTTP MCP endpoint.
🛠️ Key Features
Access to Quadratic spreadsheets
Open spreadsheet files
Run Python and SQL
Query connected databases
Hosted server exposed through streamable HTTP
🚀 Use Cases
Spreadsheet-driven analysis using Python/SQL
Retrieving data from connected databases
Interactive use of Quadratic content via Cursor
⚡ Developer Benefits
Cursor plugin installation connects to https://mcp.quadratichq.com/mcp
Includes configuration (mcp.json) for enabling the hosted MCP server
Provides usage guidance and rules for safe operation
Adds an on-demand spreadsheet “skill”
⚠️ Limitations
Cursor-plugin packaging described; no additional deployment options provided in this material
Limited tool details beyond the stated Python/SQL, file access, and database querying
Captured live from the server via tools/list.
auth
Authenticate the MCP session with Quadratic.
Actions:
• login() — Start an OAuth device authorization flow. Returns a URL the user must open in a browser to authorize. The flow is completed by confirm_login.
• confirm_login(device_code) — Complete an in-progress login by polling for user authorization. If the response indicates the user has not yet authorized, this action can be called again with the same device_code to continue polling. confirm_login is idempotent: if a later tool call reports "Not authenticated on this connection", call confirm_login again with the same device_code to re-establish auth (some clients use a new session per request, so the session that ran the tool may differ from the one that logged in).
• set_token(token, email?) — Set a JWT directly (used when the OAuth device flow is not available).
• logout() — Clear saved authentication for the current session.
Parameters2
action
string
required
Action to perform: login, confirm_login, set_token, or logout
params
any
optional
Parameters for the action (see tool description)
Raw schema
{
"type": "object",
"properties": {
"action": {
"description": "Action to perform: login, confirm_login, set_token, or logout",
"type": "string"
},
"params": {
"description": "Parameters for the action (see tool description)"
}
},
"required": [
"action"
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "AuthAction"
}
files_read
Read-only file metadata operations on Quadratic files the user has access to. No data is modified. Requires authentication.
Actions:
• list_files() — List all accessible files.
• get_file_info(file_id) — Get metadata for a single file.
Parameters2
action
string
required
Action to perform: list_files or get_file_info
params
any
optional
Parameters for the action (see tool description)
Raw schema
{
"type": "object",
"properties": {
"action": {
"description": "Action to perform: list_files or get_file_info",
"type": "string"
},
"params": {
"description": "Parameters for the action (see tool description)"
}
},
"required": [
"action"
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "FilesReadAction"
}
files_write
File management operations that create or modify state: create a new file, open an existing file to start an editing session, or close a session. Requires authentication.
Actions:
• open_file(file_id?, file_name?) — Open a file by UUID or name and start an editing session. Returns the file's web URL.
• create_file(file_name, team_uuid?) — Create a new blank spreadsheet. If team_uuid is omitted, the user's first team is used. Returns the new file's UUID and web URL; the file must be opened with open_file before it can be edited.
• close_file(file_id) — Close an active editing session.
Parameters2
action
string
required
Action to perform: open_file, create_file, or close_file
params
any
optional
Parameters for the action (see tool description)
Raw schema
{
"type": "object",
"properties": {
"action": {
"description": "Action to perform: open_file, create_file, or close_file",
"type": "string"
},
"params": {
"description": "Parameters for the action (see tool description)"
}
},
"required": [
"action"
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "FilesWriteAction"
}
read_data
Read-only queries on the open spreadsheet. No data is modified. Safe to auto-approve. Call as {"action": "<name>", "params": {...}} — per-action params are listed in the Action Reference below.
Special actions (not shown in the action enum):
• batch — {"action": "batch", "params": {"actions": [{"action": "<name>", "params": {...}}, ...]}}. Runs reads in parallel; individual failures are reported per-entry without short-circuiting.
• context — {"action": "context", "params": {"topic": "<name>"}} or {"action": "context", "params": {"action": "<name>"}}. Returns deeper docs for a topic or a single action's signature. Plural "topics" / "actions" arrays are also accepted and may be combined. Topics: python, javascript, formula, connection, validation, a1, quadratic.
Action Reference
• get_cell_data(selection, page?, sheet_name?) — Returns cell values for a selection in A1 notation. Supports comma-separated ranges to fetch multiple areas in ONE call, including across different sheets. Examples: "A1:B10, D1:E10", "TableName, OtherTable", "'Sheet1'!A1:B10, 'Sheet2'!C1:D10". Table names are globally unique so they work without sheet prefixes. For cell ranges on other sheets use 'SheetName'!Range. Only use when you need the full dataset (aggregations, lookups, analysis). The file summary already includes sample rows. Results may be paginated — use page (0-based) for additional pages.
• has_cell_data(selection, sheet_name?) — Check if any cells in a selection have data. Returns true if ANY cell contains data. Use before creating/moving tables or code to avoid spill errors. All ranges MUST be on the same sheet.
• get_code_cell_value(code_cell_position?, code_cell_name?, sheet_name?) — Get full code from an existing Python, JavaScript, or connection code cell. Do NOT use for formula cells — formulas are already in get_cell_data results and the file summary.
• get_text_formats(selection, page?, sheet_name?) — Get text formatting info. Use table column references for tables ("Table_Name[Column Name]"). Results may be paginated.
• get_validations(sheet_name?) — Get all validations in a sheet.
• get_conditional_formats(sheet_name) — Get all conditional formatting rules. Use to check existing rules before creating/updating/deleting.
• text_search(query, case_sensitive?, whole_cell?, search_code?, regex?, sheet_name?) — Search for text in cell outputs. Supports regex when enabled (e.g., "\d+", "^hello", "foo|bar"). Searches cell outputs only, not code. Booleans default false.
• get_sheet_info() — List all sheets and names.
• get_spreadsheet_context(sheet_name?, include_errors?) — Full context snapshot of the file.
• read_data(selection, sheet_name?, max_rows?) — Read cell data as compact CSV. Auto-tiers: returns all rows for small/medium data (<5000 rows), head+tail preview for large data. Preferred over get_cell_data for most reads.
• outline(sheet_name?) — Structural map of the file: sheets, bounds, tables, code cells, charts, connections, errors. Use to understand file layout before reading data.
• dependencies(position, sheet_name?, direction?) — Trace cell dependencies. direction: "forward" (what this cell reads), "reverse" (what depends on this cell), or "both" (default).
• list_connections(team_uuid?) — List all database connections in a team (PostgreSQL, MySQL, MS SQL, Snowflake, BigQuery, Mixpanel, Google Analytics, Plaid, etc.). Returns each connection's uuid, name, and type. team_uuid is optional — if omitted, the user's only team is used; multi-team users must pass it. Call this BEFORE get_database_schemas or set_sql_code_cell_value to discover the connection_ids and connection types you need.
• get_database_schemas(connection_ids, connection_type, team_uuid) — Get table/column schemas for database connections. Always call before writing SQL. Get connection_ids from list_connections. connection_type: POSTGRES, MYSQL, MSSQL, SNOWFLAKE, BIGQUERY, COCKROACHDB, etc.
• list_agent_connections(team_uuid?) — List the team's ready Agent Connections (third-party REST API bindings). Returns each connection's uuid, name, service, base U
Parameters for the action (see tool description). For batch: {actions: [{action, params}, ...]}
Raw schema
{
"type": "object",
"properties": {
"action": {
"description": "Action to perform: get_cell_data, has_cell_data, get_code_cell_value, get_text_formats, get_validations, get_conditional_formats, text_search, get_sheet_info, get_spreadsheet_context, read_data, outline, dependencies, get_database_schemas, list_connections, list_agent_connections, inspect_agent_connection, or batch",
"type": "string"
},
"params": {
"description": "Parameters for the action (see tool description). For batch: {actions: [{action, params}, ...]}"
}
},
"required": [
"action"
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "ReadDataAction"
}
write_data
Write operations on the open spreadsheet. Call as {"action": "<name>", "params": {...}} — per-action params are listed in the Action Reference below. Numbers, booleans, and nulls in cell values are coerced to strings.
Special actions (not shown in the action enum):
• batch — {"action": "batch", "params": {"actions": [{"action": "<name>", "params": {...}}, ...]}}. Runs writes sequentially; errors short-circuit the batch.
• context — {"action": "context", "params": {"topic": "<name>"}} or {"action": "context", "params": {"action": "<name>"}}. Returns deeper docs for a topic or a single action's signature. Plural "topics" / "actions" arrays are also accepted and may be combined. Topics: python, javascript, formula, connection, validation, a1, quadratic.
Action Reference
Cell Data:
• set_cell_values(top_left_position, cell_values, sheet_name?) — Sets cell values as a 2D string array (first row = headers). top_left_position: single cell in A1 notation. Don't place over existing data unless requested. Values replace existing content; use empty string to clear. For merged cells, place at the anchor (top-left) cell. Prefer this over add_data_table for tabular data; only use add_data_table when the user explicitly asks for a data table or the file already uses data tables. When writing tabular data as plain cells, format the header row afterward with set_text_formats (at least bold) so it's visually distinct — plain cells don't auto-style headers like data tables do. Don't use for formulas or code.
• delete_cells(selection, sheet_name?) — Delete cell values in a selection (A1 notation). Don't delete cells referenced by code cells unless explicitly asked. To delete table columns: "TableName[Column Name]". To delete tables: "TableName".
• move_cells(source_selection_rect, target_top_left_position, sheet_name?) — Move a rectangular block of cells. Target is the top-left corner (single cell). For spilled code cells, move just the anchor cell.
• add_data_table(sheet_name, top_left_position, table_name, table_data) — Adds a data table. Data tables are discouraged by default — only use when the user specifically requests a data table or the file already uses data tables; otherwise use set_cell_values. First row of table_data is headers. Leave 2 rows below and 2 columns right as spacing. All rows must have equal length (use empty strings for missing values). To convert existing data, use convert_to_table instead. To delete a table, use set_cell_values with empty string at the anchor. A single-value formula or code cell MAY be written into a data cell of an editable (imported/value) table — it's stored as in-place single-cell code computing a 1x1 result; avoid the table's name/column-header rows and read-only code-output tables/charts, and don't put multi-cell output (dataframes/charts) inside a table.
Code:
• set_code_cell_value(code_cell_position, code_cell_language, code_cell_name, code_string, sheet_name?) — Sets and runs a Python or JavaScript code cell. Prefer set_formula_cell_value whenever a formula can do the task; only use code when the functionality is not available in formulas (e.g. charts, ML, correlations, complex data transforms, or web/API requests). For static data use set_cell_values. For SQL use set_sql_code_cell_value. IMPORTANT: Always reference sheet data with q.cells() — never hardcode data values. For charts, use Plotly ONLY (import plotly.express or plotly.graph_objects). Do NOT use Matplotlib/Seaborn. Name the output (no spaces/special chars, _ allowed). Placement: Estimate output size before placing. Charts default to 7 wide x 23 tall cells. Cell must be empty (avoids spill error). Leave one extra column/row gap between the code cell and nearest content. Empty sheet → A1.
• set_formula_cell_value(formulas) — formulas: [{code_cell_position, formula_string, sheet_name?}]. Prefer this whenever a formula can do the task; only use set_code_cell_value when formulas can't. For basic historical stock prices use the STOCKHISTORY formula; for financial data with no formula equivalent (adjusted prices, statements, divi
This repository packages the hosted Quadratic MCP server as a Cursor plugin.
Installing it connects Cursor to Quadratic spreadsheets through the production
streamable HTTP MCP endpoint:
plugins/quadratic-mcp/mcp.json adds the hosted Quadratic MCP server.
plugins/quadratic-mcp/rules/ provides light guidance for using Quadratic MCP safely.
plugins/quadratic-mcp/skills/ adds an on-demand spreadsheet workflow skill.
plugins/quadratic-mcp/assets/logo.svg is the marketplace logo.
Usage
After installing the plugin in Cursor, open a chat and ask to work with a
Quadratic spreadsheet. If you are not authenticated yet, ask Cursor to run the
Quadratic MCP auth tool with the login action and complete the device auth
flow.
Example prompts:
"Open my Budget 2026 Quadratic file and summarize it."
"Create a Quadratic spreadsheet from this CSV."
"Add a Python code cell that analyzes sales by month."
"Show me the schema for my connected Postgres database."
Development
Validate the plugin manifest and referenced files:
bash
node scripts/validate-template.mjs
The marketplace manifest lives at .cursor-plugin/marketplace.json. The plugin
manifest lives at plugins/quadratic-mcp/.cursor-plugin/plugin.json.
Install
Tools (5)
authfiles_readfiles_writeread_datawrite_data
Remote endpoint
Streamable HTTP
Hosted server - connect over the network, no local install.