Tool generation

How a Postgres schema becomes 5–8 well-named MCP tools per table — automatically.

The introspection step

Once your data is loaded, the ingest worker queries Postgres' information_schema and pg_catalog to discover tables, columns, primary keys, foreign keys, and column cardinality. The result is a typed schema model that drives tool generation.

Per-column rules

Column traitGenerated tool(s)
text, varchar (high cardinality)search_* (Postgres full-text), filter_* (exact match)
text, varchar (low cardinality)count_*_by_* (aggregation)
int, numericfilter_* with min / max range
timestamptz, datefilter_* with after / before range
booleanfilter_* toggle
Primary keyget_*_by_id
Foreign keyget_*_for_* (cross-table join)

Worked example

Suppose you upload a products.csv with foreign keys to categories and orders. Schema introspection produces three tables. Tool generation yields:

# products
list_products
get_products_by_id
search_products            # searches: name, description
filter_products            # category, price (min/max), in_stock, created_at (after/before)
count_products_by_category

# categories
list_categories
get_categories_by_id

# orders
list_orders
get_orders_by_id
filter_orders              # customer_id, total (min/max), placed_at (after/before)
get_orders_for_product     # FK: orders.product_id → products.id

Eleven tools, no hand-written code, all visible to any MCP client via tools/list.

Argument schemas

Every generated tool has a JSON Schema for its inputs. Agents see precise types, ranges, and which fields are required. filter_* tools accept partial arguments — pass only the columns you care about.

// Example: filter_products inputSchema
{
  "type": "object",
  "properties": {
    "category": { "type": "string" },
    "price_min": { "type": "number" },
    "price_max": { "type": "number" },
    "in_stock": { "type": "boolean" },
    "created_at_after": { "type": "string", "format": "date-time" },
    "created_at_before": { "type": "string", "format": "date-time" },
    "limit": { "type": "integer", "default": 50, "maximum": 500 }
  }
}

Markdown-corpus tools

Endpoints built from Markdown / URL extraction get a different tool family geared at document retrieval rather than relational filtering:

  • search_documents — full-text across the corpus
  • get_document_by_slug — fetch the full markdown body
  • list_documents — paginated listing with title + excerpt
  • count_tags_by_tag / get_tags_for_document — tag analytics
  • list_links — outbound links extracted from each document

Write tools (Pro+ only)

When an endpoint has allow_writes on (Pro tier and above), schema-gen also produces three write tools per table that has a single-column primary key:

  • insert_<table>_meta.kind: "insert". Argument schema is the table's writable columns; required = NOT NULL columns without defaults.
  • update_<table>_by_id_meta.kind: "update_by_id". Pass the primary key plus only the columns you want to change.
  • delete_<table>_by_id_meta.kind: "delete_by_id".

Plus four built-in ingest tools (ingest_url, ingest_file, request_upload_url, ingest_uploaded_file) and a get_write_job_by_id tool for polling async results.

Metadata tables (pdf_metadata, audio_metadata, etc.) are excluded from write generation — they're populated by the ingest pipeline and shouldn't be written directly. Tables without a single-column PK are also excluded (no unambiguous "by id" key for update/delete).

See Agent writes & ingest for the full mental model and the OAuth scope (mcp:write) clients need to call them.

What's not auto-generated

  • Mass writes — no UPDATE … WHERE x = 'y' or bulk inserts. Limits blast radius.
  • Schema mods — agents can't CREATE TABLE or ALTER. Use the dashboard or Neon SQL editor.
  • Custom aggregations — sum, avg, percentile aren't generated. They're on the roadmap as opt-in aggregate_*_by_* tools.
  • Cross-table joins beyond FKs — only declared FKs produce join tools.
tips_and_updates

Tip: if your data has implied foreign keys but no actual constraint, add one before uploading. A single ALTER TABLE … ADD FOREIGN KEY in your SQL dump is enough to unlock the cross-table tools.