Quadratic
Server Details
AI access to Quadratic spreadsheets: open files, run Python/SQL, query connected databases.
- Status
- Healthy
- Last Tested
- Transport
- Streamable HTTP
- URL
- Repository
- quadratichq/quadratic-mcp-plugin
- GitHub Stars
- 0
Glama MCP Gateway
Connect through Glama MCP Gateway for full control over tool access and complete visibility into every call.
Full call logging
Every tool call is logged with complete inputs and outputs, so you can debug issues and audit what your agents are doing.
Tool access control
Enable or disable individual tools per connector, so you decide what your agents can and cannot do.
Managed credentials
Glama handles OAuth flows, token storage, and automatic rotation, so credentials never expire on your clients.
Usage analytics
See which tools your agents call, how often, and when, so you can understand usage patterns and catch anomalies.
Tool Definition Quality
Average 4.6/5 across 5 of 5 tools scored. Lowest: 3.9/5.
Each tool targets a clearly distinct concern: auth handles session lifecycle, files_read lists metadata, files_write manages file sessions, read_data queries spreadsheet contents, and write_data modifies them. No two tools have overlapping purposes.
Tool names follow inconsistent conventions: 'auth' is a bare noun, 'files_read' and 'files_write' use noun_verb order, while 'read_data' and 'write_data' use verb_noun order. This mixed pattern makes it harder to predict related tool names.
Five top-level tools form an elegant umbrella structure that groups dozens of actions into meaningful categories. The count is ideal for guiding an agent to the correct tool without overwhelming it.
The surface covers the full spreadsheet lifecycle: authentication, file management, cell/range operations, formulas, code, SQL, formatting, sheets, tables, charts, pivot tables, validation, and history. Missing file deletion/rename and some advanced sheet management are minor gaps that can be worked around.
Available Tools
5 toolsauthADestructiveInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | Action to perform: login, confirm_login, set_token, or logout | |
| params | No | Parameters for the action (see tool description) |
Tool Definition Quality
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description richly discloses behavior beyond annotations: login returns a URL, confirm_login is idempotent and can be polled repeatedly, set_token directly sets a JWT, and logout clears saved auth. It also explains the nuance that some clients use new sessions per request, which is critical for effective use. This does not contradict the annotations (destructiveHint=true aligns with logout; idempotentHint=false is clarified per-action).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a short opening sentence followed by a bulleted list of actions. Each bullet is concise, information-dense, and directly relevant. No fluff or repetition; every sentence contributes to understanding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (multiple actions, async polling, session nuances) and the generic schema, the description is remarkably complete. It covers all actions, their parameters, step-by-step flow, idempotent behavior, and error recovery. No output schema exists, but the description clarifies expected inputs and key outputs like the login URL.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema only provides generic 'action' and 'params' fields. The description compensates fully by specifying the arguments for each action: login() takes no params, confirm_login(device_code) requires a device code, set_token(token, email?) takes a token and optional email, and logout() takes none. This is essential guidance that the schema does not provide.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states 'Authenticate the MCP session with Quadratic'—a specific verb and resource. It then enumerates four distinct actions (login, confirm_login, set_token, logout), making the tool's purpose unambiguous and clearly distinct from sibling file/data tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit usage guidance is provided for each action: use login for OAuth device flow, confirm_login to complete/poll authorization, set_token when OAuth is unavailable, and logout to clear auth. It also instructs when to re-call confirm_login (on 'Not authenticated' errors) due to session differences, offering concrete when-to-use and alternative guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
files_readARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | Action to perform: list_files or get_file_info | |
| params | No | Parameters for the action (see tool description) |
Tool Definition Quality
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, so the safety profile is known. The description adds 'No data is modified' and 'Requires authentication,' which are useful behavioral details not covered by annotations. It also enumerates the exact actions, providing clarity on what the tool does beyond the hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well-organized: a top-line purpose statement, then a bulleted list of actions. Every sentence or bullet adds distinct value, with no redundant content or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple metadata tool with two actions, the description is largely complete given the read-only and idempotent annotations. It lacks return-value details and parameter types/formats, but the absence of an output schema and the low complexity keep this from being a major gap. The description sufficiently supports correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides only a generic 'params' object with a note to see the tool description. The description compensates fully by specifying the two actions and their parameters: list_files() takes no params and get_file_info(file_id) takes a file_id. This is essential meaning that the schema lacks, giving the agent the information needed to invoke the tool correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear statement: 'Read-only file metadata operations on Quadratic files the user has access to.' This uses a specific verb ('read'), resource ('file metadata'), and scope ('user has access'), and the read-only qualifier distinguishes it from the sibling files_write. The two listed actions further clarify the exact operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description states it is for read-only metadata and requires authentication, giving clear context for when to use it. However, it does not explicitly mention alternatives like read_data or exclude content reads, so the differentiation from sibling tools is implicit rather than direct.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
files_writeADestructiveInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | Action to perform: open_file, create_file, or close_file | |
| params | No | Parameters for the action (see tool description) |
Tool Definition Quality
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate mutation/destruction, and the description adds meaningful context: it notes authentication requirements, describes return values (web URL, UUID), and explains the open-before-edit sequencing. It does not delve into destructive specifics, but the annotation already flags that.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description opens with a one-sentence summary then uses a clean bulleted list for each action. Every sentence adds needed information—parameters, return values, and preconditions—with no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a multi-action tool with no output schema, the description covers return values, parameter defaults, sequencing, and authentication. It lacks error-handling details and explicit alternatives, but is sufficient for an agent to invoke the tool correctly in most cases.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the schema has high coverage, its 'params' property just points to the description. The description compensates by fully listing each action's parameters, optionality markers, and default behaviors, which goes beyond the top-level schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states this is for file management operations that create or modify state, and enumerates three concrete actions (open_file, create_file, close_file) with their resources. It distinguishes from siblings like files_read, though it does not explicitly contrast with write_data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides useful usage context such as requiring authentication, the need to open a file before editing, and the default behavior when team_uuid is omitted. However, it does not explicitly state when to use this tool instead of files_read or write_data, leaving some ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_dataARead-onlyIdempotentInspect
Read-only queries on the open spreadsheet. No data is modified. Safe to auto-approve. Call as {"action": "", "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": "", "params": {...}}, ...]}}. Runs reads in parallel; individual failures are reported per-entry without short-circuiting. • context — {"action": "context", "params": {"topic": ""}} or {"action": "context", "params": {"action": ""}}. 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?: {"": {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.
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | 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, export_pdf, get_database_schemas, list_connections, list_agent_connections, inspect_agent_connection, or batch | |
| params | No | Parameters for the action (see tool description). For batch: {actions: [{action, params}, ...]} |
Tool Definition Quality
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint/idempotentHint annotations, the description adds 'Safe to auto-approve', explains batch per-entry failure without short-circuiting, pagination for large results, team_uuid fallback behavior for single-team users, and secret substitution via {{SECRET_NAME}}. These are meaningful operational disclosures.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Extremely long but well-organized into sections (general, special actions, action reference, batch). Each action entry is concise and front-loaded with behavior. Some repetition (e.g., team_uuid optional note) but every sentence adds necessary operational detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool is a dispatcher for 18+ sub-actions with no output schema, the description is remarkably complete: it covers return shapes (e.g., list_connections returns uuid/name/type, export_pdf returns mime_type/size_bytes/data_base64), pagination, error handling, prerequisites, and optional parameter behavior. Nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema only has 'action' and 'params' with generic descriptions. The description provides full parameter semantics for every sub-action, including A1 notation selection formats, optional parameters with defaults, regex examples, output formats for export_pdf, and connection types. This compensates entirely for schema sparsity.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description states 'Read-only queries on the open spreadsheet' with explicit 'No data is modified', clearly distinguishing from write_data sibling. It enumerates a full action reference, making the dispatcher role unambiguous. The verb+resource pairing is specific and actionable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use guidance: 'Use before creating/moving tables or code to avoid spill errors', 'Call this BEFORE get_database_schemas or set_sql_code_cell_value', 'Preferred over get_cell_data for most reads', and 'Do NOT use for formula cells'. Also includes call format and special batch/context usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
write_dataADestructiveInspect
Write operations on the open spreadsheet. Call as {"action": "", "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": "", "params": {...}}, ...]}}. Runs writes sequentially; errors short-circuit the batch. • context — {"action": "context", "params": {"topic": ""}} or {"action": "context", "params": {"action": ""}}. 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(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, 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.
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | Action to perform: set_cell_values, delete_cells, move_cells, add_data_table, set_code_cell_value, set_formula_cell_value, rerun_code, set_text_formats, set_borders, merge_cells, unmerge_cells, add_sheet, duplicate_sheet, rename_sheet, delete_sheet, move_sheet, color_sheets, set_frozen_panes, convert_to_table, table_meta, table_column_settings, resize_columns, resize_rows, set_default_column_width, set_default_row_height, insert_columns, insert_rows, delete_columns, delete_rows, add_logical_validation, add_list_validation, remove_validation, update_conditional_formats, add_chart, update_chart, delete_chart, set_pivot_table, set_sql_code_cell_value, import_file, undo, redo, or batch | |
| params | No | Parameters for the action (see tool description). For batch: {actions: [{action, params}, ...]} |
Tool Definition Quality
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even though annotations already mark destructiveHint=true and readOnlyHint=false, the description adds substantial behavioral detail: 'Values replace existing content; use empty string to clear,' 'Runs writes sequentially; errors short-circuit the batch,' 'Cell must be empty (avoids spill error),' and 'Charts float over the grid... the anchor is nudged to free space.' No contradictions with the annotations are present.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear section headers and a front-loaded usage pattern. However, it contains some redundancy, such as the data-tables-discouraged caveat repeated in add_data_table and convert_to_table, and the 'prefer formula over code' guidance repeated across multiple entries. The overall length is justified by 40+ actions, but slight trimming would improve conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity and the absence of an output schema, the description is remarkably complete. It covers special actions (batch, context), placement rules, error behavior, return values when relevant (e.g., 'Returns the chart_id'), and cross-tool prerequisites like calling get_database_schemas. The action reference leaves little ambiguity for an agent to invoke the correct action and params.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema only provides a generic 'params' object with 'see tool description,' but the description compensates richly by defining every parameter per action, including A1 notation, base64 file_data, booleans like 'right: true=insert right, false=insert left,' formatting enums, and examples such as 'Percentages: .01 → 1%, 1 → 100%.' This vastly exceeds the schema's minimal descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Write operations on the open spreadsheet,' clearly stating the verb and resource. It is distinct from sibling tools like read_data because it explicitly frames the tool as performing writes, and it enumerates all supported actions (set_cell_values, delete_cells, add_chart, etc.).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Extensive when-to-use guidance is provided, such as 'Prefer set_cell_values over add_data_table... only use add_data_table when the user explicitly asks' and 'Prefer set_formula_cell_value whenever a formula can do the task; only use code when the functionality is not available.' It also gives explicit when-not guidance like 'Do NOT call rerun_code after set_code_cell_value...' and cross-tool requirements like 'Always call get_database_schemas before writing SQL.'
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Claim this connector by publishing a /.well-known/glama.json file on your server's domain with the following structure:
{
"$schema": "https://glama.ai/mcp/schemas/connector.json",
"maintainers": [{ "email": "your-email@example.com" }]
}The email address must match the email associated with your Glama account. Once published, Glama will automatically detect and verify the file within a few minutes.
Control your server's listing on Glama, including description and metadata
Access analytics and receive server usage reports
Get monitoring and health status updates for your server
Feature your server to boost visibility and reach more users
For users:
Full audit trail – every tool call is logged with inputs and outputs for compliance and debugging
Granular tool control – enable or disable individual tools per connector to limit what your AI agents can do
Centralized credential management – store and rotate API keys and OAuth tokens in one place
Change alerts – get notified when a connector changes its schema, adds or removes tools, or updates tool definitions, so nothing breaks silently
For server owners:
Proven adoption – public usage metrics on your listing show real-world traction and build trust with prospective users
Tool-level analytics – see which tools are being used most, helping you prioritize development and documentation
Direct user feedback – users can report issues and suggest improvements through the listing, giving you a channel you would not have otherwise
The connector status is unhealthy when Glama is unable to successfully connect to the server. This can happen for several reasons:
The server is experiencing an outage
The URL of the server is wrong
Credentials required to access the server are missing or invalid
If you are the owner of this MCP connector and would like to make modifications to the listing, including providing test credentials for accessing the server, please contact support@glama.ai.
Discussions
No comments yet. Be the first to start the discussion!
Related MCP Servers
- FlicenseBqualityDmaintenanceEnables AI assistants to read and edit Excel files and perform PostgreSQL queries, streamlining data analysis workflows.12
- Alicense-qualityDmaintenanceEnables querying Excel and CSV files using SQL via natural language, allowing AI assistants to analyze data without manual SQL writing.1MIT
- AlicenseCqualityFmaintenanceEnables conversational data analysis of Excel/CSV files through natural language queries, powered by 395 Excel functions via HyperFormula and multi-provider AI. Supports advanced analytics, bulk operations, financial modeling, and large file processing with intelligent chunking.353636MIT
- Alicense-qualityCmaintenanceEnables users to ask questions about their spreadsheets in plain English and receive instant answers using DuckDB-powered analytics, supporting multiple file formats like Excel, CSV, and Parquet.2MIT