Skip to main content
Glama

write_data

Destructive

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(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.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionYesAction 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
paramsNoParameters for the action (see tool description). For batch: {actions: [{action, params}, ...]}

Schema Changelog

Changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. Changed1 schema field changed
    • changedInput schema / properties / action / description
      Previous value: -"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, set_sql_code_cell_value, import_file, undo, redo, or batch"New value: +"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"
  2. Changed1 schema field changed
    • changedInput schema / properties / action / description
      Previous value: -"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, 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, set_sql_code_cell_value, import_file, undo, redo, or batch"New value: +"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, set_sql_code_cell_value, import_file, undo, redo, or batch"
  3. First observed

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint: true, and the description aligns with that. It adds substantial behavioral context beyond the annotations: numeric/boolean/null coercion to strings, batch short-circuiting, spill error avoidance for code cells, the requirement to call get_database_schemas before SQL, chart float behavior, pivot table read-only cells, and many other operational details. It also notes that set_code_cell_value, set_formula_cell_value, and set_sql_code_cell_value run automatically so rerun_code should not be called after them. This goes far beyond the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely long, but it is necessary given the tool's breadth (40+ actions). It is well-structured with clear headings (Cell Data, Code, Import, Formatting, Sheets, Tables, etc.), action signatures, and inline notes. It front-loads the purpose and call format. While not concise in length, every sentence serves a purpose and the structure improves scannability. It earns a 4 rather than 5 only because some individual action notes are verbose and could be tightened, but overall it is appropriate for the complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with this many actions and no output schema, the description is remarkably complete. It covers all action signatures, parameter details, usage heuristics, edge cases (e.g., merged cells, spill errors, data table spacing), return values where relevant (e.g., add_chart returns chart_id), and even special behaviors like the context action for deeper docs. It gives the agent everything needed to call any action correctly without external reference. There are no significant gaps for an agent to misuse the tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema only defines 'action' and a generic 'params' object with no per-action schema. The description carries the entire burden of parameter documentation, and it does so comprehensively: each action is listed with its exact parameter names, types, defaults, and usage notes (e.g., 'top_left_position: single cell in A1 notation', 'color: hex string', 'line: line1/line2/line3', 'size: auto/default/pixels'). Even edge cases and constraints are explained (e.g., 'sheet names: unique, max 31 chars'). This fully compensates for the schema's lack of detail.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence clearly states 'Write operations on the open spreadsheet', immediately establishing the tool's scope and distinguishing it from read tools like read_data. It then enumerates all supported actions, leaving no ambiguity about what the tool does. The description is explicit about the verb (write) and the resource (spreadsheet).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides extensive when-to-use guidance both at the tool level (write operations vs. read operations implied by sibling names) and at the action level. For example, it explicitly says 'Prefer this over add_data_table' for set_cell_values, 'only use code when functionality is not available in formulas', and 'Use STOCKHISTORY formula for basic historical stock prices'. It also gives exclusions like 'Don't use for formulas or code' for certain actions, and explains when to use batch and context. This fully equips an agent to select the right action.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

TDQS

A4.2/5.0
Disambiguation5/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.

Naming Consistency2/5

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.

Tool Count5/5

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.

Completeness4/5

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.