MDM MCP
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MDM MCPCreate a dataset for job applicants with name, phone, experience, and stage."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MDM MCP - Master Data Management for Conversational Agents
A backend-only master data management system exposed as a Model Context Protocol (MCP) server. Non-technical users describe what they want to track in plain language; an AI agent (OpenCode, Claude Code, or any MCP client) creates the schema, captures records, and answers questions through 16 well-documented tools - no GUI, no spreadsheet skills, no SQL. The agent is the interface; the data lives in clean local JSON.
User ("track my job applicants") → Agent → MCP tools → JSON storage
↑ you are here (server + skill)1. Quickstart (60 seconds, Docker only)
bash setup.sh # builds image, smoke-tests the MCP handshake, writes client configs
bash demo/demo.sh # optional: 30-second scripted walkthrough of the product
opencode # OpenCode: server already registered via opencode.json
# or
claude # Claude Code: approve the "master-data" project server when promptedThen simply talk:
"I want to track candidates for the Java developer role - name, phone, experience, and which stage they're in." "Add Rahul Sharma, 9876543210, 5 years, applied yesterday." "Who applied in the last week with more than 3 years experience?" "How many candidates are in each stage?"
Requirements: Docker + (OpenCode or Claude Code). Nothing else - no Python, no
venv, no database server, no ports. Data persists in the Docker volume mdm-data
(reset anytime: docker volume rm mdm-data).
uv venv --python 3.12 .venv
uv pip install -e . --python .venv/bin/python
.venv/bin/mdm-mcp # stdio MCP server; data in ./data (override with MDM_DATA_DIR)Point opencode.json / .mcp.json at .venv/bin/mdm-mcp instead of docker run.
Related MCP server: Super-MCP
2. The problem
People without spreadsheet experience waste significant time maintaining records in Excel/Google Sheets: column discipline, filters, formulas, and data types all demand training. Existing tools assume the user drives a GUI; AI agents remove that assumption.
Solution: expose a form-like data backend to an agent. The agent acts as a data clerk - proposes a schema (like building a Google Form), captures records from conversation, validates them instantly, and answers questions - while the server enforces types, safety gates, and context limits.
Three personas anchor the design (used as acceptance scenarios, not features):
Persona | What they exercise |
Hiring partner | Dataset per JD, enum stages, 100s of applicants, typo-tolerant fuzzy name search, bulk CSV import |
Business owner | Inventory/vendors/payments/employees, numeric + date validation, combined filters, bulk edits, totals |
Individual | Health logs, investments, schedules - date-heavy, low volume, high frequency |
User mental model: Workspace → Datasets → Columns (typed) → Rows.
3. Tool catalog (16 tools)
Datasets & columns - create_dataset, list_datasets, describe_dataset,
add_column, update_column, remove_column, delete_dataset
Rows - add_rows, get_row, update_rows, delete_rows, validate_rows,
search_rows, summarize_dataset
Files - import_rows, export_rows
Column types: string, text, boolean, integer, float, phone, date, enum with
Google-Forms-style constraints: required, default, min_value/max_value,
pattern, enum options.
4. Engineering for user-friendliness
This section is the heart of the assessment: the server is designed so that whatever the user says, the agent can fulfil safely.
Agent-coaching server instructions + skill file - the server ships
instructionsand a skill (.opencode/skills/master-data-management/,.claude/skills/...) teaching the agent to: propose schemas before creating, convert "yesterday" to an ISO date, null-fill unmentioned fields, answer with tables, and confirm before destructive actions.Plain-language validation - every failure is a sentence a human can act on:
Column 'phone' must be a valid Indian mobile number (10 digits, optional +91 or 0 prefix). Column 'stage' must be one of: Applied, Screened, Rejected.Per-column checks report all problems in a row, not just the first.
Lenient inputs -
"5"becomes the number 5,"true"becomes a boolean, numeric row ids (2vs"2") both work; empty CSV cells become nulls.Typo-tolerant search -
search_rows(fuzzy=true, query="Rahual")finds "Rahul Sharma" (rapidfuzz, similarity-scored).Safety gates, no undo needed - delete/bulk-edit/schema-changing tools return a preview +
requires_confirmation: true; execution needs explicitconfirm/dry_run=false.Agent-context protection - server-enforced:
limitdefault 20 / max 100 withtotal+next_offseton every list, column projection, batch cap 100 rows, sample caps, aggregate-only summaries. The conversation never drowns in rows.Structured results -
{"ok": true, ...}/{"ok": false, "error": "<reason>"}so the agent converses about failures instead of crashing.
5. Architecture
mdm_mcp/
├── models/ Pydantic: ColumnSpec, DatasetSchema, ColumnUpdate, FilterCondition
├── storage/ JsonRepository (interface): dir-per-dataset, schema.json + rows.json,
│ atomic temp-file writes, MDM_DATA_DIR override
├── validation/ RowValidator: pydantic TypeAdapter coercion per column + constraint
│ checks → plain-language issues; ONE engine reused by 4 tools
├── search/ FilterEngine: {column, op, value} DSL (11 ops) + rapidfuzz fuzzy
│ scoring; reused by search, bulk update/delete, export
├── services/ dataset_service, row_service, file_service (all business logic)
├── tools/ Thin FastMCP registrations: docstrings + Pydantic-typed args ARE
│ the generated tool documentation (JSON schema)
└── server.py FastMCP server (stdio) + agent instructionsKey decisions (full rationale in openspec/changes/archive/2026-08-30-mcp-master-data-management/design.md):
Local JSON over a database - zero infrastructure, human-inspectable files, single-user localhost scope; storage sits behind a repository interface so MongoDB can slot in without touching tools.
Pydantic dynamic validation - one validator instance per dataset reused by add/update/import/validate; pydantic gives type coercion and error localization for free.
One FilterEngine, four consumers - search, bulk update, bulk delete, export share identical filter semantics.
Official
mcpSDK (FastMCP) - tool JSON schemas derive automatically from typed signatures + docstrings, so documentation debt is structurally impossible.
6. Spec-driven development (OpenSpec)
The project was built with an artifact-driven workflow (openspec/), where code starts
only after behavior contracts exist. All artifacts are preserved in
openspec/changes/archive/2026-08-30-mcp-master-data-management/:
Artifact | Contents |
| Problem, personas, mental model, tool surface, deferred scope |
| 4 capability specs - |
| Decisions with rejected alternatives, risks/trade-offs (JSON rewrite cost, no locking, coercion surprises) |
| 24 phase-ordered tasks, each with its own verification step |
Rules followed throughout: no implementation without a spec covering it;
openspec validate green before any commit; implementation verified against the
spec scenarios (e.g. the "Rahual finds Rahul" and "100-row batch cap" scenarios are
literal pytest cases).
7. Phase-wise delivery (one commit per phase)
Phase | Commit | Delivered |
Planning |
| All OpenSpec artifacts, validated |
1 - Foundation |
| Models, atomic JSON storage, validator, create/list/describe/add/get, 47 tests |
2 - Schema & updates |
| Column lifecycle, preview→confirm deletions, partial updates, dry-run validation |
3 - Search & bulk |
| Filter DSL, fuzzy search, summaries, bulk-by-filter, CSV/JSON import/export |
4 - Polish |
| Docstring audit (automated), README, 3 persona walkthrough suites |
Hardening |
| Console-script cwd fix, numeric ids, richer agent instructions |
Packaging |
| Docker one-command setup + 30-second demo |
8. Testing strategy (127 tests)
Layer | What it proves |
Unit ( | Every column type, constraint, rejection message, filter op, atomic-write behavior |
Service integration ( | Full workflows incl. pagination, confirm gates, import/export roundtrips |
Persona walkthroughs ( | The 3 personas as end-to-end scenarios: recruiter funnel, business-owner restock + totals, individual health log |
MCP wire tests ( | Tool registration (16), schema descriptiveness, docstring audit, structured results, destructive tools default to preview |
Manual/automated E2E | MCP Inspector over real stdio; scripted Docker client session (create → validate → persist across two container runs); live OpenCode agent conversations incl. a bad-phone recovery flow |
9. Example interaction
User: add my friend Aman Gupta to the invitees, his phone is 123
Agent: ⚙ master-data_add_rows {..., "phone": "123"}
Server: {"ok": true, "added": 0, "rejected": 1,
"results": [{"row": 0, "status": "rejected",
"errors": ["Column 'phone' must be a valid Indian mobile number
(10 digits, optional +91 or 0 prefix)."]}]}
Agent: Aman wasn't added yet - the phone column requires a valid Indian mobile
number, so "123" was rejected. Do you have his full number?10. Project layout
├── Dockerfile, setup.sh, .dockerignore one-command Docker packaging
├── demo/ 30-second scripted demo (inside Docker)
├── mdm_mcp/ the server (see Architecture)
├── tests/ 127 tests, 4 layers
├── .opencode/skills/, .claude/skills/ agent skill: SKILL.md (operating manual)
│ + reference.md (full tool API reference)
├── opencode.json, .mcp.json client configs (generated by setup.sh)
├── openspec/ spec-driven development artifacts (archive)
└── README.md this fileStack: Python 3.12, official MCP SDK (FastMCP, stdio), Pydantic v2, rapidfuzz,
stdlib csv/json. Dependencies kept deliberately minimal.
11. Installing the agent skill on another machine
The skill is a self-contained folder (SKILL.md operating manual + reference.md
full tool API reference). Copy it into either client's skills directory:
# Claude Code - project-level (auto-detected in that project)
mkdir -p /path/to/project/.claude/skills
cp -r .claude/skills/master-data-management /path/to/project/.claude/skills/
# Claude Code - personal (all projects)
cp -r .claude/skills/master-data-management ~/.claude/skills/
# OpenCode - project-level
mkdir -p /path/to/project/.opencode/skills
cp -r .opencode/skills/master-data-management /path/to/project/.opencode/skills/
# OpenCode - global
cp -r .opencode/skills/master-data-management ~/.config/opencode/skills/Then start a conversation with the server attached (opencode.json / .mcp.json
from setup.sh, or claude mcp add master-data -- docker run -i --rm -v mdm-data:/data mdm-mcp:latest).
Auto vs manual invocation: skills load automatically when a request is
data-related; they are not listed in the / menu (that menu shows commands, a
separate mechanism). For explicit invocation, both clients also ship a
/master-data <request> project command (.opencode/command/, .claude/commands/)
that loads the skill guidance on demand.
12. Restarting & resuming (your data never goes anywhere)
There is no long-running server to babysit. The MCP client (OpenCode / Claude Code)
starts the container automatically each session and stops it when done (--rm) - that
is by design. Your data lives outside the container and survives everything:
What closed | How to resume |
Terminal / OpenCode / Claude Code session | Just relaunch |
Docker Desktop | Start it, then relaunch your client. Same behavior. |
Machine reboot | Same - relaunch the client. Nothing else to do. |
Local (non-Docker) run | Re-run |
Where your data is:
Docker setup → Docker volume
mdm-data→/data/<dataset>/schema.json+rows.json(inspect:docker run --rm -v mdm-data:/data alpine sh -c "ls /data && cat /data/<dataset>/rows.json")Local setup →
./data/<dataset>/(plain JSON, human-readable)
Quick resume check - open your client and ask "what am I tracking?" (list_datasets),
or verify from the shell:
docker run --rm -v mdm-data:/data alpine ls /data # Docker setup
ls ./data # local setupMaintenance one-liners:
bash setup.sh # rebuild/re-verify/re-generate client configs (safe, cached)
bash scripts/resume_check.sh # prove persistence: write in one session, read in a new one
docker volume rm mdm-data # wipe all data and start fresh
docker rmi mdm-mcp:latest # remove the image (setup.sh rebuilds it)Note: local runs store data in ./data, Docker runs in the volume - these are two
different stores. Pick one mode and stay with it; switching modes does not lose data,
it just looks at the other location.
13. Evaluation checklist
bash setup.sh→ handshake smoke test passesbash demo/demo.sh→ import with rejects, fuzzy match, dry-run bulk edit, summaryStart
opencode(orclaude) in this folder and hold a natural conversationTry a mistake on purpose (bad phone, unknown person) - observe recovery UX
Inspect
data/(ordocker run --rm -v mdm-data:/data alpine cat /data/<dataset>/rows.json)the storage is readable JSON
.venv/bin/python -m pytest(local setup) - 127 tests green
Available Tools
16 toolsadd_columnA
Add a new typed column to an existing dataset.
Existing rows are backfilled with the column's default value, or null when no default is set. Use this when the user wants to start tracking something new in an existing dataset ("also note each candidate's expected salary").
Args: dataset: Exact dataset name, e.g. "Candidates". column: The new column definition (same shape as in create_dataset).
Returns: {"ok": true, "dataset", "column", "type", "backfilled_rows": } on success, {"ok": false, "error": ""} when the column already exists or the definition is invalid (e.g. enum without options).
Example: add_column(dataset="Candidates", column={"name": "expected_salary", "type": "float", "min_value": 0})
| Name | Required | Description | Default |
|---|---|---|---|
| column | Yes | ||
| dataset | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It explains the important side effect that existing rows are backfilled with the column's default value or null, and it documents both success and failure return shapes, including specific failure reasons such as duplicate columns and invalid enum definitions. It omits permission or reversibility details but covers the core mutation behavior well.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized: purpose, behavioral consequence, usage trigger, arguments, return values, and example. Every section earns its place, and the key facts are front-loaded rather than buried. There is no redundant or filler content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter mutation tool with no annotations and an opaque column object schema, the description covers backfill behavior, success and error returns, failure triggers, and a runnable example. It is not fully self-contained because the complete column definition shape lives in create_dataset, but it gives enough pointers for an agent to proceed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage, so the description must compensate. It meaningfully describes dataset as needing the exact name, and it explains that column uses the same shape as create_dataset, backed by an example. However, the full column definition is delegated to another tool rather than documented here, so agents still need cross-tool context to construct valid column objects.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action, 'Add a new typed column to an existing dataset', making both the resource and operation explicit. The use case 'start tracking something new in an existing dataset' and the concrete natural-language example further clarify its scope and distinguish it from sibling tools like update_column, remove_column, and create_dataset.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear trigger condition: 'Use this when the user wants to start tracking something new in an existing dataset', including a sample user request. It does not explicitly name alternatives or say when not to use this tool, but the situational guidance is unambiguous enough for selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_rowsA
Add one or more rows to a dataset with per-row validation.
Use this to capture records the user dictates in conversation. Each row is an object mapping column names to values; every row is validated against the dataset schema and valid rows are saved while invalid rows are reported back with plain-language reasons. At most 100 rows per call - split larger batches.
Check describe_dataset first so column names, types, and constraints match exactly.
Args: dataset: Exact dataset name, e.g. "Candidates". rows: List of row objects, e.g. [{"name": "Asha", "phone": "9876543210"}].
Returns: {"ok": true, "dataset", "added": , "rejected": , "results": [{"row": , "status": "added", "row_id": ""} | {"row": , "status": "rejected", "errors": ["..."]}]} Relay every rejected row's errors to the user in plain language.
Example: add_rows(dataset="Candidates", rows=[ {"name": "Asha Verma", "phone": "9876543210", "stage": "Applied", "applied_on": "2026-08-30"} ])
| Name | Required | Description | Default |
|---|---|---|---|
| rows | Yes | ||
| dataset | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full disclosure burden. It does this well by explaining that invalid rows are rejected while valid rows are saved, that the call is limited to 100 rows, and that rejected rows are reported with plain-language reasons. It also provides the complete return shape, making side effects and failure behavior transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is organized into a clear summary, usage note, Args, Returns, and Example. Every section adds necessary information: the prerequisite check, the limit, the return contract, and a concrete example. There is no filler or redundancy that dilutes the guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter tool with no annotations, the description is complete: it explains when to use it, how to prepare, what the inputs mean, what outputs look like, and how to handle rejected rows. The example further anchors the expected call shape. No critical operational detail is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must fully compensate. It clearly explains that dataset is the exact dataset name with an example, and that rows is a list of row objects mapping column names to values with an inline example. It also adds the 100-row limit and validation behavior that the schema does not convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Add one or more rows to a dataset with per-row validation.' It clearly identifies the operation as adding rows and even differentiates its behavior from related tools by emphasizing validation and partial saves.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear usage context: use this to capture records the user dictates in conversation, check describe_dataset first to ensure columns and constraints match, and relay rejected rows. It does not explicitly enumerate when not to use it versus alternatives like import_rows or update_rows, so it misses the full explicit when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_datasetA
Create a new dataset (a table) with user-defined typed columns.
Use this whenever the user wants to start tracking something new - candidates, inventory, payments, a health log. Columns behave like spreadsheet headers with Google-Forms-style validation. Always propose the column list to the user and get their confirmation before calling this tool.
Args: name: Unique dataset name, e.g. "Candidates" (case-insensitive uniqueness). columns: One or more column definitions. description: Optional short description of what this dataset tracks.
Column types: string, text, boolean, integer, float, phone, date, enum. Column attributes: required, default, min_value/max_value (numeric columns), pattern (string/text columns), options (enum columns, at least one value).
Returns: {"ok": true, "dataset": "", "columns": [{"name", "type"}]} on success, {"ok": false, "error": ""} on failure.
Example: create_dataset(name="Candidates", description="Applicants for the Java JD", columns=[ {"name": "name", "type": "string", "required": true}, {"name": "phone", "type": "phone"}, {"name": "experience", "type": "float", "min_value": 0}, {"name": "stage", "type": "enum", "options": ["Applied", "Screened", "Rejected"]}, {"name": "applied_on", "type": "date"} ])
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| columns | Yes | ||
| description | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses behavior: it creates a new dataset, enforces case-insensitive uniqueness, defines column validation rules, and specifies both success and failure return formats. The example illustrates exact input/output structures.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Organized with purpose, args, returns, and example. Every sentence adds value, and the example is illustrative. Length is justified by tool complexity; nothing is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers what the tool does, when to use it, required pre-call confirmation, parameter semantics, return values, and a realistic example. With no output schema, it still fully explains output structure and error handling.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% (schema only lists names/types), but the description explains each parameter in depth, including column type list, per-type attributes, and constraints (e.g., enum requires at least one option). This vastly exceeds schema detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states the tool creates a new dataset (table) with typed columns and gives concrete use cases (candidates, inventory, payments). It clearly distinguishes from siblings like add_column, list_datasets, and delete_dataset.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides direct guidance: 'Use this whenever the user wants to start tracking something new' and mandates a workflow ('Always propose the column list... get confirmation before calling'). This is unambiguous and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_datasetA
Delete an entire dataset and all of its rows after explicit confirmation.
Destructive: without confirm=true the tool only returns a preview (row count, column count). Call it with confirm=false first, tell the user what will be lost, and only re-invoke with confirm=true after they agree.
Args: name: Exact dataset name to delete. confirm: Must be true to actually delete (default false = preview only).
Returns: {"ok": true, "deleted": "", "rows_removed": } after confirmation, {"ok": true, "requires_confirmation": true, "preview": {...}} without.
Example: delete_dataset(name="Old JD", confirm=false)
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| confirm | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description fully discloses destructive behavior, the confirm-gate mechanism, preview vs. actual deletion, and exact return formats. It highlights the irreversible nature and requires explicit confirmation, which is comprehensive for an agent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is logically structured: purpose, safety warning, parameters, returns, and example. Every section serves a purpose and is front-loaded with the critical safety note. No fluff or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite the lack of annotations and rich schema, the description covers all necessary context: safety, usage workflow, parameter semantics, return values, and a concrete example. An agent can call the tool correctly with only this description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides zero descriptions (0% coverage), but the description fully explains both parameters: 'name' as the exact dataset name and 'confirm' with its default and behavioral effect. An example ties it together, far exceeding what the schema alone offers.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb ('Delete') and resource ('an entire dataset and all of its rows'), which clearly distinguishes it from sibling tools like delete_rows. The intent is unambiguous and directly actionable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides an explicit two-step workflow: first invoke with confirm=false to preview, then with confirm=true after user agreement. This tells the agent exactly when and how to use the tool, though it does not compare directly to delete_rows, the workflow is complete and self-contained.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_rowsA
Delete rows by explicit ids, or in bulk for every row matching a filter.
Destructive: without confirm=true the tool only returns a preview listing the rows that would be deleted. Call it with confirm=false first, tell the user what will be lost, and only re-invoke with confirm=true after they agree.
Args: dataset: Exact dataset name, e.g. "Candidates". row_ids: Explicit row ids to delete, e.g. ["4"]. Mutually exclusive with conditions. conditions: Filter selecting rows to delete, e.g. [{"column": "experience", "op": "lt", "value": 2}]. confirm: Must be true to actually delete (default false = preview only).
Returns: {"ok": true, "dataset", "deleted": , "row_ids": [...], "not_found": [...]} after confirmation, {"ok": true, "requires_confirmation": true, "preview": {...}} without.
Example: delete_rows(dataset="Candidates", conditions=[{"column": "stage", "op": "eq", "value": "Rejected"}])
| Name | Required | Description | Default |
|---|---|---|---|
| confirm | No | ||
| dataset | Yes | ||
| row_ids | No | ||
| conditions | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral disclosure burden and does so thoroughly. It labels the operation as destructive, explains the preview vs. actual deletion behavior, documents the confirm default, and specifies both return shapes. This is far beyond what the bare input schema conveys.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact yet information-dense: purpose, safety workflow, args, return values, and example are clearly labeled and easy to parse. The destructive warning is front-loaded, and every sentence contributes to safe and correct invocation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers all needed context: how to preview, how to confirm, what arguments to pass, what responses to expect, and a concrete example. Despite having no annotations, an agent has everything necessary to invoke the tool safely and interpret its output.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description fully compensates by providing a dataset example, row_ids example with mutual exclusivity, a structured conditions example, and confirm default semantics. Each parameter is given practical meaning beyond its raw type definition.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with a specific verb and resource: 'Delete rows by explicit ids, or in bulk for every row matching a filter.' This clearly distinguishes it from siblings like delete_dataset, add_rows, and update_rows, and identifies the two supported deletion modes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit workflow guidance: call with confirm=false first, tell the user what will be lost, then re-invoke with confirm=true after agreement. It also clarifies that row_ids and conditions are mutually exclusive. It doesn't explicitly name alternative sibling tools for when not to use it, but the usage context is otherwise strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
describe_datasetA
Show a dataset's full column definitions (types and constraints) and row count.
Use this before adding or searching rows so you know the exact column names, types, and constraints. Optionally include a few sample rows (capped at 5) to see what the data looks like.
Args: name: Exact dataset name, e.g. "Candidates". sample_rows: Optional number of first rows to include, 0-5 (default 0).
Returns: {"ok": true, "dataset", "description", "row_count", "columns": [{"name", "type", "required", "default?", "options?", ...}], "samples": [{"id", ...}]} on success, {"ok": false, "error": ""} when the dataset does not exist.
Example: describe_dataset(name="Candidates", sample_rows=3)
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| sample_rows | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the behavioral burden. It discloses the return format on success and failure, the sample row cap of 5, the default of 0, and that it describes column definitions and row count. 'Show' implies a read-only operation, though it does not explicitly state that no data is modified.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a front-loaded purpose sentence, followed by usage context, Args, Returns, and an Example. Every section earns its place, and the format makes key facts easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no annotations, the description is complete for a two-parameter introspection tool: it covers purpose, when to use it, parameter semantics, expected return shape, error behavior, and an example call. No critical operational detail is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has no property descriptions (0% coverage), so the description must fully explain parameters. It does: 'Exact dataset name, e.g. "Candidates"' adds precision, and 'Optional number of first rows to include, 0-5 (default 0)' clarifies range, default, and meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Show a dataset's full column definitions (types and constraints) and row count.' This clearly differentiates it from sibling tools like search_rows or get_row, which retrieve data rows rather than schema metadata.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states 'Use this before adding or searching rows so you know the exact column names, types, and constraints,' giving clear when-to-use guidance. It does not explicitly name alternatives or state when-not-to-use, but the intended context is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
export_rowsA
Export rows (optionally filtered and projected) to a CSV or JSON file.
Use this when the user wants their data back in a spreadsheet-friendly form. Filters use the same conditions syntax as search_rows. The id column is always included. Refuses to overwrite an existing file unless overwrite=true.
Args: dataset: Exact dataset name, e.g. "Candidates". file_path: Destination path for the .csv or .json file. format: "auto" (default, infers from extension), or force "csv"/"json". conditions: Optional filter, e.g. [{"column": "stage", "op": "eq", "value": "Applied"}]. columns: Optional column projection, e.g. ["name", "phone"]. overwrite: Allow replacing an existing file (default false).
Returns: {"ok": true, "dataset", "file": "", "format", "rows_exported": }.
Example: export_rows(dataset="Candidates", file_path="~/Documents/applied_august.csv", conditions=[{"column": "applied_on", "op": "between", "value": ["2026-08-01", "2026-08-31"]}])
| Name | Required | Description | Default |
|---|---|---|---|
| format | No | auto | |
| columns | No | ||
| dataset | Yes | ||
| file_path | Yes | ||
| overwrite | No | ||
| conditions | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does well: it reveals that the id column is always included, that existing files are not overwritten without overwrite=true, that format is inferred from the file extension unless forced, and what the return object looks like. This is meaningful behavior beyond the schema; only a few edge details like file-size limits or permission requirements are absent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is organized with a summary line, a usage note, a compact Args list, a Returns line, and a worked example. It is long only because there are six parameters to clarify, and every section adds useful information without repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a six-parameter export tool with no annotations and an output schema, the description is comprehensive: it covers filters, projection, format inference, overwrite safety, return shape, and includes an example. There is no missing information an agent would need to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description compensates fully by explaining every parameter, providing concrete examples for conditions and the overall call, and noting defaults for format and overwrite. An agent can construct a correct invocation from the description alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb-resource-action statement: 'Export rows (optionally filtered and projected) to a CSV or JSON file.' This unambiguously distinguishes it from sibling read/search/write tools, and the 'spreadsheet-friendly form' phrasing reinforces the practical purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says when to use the tool ('Use this when the user wants their data back in a spreadsheet-friendly form') and connects filtering to the search_rows syntax, which helps an agent reason about shared semantics. It does not explicitly contrast with search_rows or other alternatives, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_rowA
Fetch a single row by id, optionally limited to specific columns.
Use this when the user asks about one record ("show me row 12", "what is Asha's phone number?"). Ask for only the columns you need to keep the response small.
Args: dataset: Exact dataset name, e.g. "Candidates". row_id: The row id, e.g. "12". columns: Optional list of column names to project, e.g. ["name", "stage"].
Returns: {"ok": true, "dataset", "row": {"id", ...requested columns}} on success, {"ok": false, "error": ""} for unknown ids or columns.
Example: get_row(dataset="Candidates", row_id="12", columns=["name", "phone"])
| Name | Required | Description | Default |
|---|---|---|---|
| row_id | Yes | ||
| columns | No | ||
| dataset | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden. It discloses success and error return shapes, including what happens for unknown ids or columns, and the projection behavior. It does not explicitly state the operation is read-only, though 'Fetch' and the return contract make that reasonably clear.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose, then gives usage guidance, args, returns, and an example in a compact, organized format. Every section adds necessary information and there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a three-parameter read tool with no annotations and no property descriptions in the schema, the description provides everything needed: purpose, when to use, parameter semantics, return contract, error behavior, and a concrete example. Nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must fully compensate, and it does. It explains dataset as an exact name, row_id with an example, and columns as an optional projection list, plus a complete call example. All three parameters are effectively documented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Fetch a single row by id,' optionally limited to columns. It clearly distinguishes this tool from siblings like search_rows by emphasizing single-record retrieval, and includes concrete user-phrase examples.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit when-to-use condition with examples like 'show me row 12' and advises requesting only needed columns to keep responses small. However, it does not explicitly name when-not-to-use or point to search_rows for multi-record queries, so it stops short of full alternative guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
import_rowsA
Import rows into a dataset from a CSV or JSON file, in two safe steps.
Step 1 (confirm=false, default): returns a mapping preview - how each file column maps to a dataset column, unmatched file columns, missing required dataset columns, and a small sample. Share the mapping with the user and let them confirm or adjust the file.
Step 2 (confirm=true): imports. Every row is validated against the dataset schema; valid rows are added and invalid rows are reported with plain-language reasons. CSV values are coerced automatically ("5" becomes the number 5, "true" becomes a boolean).
Args: dataset: Exact dataset name, e.g. "Candidates". file_path: Path to the .csv or .json file on this machine. format: "auto" (default, infers from extension), or force "csv"/"json". confirm: Must be true to actually import (default false = preview only). create_if_missing: When the dataset does not exist, create it first with one string column per file header, then import (default false).
Returns: Preview: {"ok": true, "requires_confirmation": true, "preview": {...}}. Commit: {"ok": true, "dataset", "added": , "rejected": , "rejected_rows": [{"row": , "errors": ["..."]}]}.
Example: import_rows(dataset="Candidates", file_path="~/Downloads/applicants.csv")
| Name | Required | Description | Default |
|---|---|---|---|
| format | No | auto | |
| confirm | No | ||
| dataset | Yes | ||
| file_path | Yes | ||
| create_if_missing | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden and does so well: it reveals that previews happen before commit, that rows are validated against the schema, that CSV values are coerced, and that invalid rows are reported. It stops short of explicitly stating whether the preview is fully non-mutating or whether the import is transactional.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every section earns its place: purpose, two-step behavior, parameter definitions, return shapes, and an example. It is well-structured with clear headers and front-loaded with the core behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex two-phase tool with five parameters and no annotations, the description covers the full call contract: all parameters, both phase return shapes, defaults, validation behavior, and an example. Nothing essential for invoking it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description compensates fully by explaining every parameter: dataset name, file path, format auto/csv/json, confirm gating the actual import, and create_if_missing behavior. The example reinforces how the parameters are used together.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence names a specific action ('Import rows into a dataset'), the source formats (CSV/JSON), and the two-step preview/commit model. This makes it easy to distinguish from file-export or manual-row tools, but it never explicitly names sibling tools or states what it is not.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly explains the intended workflow: call with confirm=false first, share the mapping with the user, then call with confirm=true to commit. It also explains create_if_missing behavior and defaults, but it does not explicitly compare against alternatives like add_rows or validate_rows.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_datasetsA
List all datasets with row counts and a name:type column summary.
Use this to discover what the user is already tracking before creating or querying a dataset. Results are paginated: use next_offset from the response to fetch the next page instead of raising the limit.
Args: limit: Page size (1-100, default 20). offset: Number of datasets to skip (default 0).
Returns: {"ok": true, "datasets": [{"name", "description", "row_count", "columns"}], "total": , "count": , "next_offset": }.
Example: list_datasets(limit=50)
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It clearly discloses pagination behavior, instructs the agent to use next_offset rather than raising the limit, and specifies the exact response shape. This goes well beyond a simple 'lists datasets' and gives the agent actionable behavior expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded: a one-sentence purpose, a usage context line, then a compact Args/Returns/Example layout. Every section earns its place and the example is genuinely useful. No filler or redundant restatement.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter list tool, this description is complete: it covers behavior, pagination, parameter semantics, and return shape, and even gives an example. The presence of an output schema means the described Returns section is a bonus, and the pagination warning covers a common mistake. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must fully compensate. It does: the Args section adds meaning beyond the schema by explaining limit as page size with a valid range (1-100), explaining offset as the number of datasets to skip, and restating defaults. This is exactly what an agent needs to call the tool correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb-resource pair: 'List all datasets' and adds the distinguishing detail of row counts and a name:type column summary. This sets it apart from siblings like search_rows, create_dataset, and describe_dataset, so an agent can tell what it does without inspecting the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool: 'Use this to discover what the user is already tracking before creating or querying a dataset.' This is clear contextual guidance, though it does not explicitly name alternative tools or exclusion conditions, so it falls just short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_columnA
Remove a column from a dataset after explicit confirmation.
Destructive: without confirm=true the tool only returns a preview of what would be dropped. Call it with confirm=false first, tell the user what will be lost, and only re-invoke with confirm=true after they agree.
Args: dataset: Exact dataset name, e.g. "Candidates". column: Column name to remove. confirm: Must be true to actually remove (default false = preview only).
Returns: {"ok": true, "dataset", "removed", "rows_updated"} after confirmation, {"ok": true, "requires_confirmation": true, "preview": {...}} without, {"ok": false, "error": ""} for unknown columns.
Example: remove_column(dataset="Candidates", column="temporary_note", confirm=false)
| Name | Required | Description | Default |
|---|---|---|---|
| column | Yes | ||
| confirm | No | ||
| dataset | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does so thoroughly. It discloses that the tool is destructive, that confirm defaults to false and produces only a preview, and it documents all three return shapes including the error case for unknown columns.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the most important safety warning, then efficiently documents parameters, return values, and an example. Every section earns its place and nothing is redundant or vague.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive three-parameter tool with no annotations, the description is fully complete. It covers the safe workflow, required arguments, default behavior, return values, and an example invocation, leaving no critical gap for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must explain parameters itself, and it does. It defines dataset as an exact name with an example, defines column as the column name to remove, and explains that confirm must be true to actually remove, contrasting with its default false.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Remove a column from a dataset,' and immediately distinguishes itself from related operations like add_column and update_column. The 'after explicit confirmation' qualifier further clarifies the tool's special destructive nature.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit procedural guidance: call with confirm=false first, show the user what will be lost, and only re-invoke with confirm=true after agreement. This clearly tells the agent when and how to use the tool, including the safe alternative flow.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_rowsA
Search rows with exact filters, or typo-tolerant fuzzy matching, with sorting and pagination.
Two search modes:
Exact: pass conditions built from {column, op, value}. Ops: eq, ne, gt, gte, lt, lte, contains, in, between, is_empty, is_not_empty. Combine conditions to narrow further (AND).
Fuzzy: pass fuzzy=true plus a query string to match string/text columns tolerantly against typos and misspellings ("Rahual" finds "Rahul Sharma"). Results are ordered by similarity and carry an _score. Narrow with fuzzy_columns to search only specific text columns.
Results are always paginated: page with next_offset instead of raising the limit, and request only the columns you need via columns.
Args: dataset: Exact dataset name, e.g. "Candidates". conditions: Exact-mode filters, e.g. [{"column": "stage", "op": "eq", "value": "Applied"}]. fuzzy: Set true for typo-tolerant matching (requires query). query: Text to fuzzy-match, e.g. "Rahual". fuzzy_columns: Optional text columns to fuzzy-match against (default: all text columns). fuzzy_threshold: Minimum similarity score 1-100 (default 80). sort_by: Column to sort by (exact mode). sort_order: "asc" (default) or "desc". limit: Page size 1-100 (default 20). offset: Rows to skip for pagination (default 0). columns: Column projection, e.g. ["name", "stage"]; id is always included.
Returns: {"ok": true, "dataset", "rows": [{"id", ...columns, "_score"?}], "total": , "count": , "next_offset": }.
Example: search_rows(dataset="Candidates", conditions=[ {"column": "applied_on", "op": "between", "value": ["2026-08-01", "2026-08-31"]}, {"column": "stage", "op": "ne", "value": "Rejected"} ], sort_by="applied_on", sort_order="desc", columns=["name", "stage"]) search_rows(dataset="Candidates", fuzzy=true, query="Rahual", fuzzy_columns=["name"])
| Name | Required | Description | Default |
|---|---|---|---|
| fuzzy | No | ||
| limit | No | ||
| query | No | ||
| offset | No | ||
| columns | No | ||
| dataset | Yes | ||
| sort_by | No | ||
| conditions | No | ||
| sort_order | No | asc | |
| fuzzy_columns | No | ||
| fuzzy_threshold | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure, and it delivers thoroughly. It explains pagination behavior ('page with next_offset instead of raising the limit'), fuzzy result ordering by similarity, the inclusion of _score in fuzzy mode, and that id is always included in column projection. These details go far beyond the schema and give the agent a precise model of the tool's runtime behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but every section earns its place given the 11 parameters and two distinct modes. It is well-structured with a summary, mode explanations, an Args list, Returns format, and two concrete examples. Information is front-loaded, and the format makes scanning easy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the full behavior of the tool, including exact and fuzzy modes, operator semantics, pagination, sorting, projection, output shape, and example calls. For a read-oriented search tool with no annotations, this is complete enough for an agent to select and invoke it correctly without further clarification.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description compensates completely by documenting every parameter with types, defaults, formats, and examples. It explains the structure of conditions, the supported operators, limits on limit, the meaning of fuzzy_threshold, and the projection behavior of columns. This is exemplary parameter documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Search rows with exact filters, or typo-tolerant fuzzy matching, with sorting and pagination.' This clearly distinguishes it from siblings like get_row (single row lookup) and summarize_dataset (aggregation). The two search modes are explicitly named and explained, making the tool's purpose unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear guidance on when to use exact mode versus fuzzy mode, including the conditions required for each and examples. It does not explicitly contrast search_rows with sibling tools like get_row or validate_rows, so there are no exclusion rules, but the usage context is otherwise well defined.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
summarize_datasetA
Summarize a dataset with aggregates instead of raw rows.
Use this when the user asks for totals or breakdowns ("how many candidates per stage?", "total inventory value?") - it returns row count, count/min/max/ avg/sum for every numeric column, and value breakdowns for every enum column, without ever dumping rows into the conversation.
Args: dataset: Exact dataset name, e.g. "Inventory".
Returns: {"ok": true, "dataset", "row_count": , "numeric": {"": {"count", "min", "max", "avg", "sum"} or {"count": 0}}, "enums": {"": {"": }}}.
Example: summarize_dataset(dataset="Inventory")
| Name | Required | Description | Default |
|---|---|---|---|
| dataset | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It clearly discloses that it returns aggregates, never dumps rows into the conversation, and provides the exact return structure. It does not explicitly state whether the dataset is modified, but the summarize intent and output shape strongly imply a read-only operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded: purpose, when to use, arguments, return format, and an example. Every section earns its place without unnecessary filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the low complexity (one parameter) and the detailed return schema embedded in the description, an agent has everything needed to invoke the tool correctly. The example call is clear and the return shape is fully specified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter has no schema description (0% coverage), so the description must compensate. It does by specifying 'Exact dataset name' and giving an example, which is adequate for a single string parameter. It could add guidance on discovering valid dataset names, but the example removes most ambiguity.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description begins with a specific verb and resource: 'Summarize a dataset with aggregates instead of raw rows.' It further distinguishes itself from row-returning siblings by explaining it returns row count, numeric stats, and enum breakdowns rather than rows.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit context: 'Use this when the user asks for totals or breakdowns' with concrete examples. It does not explicitly name alternatives such as search_rows, but the contrast with raw rows implicitly routes the agent away from row-level tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_columnA
Change a column's name, type, or constraints on an existing dataset.
Only the fields you explicitly provide are changed. After the change every stored row is revalidated: rows that no longer satisfy the new definition are reported with their row ids and errors, and their values are preserved so the user can decide how to fix them. Renaming a column moves the values under the new name in all rows.
Args: dataset: Exact dataset name, e.g. "Candidates". column: Current column name to change. changes: Fields to change, e.g. {"max_value": 10} or {"name": "full_name"}.
Returns: {"ok": true, "dataset", "column", "renamed_from": , "rows_checked": , "invalid_rows": {"": [""]}} on success, {"ok": false, "error": ""} for unknown columns or invalid changes.
Example: update_column(dataset="Candidates", column="experience", changes={"max_value": 20})
| Name | Required | Description | Default |
|---|---|---|---|
| column | Yes | ||
| changes | Yes | ||
| dataset | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and exceeds it: it discloses that only provided fields change, every stored row is revalidated, invalid rows are preserved and reported with errors, and renaming moves values. It also documents success and error return shapes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose and side effects, then organized into compact Args, Returns, and Example sections. Every sentence adds useful information; the example is illustrative rather than redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with no annotations and no parameter descriptions in the schema, this description is complete: it explains side effects, validation behavior, error cases, return contract, and invocation via a realistic example. An agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage, but the Args section fully compensates: dataset is defined as an exact name, column as the current column name, and changes is illustrated with concrete examples like {'max_value': 10} and {'name': 'full_name'}. The example call reinforces the parameter shapes.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb ('Change'), a concrete resource ('a column'), and the scope ('existing dataset'). Naming 'name, type, or constraints' clearly distinguishes it from sibling tools like add_column and remove_column.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly establishes that this is for modifying an existing column and requires the current column name. However, it does not explicitly name alternatives or say 'use add_column instead when adding a new column', so it stops short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_rowsA
Update rows by explicit ids, or in bulk for every row matching a filter.
Only the provided columns change; everything else stays as-is. New values are validated together with the rest of each row, so an invalid change leaves that row untouched and is reported with plain-language errors.
Bulk mode (conditions): defaults to a dry-run preview. Review the preview with the user, then re-invoke with dry_run=false to apply. Never set dry_run=false on the first call when a filter may match many rows.
Args: dataset: Exact dataset name, e.g. "Candidates". values: Column values to set, e.g. {"stage": "Rejected"}. row_ids: Explicit row ids to update, e.g. ["3", "7"]. Mutually exclusive with conditions. conditions: Filter selecting rows to update, e.g. [{"column": "stage", "op": "eq", "value": "Screened"}]. dry_run: Bulk mode only - true (default) previews; false applies the update.
Returns: Id mode: {"ok": true, "dataset", "updated", "rejected", "not_found", "results": [...]}. Bulk mode dry-run: {"ok": true, "requires_confirmation": true, "preview": {...}}. Bulk mode applied: {"ok": true, "dataset", "matched", "updated", "rejected", "results": [...]}.
Example: update_rows(dataset="Candidates", values={"stage": "Rejected"}, conditions=[{"column": "score", "op": "lt", "value": 3}], dry_run=true)
| Name | Required | Description | Default |
|---|---|---|---|
| values | Yes | ||
| dataset | Yes | ||
| dry_run | No | ||
| row_ids | No | ||
| conditions | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden, and it delivers: it explains that only provided columns change, that validation happens against the full row, that invalid rows remain untouched with plain-language errors, and how dry-run preview works before the real update. Return shapes are also given for all three operation modes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is organized into summary, args, returns, and an example. It is detailed but every section earns its place; the returns section is particularly valuable for distinguishing the three possible response shapes.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with five parameters and nested objects, this is complete: both invocation modes are covered, all parameters are explained with examples, the dry-run safety workflow is explicit, and return values are specified. Nothing an agent needs to call it safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description fully compensates by documenting each parameter with concrete examples, including the exact dataset name requirement, the structured conditions filter, and the mutual exclusivity of row_ids and conditions. This goes far beyond the raw schema types.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Update rows') and clearly distinguishes two modes: explicit ids and filter-based bulk updates. This makes the tool's scope immediately clear and differentiates it from sibling tools like search_rows, add_rows, and delete_rows.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides precise when-to-use guidance: bulk mode defaults to a dry-run preview, the user should review it before applying, and the agent is explicitly instructed to never set dry_run=false on the first call when a filter may match many rows. This is actionable and prevents risky behavior.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
validate_rowsA
Validate rows against a dataset's schema without saving anything.
Use this to pre-check data before committing it - e.g. when the user pastes a list of records and wants to know what would be rejected and why. Valid rows come back normalized (types coerced, defaults filled) so you can show the user exactly what would be stored.
Args: dataset: Exact dataset name, e.g. "Candidates". rows: List of row objects to check (max 100 per call).
Returns: {"ok": true, "dataset", "total": , "valid": , "invalid": , "results": [{"row": , "status": "valid", "normalized": {...}} | {"row": , "status": "invalid", "errors": ["..."]}]}.
Example: validate_rows(dataset="Candidates", rows=[{"name": "Asha", "phone": "9876543210"}])
| Name | Required | Description | Default |
|---|---|---|---|
| rows | Yes | ||
| dataset | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does well: it explicitly states no writes occur, discloses the 100-row per call cap, describes normalization of valid rows, and documents the exact return structure including valid and invalid result shapes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized with purpose, usage guidance, args, return shape, and an example. Every section adds value and is front-loaded with the core non-destructive behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a validation tool with no annotations, the description is complete: it covers what the tool does, when to use it, parameter semantics, limits, return format, and provides a concrete invocation example.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explains dataset as an exact name with an example, and rows as a list of row objects with a max count. It could add detail on how row keys map to schema fields, but the example and context make the parameters actionable.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Validate rows against a dataset's schema without saving anything.' This both states the operation and differentiates it from sibling tools like add_rows or update_rows by emphasizing the dry-run nature.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear when-to-use guidance: 'Use this to pre-check data before committing it,' with a concrete example scenario. It does not explicitly name alternatives or state when not to use the tool, but the 'without saving anything' framing strongly implies the contrast with saving tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
16 tool updates
v0.1.0- First observed
add_column - First observed
add_rows - First observed
create_dataset - First observed
delete_dataset - First observed
delete_rows - First observed
describe_dataset - First observed
export_rows - First observed
get_row - First observed
import_rows - First observed
list_datasets - First observed
remove_column - First observed
search_rows - First observed
summarize_dataset - First observed
update_column - First observed
update_rows - First observed
validate_rows
TDQS
Scored across 16 tools
Every tool targets a distinct resource and action: dataset discovery, schema manipulation, row CRUD, search, validation, aggregation, and file import/export. Even similar operations like update_rows, delete_rows, and search_rows are clearly separated by intent and behavior.
All 16 tools follow a consistent verb_noun snake_case pattern (create_dataset, add_column, search_rows, export_rows, etc.). The few descriptive verbs like describe_dataset, summarize_dataset, and validate_rows still fit the same predictable convention.
At 16 tools, the server is slightly above the ideal 3-15 band, but the count is well-justified by the full CRUD surface for datasets, columns, and rows plus import/export. Each tool has a non-overlapping purpose and earns its place.
The surface covers dataset lifecycle, column management, row CRUD, search, validation, summarization, and file import/export. Minor gaps exist, such as no rename/update-dataset-metadata operation, but agents can work around these without dead ends.
Maintenance
Related MCP Connectors
An agent-native database over MCP: shared, validated, structured records in every AI chat.
Hosted MCP server for AI-driven data ops. Create apps, manage schemas, and CRUD structured data.
Let AI agents query data and act across all your business apps via MCP.
- mcpOAuthcom.gibsonai
GibsonAI MCP server: manage your databases with natural language
Related MCP Servers
- FlicenseCqualityDmaintenanceAn application that demonstrates the future of user interactions through natural language with LLMs, enabling user registration, authentication, and data interaction exclusively via Model Context Protocol (MCP) tools.1170-
- AlicenseNot gradedqualityDmaintenanceDynamically generates MCP tools from any OData or OpenAPI spec, enabling natural-language queries via SAP AI Core.MIT
- AlicenseNot gradedqualityBmaintenanceMCP server that enables AI agents to read and write records in a live REST API generated from pasted data, with tools for listing, querying, inserting, updating, and deleting records.AGPL 3.0
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to manage CRM data including companies, contacts, prospects, pipelines, forecasts, and tasks via typed MCP tools, with local SQLite storage and a JSON CLI.MIT