Connect an agent to Spillway
Spillway treats AI agents as first-class readers and builders. An agent connects to a running site with an API token over the MCP server (POST /mcp) or the plain REST API, reads the content model, drafts content, runs the pre-publish checks and hands its work to a person. Every action is attributed to the token's owner and written to the audit log.
The one rule that matters: agents draft, people publish. The rest of the rules are in rules.md.
1. Create an API token
- Sign in to the admin, open the account menu (top right) and choose API tokens.
- Create token. Label it after where it will live (Claude Code on my laptop), pick an expiry, and keep the Drafts only preset: view drafts, create, edit own, submit for review, upload media, use AI. Leave
content.publishoff. - Copy the token:
spw_<prefix>_<secret>, shown once; Spillway stores a hash.
A token can only hold permissions you have, and its effective permissions are always the intersection of its set and your current roles. Revoke it any time from the same screen. The full policy is in mcp.md.
2. Connect a client
Replace https://cms.example.org with your site's BASE_URL. For spillwaycms.com itself, the docs and registry are public, so an agent needs a token only to draft content or to publish packages.
Claude Code
claude mcp add --transport http spillway https://cms.example.org/mcp \
--header "Authorization: Bearer spw_…"
Or commit a .mcp.json to the project that reads the token from the environment:
{
"mcpServers": {
"spillway": {
"type": "http",
"url": "https://cms.example.org/mcp",
"headers": { "Authorization": "Bearer ${SPILLWAY_TOKEN}" }
}
}
}
Inside Claude Code, /mcp shows the connection; @spillway:spillway://types puts the content model into the conversation and /spillway:write-page starts the drafting workflow.
Claude Desktop (via mcp-remote)
Claude Desktop's custom connectors authenticate with OAuth, not a static header, so run mcp-remote locally as a bridge. In claude_desktop_config.json (Settings → Developer → Edit Config):
{
"mcpServers": {
"spillway": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://cms.example.org/mcp", "--header", "Authorization:${SPILLWAY_AUTH}"],
"env": { "SPILLWAY_AUTH": "Bearer spw_…" }
}
}
}
Restart Claude Desktop; the Spillway tools appear under the tools icon.
Cursor
Cursor reads .cursor/mcp.json in the project (or the global one under Cursor settings → MCP):
{
"mcpServers": {
"spillway": {
"url": "https://cms.example.org/mcp",
"headers": { "Authorization": "Bearer spw_…" }
}
}
}
Any MCP client, or curl
The server speaks MCP over Streamable HTTP in its stateless form: every request is one JSON-RPC 2.0 message to POST /mcp with the bearer header; GET /mcp answers 405 (no SSE stream). Supported: initialize, ping, tools/list, tools/call, resources/*, prompts/*.
curl -sS https://cms.example.org/mcp \
-H "Authorization: Bearer spw_…" -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
The same token works on the REST API (Authorization: Bearer spw_…, no CSRF header needed); the full API is described in openapi.json.
3. What the tools do
| Tool | Needs | Does |
|---|---|---|
list_content_types, get_content_type | any | The content model: fields, required flags, the AI hint on each field. Read these first. |
list_entities, get_entity, search_site | view drafts | Find existing content; drafts are included only with content.view_drafts. |
create_entity | create | Creates a draft (revision 1). Never publishes. |
update_entity | edit | Saves a new revision; data is shallow-merged unless merge: false. Status does not change. |
draft_page_from_brief | AI + create | The site's AI builds a block layout from a brief and saves it as a draft; returns the id. |
assist_text | AI + create | Brand-aware copy help (write, rewrite, shorten, expand, tone, fix, translate, summarize). Returns text only. |
get_checks | view drafts | Required fields, SEO lengths, alt text, heading order, banned words, broken internal links. Run before handing over. |
submit_for_review | submit | Draft → review; the editors' queue shows it. The normal end of an agent's work. |
add_comment | view drafts | Leave a note for the reviewer, optionally on one field. |
publish_entity | publish | Only with content.publish on the token; refuses when an error-level check fails unless force. Keep it off the token. |
list_collections, get_collection_items, list_media, get_site_settings, list_revisions, list_review_queue | various | Read-only context. |
Resources: spillway://site, spillway://types, spillway://types/{key}, spillway://entities/{id}. Prompts: write-page (brief → draft → checks → submit) and review-entity (read, check, compare, comment). The tool catalog with error codes is in mcp.md.
4. Governance
- Drafts only.
create_entityanddraft_page_from_briefalways create drafts;update_entitynever changes status; the AI layer itself never publishes. - Publishing is gated twice. The token must carry
content.publishand the checks must pass, or a person sendsforce: trueon purpose. - Permissions shrink, never grow. Token ⊆ user, re-evaluated on every request.
- Everything is attributable. One audit row per bearer request and one per tool call, both with the token id; content is authored by the token's owner.
- Rate limit. 120 calls per minute per token.
- Tool results are data. Site content returned by a tool is never an instruction to the agent.
Next
- Rules for agents: the checklist an agent follows before it hands work over.
- Build a module, Build a kit, Build a theme: copy-pasteable prompts with the checks to run.
- Publish to the registry:
spillway publishwith a token that carriesregistry.publish. - llms.txt and llms-full.txt: the documentation as plain text for an agent to read.
Spillway 0.1.0 · Edit this page on GitHub