alfredo
Allows using Cloudflare D1 as the database backend for a workspace, accessed through a Cloudflare Worker.
Allows using a Supabase project as the database backend for a workspace, with schema and row-level security managed by Alfredo.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@alfredowhat did we decide about pricing in the last sprint?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Alfredo is a Mac app with four tabs, Board, Docs, Canvas and Meetings, that answers questions about everything written in them. It records and transcribes your meetings on your own machine, and it hands the whole workspace to whatever AI agent you already use through a local MCP server, so you can say "what did we decide about pricing" or "put last week's unfinished cards in this cycle" and mean it. Every agent that speaks MCP connects the same way: Cursor, Codex, Claude Code, Gemini CLI, VS Code, Zed, your own.
There is no account, no server of ours, and no subscription. Each workspace lives in a database you choose: a folder on this Mac, your Supabase project, or your Cloudflare account.
What it replaces
Instead of | Alfredo's tab | Their list price, per person, per month |
Linear Business | Board: cards, cycles, backlog | $16 |
Notion Business | Docs, and the AI that reads them | $20 |
Miro Business | Canvas: frames, stickies, arrows | $20 |
Granola Business | Meetings: transcripts and notes | $14 |
Glean-class search over all of it | Ask it anything, with citations | $45 to $75, with a seat minimum |
Prices as published in September 2026. A team of ten pays about $8,400 a year for the first four. Alfredo is MIT licensed and costs nothing; the only bill is the database, which is free on this Mac, free on Supabase and Cloudflare at the sizes a workspace runs at, and yours either way.
That is not a claim that Alfredo is as good as any of them at their own game. It is one app, built for a team that would rather own the data and the bill.
Related MCP server: linked-docs
Get it
Download the latest release.
On a Mac, open the .dmg and drag Alfredo into Applications; it is signed and
notarized, so it opens like any other app. On Windows and Linux, unzip it and
run it. The Windows build is not code-signed yet, so SmartScreen asks once:
More info, then Run anyway.
If someone sent you an invite, open Alfredo, choose Add workspace, then I have a link, and paste their link.
Run it
Needs Node 22 or newer.
npm install
npm run dev # http://localhost:5210Or build the desktop app for the machine you are on:
npm run desktop:install # macOS, straight into /Applications
npm run desktop:build:win # Windows, into dist-app/win-unpacked
npm run desktop:build:linux # Linux, into dist-app/linux-unpackedBuild it on the platform you want it for: npm only installs the native pieces (the embedding runtime, the terminal) for the machine doing the installing.
The first screen asks where your first workspace should live. Nothing else is required to start.
Where it runs
Most of Alfredo is Node, WebAssembly and a browser, so it runs wherever those do. Two things are genuinely Apple's, and the app says so rather than pretending:
macOS (Apple silicon) | Linux and Windows | |
Board, Docs, Canvas, projects, people | Yes | Yes |
Your database: this machine, Supabase, Cloudflare | Yes | Yes. The local one is PGlite, which is WebAssembly |
The brain: chunking, embeddings, hybrid search | Yes | Yes. The embedding model has Linux and Windows builds |
MCP server for your own AI | Yes | Yes |
Meetings you write yourself | Yes | Yes |
A packaged desktop app | Yes | Yes. Built by CI on each one |
Recording a meeting | The room and the call together, through a small ScreenCaptureKit helper | The microphone, always. The call as well on Windows if a loopback device is installed (see below) |
Transcribing it here | Parakeet through FluidAudio (CoreML) | Parakeet through ONNX Runtime, the same weights |
Hearing both sides of a call
Both operating systems will hand a program the audio they are playing, and Alfredo asks each one in its own way, records it alongside the microphone, and mixes the two into a single track.
how | build it with | |
macOS | ScreenCaptureKit, in |
|
Windows | WASAPI loopback, in |
|
Both helpers take the same arguments and answer with the same words, so the server does not know which one it is talking to. Neither needs a virtual cable or a driver. CI compiles both on every push, and runs the Windows one.
Without a helper, ffmpeg records the microphone alone, because DirectShow
cannot see the render side by itself. Alfredo still picks up a loopback device
if you happen to have one (VB-Cable, virtual-audio-capturer, Stereo Mix), and
Meetings says on the page which of the two it is going to record, rather than
letting you find out after an hour. On Linux, route the call into a PulseAudio
monitor source and point CRM_AUDIO_DEVICE at it.
Transcription, on whatever machine you have
Parakeet is NVIDIA's model, not Apple's, and Alfredo reaches it two ways:
through | download | |
macOS, Apple silicon | FluidAudio, CoreML | built once by |
Windows, Linux, Intel Macs | ONNX Runtime, which Alfredo already carries for its embeddings | the ONNX export, about 640 MB, fetched by the Download button in Meetings |
Same weights, same parakeet-tdt-0.6b-v3, same machine doing the work. The
ONNX side is three graphs, run in server/parakeet-onnx.ts: log-mel features,
the conformer encoder, then greedy TDT decoding, which is RNN-T with the joint
network also saying how many frames to skip. Long recordings go through in
thirty-second pieces that overlap by two seconds, and a piece starts at the
first whole word after the overlap, so nothing is heard twice and no word is
cut in half at a seam.
Set ALFREDO_TRANSCRIBE=onnx on a Mac to use that path instead of CoreML, or
hosted to skip local transcription entirely.
Secrets live in the macOS keychain where there is one, and in a 0600 file
beside the workspace registry where there is not.
Checked on every push, on all three: .github/workflows/build.yml installs
Alfredo on macOS, Windows and Linux, type-checks it, builds it, packages the
desktop app, compiles both system-audio helpers and runs the Windows one, and
then runs scripts/smoke.mjs, which starts the server, makes a workspace,
writes a doc, a card and a meeting into the local database and reads them back,
reads the workspace into the brain and asks a question of it (which is the
embedding model running on that machine), and asks the MCP server for its
tools. Run it yourself with
npm run build:server && node scripts/smoke.mjs.
Everything goes through the database
There is no Alfredo backend. The app talks to one database per workspace, and every last thing it knows lives in there: cards, docs, canvases, meetings, people, roles, invitations, which tabs the workspace has, and the passages the brain searches. Switching workspace switches database.
Where | Good for | Setup | Enforced by |
This Mac | Yourself, offline | None. A folder under | Nothing to enforce: one person |
Supabase | A team | Paste a personal access token, Alfredo creates the tables | Postgres row-level security |
Cloudflare D1 | A team, on your own account | One click with your | A Worker that owns the only door to D1 |
Supabase:
db/schema.sqlanddb/policies.sql, both safe to run again.Cloudflare:
cloudflare/schema.sqlandcloudflare/worker.mjs.This Mac: the same schema, in PGlite (Postgres compiled to WebAssembly).
Because the rules live in the database, the app is not what stands between a teammate and a project they are not in. An invited teammate's copy of Alfredo holds no secret key at all: it connects with the publishable key and their own sign-in, and the list of projects they see is Postgres's answer, not the app's.
Moving a workspace between databases is a matter of pointing Alfredo at the other one; nothing of yours is left behind on a machine of ours, because there isn't one.
The brain: asking your own writing
Everything written in a workspace is cut into passages, embedded, and kept in a
chunks table beside the work itself. A question searches those passages two
ways at once and hands the best of them to the agent on your machine, which
answers from them and says where each claim came from.
Reading it in. A doc, a meeting's notes and transcript, a card or the words
on a canvas get cut on the writing's own headings, about 380 tokens a piece with
60 tokens of overlap, and every piece carries its title and heading path in
front of it, so a paragraph that says "we went with the second option" still
knows what it is an option about. Retrieval lives or dies on that, far more than
on the model. New work is read in as it is saved; everything from before is read
in once, from Settings, Models (or read_workspace_in over MCP).
The model. bge-small-en-v1.5, quantised to int8: 384 numbers a passage,
about 34 MB, downloaded on first use and then never online again. It is small on
purpose. What makes retrieval good is the chunking, a lexical pass beside the
vectors, and fusing the two.
Searching. Two lists, fused by reciprocal rank. The vectors find the passage that means what you asked even when it uses different words; full-text finds the exact part number, name or phrase that vectors always miss. Fusing them means neither has to be right on its own.
Answering. The coding agent on this Mac, from those passages only, with the bracketed number of each passage it used. When the workspace does not say, it says so rather than filling the gap. There is no hosted fallback: a company's own writing is the last thing to hand to a service nobody chose.
What it may find. The search runs as whoever is asking, through the same row-level security as the work, so a project you are not in cannot be quoted at you. Ask inside a project and the answer stays inside it.
⌘K takes a question as well as a name. The citations are chips: click one and the doc or meeting opens.
Meetings
Press Transcribe. Alfredo records the room and what the call is playing, turns it into text on this Mac with Parakeet, and deletes the audio the moment a transcript exists. The agent on this Mac then writes the note: summary, decisions, open questions, and action items with owners and dates resolved (nobody lets the model do date arithmetic; it says "by Friday" and the code works out which Friday). The meeting is saved to your database and read into the brain, so the next question can quote it.
Meetings offers to download Parakeet the first time, about 600 MB, needing Xcode's command line tools. No Parakeet and no agent still leaves you a working tab: New meeting makes one you type the notes into yourself.

The transcript is one click away, and it is the only copy of the meeting that survives:

Connect Google Calendar in Settings, Connections, and what is coming up appears above the list with a Transcribe button on each.
Every AI agent, the same way
Alfredo runs a plain MCP server over
streamable HTTP at http://127.0.0.1:29981/mcp. It is a local MCP: there is
nothing in it that belongs to one vendor, so any agent that speaks MCP can list
the tools and call them.
// Cursor (~/.cursor/mcp.json), VS Code, Zed, Windsurf, Goose and the rest
// take the same thing in their own config file:
{ "mcpServers": { "alfredo": { "url": "http://127.0.0.1:29981/mcp" } } }# Codex (~/.codex/config.toml)
[mcp_servers.alfredo]
url = "http://127.0.0.1:29981/mcp"# Claude Code
claude mcp add --transport http alfredo http://127.0.0.1:29981/mcpA client that only speaks stdio can bridge with
npx mcp-remote http://127.0.0.1:29981/mcp. Add the header
x-workspace: <id> to pin one workspace; otherwise calls go to the active one.
Handing it a piece of the workspace
Every copy button in Alfredo (on a card, a column, a whole cycle, a doc, a canvas, a meeting's notes or its transcript) copies the thing and the way back to it:
Alfredo · Acme · meeting “Pricing review (notes)”
Read it again: ws_read kind:"meeting" id:"2344c5c0-…" (MCP header x-workspace: acme)
Change it: ws_write kind:"meeting" id:"2344c5c0-…"
## Summary
The team plan price will rise to $24 per seat starting in March…Paste that anywhere. An assistant with Alfredo connected can follow the handle to read the rest or write back; one without it still has the text, which is what pasting usually means anyway.
Two of the tools matter most, and they split along exactly this line:
search_workspacehands back the passages and where each came from, and nothing else. Whatever model your client runs writes the answer. This is the one to use from Cursor, Zed, VS Code or your own SDK client.ask_workspacewrites the answer as well, using the coding agent on this Mac. Nothing is sent to a service of ours: a company's own writing only ever goes to an agent you installed.
Then talk to it:
"Connect my Supabase project Acme to a new workspace called Acme." "What did we decide about the team plan price, and which meeting was it?" "Make a project called Website, put Neil in it as an editor, and move the three pricing docs into it." "Read the whole workspace in, then tell me what is unfinished this cycle."
Tool | Does |
| Every workspace and where it lives |
| Cards, docs, canvases, meetings, members |
| The workspace's name and its tabs JSON |
| Answer from the workspace's own writing, with citations |
| Read everything in, and see how far it got |
| Projects, and who is in them |
| An invite link to send someone |
| Data for tab types you add yourself |
| Add a Supabase workspace |
| Create or upgrade its tables |
| Add a Cloudflare workspace |
The server binds to 127.0.0.1, refuses browser origins and foreign hosts, and holds database keys, so it never listens on the network.
Do you need an AI at all?
No. The board, docs, canvas, meetings, projects and search all work with no AI of any kind. Transcription is Parakeet, on your Mac. Search is the embedding model, on your Mac.
Two things use a model, both through the agent on your machine: writing up a meeting, and writing the prose answer to a question. Without it you still get the transcript and the passages, and any MCP client can turn those into an answer with its own model.
People, projects and who may see what
Whoever connects the database and makes the first account runs the workspace. They invite the rest with a link, put each person in the projects they need, and give each a role there: runs it, can edit, or read only. Admin can be handed to someone else. All of it is rows in the workspace's database, so it travels with the workspace rather than with a Mac.
Projects are off until a workspace turns them on. They split one workspace into separate boards, docs, canvases and meetings inside the same database, and you switch between the ones you are in, under the workspace name. There is no "all projects" view: you see the projects you were let into.
Inviting someone. Settings, Members, type their email, choose what they may do and which projects they are in, then Copy the invitation. That puts a whole message on your clipboard, not a bare token: where to download Alfredo, what to do with the link, and which address to sign in with. Send it however you like; Alfredo has no mail server and never will.
The link itself carries where the workspace is and nothing secret: the publishable key and the invitation, both safe to read. What they can see once they are in is the database's decision, not the link's. It works once, for that address, and stops working in two weeks.
Sign in with Google works on Supabase workspaces whose project has the
Google provider on. Google will not sign anyone in inside an app window, so
Alfredo opens the system browser and catches the answer on
http://127.0.0.1:29981/auth/callback; add that to the project's redirect URLs.
Making it yours
Tabs are data, not code. Every workspace keeps a tabs JSON in its own database. Rename them, hide them, reorder them, or add your own:
[
{ "id": "board", "type": "board", "name": "Board", "columns": ["Todo", "In progress", "Review", "Done"] },
{ "id": "docs", "type": "docs", "name": "Docs" },
{ "id": "canvas", "type": "canvas", "name": "Canvas" },
{ "id": "meetings", "type": "meetings", "name": "Meetings", "hidden": true }
]Rename the board's columns per workspace with columns. Any other type is a
pack: a folder in src/v2/packs/<name>/ whose index.ts exports tabs,
keyed by type. A pack's data goes in the workspace's database through the pack
data tools, never in the code, so a tab you invent travels with the workspace
like everything else.
Cycles run 1, 2 or 4 weeks. When one ends you decide what happens to unfinished work: ask every time, roll it into the next cycle on its own, or send it back to the backlog. Whatever the setting, Carry over on the board moves what is unfinished whenever you say so, into the next cycle, the one running now, or the backlog.
The canvas is React Flow JSON, so a board made elsewhere in that format opens unchanged. Frames carry what is inside them, the hand tool pans from anywhere, scroll pans and ⌘-scroll zooms.
Docs list as a grid or a table, whichever you leave it on.
What leaves your machine
Nothing, unless you ask for it.
Where it happens | |
Transcription | Parakeet, on this Mac. Only if you have no Parakeet and you set |
Meeting write-ups | The coding agent on this Mac, or not at all |
Answers from the brain | The coding agent on this Mac, or not at all |
Embeddings | On this Mac, by a model downloaded once |
Your work | The database you chose, and nowhere else |
Keys and tokens live in the macOS keychain. .env.local is optional; see
.env.local.example.
Building on it
npm run dev # app on 5210, server on 29982
npm run build # the web build
npm run desktop:install # build the Mac app and put it in /Applications
npm run db:push # apply db/schema.sql and db/policies.sql to a Supabase projectThe app is Svelte 5 with runes. The server is Hono, one route file per
area under server/, with a Store interface each database kind implements
(SqlStore for Supabase and PGlite, CloudflareStore over the Worker), so a
feature is written once and works on all three.
License
MIT. See LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Let AI agents query data and act across all your business apps via MCP.
Make your knowledge agent-ready. One MCP endpoint, 5 connectors, 3 search modes.
Your memory, everywhere AI goes. Build knowledge once, access it via MCP anywhere.
AI agents use CalmBoard MCP to access board data, tasks, insights, and project workflows.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceConnects AI assistants to a team's product knowledge base, enabling search, capture, and navigation of glossary terms, business rules, decisions, and relations via MCP.32,433 npm-
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to intelligently search and reference documentation using hybrid semantic + keyword search via MCP protocol.-
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to query and manage a document knowledge base via MCP, with RAG-powered search and grounded answers with citations.MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to read Trello boards and cards and perform light updates, such as creating, moving, editing cards and adding checklist items, through MCP.225 npmMIT