
Seatable
io.github.seatablePublished by GitHub account seatablev1.9.5Updated Nov 7, 2026
MCP server for SeaTable — read, write, search, link, and query data in your bases
Overview
Official SeaTable MCP server that lets an assistant read, search, write, link and SQL-query rows in your SeaTable bases.
- What you can do
- Inspect base structure: list tables, get full schema, list bases and collaborators
- Read rows: paginated listing, fetch by ID, DSL filtering, search, and read-only SQL SELECT queries
- Write rows: add, batch append, update, upsert and delete rows, plus SQL INSERT/UPDATE/DELETE
- Handle file and image columns: upload base64 content and download text, PDF or binary content
- Link and unlink rows, and add options to select columns
- Utilities: row change history, base snapshots, and a health check
- When to use it
- Useful when your data lives in SeaTable bases and you want an assistant to look things up, filter and aggregate with SQL, or keep records up to date without manual copy-paste. It is deliberately limited to data operations, not schema changes such as creating or deleting tables and columns.
- Requirements
- Either the hosted endpoint for SeaTable Cloud, or a local process run with npx (Node.js 20 or newer) for self-hosted instances. Needs SEATABLE_SERVER_URL and an API token via SEATABLE_API_TOKEN, or SEATABLE_BASES for multi-base setups; managed multi-tenant mode additionally requires SEATABLE_TOKEN_SECRET. Network access to your SeaTable server.
Installation
In SourceWeft
- Open Seatable in the dashboard and add it to a workspace.
- Enable the server for the chats that should use its tools.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Other MCP clients
Follow the launch instructions in the repository.
README
SeaTable MCP
The official Model Context Protocol (MCP) server for SeaTable, built and maintained by SeaTable GmbH. It lets AI agents interact with data in your bases — reading, writing, searching, linking, and querying rows through a focused set of tools. The server intentionally focuses on data operations, not schema management (creating/deleting tables or columns), keeping the tool set lean and safe for autonomous agent use.
Quick Start
The fastest way to get started depends on your setup:
- SeaTable Cloud — Use the hosted MCP server at
mcp.seatable.com, no installation needed - Self-hosted SeaTable — Run the MCP server locally via
npxin your IDE
SeaTable Cloud (hosted MCP server)
If you use SeaTable Cloud, there is a hosted MCP server ready to use — no installation required. Configure your MCP client with the Streamable HTTP endpoint:
Claude Desktop — add to claude_desktop_config.json:
Cursor / VSCode — add to your MCP settings (JSON):
ChatGPT and other OAuth-compatible clients — use the built-in OAuth flow. In ChatGPT's developer mode, configure:
- Server URL:
https://mcp.seatable.com/mcp - Auth type: OAuth
- Authorization URL:
https://mcp.seatable.com/authorize - Token URL:
https://mcp.seatable.com/token
You will be prompted to enter your SeaTable API token during the authorization step.
Self-hosted SeaTable
For self-hosted SeaTable instances, run the MCP server locally via npx. Your IDE starts and manages the process automatically.
Claude Desktop — add to claude_desktop_config.json:
Cursor / VSCode — add to your MCP settings (JSON):
Deployment Options
If you need to run your own server instance — for example on your own infrastructure, with multi-base support, or in multi-tenant mode — use one of the options below.
HTTP Server (Network Access)
Run a local HTTP server with Streamable HTTP transport:
Multi-Base (Selfhosted)
Serve multiple bases from a single process:
Each tool automatically gets a base parameter. Use list_bases to see available bases.
Managed Mode (Multi-Tenant HTTP)
For hosting an MCP endpoint where each client authenticates with their own SeaTable API token:
SEATABLE_TOKEN_SECRET is required in managed mode. It seals the OAuth tokens the server issues, so the underlying SeaTable API token never has to be handed to a client. Keep it stable across restarts — changing it invalidates every issued access and refresh token and forces all clients to re-authorize.
Clients pass their credential via Authorization: Bearer <token> — on session initialization and on every subsequent request, including GET and DELETE. The mcp-session-id header is a routing value only; it is never accepted on its own. Each request is re-validated and must resolve to the same identity that created the session, otherwise the server answers 401 (missing/invalid credential) or 403 (valid credential, wrong session). Rate limits apply as before (60 req/min per token, 120/min per IP, 20 concurrent connections per token).
OAuth support: Managed mode also exposes OAuth 2.0 endpoints (/authorize and /token), enabling OAuth-compatible clients like ChatGPT to connect — no external OAuth provider required. During the flow the user enters their SeaTable API token; the server seals it into its own short-lived access token (1 h) and a rotating refresh token (14 d). The raw SeaTable API token is never returned to a client.
Clients must register at /register first: the returned client_id carries the client's name and its redirect_uris, and the server accepts a callback only if it is one the client registered (loopback callbacks may vary the port, per RFC 8252). PKCE with S256 is mandatory, and every authorization code is bound to the client, the exact callback and the challenge.
Where a code may be delivered. With open dynamic registration, "registered client" is not a trust statement — anyone can register. What matters is whether the code leaves the user's machine:
The confirmation cannot be skipped from the entry link: it is read from the form body only, and a POST auto-submitted by a foreign page is refused via Sec-Fetch-Site. The trusted-host list therefore removes friction — it is not a gate, and leaving it unset breaks nothing.
The consent screen leads with the destination the authorization will be sent to. The application's name is shown as self-reported, because with open registration it is chosen by whoever registered the client and cannot be verified.
The OAuth endpoints are rate limited per IP (30/min overall, 10/min for token submissions), so /authorize cannot be used as an unthrottled oracle for testing SeaTable API tokens.
OAuth endpoints follow the MCP specification (RFC 8414 metadata discovery, PKCE, dynamic client registration):
Client ID and secret are not validated — dynamic client registration generates one automatically.
Docker
Container hardening
The image is built so that code running inside the server process — for example through a vulnerable dependency — can't change the filesystem, start other programs or escalate privileges:
- Non-root: the server runs as
node(uid 1000). The code in/appis owned by root and read-only for that user. - Node permission model: the default
CMDstartsnode --permission --allow-fs-read=/app. The process may read its own code and nothing else; writing files, child processes (no shell), worker threads and native addons are denied. Outbound network access is not affected. The server needs none of the denied operations, includingdownload_file, which extracts PDF text in memory. - No tools for an attacker: npm, npx, yarn, corepack and apk are removed, and so are busybox
wget,ncandsu. The health check usesnode. There are no setuid binaries. Only apk's package list in/lib/apk/dbstays, so that vulnerability scanners can see the OS packages. Without/sbin/apkit can't install anything, and the permission model denies the server read access to it. - Pinned base image:
node:22.23.4-alpine3.24(build argumentNODE_IMAGE), withapk upgradeat build time.
At runtime, add the restrictions the image can't set itself. docker-compose.yml contains all of them:
If you override the command (e.g.
docker run … seatable/seatable-mcp node dist/index.js --sse), keep--permission --allow-fs-read=/app, otherwise the permission model is off.
OpenAI Secure MCP Tunnel
To use the server from ChatGPT without exposing it to the internet, run it next to OpenAI's tunnel-client. Setup and limitations: docs/openai-tunnel.md.
Security Model
The security characteristics differ significantly between transport modes:
⚠️ Warning: Selfhosted HTTP mode (
--sse/--http) has no authentication. Anyone who can reach the port gets full access to all configured bases, including write and delete operations. Only run it in trusted networks (localhost, Docker-internal) or behind a reverse proxy that handles authentication. For untrusted networks, use managed mode instead.
Rate Limiting
SeaTable's own API gateway enforces rate limits per base (default: 500 requests/minute per base_uuid) and per organization (monthly quota). These limits apply regardless of whether requests come from the MCP server, the web UI, or direct API calls. The MCP server does not duplicate these limits — instead, it retries automatically with exponential backoff when SeaTable returns 429 Too Many Requests.
In managed mode, the MCP server adds its own rate limits to protect the server process itself (not the SeaTable backend): 60 req/min per token, 120/min per IP, 30/min for new session creation, and 20 concurrent connections per token.
Input Validation
All tool inputs are validated with Zod schemas before execution. Write tools (add_row, append_rows, update_rows, upsert_rows) additionally validate row data against the table schema — unknown columns are rejected, and read-only columns (formula, auto-number, creator, etc.) are stripped with a note in the response.
Tool schemas are published with additionalProperties: true to remain compatible with MCP clients that may attach internal fields (e.g. _meta). Unexpected fields are ignored by the server — they do not cause errors but are not processed either. This is a deliberate trade-off: stricter validation would improve error messages for typos but risk breaking compatibility with MCP clients.
Row Responses
Row responses include all columns and SeaTable system fields (_id, _mtime, _ctime, _creator, _last_modifier). System fields are not filtered — _id is required for updates and deletes, timestamps are useful for sorting and freshness checks, and creator/modifier fields can be resolved to display names via list_collaborators.
Caching
The server caches base metadata (table/column definitions) for 60 seconds to avoid redundant API calls during write operations. Schema-reading tools (get_schema, list_tables) always bypass the cache and return fresh data. If a cached schema becomes stale (e.g. a column was renamed), the SeaTable API will reject the write and the AI agent can call get_schema to refresh.
Environment Variables
Required:
SEATABLE_SERVER_URL— Your SeaTable server URL
Authentication (one of these is required in selfhosted mode):
SEATABLE_API_TOKEN— Single-base API tokenSEATABLE_BASES— Multi-base: JSON array (e.g.'[{"base_name":"CRM","api_token":"..."}]')
Optional:
SEATABLE_MODE—selfhosted(default) ormanaged(multi-tenant HTTP with per-client auth)SEATABLE_TOKEN_SECRET— required in managed mode, min. 32 chars. Seals issued OAuth tokens and client registrations; must be stable across restarts (openssl rand -hex 32)SEATABLE_ACCESS_TOKEN_TTL— lifetime of an issued access token in seconds (default3600, range30–2592000). Lower narrows the window after a SeaTable token is revoked; higher spares users a re-prompt if their client renews badly. The refresh token is never issued shorter-lived than the access token.SEATABLE_MOCK=true— Enable mock mode for offline testingCORS_ALLOWED_ORIGINS— Comma-separated list of allowed origins for CORS (HTTP mode only, disabled if unset)OPENAI_APPS_CHALLENGE_TOKEN— Domain verification token from the OpenAI Apps submission. If set, the server answersGET /.well-known/openai-apps-challengewith it (HTTP mode only, endpoint absent if unset)METRICS_PORT— Prometheus metrics port (default:9090, HTTP mode only)
Monitoring
In HTTP mode, the server exposes Prometheus metrics on a separate port (default 9090):
Available metrics:
Plus standard Node.js metrics (memory, CPU, event loop) via prom-client.
The metrics server only starts in HTTP mode (not stdio) and binds to 0.0.0.0 — in Docker, expose the port only within your internal network.
SQL failure log
AI models often write MySQL- or PostgreSQL-style SQL that SeaTable does not accept: subqueries, JOIN, UNION, CASE WHEN, CONCAT(). To see which patterns fail in practice, every failed query_sql or execute_sql call writes one log line, without storing any customer data.
What happens on a call. runSql() in src/mcp/tools/sqlCheck.ts runs three stages; each failure is logged and counted:
In every case the model gets an error message that tells it how to restructure the query, e.g. "Run the inner SELECT on its own first, then pass its values into the outer query" or "use mid(str, pos, len) instead of SUBSTRING".
What is logged. One WARN line with the message SQL statement failed:
sql_shape is the statement with all content removed by sqlShape():
- string literals become
?, numbers become0 - table and column names (quoted or not) become
x - comments are dropped, whitespace is collapsed, the result is cut at 500 characters
- only SQL keywords (uppercase), function names (lowercase) and punctuation survive
The original statement and its parameters are never logged; a test in tests/sqlCheck.spec.ts asserts that table names and values do not appear in the log. Column names are deliberately dropped as well, since names like "Salary" or "Diagnosis" already say something about the customer.
The general
Tool call failedline that every tool writes on error is separate and unchanged. For SeaTable errors it contains SeaTable's error message and response body, which may echo column names.
How to analyse it. The most frequent failing shapes:
Failures by reason, and the function hints that were given:
In Prometheus, mcp_sql_failures_total{tool, reason} shows the same reasons over time, e.g. sum by (reason) (increase(mcp_sql_failures_total[7d])). Put that next to mcp_tool_calls_by_tool_total{tool="query_sql"} to get a failure rate.
What to do with the results.
- A shape that keeps failing with
seatable_errorand is a fixed grammar limit → add it toUNSUPPORTED_CONSTRUCTSso it is rejected before the request, with a restructuring hint. - A MySQL function that keeps appearing → add it to
FUNCTION_HINTS, and to the function mapping in the server instructions (src/mcp/server.ts). - Many
wrong_statement_*→ the tool descriptions are not clear enough. - Function names only produce hints after a failure, never a rejection, so a function SeaTable adds later cannot be blocked by an outdated list.
MCP Tools
Schema Introspection
list_tables— Get all tables with metadataget_schema— Get complete database structurelist_bases— List available bases (multi-base mode only)list_collaborators— List users with access to the base (for collaborator columns)
Reading Data
list_rows— Paginated row listing (use query_sql for filtering/sorting)get_row— Retrieve specific row by IDfind_rows— Client-side filtering with DSLsearch_rows— Search via SQL WHERE clausesquery_sql— Read-only SELECT queries with parameterized inputs
Writing Data
add_row— Add single new rowappend_rows— Batch insert rowsupdate_rows— Batch update rowsupsert_rows— Insert or update rows by key columnsdelete_rows— Remove rows by IDexecute_sql— SQL UPDATE, DELETE or INSERT with parameterized inputs
Files
upload_file— Upload a file or image to a row (base64-encoded)download_file— Read file content from a file or image column (text files and PDFs as text, binary files as download link, max 1 MB)
Linking
link_rows— Create relationships between rowsunlink_rows— Remove relationships between rows
Utilities
get_row_activities— Get change history of a row (who changed what, when, old/new values)create_snapshot— Create a snapshot of the current base (10 min cooldown)add_select_options— Add new options to single-select or multi-select columns (existing options are skipped, no duplicates)ping_seatable— Health check with latency monitoring
Supported Column Types
SeaTable bases can contain many different column types. The following table shows which types can be written via the API and what format to use.
Tool Examples
Programmatic Usage
Mock Mode
In-memory tables and rows for demos and tests without a live SeaTable instance.
Development
Prerequisites
- Node.js >= 20
Setup
Scripts
npm run dev— Start server in watch mode (tsx)npm run build— Compile TypeScriptnpm run start— Run compiled servernpm test— Run tests (vitest)npm run lint— Lint codenpm run typecheck— TypeScript type check
Testing Tools
To check how real models use the SQL tools, see Testing the SQL tools with a model.
Troubleshooting
License
MIT
Source: README.md at commit ead5893
Tools
0Version history
4- v1.9.5LatestNov 7, 2026
- v1.9.4Nov 4, 2026
- v1.9.2Nov 4, 2026
- v1.6.4Sep 16, 2026
Score
40% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
- Reached in the last 30 days25 pts
Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.
- Auth declared10 pts
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
- Tools listed15 pts
Answer tools/list without a credential, or ship a package that starts in a sandbox without one.
- DescriptionRequired15 pts
- Logo10 pts
- Documentation15 pts
- License10 pts
Declare a license in the repository or the registry entry.