Skip to main content

mcp-patterns

NocoDB MCP for schema-development work — what the server lists directly, which schema tools hide behind listTools/callTool, and the Community vs Cloud/licensed contract. Use when: - "what MCP tools can I use for schema?" - "can MCP create tables / fields / views?" - "listTools / callTool" - "how do I discover NocoDB structure?" - "MCP for nocodb-dev"

Source facts

Repository
Agents-Store/codex-plugins
Last source activity
November 1, 2026 at 02:46
Detected SKILL.md language
English
Stars
0
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
2 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
mcp-patterns
description
NocoDB MCP for schema-development work — what the server lists directly, which schema tools hide behind listTools/callTool, and the Community vs Cloud/licensed contract. Use when: - "what MCP tools can I use for schema?" - "can MCP create tables / fields / views?" - "listTools / callTool" - "how do I discover NocoDB structure?" - "MCP for nocodb-dev"
# NocoDB MCP — Discovery and Schema Writes All tools use the `mcp__plugin_nocodb-dev_nocodb__` prefix (the server is declared in this plugin's `.mcp.json`). ## The Contract: Community vs Cloud / Licensed | Edition | What the MCP server offers | Schema writes go through | |---------|----------------------------|--------------------------| | **Community Edition** | Record tools and read tools only | **REST** (`curl` on Meta API v3) — see **api-reference** | | **Cloud / licensed self-hosted** | The same listed tools, plus schema, view, hook, workflow, dashboard, script, permission, RLS, interface and docs **write** tools that stay out of the tool list | **MCP first**: `listTools(category)` → `callTool(name, arguments)`; REST is the fallback | Rule of thumb for every skill in this plugin: **on Cloud/licensed, prefer the MCP write tools; on Community Edition — or when `listTools` is missing or a tool is not in its answer — use REST.** ### Detect the edition once per session ``` mcp__plugin_nocodb-dev_nocodb__listTools category: "tables" ``` - The answer contains `createTable` / `updateTable` / `deleteTable` → Cloud/licensed. Use MCP-first. - `listTools` is absent, errors, or the `tables` category is empty → Community Edition. Use REST. `whoami` shows which user and which base the MCP credential is pinned to; effective authority is the intersection of that grant and the user's role on each resource — a 403 on a write usually means the role is not an editor/creator, not a missing tool. ## Two Kinds of Tools **Listed directly** (read tools and record CRUD — always visible): | Group | Tools | |-------|-------| | Orientation | `whoami`, `getBaseInfo`, `getBaseSchema` (every table with fields, options and views in **one** call), `getTablesList`, `getTableSchema` | | Schema reads | `listFields`, `getField`, `getFieldOptionsSchema(type)`, `listViews`, `getView`, `listFilters`, `listSorts`, `listHooks`, `getHook`, `listWorkflows`, `getWorkflow`, `listDashboards`, `listScripts`, `listBaseMembers` | | Records | `queryRecords`, `getRecord`, `countRecords`, `createRecords`, `updateRecords`, `deleteRecords`, `aggregate`, `groupByRecords`, `linkRecords`, `unlinkRecords`, `listLinkedRecords` | **Behind `listTools(category)`** (Cloud/licensed): call `listTools` with one category, read the names and argument schemas it returns, then invoke the tool through `callTool`. Categories: `workspaces`, `members`, `links`, `tables`, `fields`, `filters`, `sorts`, `views`, `shared-views`, `data-io`, `record-templates`, `date-dependencies`, `duplicates`, `audits`, `dashboards`, `comments`, `records`, `attachments`, `trash`, `permissions`, `row-colors`, `scripts`, `hooks`, `view-sections`, `base-sections`, `automation-sections`, `workflows`, `workflow-nodes`, `rls`, `interfaces`, `docs`, `form-fields`. The ones this plugin uses most: | Category | Tools | Skill | |----------|-------|-------| | `tables` | `createTable`, `updateTable`, `deleteTable` | table-management | | `fields` | `createField`, `updateField`, `deleteField`, `addFieldOptions`, `removeFieldOptions`, `setDisplayField` | field-management | | `views` | `createView`, `updateView`, `deleteView` | view-management | | `filters` | `createFilter`, `updateFilter`, `replaceFilters`, `deleteFilter` | view-management | | `sorts` | `addSort`, `updateSort`, `deleteSort` | view-management | | `shared-views` | `shareView`, `unshareView` | view-management | | `hooks` | `createHook`, `updateHook`, `deleteHook` | webhooks | | `workflows` / `workflow-nodes` | `createWorkflow`, `updateWorkflow`, `publishWorkflow`, `deleteWorkflow`, node and edge tools, `validateWorkflowNode` | workflows | | `trash` | `listTrash`, `restoreFromTrash`, `restoreRecords` | table-management | | `audits` | `listBaseAudits`, `listRecordAudits` | troubleshoot | | `docs` | `createDocument`, `updateDocument`, `patchDocument`, `moveDocument`, `deleteDocument`, `shareDocument` | api-reference | ### Calling a hidden tool ``` mcp__plugin_nocodb-dev_nocodb__listTools category: "fields" → names + argument schemas — read them, do not guess key names mcp__plugin_nocodb-dev_nocodb__callTool name: "createField" arguments: { tableId: "<tableId>", field: { title: "Phone", type: "PhoneNumber" } } ``` `callTool` validates `arguments` against the same schema `listTools` returned. If a hidden tool name is not in the answer for its category, the instance does not offer it — fall back to REST. ## MCP Payloads vs REST Payloads The two surfaces share the v3 key names, but the MCP tools wrap or split them differently: | Topic | MCP | REST (Meta API v3) | |-------|-----|--------------------| | Create a field | `createField {tableId, field:{title, type, options}}` | `POST /tables/{tableId}/fields` body `{title, type, options}` | | Update a field | `updateField {fieldId, field:{…}}` — `options` keys **merge** onto the stored ones; changing `type` replaces them | `PATCH /fields/{fieldId}` | | Select choices | `addFieldOptions` / `removeFieldOptions` (`choices:[{title,color?}]`) | `POST` / `DELETE /fields/{fieldId}/options` | | Field `options` shape | `getFieldOptionsSchema(type)` returns the exact JSON Schema; unknown keys are rejected | `FieldOptions_*` schemas in `nocodb-meta-openapi.json` | | Create a view | `createView {tableId, title, type, lock_type?, options?, fields?}` — filters and sorts are separate tools | `POST /tables/{tableId}/views` also accepts `filters`, `sorts`, `row_coloring` | | Filters | `createFilter {viewId, filter}`, groups use `group_operator: "AND"\|"OR"` | `POST /views/{viewId}/filters` | | Update a hook | `updateHook` is a **full replacement** — read with `getHook` and resend every key | `PATCH /hooks/{hookId}` | | Barcode format key | `options.format` (per `getFieldOptionsSchema("Barcode")`) | `options.barcode_format` | | `Links` type | not in the MCP enum — use `LinkToAnotherRecord` | both `Links` and `LinkToAnotherRecord` | When the two disagree, the MCP tool's own schema wins for MCP calls and the bundled OpenAPI spec wins for REST calls. Record tools write at most **100 records per call** — chunk bulk loads (see **nocodb-ops**). ## The Discovery → Change → Verify Loop ``` 1. getBaseSchema (or getTablesList + getTableSchema) ← one-call orientation / snapshot 2. plan the change (table / field / view / hook payload) 3. confirm destructive steps with the user 4. apply: callTool(createField …) on Cloud/licensed curl … /api/v3/meta/… on Community, or as fallback 5. getTableSchema(tableId) ← confirm the new shape landed 6. queryRecords / getRecord (optional) ← confirm data is still readable ``` ## Pattern — Add a Field (MCP-first) ``` Step 1: mcp__plugin_nocodb-dev_nocodb__getTablesList → find the table, note its ID Step 2: mcp__plugin_nocodb-dev_nocodb__getTableSchema tableId: <tableId> → confirm the title is free; for Lookup/Rollup confirm the link field exists Step 3: mcp__plugin_nocodb-dev_nocodb__callTool name: "createField" arguments: { tableId: "<tableId>", field: { title: "Phone", type: "PhoneNumber" } } (Community Edition: POST /api/v3/meta/bases/{baseId}/tables/{tableId}/fields) Step 4: mcp__plugin_nocodb-dev_nocodb__getTableSchema tableId: <tableId> → the new field appears in `fields` ``` ## Pattern — Verify a Formula After Creation A Formula is computed server-side; the only proof is reading records. ``` Step 1: createField via callTool, or the REST recipe in field-management field: { title: "Days Open", type: "Formula", options: { formula: "DATETIME_DIFF(NOW(), {CreatedAt}, \"days\")" } } Step 2: mcp__plugin_nocodb-dev_nocodb__queryRecords tableId: <tableId> fields: ["Title", "CreatedAt", "Days Open"] pageSize: 5 → spot-check that Days Open holds plausible numbers ``` ## Pattern — Audit Scope Before a Destructive Change ``` Step 1: mcp__plugin_nocodb-dev_nocodb__countRecords tableId: <tableId> Step 2: mcp__plugin_nocodb-dev_nocodb__countRecords tableId: <tableId> filter: { field: "Status", operator: "blank" } → rows that hold no value in the column you are about to change ``` Deleted tables, fields and views go to the base **trash** on Cloud/licensed: `listTrash` shows the entry (with `cleanup_due_at`), `restoreFromTrash(trashId)` puts it back. Deleted records can be restored with `restoreRecords` only on a NocoDB-managed source — an external source deletes for good. Still confirm before every delete. ## Best Practices 1. **Resolve IDs first.** Never pass a guessed `tableId`/`fieldId`; read `getBaseSchema` or `getTablesList` first. 2. **Snapshot before and after.** A diff of two `getTableSchema` answers is your audit trail. 3. **Read the argument schema.** `listTools(category)` and `getFieldOptionsSchema(type)` tell you the exact keys; the servers reject unknown ones. 4. **Check the edition before choosing the path.** MCP-first only where `listTools` offers the tool; otherwise REST. 5. **Verify with reads.** A successful write response does not always mean the schema cache has caught up — re-read with `getTableSchema`. 6. **Watch for view-filter blindness.** `queryRecords` with a `viewId` returns only rows visible through that view's filters. Omit `viewId` for raw audits. ## Error Handling | Error | Meaning | What to do | |-------|---------|------------| | "Table not found" | Wrong `tableId` | Re-run `getTablesList` | | "Field not found" | Stale schema cache or wrong name (names are case-sensitive) | Re-run `getTableSchema` | | Unknown key rejected on a field/view payload | `options` key not in that type's schema | `getFieldOptionsSchema(type)` / `listTools` for the exact keys | | `listTools` or `callTool` not found, or tool missing from the category | Community Edition, or an older server | Use the REST recipes in **api-reference** | | 401 / 403 from MCP | Token invalid, or the role cannot write schema | See **setup** → MCP rows; check `whoami` |
View on GitHub