npm package: @quadratichq/mcp
Description: MCP server for AI-driven interaction with Quadratic spreadsheets. Works with Cursor, Claude Desktop, and any MCP client.
Author: Quadratic
Latest version: 0.1.0

# @quadratichq/mcp

MCP server for AI-driven interaction with [Quadratic](https://quadratichq.com) spreadsheets. Build spreadsheets with AI using natural language — set cell values, write Python/JS code cells, format data, create charts, and more.

Works with **Cursor**, **Claude Desktop**, and any MCP-compatible client.

## Quick Start

### Cursor

Add to `.cursor/mcp.json` in your project (or global Cursor settings):

```json
{
  "mcpServers": {
    "quadratic": {
      "command": "npx",
      "args": ["-y", "@quadratichq/mcp"]
    }
  }
}
```

The server will automatically instruct the AI to open a live spreadsheet view in Cursor's side panel.

### Claude Desktop

Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):

```json
{
  "mcpServers": {
    "quadratic": {
      "command": "npx",
      "args": ["-y", "@quadratichq/mcp"]
    }
  }
}
```

Open `http://localhost:3300` in a browser to see the live spreadsheet while the AI works.

## Architecture

```
┌─────────────────────────────────────────────────────────────────────┐
│  AI Client (Cursor, Claude Desktop, etc.)                          │
│                                                                     │
│  "Put sales data in A1:C10"                                        │
│       │                                                             │
│       │ stdio (JSON-RPC)                                            │
│       ▼                                                             │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │  @quadratichq/mcp  (Node.js process)                        │   │
│  │                                                              │   │
│  │  ┌──────────────────┐    ┌───────────────────────────────┐  │   │
│  │  │  MCP Server       │    │  Bridge HTTP Server (:3300)   │  │   │
│  │  │  (stdio transport)│    │                               │  │   │
│  │  │                   │    │  GET /        → bridge page   │  │   │
│  │  │  Receives tool    │    │  GET /config  → embed URL     │  │   │
│  │  │  calls, forwards  │───▶│  WebSocket /ws → relay cmds   │  │   │
│  │  │  to bridge        │    │                               │  │   │
│  │  └──────────────────┘    └──────────────┬────────────────┘  │   │
│  └──────────────────────────────────────────┼──────────────────┘   │
│                                              │                      │
└──────────────────────────────────────────────┼──────────────────────┘
                                               │ WebSocket
                                               ▼
                    ┌──────────────────────────────────────────────┐
                    │  Bridge Page (browser tab at localhost:3300)  │
                    │                                               │
                    │  ┌─────────────────┐  ┌───────────────────┐  │
                    │  │                 │  │  Tool Call Log     │  │
                    │  │   Quadratic     │  │  (debug panel)     │  │
                    │  │   Spreadsheet   │  │                    │  │
                    │  │   (iframe)      │  │  → set_cell_values │  │
                    │  │                 │◀─│  ← response [5]    │  │
                    │  │                 │  │  → set_text_formats │  │
                    │  │                 │  │  ← response [6]    │  │
                    │  └────────┬────────┘  └───────────────────┘  │
                    │           │                                    │
                    └───────────┼────────────────────────────────────┘
                                │ postMessage
                                ▼
                    ┌────────────────────────┐
                    │  Quadratic Embed        │
                    │  (app.quadratichq.com)  │
                    │                         │
                    │  Executes tool calls    │
                    │  via AI tool engine     │
                    │  Returns results +      │
                    │  screenshots            │
                    └────────────────────────┘
```

The server runs as a single Node.js process with two roles:

1. **MCP Server** (stdio) — receives tool calls from the AI client via JSON-RPC over stdin/stdout
2. **Bridge Server** (HTTP + WebSocket on port 3300) — serves a page that embeds the Quadratic spreadsheet and relays commands to it

The bridge page is the key piece. The MCP server is a Node.js process that can't talk directly to a browser tab, so the bridge acts as the relay:

- **MCP Server → Bridge**: tool calls are sent over a WebSocket connection
- **Bridge → Quadratic iframe**: commands are forwarded via `postMessage`
- **Quadratic iframe → Bridge → MCP Server**: results flow back the same path in reverse

This architecture means users only need `npx @quadratichq/mcp` — the bridge loads the Quadratic spreadsheet from `app.quadratichq.com` remotely, so there's nothing else to install or run.

## Available Tools

| Category | Tools |
|---|---|
| **Cell Data** | `set_cell_values`, `get_cell_data`, `has_cell_data`, `add_data_table`, `move_cells`, `delete_cells` |
| **Code** | `set_code_cell_value` (Python/JS), `get_code_cell_value`, `set_formula_cell_value`, `rerun_code` |
| **Formatting** | `set_text_formats`, `get_text_formats`, `set_borders`, `merge_cells`, `unmerge_cells` |
| **Sheets** | `add_sheet`, `duplicate_sheet`, `rename_sheet`, `delete_sheet`, `move_sheet`, `color_sheets` |
| **Tables** | `add_data_table`, `convert_to_table`, `table_meta`, `table_column_settings` |
| **Layout** | `resize_columns`, `resize_rows`, `set_default_column_width`, `set_default_row_height`, `insert_columns`, `insert_rows`, `delete_columns`, `delete_rows` |
| **Validation** | `get_validations`, `add_logical_validation`, `add_list_validation`, `remove_validation` |
| **Conditional Formatting** | `get_conditional_formats`, `update_conditional_formats` |
| **Connections** | `get_database_schemas`, `set_sql_code_cell_value` |
| **Misc** | `text_search`, `undo`, `redo`, `get_sheet_info` |

## Configuration

Environment variables can be passed via your MCP client config:

| Variable | Default | Description |
|---|---|---|
| `EMBED_URL` | `https://app.quadratichq.com/embed` | URL of the Quadratic embed to load |
| `PORT` | `3300` | Port for the bridge server |
| `SCREENSHOTS` | `true` | Set to `"false"` to disable screenshot capture (reduces latency) |

Example with custom config:

```json
{
  "mcpServers": {
    "quadratic": {
      "command": "npx",
      "args": ["-y", "@quadratichq/mcp"],
      "env": {
        "EMBED_URL": "https://app.quadratichq.com/embed?embedId=your-embed-id",
        "SCREENSHOTS": "false"
      }
    }
  }
}
```

## Development

```bash
# Install dependencies
npm install

# Run in SSE mode (for browser-based MCP testing)
npm run dev

# Run in stdio mode (for Cursor/Claude Desktop testing)
npm run dev:stdio

# Build for production
npm run build
```

## License

MIT