MCP tools: remote-custom-data

All tool groups

remote-custom-data

Registered when: deployment configured (CUSTOM_DATA_CLUSTER_URL) + org: customData.enabled (the org flag defaults ON, but no tools exist until the deployment is configured); key names data, no persona.

alter_table

Add columns or dedupe keys to a table, or switch its mode. Additive and safe on a live table. Leaving append_only needs confirm "_append_only". Dropping or renaming a column is not done here: use query with the DDL and confirm. Call describe first: never guess table or column names. On failure the result is {error: {code, message, fix, position?}}: read fix and retry with it. Codes: CD-PG- (a Postgres error, e.g. CD-PG-42P01 unknown table, CD-PG-42703 unknown column, CD-PG-23505 duplicate key, CD-PG-42501 your data role lacks the privilege, CD-PG-57014 timeout), CD-DENY- (refused before running, e.g. CD-DENY-SCHEMA, CD-DENY-FN, CD-DENY-TXN, CD-DENY-COPY, CD-DENY-EXT), CD-WARN-FULLTABLE, CD-LIMIT-*, CD-FORBIDDEN / CD-NOT-FOUND (no access, or no such database).

ParameterTypeRequiredDescription
databasestringyesCustom database key (lowercase_snake, e.g. "outreach"). Unqualified table names resolve in this database.
tablestringyesTable name inside the database (lowercase_snake). Run describe first to see the real names.
add_columnsobject[]no
add_dedupe_keysstring[][]no
mode"normal" \"append_only"no
confirmstringno
dry_runbooleanno
operationIdstringnoIdempotency key: retrying with the same operationId and the same arguments returns the stored answer instead of applying twice (24 h). Reusing it with different arguments is a 409; while the first call runs (or if its outcome was lost) it is a 409 for up to 2 minutes, then a retry runs, so read the rows back first.

Example call:

{"name":"alter_table","arguments":{"database":"<database>","table":"<table>"}}

Related: data_status, describe, query, explain, create_table, find_rows, insert_rows, update_rows.

create_table

Create a table from a column list without writing DDL; returns the DDL it ran. Every table gets id (identity primary key), created_at and updated_at. dedupe_keys adds unique keys that insert_rows can upsert on (the durable dedupe a bot should rely on). mode "append_only" refuses UPDATE/DELETE. row_scope "project" adds project_id and limits rows to the caller's projects. dry_run=true returns the DDL without creating anything. Call describe first: never guess table or column names. On failure the result is {error: {code, message, fix, position?}}: read fix and retry with it. Codes: CD-PG- (a Postgres error, e.g. CD-PG-42P01 unknown table, CD-PG-42703 unknown column, CD-PG-23505 duplicate key, CD-PG-42501 your data role lacks the privilege, CD-PG-57014 timeout), CD-DENY- (refused before running, e.g. CD-DENY-SCHEMA, CD-DENY-FN, CD-DENY-TXN, CD-DENY-COPY, CD-DENY-EXT), CD-WARN-FULLTABLE, CD-LIMIT-*, CD-FORBIDDEN / CD-NOT-FOUND (no access, or no such database).

ParameterTypeRequiredDescription
databasestringyesCustom database key (lowercase_snake, e.g. "outreach"). Unqualified table names resolve in this database.
namestringyesNew table name (lowercase_snake, at most 40 characters).
columnsobject[]yes
dedupe_keysstring[][]noUnique keys, each a list of column names, e.g. [["email"]].
mode"normal" \"append_only"no
row_scope"none" \"project"no
dry_runbooleanno
operationIdstringnoIdempotency key: retrying with the same operationId and the same arguments returns the stored answer instead of applying twice (24 h). Reusing it with different arguments is a 409; while the first call runs (or if its outcome was lost) it is a 409 for up to 2 minutes, then a retry runs, so read the rows back first.

Example call:

{"name":"create_table","arguments":{"database":"<database>","name":"<name>","columns":[]}}

Related: data_status, describe, query, explain, alter_table, find_rows, insert_rows, update_rows.

data_status

Whether custom data is on for this API key's organization, and that these data tools are available to it. Call first. The organization is always the key's own; no tool takes an orgId. Workflow: data_status, then describe, then query / find_rows / insert_rows. On failure the result is {error: {code, message, fix, position?}}: read fix and retry with it. Codes: CD-PG- (a Postgres error, e.g. CD-PG-42P01 unknown table, CD-PG-42703 unknown column, CD-PG-23505 duplicate key, CD-PG-42501 your data role lacks the privilege, CD-PG-57014 timeout), CD-DENY- (refused before running, e.g. CD-DENY-SCHEMA, CD-DENY-FN, CD-DENY-TXN, CD-DENY-COPY, CD-DENY-EXT), CD-WARN-FULLTABLE, CD-LIMIT-*, CD-FORBIDDEN / CD-NOT-FOUND (no access, or no such database).

No parameters.

Example call:

{"name":"data_status","arguments":{}}

Related: describe, query, explain, create_table, alter_table, find_rows, insert_rows, update_rows.

delete_rows

Delete rows by primary key (keys: [{id: 1}, ...]) or by where (column -> value equality). Deleting every row is refused (CD-WARN-FULLTABLE) unless allow_full_table=true. append_only tables refuse deletes. Call describe first: never guess table or column names. On failure the result is {error: {code, message, fix, position?}}: read fix and retry with it. Codes: CD-PG- (a Postgres error, e.g. CD-PG-42P01 unknown table, CD-PG-42703 unknown column, CD-PG-23505 duplicate key, CD-PG-42501 your data role lacks the privilege, CD-PG-57014 timeout), CD-DENY- (refused before running, e.g. CD-DENY-SCHEMA, CD-DENY-FN, CD-DENY-TXN, CD-DENY-COPY, CD-DENY-EXT), CD-WARN-FULLTABLE, CD-LIMIT-*, CD-FORBIDDEN / CD-NOT-FOUND (no access, or no such database).

ParameterTypeRequiredDescription
databasestringyesCustom database key (lowercase_snake, e.g. "outreach"). Unqualified table names resolve in this database.
tablestringyesTable name inside the database (lowercase_snake). Run describe first to see the real names.
whereobjectno
keysobject[]no
allow_full_tablebooleanno
operationIdstringnoIdempotency key: retrying with the same operationId and the same arguments returns the stored answer instead of applying twice (24 h). Reusing it with different arguments is a 409; while the first call runs (or if its outcome was lost) it is a 409 for up to 2 minutes, then a retry runs, so read the rows back first.

Example call:

{"name":"delete_rows","arguments":{"database":"<database>","table":"<table>"}}

Related: data_status, describe, query, explain, create_table, alter_table, find_rows, insert_rows.

describe

Show the schema of one custom database as compact DDL: tables, columns with types, keys, indexes, relations, row counts and descriptions, only what your data role can see. Read this before writing SQL or rows. Returns {ddl, schema_digest, ...}; the digest changes only when the schema does, so skip re-reading an unchanged schema. history=true adds the DDL change log. On failure the result is {error: {code, message, fix, position?}}: read fix and retry with it. Codes: CD-PG- (a Postgres error, e.g. CD-PG-42P01 unknown table, CD-PG-42703 unknown column, CD-PG-23505 duplicate key, CD-PG-42501 your data role lacks the privilege, CD-PG-57014 timeout), CD-DENY- (refused before running, e.g. CD-DENY-SCHEMA, CD-DENY-FN, CD-DENY-TXN, CD-DENY-COPY, CD-DENY-EXT), CD-WARN-FULLTABLE, CD-LIMIT-*, CD-FORBIDDEN / CD-NOT-FOUND (no access, or no such database).

ParameterTypeRequiredDescription
databasestringyesCustom database key (lowercase_snake, e.g. "outreach"). Unqualified table names resolve in this database.
format"ddl" \"json"no
historybooleannoInclude the DDL change log.

Example call:

{"name":"describe","arguments":{"database":"<database>"}}

Related: data_status, query, explain, create_table, alter_table, find_rows, insert_rows, update_rows.

explain

Show the Postgres plan and estimated cost of one SQL statement without running it (analyze=true runs a read inside the timeout for real timings). Use when a query is slow or failed with CD-PG-57014 (timeout): look for Seq Scan on large tables and add an index with query. Same SQL rules and $1..$n params as query. Call describe first: never guess table or column names. On failure the result is {error: {code, message, fix, position?}}: read fix and retry with it. Codes: CD-PG- (a Postgres error, e.g. CD-PG-42P01 unknown table, CD-PG-42703 unknown column, CD-PG-23505 duplicate key, CD-PG-42501 your data role lacks the privilege, CD-PG-57014 timeout), CD-DENY- (refused before running, e.g. CD-DENY-SCHEMA, CD-DENY-FN, CD-DENY-TXN, CD-DENY-COPY, CD-DENY-EXT), CD-WARN-FULLTABLE, CD-LIMIT-*, CD-FORBIDDEN / CD-NOT-FOUND (no access, or no such database).

ParameterTypeRequiredDescription
databasestringyesCustom database key (lowercase_snake, e.g. "outreach"). Unqualified table names resolve in this database.
sqlstringyesThe statement to plan.
paramsany[]noValues for $1..$n, in order. Never paste values into the SQL text.
analyzebooleannoRun it (reads only) for actual timings.
timeout_msintegerno

Example call:

{"name":"explain","arguments":{"database":"<database>","sql":"<sql>"}}

Related: data_status, describe, query, create_table, alter_table, find_rows, insert_rows, update_rows.

export_rows

Export a table (optionally filtered with the find_rows query form in query) as CSV, JSON or NDJSON text, bounded by the row and byte caps. Call describe first: never guess table or column names. On failure the result is {error: {code, message, fix, position?}}: read fix and retry with it. Codes: CD-PG- (a Postgres error, e.g. CD-PG-42P01 unknown table, CD-PG-42703 unknown column, CD-PG-23505 duplicate key, CD-PG-42501 your data role lacks the privilege, CD-PG-57014 timeout), CD-DENY- (refused before running, e.g. CD-DENY-SCHEMA, CD-DENY-FN, CD-DENY-TXN, CD-DENY-COPY, CD-DENY-EXT), CD-WARN-FULLTABLE, CD-LIMIT-*, CD-FORBIDDEN / CD-NOT-FOUND (no access, or no such database).

ParameterTypeRequiredDescription
databasestringyesCustom database key (lowercase_snake, e.g. "outreach"). Unqualified table names resolve in this database.
tablestringyesTable name inside the database (lowercase_snake). Run describe first to see the real names.
format"csv" \"json" \"ndjson"
queryobjectno{select, where, order_by, limit} as in find_rows.

Example call:

{"name":"export_rows","arguments":{"database":"<database>","table":"<table>","format":"csv"}}

Related: data_status, describe, query, explain, create_table, alter_table, find_rows, insert_rows.

find_rows

Read rows from one table without writing SQL. where is a filter: {column, op, value} with op one of eq, ne, lt, lte, gt, gte, like, ilike, in, not_in, is_null, not_null; combine with {and: [...]}, {or: [...]}, {not: {...}}. select lists columns or aggregates {fn: count|sum|avg|min|max, column, as}; group_by, order_by [{column, direction}], limit (default 1000), offset. Returns the rows and the SQL it compiled to. Call describe first: never guess table or column names. On failure the result is {error: {code, message, fix, position?}}: read fix and retry with it. Codes: CD-PG- (a Postgres error, e.g. CD-PG-42P01 unknown table, CD-PG-42703 unknown column, CD-PG-23505 duplicate key, CD-PG-42501 your data role lacks the privilege, CD-PG-57014 timeout), CD-DENY- (refused before running, e.g. CD-DENY-SCHEMA, CD-DENY-FN, CD-DENY-TXN, CD-DENY-COPY, CD-DENY-EXT), CD-WARN-FULLTABLE, CD-LIMIT-*, CD-FORBIDDEN / CD-NOT-FOUND (no access, or no such database).

ParameterTypeRequiredDescription
databasestringyesCustom database key (lowercase_snake, e.g. "outreach"). Unqualified table names resolve in this database.
tablestringyesTable name inside the database (lowercase_snake). Run describe first to see the real names.
selectstring \object[]no
whereobjectno
group_bystring[]no
order_byobject[]no
limitintegerno
offsetintegerno

Example call:

{"name":"find_rows","arguments":{"database":"<database>","table":"<table>"}}

Related: data_status, describe, query, explain, create_table, alter_table, insert_rows, update_rows.

import_rows

Bulk insert or upsert CSV, JSON (array of objects) or NDJSON into a table in one transaction (bounded: 10,000 rows, 5 MB; larger is CD-LIMIT-IMPORT). column_map renames source fields to columns; mode "upsert" with on_conflict dedupes. dry_run=true returns the first mapped rows and errors without writing. Call describe first: never guess table or column names. On failure the result is {error: {code, message, fix, position?}}: read fix and retry with it. Codes: CD-PG- (a Postgres error, e.g. CD-PG-42P01 unknown table, CD-PG-42703 unknown column, CD-PG-23505 duplicate key, CD-PG-42501 your data role lacks the privilege, CD-PG-57014 timeout), CD-DENY- (refused before running, e.g. CD-DENY-SCHEMA, CD-DENY-FN, CD-DENY-TXN, CD-DENY-COPY, CD-DENY-EXT), CD-WARN-FULLTABLE, CD-LIMIT-*, CD-FORBIDDEN / CD-NOT-FOUND (no access, or no such database).

ParameterTypeRequiredDescription
databasestringyesCustom database key (lowercase_snake, e.g. "outreach"). Unqualified table names resolve in this database.
tablestringyesTable name inside the database (lowercase_snake). Run describe first to see the real names.
format"csv" \"json" \"ndjson"
datastring \object[]no
attachmentIdstringnoCanonical uploaded UTF-8 CSV/JSON/NDJSON id. Existing file-read authorization and import limits apply.
column_mapobjectno
empty_as_nullbooleanno
mode"insert" \"upsert"no
on_conflictobjectno
dry_runbooleanno
operationIdstringnoIdempotency key: retrying with the same operationId and the same arguments returns the stored answer instead of applying twice (24 h). Reusing it with different arguments is a 409; while the first call runs (or if its outcome was lost) it is a 409 for up to 2 minutes, then a retry runs, so read the rows back first.

Example call:

{"name":"import_rows","arguments":{"database":"<database>","table":"<table>","format":"csv"}}

Related: data_status, describe, query, explain, create_table, alter_table, find_rows, insert_rows.

insert_rows

Insert rows given as JSON objects (column -> value). on_conflict {columns: [dedupe key columns], action: "nothing" | "update", update_columns?} upserts on a unique key instead of failing with CD-PG-23505: use it so a retried bot run never duplicates rows. Do not send id, created_at or updated_at. Call describe first: never guess table or column names. On failure the result is {error: {code, message, fix, position?}}: read fix and retry with it. Codes: CD-PG- (a Postgres error, e.g. CD-PG-42P01 unknown table, CD-PG-42703 unknown column, CD-PG-23505 duplicate key, CD-PG-42501 your data role lacks the privilege, CD-PG-57014 timeout), CD-DENY- (refused before running, e.g. CD-DENY-SCHEMA, CD-DENY-FN, CD-DENY-TXN, CD-DENY-COPY, CD-DENY-EXT), CD-WARN-FULLTABLE, CD-LIMIT-*, CD-FORBIDDEN / CD-NOT-FOUND (no access, or no such database).

ParameterTypeRequiredDescription
databasestringyesCustom database key (lowercase_snake, e.g. "outreach"). Unqualified table names resolve in this database.
tablestringyesTable name inside the database (lowercase_snake). Run describe first to see the real names.
rowsobject[]yes
on_conflictobjectno
returningbooleannoReturn the inserted rows.
operationIdstringnoIdempotency key: retrying with the same operationId and the same arguments returns the stored answer instead of applying twice (24 h). Reusing it with different arguments is a 409; while the first call runs (or if its outcome was lost) it is a 409 for up to 2 minutes, then a retry runs, so read the rows back first.

Example call:

{"name":"insert_rows","arguments":{"database":"<database>","table":"<table>","rows":[]}}

Related: data_status, describe, query, explain, create_table, alter_table, find_rows, update_rows.

query

Run PostgreSQL 16 SQL in one custom database, in ONE transaction: SELECT (CTEs, window functions, LATERAL, JSONB operators), INSERT/UPDATE/DELETE/MERGE with RETURNING and ON CONFLICT, and DDL (CREATE TABLE/INDEX/VIEW, ALTER TABLE). Call describe first: never guess table or column names. Pass values as $1..$n in params, never inside the SQL text. Send either sql (one statement) or statements (several, run in order, all rolled back if one fails). Do not send BEGIN/COMMIT/SAVEPOINT (each call is already a transaction), COPY, CREATE EXTENSION, GRANT/REVOKE or role statements: they are refused. UPDATE/DELETE without WHERE is refused unless allow_full_table=true; DROP and TRUNCATE need confirm set to the object name. dry_run=true runs everything and rolls back (sequences still advance). The goodqa.* schema is read only. Results: {statements: [{rows, row_count, truncated, ...}]}, at most limit rows (default 1000). On failure the result is {error: {code, message, fix, position?}}: read fix and retry with it. Codes: CD-PG- (a Postgres error, e.g. CD-PG-42P01 unknown table, CD-PG-42703 unknown column, CD-PG-23505 duplicate key, CD-PG-42501 your data role lacks the privilege, CD-PG-57014 timeout), CD-DENY- (refused before running, e.g. CD-DENY-SCHEMA, CD-DENY-FN, CD-DENY-TXN, CD-DENY-COPY, CD-DENY-EXT), CD-WARN-FULLTABLE, CD-LIMIT-*, CD-FORBIDDEN / CD-NOT-FOUND (no access, or no such database).

ParameterTypeRequiredDescription
databasestringyesCustom database key (lowercase_snake, e.g. "outreach"). Unqualified table names resolve in this database.
sqlstringnoOne SQL statement. Use $1..$n placeholders for values.
paramsany[]noValues for $1..$n, in order. Never paste values into the SQL text.
statementsobject[]noSeveral statements run in order in one transaction (instead of sql).
dry_runbooleannoRun and roll back: test a write or DDL without keeping it.
allow_full_tablebooleannoAllow UPDATE/DELETE without a WHERE clause.
confirmstringnoObject name, required for DROP and TRUNCATE.
limitintegernoMax rows returned per statement (default 1000).
timeout_msintegerno

Example call:

{"name":"query","arguments":{"database":"<database>"}}

Related: data_status, describe, explain, create_table, alter_table, find_rows, insert_rows, update_rows.

update_rows

Update rows matching where (column -> value equality) with set (column -> new value). expect (column -> value) makes the update apply only if those values still hold (optimistic concurrency). An empty where changes every row and is refused (CD-WARN-FULLTABLE) unless allow_full_table=true. Call describe first: never guess table or column names. On failure the result is {error: {code, message, fix, position?}}: read fix and retry with it. Codes: CD-PG- (a Postgres error, e.g. CD-PG-42P01 unknown table, CD-PG-42703 unknown column, CD-PG-23505 duplicate key, CD-PG-42501 your data role lacks the privilege, CD-PG-57014 timeout), CD-DENY- (refused before running, e.g. CD-DENY-SCHEMA, CD-DENY-FN, CD-DENY-TXN, CD-DENY-COPY, CD-DENY-EXT), CD-WARN-FULLTABLE, CD-LIMIT-*, CD-FORBIDDEN / CD-NOT-FOUND (no access, or no such database).

ParameterTypeRequiredDescription
databasestringyesCustom database key (lowercase_snake, e.g. "outreach"). Unqualified table names resolve in this database.
tablestringyesTable name inside the database (lowercase_snake). Run describe first to see the real names.
whereobjectyes
setobjectyes
expectobjectno
allow_full_tablebooleanno
operationIdstringnoIdempotency key: retrying with the same operationId and the same arguments returns the stored answer instead of applying twice (24 h). Reusing it with different arguments is a 409; while the first call runs (or if its outcome was lost) it is a 409 for up to 2 minutes, then a retry runs, so read the rows back first.

Example call:

{"name":"update_rows","arguments":{"database":"<database>","table":"<table>","where":{},"set":{}}}

Related: data_status, describe, query, explain, create_table, alter_table, find_rows, insert_rows.

We use essential cookies to keep you signed in. See our Privacy Policy for details.