Read and write SeaTable Cloud bases: rows, SQL, links, tables, columns, views and row comments.
SeaTable ships in the w6w first-party pack. It declares 23 actions, 2 health checks, and the host runs its code in a sandbox that never sees the credential.
io.w6w.seatableSeaTable is a cloud spreadsheet-database: tables of typed columns, linked records and views, with an API for everything you can do in the grid.
This app connects to one SeaTable Cloud base with that base’s API token and lets a workflow list, fetch, append, update, delete and lock rows, run SQL against the base (SELECT, UPDATE and DELETE, with bound parameters), and read and change the structure around the data: tables, columns, views and the links between records.
It also reads and writes row comments and lists the base’s collaborators. SeaTable’s API uses a two-step credential: the long-lived API token is exchanged for a short-lived Base-Token, and this app does that exchange and the renewal for you, so a workflow only ever supplies the API token once.
Only SeaTable Cloud (cloud.seatable.io) is covered. A self-hosted SeaTable Server or Dedicated instance lives on a host of its own that a manifest cannot name in advance.
Three routes to the same 23 actions. The Workflow tab is generated from SeaTable'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.
base-metadata-get The structure of the connected base — every table with its columns and views, plus settings. Contains no row data. Use it to find table names, column names and the `link_id` / table `_id` values the link actions need.
collaborator-list The users who can see the base — the pool a collaborator column draws from. Each carries an `email` (an `…@auth.local` identifier), a display `name` and an avatar URL.
column-insert Add one column to a table. The vendor documents adding a single column at the end of the table. The response is the new column's definition including its `key`.
column-list The columns of a table (or only a view's visible ones) with their key, name, type and type-specific `data`. Link columns carry the `link_id` and linked table the link actions need.
row-append Add one or more rows (up to 1,000 per call) to a table. Row objects are keyed by column NAME — internal column keys are not accepted here, and a name that matches no column is silently ignored rather than rejected, so check the result.
row-comment-create Add a comment to a row. This endpoint takes the table's `_id` (e.g. 0000), not its name — get it from Get Base Metadata. The vendor's success answer is a plain string, so the response here is `{success: true}`.
row-comment-list All comments on one row. The answer is a bare array; each comment has an `id`.
row-delete Delete rows by ID (up to 10,000 per call), from the normal or the big-data backend. Destructive: there is no undo in this API.
row-link-create Create links between rows through a link column: the map says, for each row of the source table, which rows of the other table to link it to. Creating a link that already exists is an error, so this is not retry-safe.
row-link-delete Delete the links named in the mapping. Other links are left untouched.
row-link-list The records linked to each of the given rows through one link column. The answer is an object keyed by row ID, each holding `{row_id, display_value}` entries. Up to 10 linked records per row are returned unless a Limit is given.
row-link-update Replace links through a link column: existing links are removed and replaced with the mapping given.
row-list Rows of a table, or of one view of it. Without a view every column is returned, hidden ones included; with a view only that view's visible columns. Link columns return at most 50 linked records per row. Page with Start and Limit.
row-lock Lock rows so they cannot be edited. Already-locked rows may be included. An advanced feature of SeaTable's enterprise subscriptions; rows in the big-data backend cannot be locked.
row-unlock Unlock rows that were locked. An advanced feature of the enterprise subscriptions.
row-update Change values in one or more existing rows (up to 1,000 per call). Only the columns named in each `row` object change. Keyed by column NAME; an unknown name is silently ignored.
sql-query Run a SQL statement against the base. SELECT returns up to 10,000 rows (100 unless the statement has a LIMIT); UPDATE and DELETE change rows and are not retry-safe in general. INSERT only works on bases with the big-data backend. Bind values with `?` placeholders and the Parameters list rather than building them into the statement.
table-create Create a table, optionally with columns. The first column can only be of type text, number, date, single-select, formula or auto-number. The response is the new table's full definition, including its `_id`.
table-rename Rename a table. Later calls must use the new name, so a workflow that renames and then reads should pass the new name on.
view-list All views of a table with their settings: filters, sorts, groupings, hidden columns.
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 SeaTable's real ids.
{
"manifestVersion": "2",
"name": "seatable-example",
"steps": [
{
"id": "column-insert",
"uses": {
"app": "io.w6w.seatable",
"action": "column-insert",
"connection": "conn_YOUR_CONNECTION_ID"
},
"with": {
"tableName": "<tableName>",
"columnName": "<columnName>",
"columnType": "<columnType>"
}
}
]
}column-insert base-metadata-get collaborator-list column-list row-append +18 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 SeaTable, 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 SeaTable. The Workflow tab is where this app's
real ids are.
npm install @w6w/sdkyarn add @w6w/sdkpnpm add @w6w/sdkdeno add npm:@w6w/sdkimport { 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: "column-insert",
payload: {
tableName: "<value>",
columnName: "<value>",
columnType: "<value>",
// anchorColumn: "<value>",
// columnData: "<value>",
},
});
if (isActionRun(envelope)) console.log(envelope.value); npm install -g @w6w/cli w6w run conn_YOUR_CONNECTION_ID --action column-insert --payload '{"tableName":"<value>","columnName":"<value>","columnType":"<value>"}' Give an AI agent SeaTable — without giving it SeaTable'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.seatable#column-insert",
"input": {
"tableName": "<tableName>",
"columnName": "<columnName>",
"columnType": "<columnType>"
}
}
}
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 SeaTable connections to sign
with, and refuses rather than guesses when the answer is ambiguous.
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.
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.
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.
SeaTable'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. SeaTable itself is MIT, and the runtime that executes it is source-available (FSL).
SeaTable declares its own checks, so its health is a property of the app rather than something the host guesses at.
Latest probe of the `Cloud API (Base Operations)` component on status.seatable.com — the /api-gateway surface this app calls.