MCP Tools
The MCP server exposes tools and resources over JSON-RPC. The tools are grouped by category below. Every tool is scope-gated: a request must come with a token whose scope and connection allowlist permit the call.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.readOnlymakes write tools return403even with areadWritetoken. - 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.
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 version, uptime, and active database 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:
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:
schema is optional. The connection’s current schema is used when omitted. To target a different database, call switch_database first.
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, 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 tool calls switch_database and/or switch_schema before executing.
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. max_rows defaults to 50,000, max 100,000. 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 or the request is rejected with 400.
Output: when output_path is set, returns { "path": "...", "rows_exported": N }. Otherwise returns the export inline. A single export returns { "label": "...", "format": "csv", "row_count": N, "data": "..." }. Multiple exports (multi-table requests) return { "exports": [ { "label": "...", "format": "csv", "row_count": N, "data": "..." }, ... ] }.
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 (mutates session state).
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".