
List the user's spreadsheets, most recently modified first. Call this FIRST when you have no spreadsheet_id: each result's id IS the spreadsheet_id that get_spreadsheet, get_values and every other tool here require. Use search_spreadsheets when the user named a title. Filter by owned_by_me, shared_with_me, folder_id or modified_after. Page with page_token plus the identical filters.
Find spreadsheets by title. Call this FIRST when the user names a spreadsheet ("the Q3 forecast sheet") rather than giving an id: the id returned IS the spreadsheet_id that get_spreadsheet, get_values and every other tool here require. Matching is case-insensitive starts-with, not mid-word, so retry a shorter leading fragment if empty. Page with page_token plus the identical name and filters.
Apply alternating row or column colors (zebra striping) to a range. range accepts A1 notation (e.g. 'Sheet1!A1:E20') or a GridRange object. Provide row_properties, column_properties, or both. Returns the bandedRangeId for use in update_banding/delete_banding.
Update an existing banding rule's range or colors. Provide banded_range_id (from add_banding or get_spreadsheet) and the fields to change. range accepts A1 notation or a GridRange object. Only sub-fields you set are updated — unspecified colors are preserved.
Delete a banding rule by ID. Use get_spreadsheet to find banded_range_id values on each sheet. This is irreversible.
Set borders around a cell range. Each side (top/bottom/left/right) takes a Border with style and optional colorStyle. inner_horizontal and inner_vertical control internal lines. Omitted sides are not modified.
Add a conditional formatting rule to one or more ranges. Provide either booleanRule (condition + format) or gradientRule (minpoint/midpoint/maxpoint), exactly one. index controls insertion order; omit to append.
Delete a conditional format rule at the given 0-based index on a sheet. To inspect existing rules use get_spreadsheet with include_grid_data=True. This is irreversible.
Replace a conditional format rule at a given index, or move it to a new position. sheet_id targets the sheet; index is the rule's current 0-based position. Provide rule/gradient_rule to replace, or new_index to reorder.
Apply cell-level formatting (number format, colors, fonts, alignment, wrap, borders, padding) to a range using RepeatCellRequest. Use a GridRange to target cells. Pass only the format properties you want to set; omitted fields will not be touched.
Create a named range so the cells can be referenced by name in formulas (e.g. =SUM(SalesData)). Names should be valid identifiers. Use update_named_range to rename or move; delete_named_range to remove.
Update an existing named range's name or cell range. Provide the named_range_id (from add_named_range or get_spreadsheet); pass name and/or range to change. Only changed fields are sent.
Delete a named range by ID. Use get_spreadsheet to find named_range_id values. Formulas referencing the deleted name will break. This is irreversible.
Query a spreadsheet with a SQL-like Google Visualization query: filter rows, aggregate columns, group and sort, in one call. Use this instead of reading a whole range with get_values and filtering afterwards. Columns are referenced by SHEET LETTER not header name, e.g. "select A, sum(C) where B > 100 group by A". No joins, no subqueries, no table name. Use get_spreadsheet to find sheet names.
List the named tables defined across a spreadsheet, with their sheet, range and column types. Returns empty for a spreadsheet that uses plain ranges rather than defined tables, which is common; query_table and get_values work either way. Use get_spreadsheet for the sheet list.
Get one table's column names and types, plus the sheet and range it covers. Use this before query_table to learn what a table holds. Use list_tables to find table ids.
Add a new sheet (tab) to an existing spreadsheet with customizable properties.
Permanently delete a sheet (tab) from a spreadsheet. Cannot be undone.
Update sheet properties like title, position, visibility, or tab color.
Copy a sheet within the same spreadsheet or to a different spreadsheet.
Sorts data in rows based on a sort order per column. Supports multi-column sorting and color-based sorting.
Sets data validation rules to cells in a range. Supports number, text, date validation, dropdown lists, and custom rules. Use empty rule to clear validation.
Sets a basic filter on a sheet with optional sorting and column-specific filter criteria. Supports text, number, and date filtering.
Add a chart (bar, line, area, column, scatter, combo, stepped area) to a spreadsheet. Requires A1 ranges for domain (x-axis) and series (y-axis) data.
Update an existing chart's spec — change chart type, title, or data ranges. Provide chart_id (from add_chart) and the spec fields to change.
Lock a range from edits. warning_only=True shows a warning but still allows edits; False blocks them. Optionally restrict edits to specific editor users/groups, or allow domain users to edit.
Extend a pattern (formula, date sequence, number series) by auto-fill instead of writing each value. Provide either range (auto-fill within the range, using the first row/column as source) or source_and_destination (explicit source + dimension + fill_length). use_alternate_series=True flips the inferred series direction.
Merge cells across a range. Discards content from all cells except the top-left of each merged block; not reversible via unmerge_cells. merge_type controls the merge mode: MERGE_ALL merges everything in the range, MERGE_COLUMNS merges per column (one merge per column), MERGE_ROWS merges per row.
Unmerge previously merged cells in a range. Useful for decomposing merged template cells before editing.
Remove duplicate rows from a range, comparing only the columns listed in comparison_columns (DimensionRange list). The first occurrence is kept. Returns the count of removed rows. Irreversible.
Delete rows or columns from a sheet. range.dimension is ROWS or COLUMNS; range.start_index/end_index are zero-based, end-exclusive. This is irreversible — confirm intent before calling.
Insert empty rows or columns into a sheet. range.dimension selects ROWS or COLUMNS; range.start_index/end_index are zero-based, end-exclusive. inherit_from_before controls whether the new cells inherit formatting from the row/column before (True) or after (False).
Reorder rows or columns. source.dimension is ROWS or COLUMNS; source.start_index/end_index are zero-based, end-exclusive. destination_index is the position before which the rows/columns are inserted (zero-based, in the dimension's pre-move coordinates).
Create a collapsible row or column group for hierarchical reports. range.dimension is ROWS or COLUMNS; range.start_index/end_index are zero-based, end-exclusive. Nested groups create deeper outline levels.
Auto-fit row heights or column widths to content. dimensions.dimension is ROWS or COLUMNS; start_index/end_index are zero-based, end-exclusive. The simplest fix for truncated content after writing data.
Set column widths or row heights, or hide/show dimensions. range.dimension is ROWS or COLUMNS; range.start_index/end_index are zero-based, end-exclusive. Provide pixel_size in pixels and/or hidden. Only provided fields are modified.
Duplicate a sheet within the same spreadsheet using DuplicateSheetRequest. Unlike copy_sheet (which uses :copyTo and auto-names the result), this lets you set the new sheet's name and position. Use copy_sheet to copy across spreadsheets.
Delete an embedded chart or image by its id. The object_id is the chart_id returned by add_chart, or read from get_spreadsheet (sheets[].charts[].chartId). Irreversible.
Reposition an embedded object (chart or image) by id. Use new_sheet_id to move to another sheet, or overlay fields to set anchor cell, pixel offsets, and size on the current sheet.
Update an existing named filter view. Provide filter_view_id (from add_filter_view or get_spreadsheet) plus the fields to change. fields mask is computed from provided inputs.
Create a named filter view with persistent filter/sort criteria. Unlike set_basic_filter, multiple filter views coexist without overwriting each other. Returns filter_view_id for later update_filter_view/delete_filter_view.
Delete a named filter view by ID. Use get_spreadsheet to find filter_view_id values on each sheet. This is irreversible.
Bulk find and replace text. Provide exactly one scope: a range (GridRange), a sheet_id, or all_sheets=True. Optional flags: match_case, match_entire_cell, search_by_regex, include_formulas. Returns the number of occurrences changed.
Strip leading and trailing whitespace from string cells in a range. Returns the count of cells changed. Common cleanup after data import.
Add a table to a sheet over a GridRange (include the header row). Optionally set per-column names and types (TEXT, DOUBLE, CURRENCY, PERCENT, DATE, TIME, DATE_TIME, BOOLEAN, DROPDOWN). Returns the new table_id.
Create a new spreadsheet with specified title and optional properties.
Retrieve spreadsheet information including metadata, sheets, and optionally cell data.
Update spreadsheet properties such as title, locale, or timezone.
Validate Google Sheets credentials. Verifies credentials during setup.
Read cell values from a specified range using A1 notation (e.g., 'Sheet1!A1:B10').
Write cell values to a specified range. Supports formulas and raw values.
Append rows to the end of a table, automatically finding the last row with data.
Clear cell values from a range while preserving formatting and structure.
Read cell values from multiple ranges in a single efficient API call.
Update multiple ranges with values in a single efficient API call.
Clear values from multiple ranges in a single API call while preserving formatting.

In an mcp.json file, add the configuration below, and restart Cursor.
Learn more in the official documentation ↗
1{
2 "mcpServers": {
3 "agent-handler": {
4 "url": "https://ah-api-develop.merge.dev/api/v1/tool-packs/{TOOL_PACK_ID}/registered-users/{REGISTERED_USER_ID}/mcp",
5 "headers": {
6 "Authorization": "Bearer yMt*****"
7 }
8 }
9 }
10}
11Open your Claude Desktop configuration file and add the server configuration below. You'll also need to restart the application for the changes to take effect.
Make sure Claude is using the Node v20+.
Learn more in the official documentation ↗
1{
2 "mcpServers": {
3 "agent-handler": {
4 "command": "npx",
5 "args": [
6 "-y",
7 "mcp-remote@latest",
8 "https://ah-api-develop.merge.dev/api/v1/tool-packs/{TOOL_PACK_ID}/registered-users/{REGISTERED_USER_ID}/mcp",
9 "--header",
10 "Authorization: Bearer ${AUTH_TOKEN}"
11 ],
12 "env": {
13 "AUTH_TOKEN": "yMt*****"
14 }
15 }
16 }
17}Open your Windsurf MCP configuration file and add the server configuration below.
Click on the refresh button in the top right of the Manage MCP server page or in the top right of the chat box in the box icon.
Learn more in the official documentation ↗
1{
2 "mcpServers": {
3 "agent-handler": {
4 "command": "npx",
5 "args": [
6 "-y",
7 "mcp-remote@latest",
8 "https://ah-api.merge.dev/api/v1/tool-packs/<tool-pack-id>/registered-users/<registered-user-id>/mcp",
9 "--header",
10 "Authorization: Bearer ${AUTH_TOKEN}"
11 ],
12 "env": {
13 "AUTH_TOKEN": "<ah-production-access-key>"
14 }
15 }
16 }
17 }In Command Palette (Cmd+Shift+P on macOS, Ctrl+Shift+P on Windows), run "MCP: Open User Configuration".
You can then add the configuration below and press "start" right under servers. Enter the auth token when prompted.
Learn more in the official documentation ↗
1{
2 "inputs": [
3 {
4 "type": "promptString",
5 "id": "agent-handler-auth",
6 "description": "Agent Handler AUTH_TOKEN", // "yMt*****" when prompt
7 "password": true
8 }
9 ],
10 "servers": {
11 "agent-handler": {
12 "type": "stdio",
13 "command": "npx",
14 "args": [
15 "-y",
16 "mcp-remote@latest",
17 "https://ah-api-develop.merge.dev/api/v1/tool-packs/{TOOL_PACK_ID}/registered-users/{REGISTERED_USER_ID}/mcp",
18 "--header",
19 "Authorization: Bearer ${input:agent-handler-auth}"
20 ]
21 }
22 }
23}It’s an MCP server that exposes data and functionality from Google Sheets via tools. Your agents can invoke these tools to add sheets, sort data in a row within a sheet, copy a sheet to a new spreadsheet, and more.
Here are some common use cases:
Here are some popular tools across data types:
Sheets
Cell values
Spreadsheets
Merge Agent Handler provides platform-level capabilities that apply to all connectors, including Google Sheets:
Yes, Merge Agent Handler allows you to configure custom data loss prevention (DLP) rules for Google Sheets tool calls.
Here are examples of security rules you can set:
You can follow these steps:
1. Create your Agent Handler account. Sign up for a free account here.
2. Create a Tool Pack. Navigate to "Tool Packs" in the left sidebar and click "Create New Tool Pack." Give it a descriptive name (e.g., "Google Sheets Automation Pack").
3. Add the Google Sheets connector. Browse the available connectors and add Google Sheets to your Tool Pack.
4. Configure authentication. Choose your authentication method:
5. Select specific tools. Choose which Google Sheets tools you want to make available to your agent, or enable all tools by default.
6. Register a User. Navigate to "Registered Users" in the sidebar and create a new registered user. This represents the identity that will perform actions through your agent.
7. Save your Tool Pack. Review and save all your Tool Pack settings.
8. Connect to your agent or IDE. Copy the MCP entry URL from your Tool Pack settings. The URL format will be: https://ah-api.merge.dev/api/v1/tool-packs/{TOOL_PACK_ID}/registered-users/{REGISTERED_USER_ID}/mcp. Then add it to your IDE configuration (Cursor, Windsurf, Claude Desktop, or Visual Studio Code) using the authentication token provided.
Yes, Agent Handler for Employees lets your employees connect Claude, ChatGPT, Microsoft Copilot, Cursor, and other MCP-compatible AI tools to Google Sheets without bypassing IT governance.
Instead of setting up direct connections with personal credentials that IT can't monitor or revoke, each employee authenticates through Agent Handler and gets individual credentials tied to their identity.
IT also provisions access by role or group via SCIM. A finance analyst gets Google Sheets access to build financial reports, NetSuite to close books, and Expensify to track spend; while a sales rep gets Google Sheets to track custom metrics, Salesforce to manage pipeline, and Gong to review call recordings.
Every tool call an employee's AI makes to Google Sheets is also inspected against your DLP rules and logged to a searchable audit trail, giving security teams full visibility into what data was accessed and by whom.
Whether you're an engineer experimenting with agents or a product manager looking to add tools, you can get started for free now