Transports
The same tool catalog is available over two transports:- HTTP: MCP Streamable HTTP at
http://127.0.0.1:<port>/mcp(port from the handshake file). POST for JSON-RPC requests, GET for the SSE stream that carries server-initiated notifications. Bearer token inAuthorizationheader. - stdio: bundled
tablepro-mcpCLI bridges stdio JSON-RPC to localhost HTTP. No token needed because the bridge reuses the in-app handshake.
2025-03-26, 2025-06-18, and 2025-11-25. On initialize it echoes whichever version the client requested. If the client asks for something else, the server returns 2025-11-25. See Versioning.
Scopes and access
Each tool entry below lists its minimum token scope. The effective permission isMIN(token.scope, connection.externalAccess); see Tokens for the full scope table.
Two per-connection settings gate every call on top of the token:
- External access.
blockedhides the connection entirely:list_connectionsomits it,list_recent_tabsfilters its tabs, and any tool that targets it returns403 forbidden.readOnlyblocks write SQL:execute_querywith a write statement and anyconfirm_destructive_operationcall return403, even with areadWritetoken. The session-state toolsdisconnect,switch_database, andswitch_schemaare gated by token scope only. - AI policy
askEachTime. The first tool call per session that targets the connection shows an in-app approval dialog. TablePro waits up to 30 seconds. Deny returns403 forbiddenwith message “User denied MCP access to this connection”; no answer fails the call with a timeout error. An approval covers that connection for the rest of the session.
list_tables, list_schemas, describe_table, get_table_ddl, and execute_query query exactly the database and schema you pass them and leave the app alone: the sidebar’s selected database and every open tab stay where they are, and a tab keeps querying the database and schema it was opened on. switch_database and switch_schema are the only tools that move the app’s selection, which is what they are for.
Connection tools
list_connections
List saved connections. Connections with externalAccess: blocked are silently omitted.
Input: none.
Output:
readOnly.
connect
Open a database connection.
Input:
current_schema and server_version are present when known.
Scope: readOnly.
disconnect
Close a connection.
Input: { "connection_id": "..." }
Output: { "status": "disconnected" } on success.
Scope: readWrite.
get_connection_status
Return status, active database, server version, connect time, and last-active time for a connection.
Input: { "connection_id": "..." }
Output:
status is one of connected, connecting, disconnected, error. When error, an error object with a message field is included.
Scope: readOnly.
Schema tools
list_databases
Input: { "connection_id": "..." }
Output: { "databases": ["app", "analytics"] } (array of database names)
Scope: readOnly.
list_schemas
Input: { "connection_id": "...", "database": "app" } (database optional)
Output: { "schemas": ["public", "reporting"] } (array of schema names)
Scope: readOnly.
list_tables
Input:
type is one of TABLE, VIEW, MATERIALIZED VIEW, FOREIGN TABLE, or SYSTEM TABLE. When include_row_counts is true and the driver supports it, each entry also includes row_count.
Scope: readOnly.
describe_table
Columns, indexes, foreign keys, primary key, DDL.
Input:
database and schema are optional. The connection’s current database and schema are used when omitted.
Output:
default_value, extra, and comment are present on a column when set. ddl and approximate_row_count are present when the driver supports them.
Scope: readOnly.
get_table_ddl
Just the CREATE TABLE statement.
Input: same as describe_table (connection_id, table, database, schema).
Output: { "ddl": "CREATE TABLE ..." }
Scope: readOnly.
Query tools
execute_query
Execute a SQL query. All queries are subject to the connection’s safe mode policy. DROP, TRUNCATE, and ALTER…DROP must use confirm_destructive_operation.
Input:
max_rows and timeout_seconds come from Settings > Integrations > Server Configuration (default row limit, query timeout). max_rows is clamped to the configured maximum (default 10,000). timeout_seconds is clamped to 1-300. Single-statement queries only. Query size cap is 100 KB. database and schema are optional; when present, the query runs against them. It never changes what’s selected in the app, and omitting them runs against the connection’s currently selected database.
Output:
columns is an array of column-name strings. rows is an array of rows, where each row is an array of strings (or null) aligned to the columns order. status_message is added when the driver returns one.
Scope:
readOnlyfor SELECT, SHOW, EXPLAIN.readWritefor INSERT, UPDATE, DELETE.- DROP, TRUNCATE, ALTER…DROP are rejected. Use
confirm_destructive_operation.
readOnly returns 403 for any write SQL.
Streaming progress: pass _meta.progressToken in the request and the server sends notifications/progress events on the SSE channel as the query moves through “Connecting”, “Executing”, “Formatting result”, and “Done”. Clients that don’t include a token get the final response only.
confirm_destructive_operation
Run a DROP, TRUNCATE, or ALTER…DROP after a typed confirmation.
Input:
I understand this is irreversible. Anything else returns JSON-RPC -32602 over HTTP 200 with message Invalid params: confirmation_phrase must be exactly: I understand this is irreversible.
Output: same shape as execute_query.
Scope: readWrite or fullAccess (both grant the tools:write MCP scope). The connection’s external access must also permit writes; a readOnly connection rejects destructive operations even with a matching token.
export_data
Export query or table data as CSV, JSON, or SQL.
Input:
format is one of csv, json, sql. Defaults for max_rows and the query timeout come from Settings > Integrations > Server Configuration, the same as execute_query: omitting max_rows uses the default row limit (500), and any value you pass is clamped to the maximum row limit (default 10,000). Raise those settings to export more rows. Provide either tables or query. Table names accept letters, digits, underscore, and . for schema-qualified names. Pass output_path to write to disk instead of returning data inline; the path must resolve inside the user’s ~/Downloads directory. Anything else fails with JSON-RPC -32602 over HTTP 200 and message Invalid params: output_path must be inside the Downloads directory (/Users/you/Downloads).
Output: when output_path is set, returns { "path": "...", "rows_exported": N, "is_truncated": false }. Otherwise returns the export inline. A single export returns { "label": "...", "format": "csv", "row_count": N, "is_truncated": false, "data": "..." }. Multiple exports (multi-table requests) return { "exports": [ { "label": "...", "format": "csv", "row_count": N, "is_truncated": false, "data": "..." }, ... ] }. is_truncated is true when the row limit clipped the result.
Scope: readOnly.
switch_database / switch_schema
Input: { "connection_id": "...", "database": "analytics" } or { "connection_id": "...", "schema": "reporting" }
Output: { "status": "switched", "current_database": "analytics" } or { "status": "switched", "current_schema": "reporting" }
Scope: readWrite (moves the connection’s selected database or schema, which the sidebar follows).
Navigation tools
These open or focus tabs and windows in the running TablePro app. They requirereadOnly scope and respect the connection allowlist; tabs from externalAccess: blocked connections are filtered out.
open_connection_window
Open a connection in TablePro and bring its window to front. If the connection is already open, the existing window is focused.
Input: { "connection_id": "..." }
Output:
readOnly.
open_table_tab
Open a table tab.
Input:
database_name and schema_name are optional. If omitted, the connection’s current database/schema is used.
Output:
readOnly.
focus_query_tab
Bring an existing tab to front. The tab_id comes from list_recent_tabs.
Input: { "tab_id": "..." }
Output:
-32602 invalid params with detail tab not found.
Scope: readOnly.
list_recent_tabs
Read the cross-window tab registry. Tabs from connections with externalAccess: blocked are filtered out.
Input: { "limit": 20 } (optional, 1-500, default 20).
Output:
tab_type is one of query, table, createTable, erDiagram, serverDashboard, usersRoles. table_name, database_name, schema_name, and window_id are present when known.
Scope: readOnly.
History tools
search_query_history
Full-text search over the query history database.
Input:
connection_id is optional. limit is 1-500, default 50. since and until are optional Unix epoch seconds; both bounds are inclusive. Either may be set on its own. Pass an empty query ("") to skip the full-text filter and only narrow by date or connection.
Output:
executed_at is a Unix timestamp in seconds. error_message is included when was_successful is false.
Scope: readOnly.
Errors
Tool failures come back as JSON-RPC error envelopes. Codes follow the JSON-RPC spec plus TablePro’s reserved range:
Error responses include a
message. Example:
404 from GET/POST/DELETE /mcp with a stale Mcp-Session-Id returns the JSON-RPC envelope with code: -32001, message: "Session not found". Per the MCP spec, clients MUST treat that response as a signal to start a new initialize handshake before retrying.
401 responses carry a WWW-Authenticate challenge. A missing token returns Bearer realm="TablePro". An unknown or revoked token returns Bearer error="invalid_token". An expired token returns Bearer error="invalid_token", error_description="token expired".