Using Saybooks
Last updated 29 September 2026.
Saybooks is a place Claude can keep your records, under rules it cannot break, with everything it does written down where you can check it. This page covers what a person needs: connecting Claude, what keys and roles mean, spaces and their modules, documents, personal finances, getting your data out, and running it yourself. The rules themselves are in the specs.
Connect Claude
- Sign in with Google at saybooks.io/app. The demo books you tried stay yours, and a chooser sets up your own space: name it, tick the modules it carries, empty or with sample data. Nothing to install.
- Add Saybooks to Claude. In the Claude app: Customize → Connectors → Add (claude.ai/customize/connectors). Name it, paste the address, Continue.
Which books?NameinvoicesRemote MCP server URLhttps://saybooks.io/mcp/invoices
- Sign in and choose. Claude sends you to Google, then to a Saybooks page that asks which of your books to open, what the agent may do (owner by default, so it can set up the company profile with you), and the name it gets in the audit log. Allow, and Claude reports the connector as connected. Every action it takes from then on is logged under that name.
- Start a new chat with the connector on and say what happened.
Claude Code: claude mcp add books -t http https://saybooks.io/mcp, then /mcp in a session to sign in. Any client that speaks MCP over streamable HTTP with OAuth works the same way; the endpoint publishes its discovery metadata and accepts both dynamic registration and metadata-document client ids.
One address per kind of books
Claude allows one connector per address, and one Saybooks connection opens one space. So each kind of books has an address of its own, and you can hold several connectors side by side, say invoices and a job hunt:
https://saybooks.io/mcp | any of your spaces; consent asks which |
https://saybooks.io/mcp/invoices | your invoicing spaces only |
https://saybooks.io/mcp/hunt | your job-hunt spaces only |
https://saybooks.io/mcp/books | your full order-to-cash spaces only |
https://saybooks.io/mcp/s/<space id> | exactly that space, for two of the same kind; the id is the ws= part of the space's URL |
Each one signs in the same way and mints the same kind of key; the address only decides which spaces consent offers.
If you are building a server of your own and want the same shape: every door publishes its own protected-resource metadata at /.well-known/oauth-protected-resource/<path> and answers 401 with a pointer to it. The client sends that URL back as the resource parameter (RFC 8707) on the authorization request; the server stores it with the pending request and the consent page reads the path from it. Claude sends it. The code is in src/oauth.js.
Keys instead of sign-in
A script, a second agent, or a client without OAuth can use a key directly. In the sidebar open Share this space…, type a name for the agent, pick its role, press Mint key, and use the URL that appears: https://saybooks.io/mcp/m-…. The link is the key: whoever holds it acts as your delegate with that role. Revoke it from the same dialog; the connection made through sign-in above is a key of exactly this kind, minted for you at consent, and shows up in the same list.
Run it with a local model
The easy way is Saybooks for Mac (the app is called hostel): a free app that runs the model and Saybooks together on your Mac and passes the model the whole doctrine, which LM Studio does not. It comes with an iPhone app that asks your Mac from anywhere. What follows is the by-hand route.
Saybooks is a plain MCP server, so a model on your own machine can keep the books with nothing leaving it. Tested on a 32 GB MacBook with LM Studio and Gemma 4 26B A4B (the QAT 4-bit MLX build): a full invoice cycle first time, and a full statement cycle. What that took is its own note.
- Run Saybooks locally.
git clone,npm install,node server.jsfor the workbench atlocalhost:8140. The stdio MCP server ismcp-server.jsin the same folder. - Point LM Studio at it. Chat view → Program → Install → Edit
mcp.json:
Use the absolute path to{ "mcpServers": { "saybooks": { "command": "/usr/local/bin/node", "args": ["/path/to/saybooks/mcp-server.js"], "env": { "SAYBOOKS_WORKSPACE": "main", "SAYBOOKS_MODULES": "core,solo", "SAYBOOKS_ACTOR": "gemma-4" } } } }node.SAYBOOKS_MODULESpicks the tools the model sees:core,solois 35 tools for invoicing,core,purchases60 for statements; all eight modules is 161 and too many for a small model.SAYBOOKS_ACTORis the name on the audit trail. - Load the model with one concurrent slot and a 32k context. LM Studio defaults to four slots and reserves a full context cache for each; on a 32 GB machine that is the difference between quick and swapping.
- Talk plainly. "Set up my company: Vega Consulting, US, USD, not registered for sales tax." "Add a client, Meridian Logistics, net 30." "Invoice them for 12 hours at $250 and issue it." Paste a statement and say "here is my September card statement."
What to expect. A 26B model does one step at a time reliably and relays refusals in the system's words. It will sometimes stop mid-turn on LM Studio's current Gemma template; "continue" recovers it. It will occasionally report success on a refusal, which is what the audit trail is for, and it once invented a purchase order number, which is what the preview before issue is for. The rules held on every run. The plain-language scripts we test with are in test/local/: npm run local -- --model <id> --script plain-invoicing --instructions off.
Talking to it
Say what happened, in your own words. Claude calls the same commands the buttons call, under the same rules, and every action lands in your audit log attributed to the agent.
- "let's create an invoice": the guide asks for anything missing, one question at a time, shows you the draft and the preview link, and issues only when you say so.
- "the recruiter called, interview Thursday at 2": logged, with the next action and its due date.
- "receive 20 Widget B and finish Northwind's order": stock in, order shipped, invoice from what shipped.
- "what's due today?", "who owes me?", "show me the audit trail for Contoso": reads, never logged, always current.
Claude cannot invent an amount, a date, a name or an address: when it does not have a fact it asks you, and if it tries to write one anyway the system refuses. Everything Claude does also appears in your browser, as normal pages, the moment it happens.
Keys and roles
| Role | Can | Cannot |
|---|---|---|
| owner | Everything, including inviting people, minting keys, setting credit limits, deleting the space | Nothing |
| controller | Every business act: customers, orders, invoices, payments, credit authority | Invite, mint, delete the space, change the company profile |
| clerk | Day-to-day writes: orders, shipments, invoices, payments | Credit authority, everything an owner keeps |
| viewer | Read everything | Write anything |
A key is minted for a role. An agent holding a controller key is a controller; a command outside its role is refused with a sentence naming who to ask, and the attempt is logged. People are invited by email and sign in with Google; agents get keys. Both show up in the audit log by name.
Spaces
A space is one set of books with its own rules, its own members and its own audit log. Every space chooses its modules when it is made: invoicing, order to cash, CRM, job hunt, personal finances, any mix. The free doors, invoicing and a job hunt, are that chooser with one box ticked. Your first sign-in keeps the demo books as a space called Demo books and opens the chooser for your real one. You can have as many spaces as you like, and each key opens exactly one. Signing in again lands you in the space you used last.
Anonymous demo sandboxes at /app?demo=1 are private to your browser, seeded with example books, and deleted after 24 hours. Sign in while one is open and you keep it.
Documents
- Every invoice has a link from the moment it is drafted. Before issue it shows the real document stamped DRAFT; at issue the same link becomes the invoice; the PDF sits at the same link with
.pdfappended. The page shows the PDF's own pages, so what you preview is exactly what prints: same pagination, same fonts. Paper is A4 unless the company is in the US, Canada or Mexico. A line's first sentence prints as its title, anything after a line break prints smaller beneath it. - The document link needs no sign-in, by design: it is what you forward to your client. Anyone holding it can open that one document and nothing else.
- Issuing freezes the seller block from your company profile and the bill-to block from the client. Changing either later never reprints history.
- A voided invoice stays readable and printable, stamped VOID, with the reason at the foot. The number is never reused.
- Your logo prints on every document. Set it under Company, from a file or a public image URL.
- Currency, tax and numbering come from the company profile. Name the country (dates and amounts print the way people there write them), the currencies you bill in with a default, and your tax scheme: the tax's name, the default rate, and whether you are registered. Each invoice carries one currency from that set; a payment settles only invoices in its own currency. Not registered: no line can carry tax. Registered: every line gets the default rate unless you set a line to 0, the document says TAX INVOICE and prints your tax id under its own caption (GST No., VAT ID). The number format is yours too:
INV-{NNNN}by default,INV-{YYYY}-{NNN}to restart each year. - Reminders for overdue invoices. Ask your agent to chase an invoice, or open it and press Draft a reminder. The reminder is a draft in your voice: it must name the invoice and the amount open, and any other figure in it has to be the invoice's own, so a late fee nobody agreed can never slip in. Open it in your own mail (it arrives addressed and filled in), send it, and mark it sent with the day it went. Saybooks never sends it. Another reminder within a week of the last one asks for your reason. Invoicing, Reminders keeps what is waiting and what went.
Purchases
Full-books spaces carry a Purchases area: what you buy, from bank and card statements and receipts your agent reads. Nothing in Saybooks parses a file. The agent hands over the rows and the balances the statement prints; the statement is accepted whole when the rows reconcile to those balances, or refused with the gap named. Every row remembers its statement, its row number and the line as read. The same file is never imported twice; rows already on record are skipped and listed back.
- Standing rules. Say it ahead of time: "I'm at the Texas conference the next five days, book it to travel." Your agent records a rule with real dates, and rows from the next statement that fall in it show the suggestion ("travel?") until you confirm them, all at once or leaving out the ones that were not part of it. A rule never books anything by itself, and money coming in is never suggested as spending. Find them under Personal finances, Rules.
- Review is an act with a reason: purchase, transfer, income, fee or ignored, with a category in your own words. Amounts and dates never change; a wrong row means re-reading the statement.
- Subscriptions are declared by you and confirmed by the record. A period with no charge shows as missed; two in a row make it lapsed. Cancelled is something you say.
- Receipts are what the receipt says plus the file's hash; the file stays with you. Matching to a row is a reasoned act, refused when the total does not fit.
- Charts count reviewed purchases only, per currency, with no conversion.
- Bills, prepared for your approval. Hand your agent a vendor's invoice and say "add this bill". It records the vendor, their number, the dates and the amount as printed, and refuses the same bill forwarded twice. Only you approve paying it: the approval is refused to any agent, whatever its role. You pay from your bank, then record the payment with the day it went, linked to the statement row that shows it. Personal finances, Bills shows what is overdue and due within 30 days against the cash on your latest bank statement. Nothing here moves money.
Your accountant's ledger
Saybooks keeps the operational record; QuickBooks, Xero or your accountant's own system stays the ledger of record. The Ledger pages hand one to the other. The journal is derived from what happened, never posted or stored, so it is always current.
- Map the chart once. Three kinds of thing need one of your accountant's accounts: our derivation accounts (Accounts Receivable, Sales Revenue, Cash, Bank Fees and a few more), the categories you reviewed your spending under (groceries, software, rent), and the bank or card each statement came from. Xero matches on the code, QuickBooks on the name, so give both. Nothing is invented: anything in use and unmapped blocks the export and says so.
- Hand over a period. Pick the shape (Xero manual journal, QuickBooks journal entries, or plain CSV) and a date. Leave the start blank and it continues from the last hand-over, so month-end is a diff rather than a re-key. You get a file to import; nothing is posted into the ledger by us.
- The record answers "what did they already get?" Every hand-over keeps its period, entry and line counts, control totals, a hash and the exact file, downloadable again. Re-sending a period is allowed and always says it overlaps an earlier one, and whether the numbers changed.
- Both sides of the books. Money in comes from your invoices and orders. Money out comes from the statements your agent read: a reviewed purchase debits its category and credits the card it was paid from, a fee debits Bank Fees. A transfer posts nothing, which is how money already recorded elsewhere in these books avoids being counted twice.
- One line, several things. A payroll run is wages, employer taxes and the processor's fee; a warehouse trip is supplies and groceries. Split the row into parts that add to it exactly, and the ledger sees one posting per part against the one bank line. The row itself never moves: the statement said what it said.
- Every statement row posts, or is named. A transfer says where the money went (savings, an owner draw, the card being paid off) and posts against it, so the ledger's bank balance keeps tying to the statement. Whatever does not post, a row nobody has reviewed, or a receipt already recorded against an invoice here, is listed with its value, every time, because that is exactly the difference the accountant would otherwise have to hunt for.
- One currency per hand-over. A period holding two is refused until you name one.
- Preliminary financials before the close. Ask "how did we do last quarter?" or open Ledger, Financials: a profit and loss for the period and a balance sheet at its end, derived from the same journal. Each bank or card account starts from the opening balance its first statement printed and is checked against its latest closing balance, so you see whether it ties. The page says what it leaves out (rows not reviewed yet, transfers it cannot place) and is marked preliminary, because the accountant's adjustments still come after. A quarter, a month or a year that has not ended runs to today.
The column layouts follow each product's published import template. If your import wants a column spelt differently, tell us and it is a one-line change: the formats are a table in src/modules/bridge/views.js.
Refusals
Every rule in your books applies to Claude exactly as it applies to you. When a command is not allowed, the answer is one sentence with the reason, shown identically on the button's tooltip, in the thrown error and in the agent's reply, and written to the audit log. A real one:
Claude relays it and asks a person what to do. It does not split the order or quietly raise the limit; raising a limit is its own logged act by someone with the authority.
Export and delete
- Export, in the menu under your name (on a Mac, at the bottom of the Home page): one click downloads every table of the space as one JSON file, audit log included.
- Bring books in: the same file goes back in. On saybooks.io, New space offers Choose export file and makes a space of it; on a Mac, empty books offer it on their Home page. Everything comes along, history and audit trail included, and the import itself goes on the record. It only goes into empty books, so nothing is ever mixed or overwritten, and an export from a newer version than the one taking it is refused whole.
- Journal export: a balanced double-entry journal derived from the books, as CSV for QuickBooks or Xero, under Journal. Saybooks is not accounting software; your accountant's ledger stays where it is and this feeds it.
- Delete: one button permanently removes the space, its database, every key and every invitation. Type the space's name to confirm. There is no undo.
Run it yourself
Saybooks is open source under AGPL-3.0. Node 20 and nothing else.
git clone https://github.com/alviso/saybooks.git
cd saybooks && npm ci
node server.js # workbench at http://127.0.0.1:8140, one local workspace, you are the owner
npm test # the 24-gate contract and every conformance scenario
Environment: SAYBOOKS_PORT (default 8140); SAYBOOKS_DEMO=1 turns on the hosted mode with sandboxes, Google sign-in and the public pages; SAYBOOKS_PUBLIC_URL is the origin printed into document links; SAYBOOKS_ADMIN is the Google account allowed to open /admin. Google sign-in needs OAuth client credentials; see src/auth.js. A Dockerfile is included and is what runs saybooks.io.
Local MCP for development: node mcp-server.js speaks stdio. Over HTTP, each key's URL is its own endpoint; a sandbox's bare id is a key too.
Questions
Does Saybooks send my invoices or take payments?
No. It produces documents and records payments you received. It never emails anyone, never charges a card, never moves money. You send the link or the PDF yourself.
Does it sync with QuickBooks Online or Xero?
It hands over, rather than syncing. The Ledger pages export a period as a Xero manual journal, QuickBooks Online journal entries, or plain CSV, mapped to your accountant's own chart of accounts, and every hand-over keeps its control totals and the exact file. Nothing is posted into your ledger over an API, and nothing is read back out of it.
What currencies does it handle?
Any currency your company declares, and each invoice carries its own. What it does not do is convert between them: a period holding two currencies comes back grouped by currency rather than translated, and a ledger hand-over covering two is refused until you name one.
Can I use it without an AI agent?
Yes. Every command has a screen in the web workbench, and a click and a sentence to Claude are the same event, logged and refused the same way. The agent is the fast path, not the only one.
Is it accounting software?
No. It keeps the operational record upstream of the ledger: quotes, orders, shipments, invoices, receivables, pipeline, and reviewed spending from your bank statements. Your accountant's system stays the ledger of record and the hand-over feeds it.
What happens to my books if Saybooks disappears?
Export takes everything with you, in JSON, audit log included, any day. The code is public under the AGPL and runs on a laptop. Your data does not depend on the hosted service existing.
Something is wrong.
hello@saybooks.io, or open an issue on GitHub. If it is a rule that let something through that it should have refused, say so first: that is the bug we care most about.
Written and maintained by Peter Varga, who also runs Portland AI Works.