
List databases in the account. Filter by name with pattern (a SQL LIKE pattern, e.g. 'PROD%'), cap the page with limit, and page with cursor: pass pageinfo.nextcursor from the previous response while hasnextpage is true. Use get_database instead when you already know the one database you want.
Create a new database in Snowflake. Use list_databases to check the name is free.
Alter an existing database in Snowflake. Use list_databases to find database names.
Drop a database from Snowflake. With cascade=false this refuses if the database still holds schemas, because Snowflake itself would drop them without warning. Pass cascade=true to drop them with it. Use list_databases to find names.
Get details of a specific database. Use list_databases to find database names.
List schemas in a database. Filter by name with pattern (a SQL LIKE pattern, e.g. 'PUBLIC%'), cap the page with limit, and page with cursor: pass pageinfo.nextcursor from the previous response while hasnextpage is true. Use listdatabases to find the database, and getschema for one named schema.
Create a new schema in a database. Use list_databases to find the parent database.
Alter an existing schema in Snowflake. Use list_schemas to find schema names.
Drop a schema from a database. With cascade=false this refuses if the schema still holds tables, because Snowflake itself would drop them without warning. Pass cascade=true to drop them with it. Use list_schemas to find names.
Get details of a specific schema. Use listdatabases and listschemas to find names.
List roles in the account. Filter by name with pattern (a SQL LIKE pattern, e.g. 'ADMIN%'), cap the page with limit, and page with cursor: pass pageinfo.nextcursor from the previous response while hasnextpage is true. Use get_role instead when you already know the one role name you want.
Create a new role in Snowflake. Use list_roles to check the name is free.
Drop a role from Snowflake. Use list_roles to find role names.
Get details of a specific role. Use list_roles to find role names.
List grants: what a role holds (role), what roles a user has (user), what is granted on an object (objectname with objecttype), or future grants on a container (future=true, objectname with objecttype DATABASE or SCHEMA). Call before revokeprivilege. Page with limit/offset; offset + limit must stay under 10000. Use listroles, listusers, listdatabases/listschemas/listtables for names.
Grant privileges to a role on a Snowflake object. Use listroles for roles and listdatabases/listschemas/listtables for object names. Use list_grants to see what a role already holds.
Revoke privileges from a role on a Snowflake object. Use listroles for roles and listdatabases/listschemas/listtables for object names. Use list_grants to see what a role already holds.
Grant a role to a user or another role. Use listroles for roles and listusers for users.
Revoke a role from a user or another role. Use listroles for roles and listusers for users.
Execute a SQL statement in Snowflake (query, DDL, or DML). Use listwarehouses to find a warehouse. Use executesql_readonly for reads.
Execute a read-only SQL statement in Snowflake (SELECT, WITH, SHOW, DESCRIBE, EXPLAIN, VALUES, LIST). Rejects DDL/DML and multi-statement input. Use execute_sql for writes.
Get the status of an asynchronous SQL statement, including one that failed or was cancelled. Takes the statementhandle from executesql or executesqlreadonly with async_exec=true. Returns running, success, failed or cancelled; a failure carries Snowflake's error code. Polling a finished statement costs as much as fetching its first result page, so poll sparingly.
Fetch results from a completed SQL query with pagination. Takes the statementhandle returned by executesql or executesqlreadonly.
Cancel a running SQL statement. Takes the handle returned by an async executesql. The real outcome is read back afterwards, so a statement that had already finished reports success rather than cancelled -- its writes applied. Use getstatement_status to poll a handle without cancelling it.
List stages in a schema. Filter by name with pattern (a SQL LIKE pattern, e.g. 'LOAD%'), cap the page with limit, and page with cursor: pass pageinfo.nextcursor from the previous response while hasnextpage is true. Use listschemas to find the schema, and getstage for one named stage.
Create a new stage for data loading/unloading. Use list_schemas to find the parent schema.
Drop a stage from Snowflake. Use list_stages to find stage names.
Get details of a specific stage. Use list_stages to find stage names.
List files in a stage. Filter with pattern (a regex, e.g. '.*[.]csv'), cap the page with limit, and page with cursor: pass pageinfo.nextcursor while hasnextpage is true. Snowflake's LIST takes no limit of its own, so the whole listing is read and the page is cut here. Use list_stages to find stage names.
Describe a stage to see its properties and file format settings. Use liststages to find stage names; use getstage for the summary instead.
Load data from a stage into a table. tablename is database.schema.name, stagename is @database.schema.stage. Supports file patterns, error handling modes and validation. purge=true deletes the source files from the stage after a successful load; force=true reloads files already loaded, duplicating their rows. Use listtables for the target and liststages for the source stage.
Unload data from a table or query to a stage. Build stagename as @database.schema.stage from liststages output. Supports file format and partitioning options. overwrite=true replaces files already at the destination path. Use list_stages to find the destination stage.
List tables in a schema. Filter by name with pattern (a SQL LIKE pattern, e.g. 'SALES%'), cap the page with limit, and page with cursor: pass pageinfo.nextcursor from the previous response while hasnextpage is true. Use listschemas to find the schema, and gettable for one named table.
Create a new table in Snowflake. Use list_schemas to find the parent schema.
Alter an existing table in Snowflake. Use listtables to find tables and describetable for current columns.
Drop a table from Snowflake. Use list_tables to find table names.
Get the structure and column definitions of a table. Use listtables to find table names, and listdatabases/list_schemas for the container.
Get details of a specific table. Use listtables to find table names. Use describetable for its columns.
List tasks in a schema. Filter by name with pattern (a SQL LIKE pattern, e.g. 'ETL%'), cap the page with limit, and page with cursor: pass pageinfo.nextcursor from the previous response while hasnextpage is true. Use listschemas to find the schema, and gettask for one named task.
Create a new scheduled task in Snowflake. The task starts SUSPENDED; call resumetask to begin scheduled runs. Use listwarehouses for a valid warehouse and listtasks for predecessor names to pass in after. Note that usertasktimeoutms and suspendtaskafternumfailures are settable but not readable back: SHOW TASKS omits them, so get_task returns null for both.
Alter an existing task in Snowflake. The task must be suspended first: call suspendtask, then altertask, then resumetask, or Snowflake rejects the change with error 091421. Use listtasks to find task names.
Drop a task from Snowflake. Use list_tasks to find task names.
Resume a suspended task to start scheduled execution. Use list_tasks to find task names and their state.
Suspend a running task to stop scheduled execution. Use list_tasks to find task names and their state.
Execute a task immediately without waiting for schedule. Does not change the task's STARTED/SUSPENDED state - use gettaskhistory to follow the run. Use list_tasks to find task names.
Get execution history for a task: recent runs with status, timing and errors. Covers the last 7 days, newest first, capped by limit. There is no cursor: if pageinfo.hasnextpage is true, re-call with a higher limit (max 1000). Use listtasks to find task names. The history comes from TASKHISTORY, so pass a warehouse unless the user has a DEFAULTWAREHOUSE; use list_warehouses to find one.
Get details of a specific task, including state, schedule and definition. Use listtasks to find task names. usertasktimeoutms and suspendtaskafternumfailures are always null: SHOW TASKS does not return them.
List users in the account. Filter by name with pattern (a SQL LIKE pattern, e.g. 'ADMIN%'), cap the page with limit, and page with cursor: pass pageinfo.nextcursor from the previous response while hasnextpage is true. Use get_user instead when you already know the one username you want.
Create a new user in Snowflake. Use listusers to check the name is free, listroles for defaultrole, listwarehouses for defaultwarehouse, and listdatabases/listschemas for defaultnamespace.
Alter an existing user in Snowflake. Pass an empty string to clear a string property (not newname). Use listusers for usernames, listroles for defaultrole, listwarehouses for defaultwarehouse, and listdatabases/listschemas for default_namespace.
Drop a user from Snowflake. Use list_users to find usernames.
Get details of a specific user. Use list_users to find user names.
Validate Snowflake credentials by executing a lightweight query. Works with every auth option the connector ships. Returns {success, message}.
List warehouses in the account. Filter by name with pattern (a SQL LIKE pattern, e.g. 'PROD%'), cap the page with limit, and page with cursor: pass pageinfo.nextcursor from the previous response while hasnextpage is true. Use get_warehouse instead when you already know the one warehouse you want.
Create a new virtual warehouse in Snowflake. Use list_warehouses to check the name is free.
Alter an existing warehouse in Snowflake. Use list_warehouses to find warehouse names.
Drop a warehouse from Snowflake. Use list_warehouses to find warehouse names.
Resume a suspended warehouse. Use list_warehouses to find warehouses and their state.
Suspend a running warehouse to stop billing. Use list_warehouses to find warehouses and their state.
Get details of a specific warehouse. Use list_warehouses to find warehouse names.

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 lets you access data from a Snowflake instance via tools. Your agents can invoke these tools to modify databases, create a schema in a database, list user roles, and more.
Snowflake offers an official MCP server. But you can also access Snowflake MCP servers from 3rd-party platforms, like Merge Agent Handler.
Here are just a few popular use cases:
Here are some widely-used tools:
Databases
Schemas
Roles
Here are just a few reasons:
Yes, Merge Agent Handler supports granular security controls, including DLP policies, which allow you to define rules governing how agents interact with external systems like Snowflake.
Here are some rules you can set:
You can take these steps:
1. Create (or sign in to) an Agent Handler account, then open the dashboard where you can manage connectors and Tool Packs.
2. Create a Tool Pack for the workflow you want (e.g., “Snowflake analytics copilot”), since Tool Packs define which connectors and tools your agent can access.
3. Add the Snowflake connector to that Tool Pack and configure access using least-privilege permissions (via your Tool Pack configuration and RBAC/policies).
4. Create a Registered User (the identity your agent will execute tool calls as) and complete the Snowflake authentication flow when prompted.
5. Connect your agent runtime to Agent Handler (either via MCP or the SDK pattern) so your agent can discover tools by calling “list tools” and then execute Snowflake tool calls through Agent Handler.
6. Validate end-to-end behavior using the Tool Pack tester / Evaluation Suite, starting with low-risk read-only queries, then iterating until outputs are consistent.
7. Before production, configure security rules (DLP) and alerts to scan Snowflake tool inputs and outputs, and to block, redact, or log sensitive data patterns.
Whether you're an engineer experimenting with agents or a product manager looking to add tools, you can get started for free now