The server defines 25 tools with consistent structure and generally clear descriptions. All tools have JSON Schema input definitions with property descriptions. However, there are notable gaps: (1) Output schemas are not documented, the tool handler returns JSON stringified results without a formal schema declaration for downstream agents to parse. (2) Some parameters lack type constraints (enums, min/max) where they should have them, e.g., column 'uidt' accepts free-form strings instead of an enum of valid UI Data Types. (3) Error handling is basic, the server catches NocoDBError and wraps it in McpError, but doesn't provide actionable recovery guidance. (4) Tool descriptions vary in quality, some like 'create_table' are detailed (100+ chars), others like 'list_bases' are minimal (48 chars). (5) Several tools use 'additionalProperties: true' for data payloads (insert_record, bulk_insert, update_record), which abdicate schema responsibility to the caller. This is pragmatic for flexible database operations but makes it hard for LLMs to validate correctness upfront.
Add a new column to an existing table. For SingleSelect: provide options in meta. For QrCode/Barcode: provide reference column ID. PhoneNumber uses standard text storage.
Perform aggregation operations on a column
Attach an uploaded file to a record
Insert multiple records into a table
Create a new table in a base with specified columns. Supports various column types including SingleSelect (with options), PhoneNumber, QrCode, and Barcode.
Create a new view for a table
Output schemas not documented. Tool handlers return JSON stringified results (see src/index.ts CallToolRequestSchema handler), but there is no declaration of what fields, types, or structure the response contains. This forces LLMs to infer the response shape, risking parsing errors and downstream tool-chaining failures.
Column 'uidt' parameter in create_table and add_column accepts free-form strings instead of a constrained enum. The description lists valid types ('SingleLineText', 'LongText', 'SingleSelect', etc.) but does not enforce them as JSON Schema enum. This invites LLMs to hallucinate invalid types.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 57 | 2026-07-28+ | v2 |
| 2026-03-09 | D | 50 | - | v1 |
Delete a column from a table
Delete a single record
Delete a table from the database
Get information about file attachments in a record
Get detailed information about a specific base/project
Get a single record by ID
Get detailed information about a table including its schema
Get records from a specific view
Group records by a column and get counts
Insert a single record into a table
List all available NocoDB bases/projects
List records from a table with optional filtering, sorting, and pagination
List all tables in a base
List all views for a table
Execute an advanced query with filtering, sorting, and field selection
Search for records containing a query string
Update a single record
Upload a file attachment to NocoDB storage
Upload files to NocoDB storage from URLs
Record data parameters use 'additionalProperties: true' without field validation. insert_record, bulk_insert, and update_record accept arbitrary 'data' objects (src/tools/record.ts). The server does not validate that the fields match the table schema, letting invalid data silently pass through to the API. This violates the principle of failing fast with actionable errors.
Error handling is minimal. The server catches NocoDBError and wraps it as McpError, but does not classify errors (retryable vs. user-fixable vs. fatal) or provide recovery guidance. E.g., if a user passes an invalid base_id, the response is a generic error, no hint to call list_bases() to discover valid IDs.
Destructive operations (delete_table, delete_column, delete_record) lack confirmation or dry-run options. An agent invoking delete_table with a typo in the table_id will immediately destroy data with no undo. No support for pattern:confirmation-request.
Minimal tool descriptions. list_bases (48 chars), delete_table (55 chars), delete_column (50 chars), list_views (55 chars) are below the 70-char baseline. These give LLMs minimal signal for tool selection, increasing the risk of wrong tool choice when many similar tools exist.
No documented pagination limits or defaults. list_records defaults to limit=25 (described in tool description), but other list tools (list_bases, list_tables, list_views) have no documented max results or pagination parameters. Large result sets risk context window exhaustion.
Missing tool annotations. No tools declare destructiveHint, readOnlyHint, or idempotentHint capabilities (mcp-sdk supports these via tool metadata). This leaves agents guessing which operations are safe to retry and which are irreversible.