Developers
MCP server
AI agents use OpenRows through the Model Context Protocol, two ways, with the same tools:
- Remote:
POST /mcpon the API (Streamable HTTP, stateless, JSON answers), for personal access tokens only (src/mcp/routes.ts, thetokenaccess rule of the route registry). The tools call the REST API v1 through@openrows/sdkwith the caller's own token, sent back into the app in process (app.request, no network hop), so each call passes the sameauthorize(), RLS, edit permissions and rate limits as the token calling/api/v1itself (an MCP request costs one request of the token's bucket plus one per API call). Only the tools the token's scopes allow are listed. - Local:
packages/mcp-server,openrows-mcp-serverover stdio, configured byOPENROWS_API_KEYandOPENROWS_URL. Published on npm as@openrows/mcp-serverwith provenance, so MCP clients start it withnpx -y @openrows/mcp-server(npx -y @openrows/mcp-server --helpprints the settings).
Releases
.github/workflows/release-packages.yml publishes @openrows/sdk, @openrows/mcp-server and
@openrows/n8n-nodes-openrows on a pushed sdk-v<version>, mcp-server-v<version> or
n8n-v<version> tag: the tag must name the package's version and a commit on main, NPM_TOKEN
must be set, the package's tests and npm run check:packages (the tarball holds only dist/,
README, LICENSE and package.json) must pass, then npm publish --provenance --access public
from a GitHub-hosted runner. The MCP server depends on the SDK by a caret range, so a release of
both tags the SDK first. Nothing is published from a local machine.
Users' guide: packages/mcp-server/README.md and the
/docs/api/mcp page (snippets with the server's own URL). GET /llms.txt lists the docs for
agents.
Tests
packages/mcp-server/src/tools.test.ts: every tool through an in-memory MCP client against a fake fetch (requests, Zod refusals, errors, size caps, scope filtering).packages/mcp-server/src/stdio.test.ts: the built bin over real stdio with the SDK'sStdioClientTransport(as Claude Code starts it) against a fake API: lists tools and bases, updates records, never prints the token.packages/server/test/integration/mcp.test.ts: real Postgres, the server on a random port; the inspector-style flow (list, describe, create, search, page, update, get, comment, delete) over Streamable HTTP at/mcpand through the stdio server's tools; a read-only token (only the read tools over HTTP, 403 over stdio, nothing written); a read-only member's token; another tenant's token (404s); no token, a session cookie or a bad token (401).authz-matrix.test.ts:POST/GET/DELETE /mcpandGET /llms.txt.
Manual check: Claude Code lists and updates records
Run against the dev stack (docker/compose.sh dev up -d --wait, app on http://localhost:8180)
or app.openrows.io:
- Sign in, open a base with a table (or
npm run db:seed -- --email <you>for the demo workspace), and create a personal access token in Settings → "Developer: personal access tokens" withschema.bases:read,data.records:readanddata.records:write. - Remote:
claude mcp add --transport http openrows http://localhost:8180/mcp --header "Authorization: Bearer <token>". Local instead, from npm:claude mcp add openrows --env OPENROWS_API_KEY=<token> --env OPENROWS_URL=http://localhost:8180 -- npx -y @openrows/mcp-server(or, to try a change from a checkout,npm run build -w @openrows/mcp-serverandnode packages/mcp-server/dist/bin.jsin place ofnpx -y …). claude mcp listshowsopenrowsconnected; in a session,/mcplists its 8 tools (7 with the remote server and this token: noadd_comment).- Ask: "List my OpenRows bases, then show the first 5 records of the Tasks table" (Claude calls
list_bases,describe_base,list_records). Then: "Set the Status of the first one to Done" (update_records). The grid shows the change live. - With a read-only token (no
data.records:write), ask for a change: the remote server has no write tools; the local one answers a 403 namingdata.records:write. claude mcp remove openrowsand revoke the token.
The automated equivalent of steps 2 to 5 is mcp.test.ts and stdio.test.ts above (the same
MCP SDK client Claude Code uses, over the same transports).