First-party app
NocoDB

NocoDB

NocoDB: read and write records in bases and tables, follow links, and inspect schemas and views.

stable SpreadsheetsDatabases

About

NocoDB ships in the w6w first-party pack. It declares 13 actions, 3 health checks, and the host runs its code in a sandbox that never sees the credential.

App id
io.w6w.nocodb
Version
0.1.1
Author
w6w
Licence
MIT
Categories
Spreadsheets · Databases

Overview

NocoDB turns an existing database into something that reads and writes like a spreadsheet, and this app is built around exactly that: reading and writing records in its bases and tables, following the links between them, and inspecting the schema and saved views that shape what a table actually looks like.

Because NocoDB enforces a modest request budget per account, this app is shaped around using it efficiently rather than working around it after the fact — writes accept many rows in a single request instead of one at a time, reads default to a larger page than the API itself defaults to, and a dedicated counting action answers “how many rows match” without paging through them all. Linked records — the equivalent of a lookup between two tables — get their own actions, since NocoDB returns them from a separate endpoint rather than alongside the row that references them.

NocoDB is open source and just as often self-hosted as it is used through its cloud offering, and this app works the same way against either. A base built on top of an existing production database is flagged as such, since writing to one of those reaches further than an ordinary NocoDB-native table would.

Build with NocoDB

Three routes to the same 13 actions. The Workflow tab is generated from NocoDB's own manifest and carries its real ids, so it is copy-pasteable; the Code and CLI examples are the same call for any action on any app, so every app-specific value in them is a blank you fill in.

List bases

base-list

The bases this token reaches — which is whatever its creator reaches, since a NocoDB token has no scope of its own. Flags bases backed by an EXTERNAL DATABASE, where a delete goes through to the customer's production Postgres.

List linked records

link-list

The records on the other end of a link — which do NOT come back with the parent record, so their absence looks like an empty link. One request per record per field, against a budget of 60 a minute, so filtering the child table is often cheaper.

Link or unlink records

link-set

Connect records across tables, which `record-update` CANNOT do — links have their own endpoint. Adding is additive; `replace` reads first and reconciles, costing three requests against a budget of 60 a minute.

Count records

record-count

How many rows match, in one request rather than by paging — which matters when the budget is 60 requests a minute. The `where` trap is quieter here: a filter with spaces returns ZERO, which is a plausible answer.

Create records

record-create

Insert one row or many in a single request — which is the difference between an import taking a second and seventeen minutes, at 60 requests a minute. Returns the generated IDS IN ORDER, which is the only way to get them.

Delete records

record-delete

Remove rows by id — NocoDB deliberately offers no delete-by-filter here, so a workflow has to list first and decide. Deletion is final: the interface's undo is a session thing, and an external-database base loses the row too.

Get a record

record-get

One row by its PRIMARY KEY — not its position in a view, which changes whenever anybody sorts. Unlike a filtered list, a missing record here is a 404 rather than an empty result.

List records

record-list

Read rows, filtered and sorted. NocoDB's `where` syntax takes NO SPACES between the parts of a condition — with them the request succeeds and returns nothing — so this checks first. A `viewId` applies your filter ON TOP of the view's own.

Update records

record-update

Change one row or many in one request — each carries its own primary key in the body. It is a PATCH, so fields you omit are left alone and clearing one means sending `null`. There is no conditional update, so concurrent writes race silently.

Get a table's schema

table-get

The columns a write has to satisfy. Separates WRITABLE columns from computed ones — a formula or rollup is rejected in terms of the column rather than the rule — reports the select options, and gives the LINK FIELD IDS the link actions need.

List tables

table-list

The tables in a base with their IDS — which is what every record action takes, since nothing accepts a table's title. Ids survive a rename, so a workflow keyed on one does not break the day somebody tidies the base.

List views

view-list

A table's saved filters and sorts — queries somebody already wrote and maintains, which is usually better than reimplementing them in a workflow. Counts SHARED views, which serve their rows to anybody with the link.

List a table's webhooks

webhook-list

What fires when this table changes — the thing to check before a bulk write, since inserting a thousand rows fires a thousand webhooks and nothing in the data API mentions it. Separates the disabled ones, which are still listed.

A workflow step names the app and the action, and the editor fills in the connection when you pick one. This is the Step shape from the workflow spec, carrying NocoDB's real ids.

{
  "manifestVersion": "2",
  "name": "nocodb-example",
  "steps": [
    {
      "id": "link-list",
      "uses": {
        "app": "io.w6w.nocodb",
        "action": "link-list",
        "connection": "conn_YOUR_CONNECTION_ID"
      },
      "with": {
        "tableId": "<tableId>",
        "linkFieldId": "<linkFieldId>",
        "recordId": "<recordId>"
      }
    }
  ]
}

Here are some of the things you can do

  • List linked records

    read
    link-list
  • List bases

    search
    base-list
  • Link or unlink records

    perform
    link-set
  • Count records

    read
    record-count
  • Create records

    perform
    record-create

+8 more actions available

Every app-specific value here is a blank you have to fill in. An app action is reached through the connection that authenticates it, so the address is a connection id, not the app id — and connections belong to your account, so a public page cannot know yours. Create one for NocoDB, then fill in the three blanks: conn_YOUR_CONNECTION_ID, the action key, and the parameters that action declares. The call itself is real — the shape is transcribed from the studio's own snippet builder, which prints the same kind of blanks — but nothing in it is specific to NocoDB. The Workflow tab is where this app's real ids are.

Install
npm install @w6w/sdk
yarn add @w6w/sdk
pnpm add @w6w/sdk
deno add npm:@w6w/sdk
Code
import { W6wClient, isActionRun } from "@w6w/sdk";

// Reads W6W_BASE_URL and W6W_TOKEN from the environment when omitted.
const client = new W6wClient();

const envelope = await client.run({
  urn: "conn_YOUR_CONNECTION_ID",
  action: "link-list",
  payload: {
    tableId: "<value>",
    linkFieldId: "<value>",
    recordId: "<value>",
    // fields: "<value>",
    // limit: "<value>",
    // offset: "<value>",
  },
});

if (isActionRun(envelope)) console.log(envelope.value);
Install the CLI
npm install -g @w6w/cli
CLI
w6w run conn_YOUR_CONNECTION_ID --action link-list --payload '{"tableId":"<value>","linkFieldId":"<value>","recordId":"<value>"}'

Give an AI agent NocoDB — without giving it NocoDB's credentials. One MCP endpoint exposes every app, function and workflow the caller is entitled to, as tools it can discover and run. Access is granted per team while we onboard.

One tool call
{
  "name": "w6w_invoke",
  "arguments": {
    "ref": "app:io.w6w.nocodb#link-list",
    "input": {
      "tableId": "<tableId>",
      "linkFieldId": "<linkFieldId>",
      "recordId": "<recordId>"
    }
  }
}

Every tool names its target with a single ref. The app: form above doesn't name a connection at all — the host resolves which of the caller's NocoDB connections to sign with, and refuses rather than guesses when the answer is ambiguous.

What the agent gets

Credentials it can't read

The token is attached host-side, at the moment of the call. It is never a tool argument, never in the model's context, and never in a transcript — so a prompt injection has nothing to exfiltrate.

A tool surface scoped to the caller

Tools are derived per end user from what that person has actually connected and is entitled to — not one shared bot identity carrying the union of everyone's access.

A durable workflow in one call

Multi-step work runs on the workflow engine and returns a run handle the agent can poll — retries, branching and state survive the conversation that started them.

Health-aware discovery

NocoDB's declared health checks are on the surface too, so an agent can tell "the vendor is down" from "your credential expired" before it burns a retry on either.

The MCP surface is part of the hosted platform. NocoDB itself is MIT, and the runtime that executes it is source-available (FSL).

Request MCP access

Health checks

NocoDB declares its own checks, so its health is a property of the app rather than something the host guesses at.

service

NocoDB status

Declared unavailable twice over — NocoDB's status page publishes no machine-readable feed, and it would speak only for the cloud, while most NocoDB is self-hosted. The `instance` check reads the connection's own server instead.

dependency

NocoDB instance healthy

Reads this connection's own server through the UNAUTHENTICATED `/api/v1/health`, so an outage cannot hide behind a credential problem. Reports the process UPTIME, because a repeatedly small one is a container crash-looping — a pattern no single check would show.

quota

Rate-limit headroom

Reads NocoDB's own `x-ratelimit-remaining`, which is a real and current number — and a small one: 60 requests a minute per caller, shared by every workflow on this connection. The probe itself spends one of them.