mcpbeat Sign in

Quadratic MCP Server

by quadratichq Your server? Claim it
answering

Quadratic is answering right now. Last checked 10 min ago. It exposes 9 tools. Last commit 19 Jun 2026.

AI access to Quadratic spreadsheets: open files, run Python/SQL, query connected databases.

Uptime history 91 days of history · worst day 99%
91 days agonow
100.0%
Uptime 24h
91 of 91 checks
9
Tools
read from the server
630 ms
Response time
average over 24h
0
Stars
last commit 19 Jun 2026

What changed 10

Every tool that appeared, vanished or quietly changed what it asks for. Recorded since 12 August 2026. No other catalogue keeps this.

3 Nov 4 tools appeared doc_read, doc_write, slide_read and 1 more
3 Nov 2 tool descriptions were rewritten files_read, files_write
27 Oct a tool description was rewritten files_write
26 Aug a tool description was rewritten write_data
12 Aug a tool description was rewritten read_data
12 Aug a tool changed the parameters it asks for read_data

Nothing serious here today

Today is the operative word: we check Quadratic every 15 minutes and re-read its code on every release. Watch it and you find out the day that stops being true.

Three servers free · no card

Connect this server

Endpoint below is the one we actually reach during checks — not the one copied from a README. Last verified 10 min ago.

run in your terminal
claude mcp add quadratic-mcp --transport http https://mcp.quadratichq.com/mcp
Settings → Connectors → Add custom connector, then paste this address
https://mcp.quadratichq.com/mcp
~/.codex/config.toml
[mcp_servers.quadratic-mcp]
url = "https://mcp.quadratichq.com/mcp"
.cursor/mcp.json
{
  "mcpServers": {
    "quadratic-mcp": {
      "url": "https://mcp.quadratichq.com/mcp"
    }
  }
}
.vscode/mcp.json
{
  "servers": {
    "quadratic-mcp": {
      "type": "http",
      "url": "https://mcp.quadratichq.com/mcp"
    }
  }
}

Available tools 9

Read directly from the server with tools/list, grouped by what they act on. If a tool disappears, we record the date.

data
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, chart, pivot_table. 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). • export_pdf(options?) — Export the file as a PDF with Excel-parity print semantics. Returns {mime_type, size_bytes, data_base64}. options is a camelCase object: {sheetIds?: [id], fileName?, pageSetup?: {paperSize ("letter"|"legal"|"tabloid"|"a3"|"a4"|"a5"|...), orientation ("portrait"|"landscape"), margins {left,right,top,bottom,header,footer} (inches), scaling ({type:"zoom",percent} or {type:"fitTo",width?,height?}), pageOrder ("downThenOver"|"overThenDown"), centerHorizontally?, centerVertically?, printGridlines?, printHeadings?, header/footer {odd:{left,center,right}, even?, first?} with Excel codes (&P page, &N total, &D date, &T time, &F file, &A sheet, &B bold)}, sheetOptions?: {"<sheetId>": {pageSetup?, printArea? ("A1:F20"), repeatRows? ([1,2]), repeatCols?, rowBreaks?, colBreaks?}}}. Omit options for sensible defaults (letter portrait, 100% zoom, all sheets). • 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 URL, auth pattern, and `{{SECRET_NAME}}` references to use in fetch code. team_uuid is optional — if omitted, the user's only team is used; multi-team users must pass it. Reference secrets via `{{SECRET_NAME}}` in Python/JavaScript fetch code; the connection proxy substitutes team secret values at request time. • inspect_agent_connection(connection_id, team_uuid?) — Get the full schema (resources, endpoints, fields, docs URLs) and plan for one ready Agent Connection by uuid (from list_agent_connections). Call BEFORE writing fetch code against a connection so you don't guess at endpoints. team_uuid is optional with the same single-team fallback as list_agent_connections. Batch: • batch(actions) — actions: [{action, params}]. Runs reads in parallel through this same tool; per-entry failures are reported in the result without short-circuiting the batch. `action` may be any name from this reference. Nested `context` items are allowed and returned alongside the reads.
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, chart, pivot_table. 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(top_left_position, table_name, table_data, sheet_name?) — 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, dividends, real-time/intraday, technicals, economic data) use set_code_cell_value with Python + q.financial. Don't prefix formulas with =. code_cell_position can be a single cell ("A1"), range ("A1:A10"), or collection ("A1,A2:B2"). Cell references adjust relatively (like copy-paste). Use $ for absolute references ($A$1). Place near referenced data, no extra spacing needed. Aggregations go directly below or beside data. • rerun_code(sheet_name?, selection?) — Re-run code cells. Do NOT call after set_code_cell_value, set_formula_cell_value, or set_sql_code_cell_value — those already run automatically. Only use to refresh unchanged code (e.g., external data). • set_sql_code_cell_value(code_cell_position, code_cell_name, connection_kind, sql_code_string, connection_id, sheet_name?) — Sets and runs a SQL connection code cell. connection_kind: POSTGRES, MYSQL, MSSQL, SNOWFLAKE, BIGQUERY, COCKROACHDB, MARIADB, SUPABASE, NEON, MIXPANEL, GOOGLE_ANALYTICS, PLAID, QUICKBOOKS. Always call get_database_schemas before writing SQL. Cell must be empty. Empty sheet → A1. Import: • import_file(file_name, file_data, sheet_name?, insert_at?) — Import CSV/Excel/Parquet. file_data: base64-encoded. Extension determines format (.csv, .xlsx/.xls, .parquet/.parq/.pqt). To create a new file from an import, call files create_file first, then import_file. Formatting: • set_text_formats(formats) — formats array: [{selection, bold?, italic?, underline?, strike_through?, text_color?, fill_color?, align?, vertical_align?, wrap?, font_size?, number_type?, currency_symbol?, numeric_decimals?, numeric_commas?, date_time?, sheet_name?}]. For table columns use table references ("Table_Name[Column Name]") instead of A1 ranges. Colors: hex ("#FF0000"), empty string to remove. align: "left"/"center"/"right". vertical_align: "top"/"middle"/"bottom". wrap: "wrap"/"clip"/"overflow". number_type: "number"/"currency"/"percentage"/"exponential" (currency requires currency_symbol, e.g. "$"). numeric_decimals: integer >= 0, number of decimal places to display (e.g. "format percents as 2 decimals" → 2). Percentages: .01 → 1%, 1 → 100%. date_time: chrono format e.g. "%Y-%m-%d". font_size: points (default 10). Set to null to clear any format. • set_borders(borders) — borders: [{selection, border_selection, color, line, sheet_name?}]. border_selection: all/inner/outer/horizontal/vertical/left/top/right/bottom/clear. line: line1 (thin)/line2 (medium)/line3 (thick)/dotted/dashed/double/clear. color: CSS color string. • merge_cells(selection, sheet_name?) — Merge a range of cells (e.g. A1:D1). All values except top-left are cleared. • unmerge_cells(selection, sheet_name?) — Unmerge merged cells overlapping the selection. Sheets: • add_sheet(sheet_name, insert_before_sheet_name?) — Sheet names: unique, max 31 chars, no / \ ? * : [ ] • duplicate_sheet(sheet_name_to_duplicate, name_of_new_sheet) • rename_sheet(sheet_name, new_name) • delete_sheet(sheet_name) • move_sheet(sheet_name, insert_before_sheet_name?) • color_sheets(sheet_names_to_color) — [{sheet_name, color}]. color: CSS color string. • set_frozen_panes(sheet_name?, frozen_row_count, frozen_column_count) — freeze/pin rows from row 1 and columns from column 1. Use 0 to unfreeze an axis. Tables: • convert_to_table(selection, table_name, first_row_is_column_names, sheet_name?) — Convert existing cell data to a data table. Only use when the user explicitly asks for a data table or the file already uses data tables; otherwise keep data as plain cells. Selection must NOT contain code cells or existing tables. Table name row is added above, pushing data down by one row. • table_meta(table_location, new_table_name?, show_name?, show_columns?, alternating_row_colors?, first_row_is_column_names?, sheet_name?) — Set table metadata. table_location: anchor cell (top-left, e.g. A5). • table_column_settings(table_location, column_names, sheet_name?) — column_names: [{old_name, new_name, show}]. Only include columns to change. To delete columns use delete_cells with "TableName[Column Name]". Layout: • resize_columns(selection, size, sheet_name?) — size: "auto" (fit content), "default", or pixels (20-2000). • resize_rows(selection, size, sheet_name?) — size: "auto", "default", or pixels (10-2000). • set_default_column_width(size, sheet_name?) — size in pixels (20-2000, default 100). • set_default_row_height(size, sheet_name?) — size in pixels (10-2000, default 21). • insert_columns(column, right, count, sheet_name?) — column: letter (e.g. "C"). right: true=insert right, false=insert left. • insert_rows(row, below, count, sheet_name?) — row: number. below: true=insert below, false=insert above. • delete_columns(columns, sheet_name?) — columns: array of letters (e.g. ["A", "C"]). • delete_rows(rows, sheet_name?) — rows: array of numbers (e.g. [1, 5, 10]). Charts (Excel-native; prefer over Plotly/Chart.js code cells for standard charts of sheet data — see the "chart" topic for details): • add_chart(chart_type, position, series, sheet_name?, title?, name?, categories?, legend?, x_axis_title?, x_axis_min?, x_axis_max?, x_axis_number_format?, y_axis_title?, y_axis_min?, y_axis_max?, y_axis_number_format?, width_cells?, height_cells?, chart_3d_rot_x?, chart_3d_rot_y?, chart_3d_perspective?, chart_3d_depth_gap?) — Adds an Excel-native chart anchored at position (single cell). chart_type: column, column_stacked, column_percent_stacked, bar, bar_stacked, bar_percent_stacked, line, line_stacked, area, area_stacked, pie, doughnut, scatter, scatter_line, bubble, radar, radar_filled, stock, column_3d, bar_3d, line_3d, area_3d, pie_3d, waterfall, funnel, histogram, pareto, box_whisker, treemap, sunburst, region_map. series: [{values, name?, bubble_sizes?, color?}] where values is one row or column of numbers in A1 ("B2:B13", table references allowed). categories: labels range (x values for scatter/bubble). Charts float over the grid (no spill errors); the anchor is nudged to free space if the cell would cover content. Returns the chart_id for update_chart/delete_chart. • update_chart(chart_id, sheet_name?, chart_type?, position?, series?, title?, name?, categories?, legend?, axis and 3d options as in add_chart) — Changes an existing chart; omitted arguments leave that part unchanged. Chart ids are returned by add_chart and listed in the file context under "Native Chart". • delete_chart(chart_id, sheet_name?) — Removes a chart. Pivot Tables: • set_pivot_table(action, pivot_table_name?, sheet_name?, source?, destination?, rows?, columns?, values?, filters?, layout?, values_layout?, row_grand_total?, column_grand_total?, subtotal_position?) — Creates ("create"), reconfigures ("update"), or removes ("delete") a PivotTable: a live cross-tabulation that groups source rows and aggregates values, recomputing when the source changes. Prefer it over SUMIFS or a Python groupby for "totals by category" requests. Reference source columns by header name, not letter. source (create): A1 range with a header row or a table name. destination (create): "new_sheet" (default) or a top-left cell. rows/columns: [{field, label?, sort?, show_totals?, group_by?, numeric_interval?}]. values (at least one): [{field, aggregation?, name?, show_as?, number_format?, decimals?, visual?}]. filters: [{field, include?, exclude?}]. For update: null leaves an area as it is, an empty array clears it — send only the areas you're changing. pivot_table_name is required for update/delete; names are listed in the file context. The report's cells are read-only; change it with this action. See the "pivot_table" topic for details. Validation: • add_logical_validation(selection, show_checkbox?, ignore_blank?, sheet_name?) — True/false validation with optional checkbox. • add_list_validation(selection, list_source_list?, list_source_selection?, drop_down?, ignore_blank?, sheet_name?) — list_source_list: comma-separated values ("Item 1, Item 2"). list_source_selection: A1 cell reference. Use one, not both. • remove_validation(selection, sheet_name?) — Remove all validations from the selection. Conditional Formatting: • update_conditional_formats(sheet_name, rules) — rules: [{action, id?, selection?, type?, rule?, bold?, italic?, underline?, strike_through?, text_color?, fill_color?, apply_to_empty?, color_scale_thresholds?, auto_contrast_text?}]. action: "create"/"update"/"delete". type: "formula" (apply styles when formula is true) or "color_scale" (gradient colors). For formula type: rule examples: "A1>100", "ISBLANK(A1)", "AND(A1>=5,A1<=10)". For color_scale: thresholds: [{value_type: "min"/"max"/"number"/"percent"/"percentile", value, color}]. For table columns use table references instead of A1 ranges. For delete: only id required. History: • undo(count?) — Default 1. • redo(count?) — Default 1. Batch: • batch(actions) — actions: [{action, params}]. Runs writes sequentially through this same tool; errors short-circuit the batch. `action` may be any name from this reference. Nested `context` items are allowed and returned alongside the writes.
doc
doc_read
Read-only queries on the open document (a file whose kind is DOC). No data is modified. Safe to auto-approve. Open the document first with files_write(open_file). Call as {"action": "<name>", "params": {...}}. Blocks are named by a path "<section>.<block>" (e.g. "0.3") and carry a hash; doc_write needs the hash to change or delete a block. Actions: • doc_outline() — Headings with their paths and hashes, plus block count, word count and block types. Start here for long documents. • read_doc(format?, from?, limit?) — Blocks in order, each {path, hash, type, content}. format: "markdown" (default) or "json" (ProseMirror JSON). Paginate with from (default 0) and limit (default 200, max 1000); next_from is null on the last page. • search_doc(query, limit?, case_sensitive?, whole_word?, regex?) — Text matches, each with the block's path and hash and a snippet. • context() — The full guide to documents: block model, Markdown support, placeholders, batches.
doc_write
Edits to the open document (a file whose kind is DOC). Edits apply live for anyone viewing the document. Requires edit access. Call as {"action": "<name>", "params": {...}}. Read the document first (doc_read): paths shift as blocks are added or removed, and replace_blocks / delete_blocks must pass each block's hash from that read — if a block changed since, the edit is refused and nothing changes. Every edit returns the paths and hashes of the blocks it wrote, and saved: false if it hadn't been confirmed yet (it is still applied). content is Markdown by default (headings, emphasis, links, lists, quotes, code, tables, images, ---), or ProseMirror JSON with format: "json". Keep any <qd-node .../> placeholders from read_doc when writing content back; they stand for footnotes, comments and other content Markdown can't express. Actions: • append(content, format?) — Add blocks at the end. • insert_blocks(position, path?, hash?, content, format?) — position: "start", "end", "before" or "after"; before/after need the anchor block's path. • replace_blocks(blocks, content, format?) — Replace consecutive blocks in one section; blocks: [{path, hash}, ...]. • delete_blocks(blocks) — Delete consecutive blocks in one section; blocks: [{path, hash}, ...]. • find_replace(find, replace, case_sensitive?, whole_word?, regex?) — Replace text throughout; replacements keep the formatting of the text they replace. • batch(operations) — Up to 100 edits as one all-or-nothing change: {"operations": [{"action": "<name>", "params": {...}}, ...]}. Paths in later operations refer to the document as earlier ones left it.
files
files_read
Read-only file metadata operations on Quadratic files the user has access to. No data is modified. Requires authentication. Files are spreadsheets (kind GRID, edited with read_data / write_data), documents (kind DOC, edited with doc_read / doc_write) or presentations (kind SLIDE, edited with slide_read / slide_write). Actions: • list_files(kinds?) — List accessible files with their kind. kinds: ["GRID"], ["DOC"] or ["SLIDE"] limits the list to those kinds. • get_file_info(file_id) — Get metadata for a single file, including its kind and web URL.
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 spreadsheet, document or presentation by UUID or name and start an editing session. Returns the file's kind and web URL. Use read_data / write_data on a spreadsheet, doc_read / doc_write on a document and slide_read / slide_write on a presentation. The open is remembered for your user across MCP sessions (last open wins) — clients that use a new session per request do not need to re-open after auth(confirm_login). • create_file(file_name, team_uuid?, kind?) — Create a new blank spreadsheet (kind "GRID", the default), document (kind "DOC") or presentation (kind "SLIDE"). 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.
slide
slide_read
Read-only queries on the open presentation (a file whose kind is SLIDE). No data is modified. Safe to auto-approve. Open the presentation first with files_write(open_file). Call as {"action": "<name>", "params": {...}}. Slides and shapes have stable ids; slide_write addresses edits by them. Shape positions and sizes (xfrm: x, y, cx, cy, rot) are in EMU (914400 per inch, 12700 per point) unless units is "in" or "pt". Actions: • deck_outline() — Every slide's id, index, layout, title, shape count, whether it has notes and open comments, plus slide size, footer, comment count and available layouts. Start here. • read_deck(format?, units?, from?, limit?, slide_ids?) — Slides with their shapes (type sp / pic / cxnSp / tbl, xfrm, placeholder, geometry, text, fill, line, table style/column widths/row heights/cells), notes and comments, plus the theme (colors and fonts) and footer. format: "markdown" (default) or "json" (ProseMirror JSON). Paginate with from (default 0) and limit (default 50, max 500), or pass slide_ids; next_from is null on the last page. • search_deck(query, limit?, case_sensitive?, whole_word?, regex?) — Text matches across shapes, table cells and notes, each with slide id, shape id and a snippet. • read_comments(slide_id?, include_resolved?) — Comment threads (author, text, replies, resolved, anchor shape) for the deck or one slide. • context() — The full guide to presentations: slides, shapes, units, layouts, Markdown text, batches.
slide_write
Edits to the open presentation (a file whose kind is SLIDE). Edits apply live for anyone viewing the presentation. Requires edit access. Call as {"action": "<name>", "params": {...}}. Read the presentation first (slide_read deck_outline or read_deck) to get slide and shape ids. Every edit returns what it wrote (new ids, placeholder shapes, z-order) and saved: false if it hadn't been confirmed yet (it is still applied). Text content is Markdown by default (paragraphs, - bullets with two-space nesting, 1. numbering, **bold**, *italic*, ~~strike~~, <u>, <sup>, <sub>, links), or ProseMirror JSON with format: "json". Lengths are EMU unless units is "in" or "pt". Layouts: title, obj (Title and Content, the default), secHead, twoObj, twoTxTwoObj, titleOnly, blank, objTx, picTx — names or labels. Actions: • add_slide(layout?, after_slide_id?, index?, title?, body?, notes?, format?) — Add a slide and fill its title/body placeholders. Returns the slide id and its shapes. • delete_slides(slide_ids) / duplicate_slides(slide_ids) / move_slide(slide_id, index). • update_slide(slide_id, layout?, background?, transition?, hidden?, notes?, format?) — null clears background or transition; a new layout keeps placeholder text. reset_slide(slide_id) — Put placeholders back where the layout has them (PowerPoint's Reset). • set_text(slide_id, shape_id? | placeholder?, cell?, content, format?) — Replace a shape's text; placeholder is "title", "subtitle" or "body"; cell: {row, col} for a table. • format_text(slide_id, shape_id? | placeholder?, cell?, paragraphs?, match?, case_sensitive?, whole_word?, regex?, style) — Format text in place without retyping it. style: {bold?, italic?, underline?, strike?, superscript?, subscript?, font_family?, font_size_pt?, color?, highlight?, caps: "all" | "small"?, letter_spacing_pt?, link?, align: "left" | "center" | "right" | "justify"?, line_height?, space_before_pt?, space_after_pt?, indent_pt?, list: "none" | "bullet" | "number"?}; null clears a property. Scope with paragraphs (zero-based indices as read_deck lists them) and/or match (only the matching text; paragraph properties apply to paragraphs containing a match). Omit cell on a table to format every cell. • add_shape(slide_id, shape, geometry?, xfrm?, units?, name?, text?, format?, fill?, line?, body_pr?, src?, rows?, cols?, cells?) — shape: "text_box", "shape" (with geometry e.g. rect, ellipse, rightArrow), "connector", "picture" (src data/https URL) or "table" (rows/cols or cells text). Omit xfrm for a centered default size. • update_shape(slide_id, shape_id, xfrm?, units?, name?, geometry?, fill?, line?, body_pr?, hidden?, descr?, src?, crop?) — xfrm may be partial; null removes fill, line, descr or crop. src and crop ({l?, t?, r?, b?} fractions of each edge) are for pictures. • delete_shapes(slide_id, shape_ids) / duplicate_shapes(slide_id, shape_ids) / reorder_shapes(slide_id, shape_ids, move: "front" | "back" | "forward" | "backward"). • align_shapes(slide_id, shape_ids, alignment: "left" | "center" | "right" | "top" | "middle" | "bottom") — One shape aligns to the slide, several to each other. distribute_shapes(slide_id, shape_ids, axis: "horizontal" | "vertical") — Space three or more shapes evenly. • group_shapes(slide_id, shape_ids) — Group two or more shapes; they then share a group_id. ungroup_shapes(slide_id, shape_ids) — Dissolve the groups those shapes belong to. • edit_table(slide_id, shape_id, op: "insert_row" | "delete_row" | "insert_column" | "delete_column", at). • format_table(slide_id, shape_id, style?, first_row?, band_row?, col_widths?, row_heights?, units?, cells?, cell_fill?, cell_anchor?) — Table style (mediumStyle2Accent1, lightStyle1, themedStyle1Accent1, noStyle), header row and banding, one width per column / one height per row (the table resizes to fit), and fill or text anchor (t|ctr|b) for the given cells (default all). merge_cells(slide_id, shape_id, from, to) / split_cell(slide_id, shape_id, cell) — Merge the rectangle of cells (their text joins the top-left cell) or split a merged cell again. • find_replace(find, replace, case_sensitive?, whole_word?, regex?) — Replace text throughout; replacements keep the formatting of the text they replace. • update_presentation(slide_size_preset?, slide_size?, units?, scale_content?, theme?, footer?) — slide_size_preset is "16:9" | "4:3" | "16:10", slide_size is a custom {cx, cy}; shapes scale to the new size unless scale_content is false. theme: {name?, colors?: {dk1, lt1, dk2, lt2, accent1–accent6, hlink, folHlink}, fonts?: {major, minor}} merges into the current theme. footer: {show_slide_number?, show_date?, footer_text?} or null to remove. • add_comment(slide_id, shape_id?, x?, y?, units?, text) — Start a comment thread, anchored to a shape when shape_id is given. reply_to_comment(comment_id, text) / update_comment(comment_id, text?, resolved?) / delete_comments(comment_ids). • batch(operations) — Up to 100 edits as one all-or-nothing change: {"operations": [{"action": "<name>", "params": {...}}, ...]}. Ids created by earlier operations aren't available to later ones in the same batch.
auth
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.

Endpoints

URLTransportStateLatencyChecked
https://mcp.quadratichq.com/mcp streamable-http answering 673 ms 10 min ago

Alternatives to Quadratic

same job, measured the same way
A2db
by agentic-eng

Safe, read-only database access for AI agents. 5 databases, batch queries, SQLGlot.

124 installs/wk local only
PlanetScale
by planetscale

Connect to PlanetScale databases, branches, schema, query insights, and execute SQL

answering
Postgres
by waystation

Connect to your PostgreSQL database to query data and schemas.

answering
QueryDesk
by querydesk

Governed SQL access to your databases: redaction, query review and an audit log.

answering
Dataassist Io
by dataassistio

Query your org's data in natural language — read-only MCP access to SQL, NoSQL, files & warehouses.

answering
Dbx
by t8y2

Query databases from AI agents using connections configured in DBX.

9 790 installs/wk local only
Supabase
by waystation

Connect to your Supabase database to query data and schemas.

answering
Litebase
by cloudcorprecords

SQLite database access for agents: query, write, create and describe tables, record insights.

289 installs/wk local only

Quadratic — questions

Answers built from our own checks of this server.

What can Quadratic do?
It exposes 9 tools, read directly from the server on our last check. Among them: auth, doc_read, doc_write, files_read, files_write, read_data and 3 more. The full list with descriptions is on this page — we take it from the server itself via tools/list, not from a README. How MCP servers expose tools in the first place →
What is Quadratic mostly used for?
Its tools cluster around files, data and slide. That is what this server is built to work with — the grouping comes from the actual tool names, not from a category we assigned.
Is Quadratic working right now?
We send a real MCP handshake every 15 minutes. Over the last 24 hours 91 of 91 checks got a reply (100.0%), average response time 630 ms. The bar chart above shows every period we have measured.
How do I connect Quadratic?
Copy the ready config from this page. We generate it for Claude Code, Claude Desktop, Codex, Cursor and VS Code, each in the form that client actually reads. It is a remote server, so there is nothing to install — the client connects to the address.
Does Quadratic need an API key?
No. Quadratic completed a full MCP handshake with us as an anonymous client and listed its tools without asking for anything. All 9 of them are readable on this page. This is what we observed, not what the docs claim.
How fast is Quadratic?
It answers our handshake in 630 ms on average, which is faster than 18% of all working MCP servers we measure. That is on the slow side — worth knowing if the tool sits inside an interactive loop. The comparison comes from our own checks across the whole registry, every 15 minutes.
Is Quadratic open source?
The code is open source: it is published under the MIT licence, written in JavaScript and 0 stars on GitHub. The licence covers the code in the repository, not the hosted service at mcp.quadratichq.com, which runs on its operator's own terms.