Docs · AI agents

Connect AI agents to Slate

Slate runs an MCP server, so Claude, Cursor, VS Code and other AI tools can search and read your pages, databases and playbooks, and answer with your own notes instead of guessing.

  • Read-only by default. A key can also create; nothing ever edits or deletes.
  • One key per agent. Revoke any time.
  • 8 tools: 5 to read, 3 to create.
Endpointhttps://slate.noman.io/api/mcp

Quick start

  1. Create a key. In Slate, open Settings › AI agents, name the key after the agent that will use it (say, “Claude on my laptop”), choose what it can do (Read only, or Read and create to let it add pages, databases and playbooks) and choose Create key. Copy it: it's shown only once.Open Slate
  2. Add Slate to your AI client with the key, using the steps for your client below.
  3. Ask about your workspace. For example:
    • Which units are late on rent this month?Queries your Rent Ledger database by status.
    • Find my notes about the Q3 launch and summarize them.Searches the workspace, then reads the pages it finds.
    • What does our refund playbook say to do for an order over 30 days old?Looks up the playbook and walks through its steps.
    • What databases do I have, and what does each one track?Lists your databases with their properties.
    • Turn these meeting notes into a page under Projects.Creates a page (with a key that can create).
    • Make a database of my vendors with name, phone and contract end date.Creates a database with those columns and rows.

Set up your client

Replace slate_YOUR_KEY with the key you created. Pick your client:

  1. Run this in a terminal, with your key in place of slate_YOUR_KEY:

    Terminal
    claude mcp add --transport http slate https://slate.noman.io/api/mcp \
      --header "Authorization: Bearer slate_YOUR_KEY"
  2. Start Claude Code and run /mcp: slate should be listed as connected.

Add --scope user to use Slate in every project, not just this one.

Tools

Agents choose these tools themselves; you just ask in your own words. Results come back as readable text and as structured JSON.

Reading (every key)

search_workspaceSearch the workspace Read-only

Find pages, databases, database records and playbooks whose title or text matches a query. Returns ids to use with read_page or query_database.

querytextrequiredWords to look for.
limitnumber 1–50At most this many results (default 10).
read_pageRead a page Read-only

Read a page as Markdown: its title, where it lives, its text and the pages inside it. Database records include their property values; playbooks list their inputs and steps.

page_idtextrequiredThe page's id (from search_workspace or a link).
list_databasesList databases Read-only

Every database in the workspace, with its properties (name, type, choices) and how many records it has.

No parameters.

query_databaseQuery a database Read-only

Get records from a database, optionally filtered and sorted by property values. Values come back by property name.

databasetextrequiredThe database's id, its page's id (from search_workspace), or its exact name.
filterslist of objectsAll must match.
filters[].propertytextrequiredProperty name.
filters[].operatorone of "equals", "not_equals", "contains", "greater_than", "less_than", "is_empty", "is_not_empty"required
filters[].valuestring or number or boolean
sortobject
sort.propertytextrequired
sort.directionone of "ascending", "descending"
limitnumber 1–200At most this many records (default 50).
list_playbooksList playbooks Read-only

Playbooks are step-by-step procedures in the workspace. Each has a 'when to use' line, typed inputs and sections of steps. Use this to find the right procedure for a situation and follow it (running them for you isn't available yet).

No parameters.

Creating (keys with “Read and create”)

These only add. A new page or playbook can go inside an existing page, where it appears as a link at the end of that page; nothing else that exists is changed, and nothing is deleted. A playbook is checked the way the builder checks it, and anything that would break a run comes back as an error to fix before it's made. Each answer includes the new page's address.

create_pageCreate a page Creates

Create a new page with a title and Markdown text (headings, lists, to-dos like '- [ ] task', tables, code). It's added at the top level, or inside an existing page, where it shows as a link in that page's text. Returns the new page's id and address. Creates only; it never changes existing pages.

titletextrequiredThe page's title.
contenttextThe page's text, in Markdown.
parent_page_idtextPut it inside this page (an id from search_workspace or read_page). Leave out to add it at the top level.
create_databaseCreate a database Creates

Create a new database: a table of records with typed properties (columns), optionally filled with rows, shown as a table, board or list. Every database has a title property (its first column). Select, multi_select and status choices not listed in `options` are added from the rows. Returns the new database's page id and address. Creates only; it can't add rows to existing databases.

titletextrequiredThe database's name.
descriptiontextA line about what it holds (optional).
parent_page_idtextPut it inside this page (an id from search_workspace or read_page). Leave out to add it at the top level.
title_propertytextName of the title column (default “Name”).
propertieslist of objectsThe other columns, in order. Leave out for a simple Status column.
properties[].nametextrequired
properties[].typeone of "text", "number", "currency", "checkbox", "date", "select", "multi_select", "status", "url", "email", "phone"required
properties[].optionslist of textChoices for select, multi_select and status.
rowslist of objectsRows to start with: objects keyed by property name, e.g. {"Name": "Unit 1A", "Rent": 1300, "Paid": true, "Due": "2026-12-01"}. Numbers as numbers, checkboxes as true/false, dates as YYYY-MM-DD, multi_select as a list.
viewone of "table", "board", "list"How it opens (default table). A board groups by the first status or select column.
create_playbookCreate a playbook Creates

Create a playbook: a step-by-step procedure people run in Slate, with inputs asked for at the start and sections of steps. Step types: check (do something and confirm it), ask (a question; save_as names the answer), say (something to tell someone), decide (branch on an input or answer), call (an HTTP request; save_as names the response) and finish (ends the run with an outcome). Use {{name}} in text to insert an input or answer (inputs are named from their label: “Order number” → order_number). go_to targets are a section title, "next" or "finish". The playbook is checked before it's created: problems come back as an error to fix.

titletextrequired
when_to_usetextWhen someone should run it, e.g. “A customer asks for a refund.”
parent_page_idtextPut it inside this page (an id from search_workspace or read_page). Leave out to add it at the top level.
inputslist of objectsWhat to ask for when a run starts.
inputs[].labeltextrequiredWhat people see, e.g. “Order number”.
inputs[].typeone of "text", "number", "date", "yesno", "choice"
inputs[].requiredboolean
inputs[].optionslist of textChoices for type “choice”.
guidelineslist of textShort rules to keep in mind during every run.
sectionslist of objectsrequired
sections[].titletextrequired
sections[].descriptiontext
sections[].stepslist of objectsrequired
sections[].steps[].typeone of "check", "ask", "say", "decide", "call", "finish"required
sections[].steps[].texttextWhat to do, ask or say; for finish, the outcome; for decide, an optional note.
sections[].steps[].expecttextcheck: what you should see when it worked.
sections[].steps[].answerone of "text", "number", "yesno", "choice"ask: the kind of answer (default text).
sections[].steps[].choiceslist of textask with answer “choice”.
sections[].steps[].save_astextask, call: the name later steps use, e.g. accepts_credit.
sections[].steps[].valuetextdecide: the input or answer to check (its name).
sections[].steps[].isone of "is", "is_not", "contains", "gt", "lt", "set", "not_set"decide: the comparison (default is).
sections[].steps[].compare_totextdecide: what to compare with.
sections[].steps[].then_go_totextdecide: where to go when it holds (default next).
sections[].steps[].otherwise_go_totextdecide: where to go otherwise. check, call: where to go if it fails.
sections[].steps[].methodone of "GET", "POST", "PUT", "PATCH", "DELETE"
sections[].steps[].urltext
sections[].steps[].headerstextcall: one “Name: value” per line.
sections[].steps[].bodytext

Security & privacy

  • Read-only unless you choose otherwise. Keys can only read unless created with Read and create. Even then, agents only add new pages, databases and playbooks: no tool edits or deletes anything.
  • Limits on creating. A key can create at most 20 things a minute, and one database at most 200 rows at once. Agent text is kept as text: it can't embed other pages or databases.
  • Scoped to your account. A key reads every workspace in the account that created it, and nothing else. Pages in Trash aren't visible.
  • One key per agent, revocable. Settings › AI agents lists your keys with when each was last used. Revoking one stops it on the agent's next request.
  • Stored as a hash. Slate keeps only a fingerprint of each key, which is why it's shown once. If you lose it, revoke it and create another.
  • Treat a key like a password. Keep it out of shared files and Git; prefer an environment variable where your client supports one.
  • Your content is data, not instructions. Slate labels page content that way for the agent, but agents can still be swayed by what they read, so check before acting on anything important.

Troubleshooting

“Add an agent key” (401)

The request had no key, or it wasn't in the right form. Send exactly Authorization: Bearer slate_…, with one space after Bearer.

“This agent key is not valid, or was revoked” (401)

Check the key was copied whole, with no space or line break at either end (pasting often adds one). If it was revoked or lost, create a new key.

Slate doesn't show up in my client

Restart the client after editing its config, and check the file is valid JSON (a missing comma is easy to miss). Then try the curl check under Other clients: if that lists the tools, the key and endpoint are fine.

My client wants me to sign in

Slate uses keys rather than a sign-in flow. Add it through the client's config file with the key in a header, or through mcp-remote as shown above.

The agent can't find a page

Agents see what's in your workspace now, apart from pages in Trash. Ask it to search by a word from the page's title, or give it the page's link.

“Unable to read the workspace right now” (503)

Slate couldn't reach its database for a moment. Try again shortly.

“This agent key can only read”

The key was created as Read only. Create a new key with Read and create in Settings › AI agents, and use that one where the agent should be able to create.

A new page doesn't show in Slate yet

Slate checks for changes every few seconds while the tab is open, and right away when you come back to it. If you were in the middle of editing, it waits until your changes are saved.

“Too many requests” (429)

Each key can make 120 requests a minute, and each address 300. Wait the number of seconds in the Retry-After header (the message says it too), then carry on. Normal use never gets near this.

Technical details

Endpoint
https://slate.noman.io/api/mcp
Transport
Streamable HTTP. One JSON-RPC message per POST, answered with JSON; no sessions and no server-sent stream (GET answers 405).
Authentication
Authorization: Bearer slate_…. Keys are 43 random characters after the slate_ prefix.
Protocol versions
2025-06-18, 2025-03-26, 2024-11-05
Capabilities
Tools (tools/list, tools/call) and ping. A key sees the reading tools (readOnlyHint), plus the creating ones (readOnlyHint: false, destructiveHint: false) when its scope allows.
Rate limits
120 requests a minute per key and 300 per IP address; creating, 20 a minute per key. Over a limit: 429 with Retry-After.
Server name
slate
Source
The server is src/app/api/mcp and src/lib/mcp.ts; the tools are src/lib/agent-tools.ts in the GitHub repository.
Example: initialize
curl https://slate.noman.io/api/mcp \
  -H "Authorization: Bearer slate_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'