todox MCP Server
Click on "Install 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., "@todox MCP ServerGet context for my current project"
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.
todox
Working memory for developers and their agents. Not a checklist — a log your next session can actually resume from.
An issue tracker is written human-to-human. todox is written agent-to-agent, with a human reading over its shoulder. Every task carries the decisions behind it, the approaches that failed, the questions still open, and the note the last session left behind.
A fresh agent calls get_context, reads that, and starts where the last one
stopped — without walking into a wall somebody already hit. The briefing is
capped rather than unbounded, and it reports what the caps left out instead of
trimming in silence.
What goes in a log
kind | what it means |
| what you chose, and why the alternatives lost |
| an approach that did not work — the highest-value entry, because it stops the repeat |
| something only a human can answer |
| end-of-session state, written for a stranger |
| everything else |
Two things fall out of treating the log as the product:
Stale context is flagged, and never faked. Linked files are hashed by the side that can see them — the agent — and the server stores the hashes and compares. If the code moves on,
get_contextsays the note may be lying. Until an agent has actually looked, the note is marked as never checked rather than claimed to be fresh: context that lies is worse than none, and that includes lying about how sure we are.Reports come from the log, not from commits. Every status change is an event, so what did I finish today, how long did it take, which model did it is a query rather than archaeology.
A file can be asked what is known about it. The same links that carry the hashes are readable from the other end:
get_file_contexttakes a path and answers with the tasks that touched it, their dead ends, and any standing note attached to it. Paths are folded to their repo-relative form, so a link made on one machine is found from another.
Related MCP server: personal-kg-mcp
Try it
todox.dev — anyone can register. Small personal deployment, no uptime promise. Self-host if the log matters to you.
Run your own
pnpm install
cp .env.example .env.local # any Postgres 15+; see below for a container
pnpm db:migrate # idempotent
pnpm seed # optional demo account: demo / todox-demo
pnpm devConnect an agent
todox is a remote MCP server. There is nothing to install and no repository to clone: point any MCP client at the URL with an agent token.
Create a token on the Account page and it hands you text you can paste straight into whichever agent you use, plus the config snippet for the four common ones. The shape is always the same — one URL, one header:
# Claude Code. --scope user, because the default is this directory only.
claude mcp add --scope user --transport http todox https://www.todox.dev/api/mcp \
--header "Authorization: Bearer todox_…"// OpenCode v1 — ~/.config/opencode/opencode.json.
// MCP key is `mcp` (server name is a direct key under it), NOT `mcpServers`.
// `type` is `"remote"`, NOT `"http"` — the Claude/Cursor/VS Code value is
// silently ignored on OpenCode.
{
"mcp": {
"todox": {
"type": "remote",
"url": "https://www.todox.dev/api/mcp",
"headers": { "Authorization": "Bearer todox_…" }
}
}
}// OpenCode v2 — same key, server now nested under `mcp.servers`.
{
"mcp": {
"servers": {
"todox": {
"type": "remote",
"url": "https://www.todox.dev/api/mcp",
"headers": { "Authorization": "Bearer todox_…" }
}
}
}
}# Codex — ~/.codex/config.toml
[mcp_servers.todox]
url = "https://www.todox.dev/api/mcp"
http_headers = { Authorization = "Bearer todox_…" }// Cursor — ~/.cursor/mcp.json, the one in your home directory.
{
"mcpServers": {
"todox": {
"type": "http",
"url": "https://www.todox.dev/api/mcp",
"headers": { "Authorization": "Bearer todox_…" }
}
}
}// VS Code — the user-level mcp.json ("MCP: Open User Configuration").
// The root key is "servers", NOT "mcpServers". This is the one client
// that differs, and getting it wrong is silent.
{
"servers": {
"todox": {
"type": "http",
"url": "https://www.todox.dev/api/mcp",
"headers": { "Authorization": "Bearer todox_…" }
}
}
}The MCP config key and the
typevalue differ per agent, and the wrong combination is silently ignored — no error, no warning, the tool just does not show up:
agent
key
typeClaude Code
mcpServers.NAME
"http"OpenCode v1
mcp.NAME
"remote"OpenCode v2
mcp.servers.NAME
"remote"Cursor
mcpServers.NAME
"http"VS Code (Copilot Chat)
servers.NAME
"http"Codex
TOML
[mcp_servers.NAME]n/a
Where those files live differs by platform, and VS Code is the one that is not where a Linux habit puts it:
agent | macOS | Linux | Windows |
Claude Code |
| same | same |
Cursor |
| same | same |
Codex |
| same | same |
OpenCode |
| same | same |
VS Code |
|
|
|
Install it globally, not per project. Every one of these tools defaults to
the directory you are standing in — claude mcp add without a scope,
.cursor/mcp.json, .vscode/mcp.json — and a memory that only exists in one
repository is the opposite of the point. It also fails quietly: the tools
simply are not there in the next project, so the agent never mentions them.
Spell out "type": "http". A client that finds a url without one tends to
assume a local command and fails with something unhelpful.
Then tell your agent to use it
Connecting is not the same as being used, and the gap is bigger than it looks.
An MCP server's instructions are background reading; a skill or a CLAUDE.md
rule is an instruction. When they disagree, the server loses — measured, in a
fresh project, with todox connected the whole time and never once called.
So put four lines in the memory file your agent actually obeys:
todox MCP is installed here — persistent memory across projects.
- Call `get_context` before starting non-trivial work (cwd = your working
directory). It registers a new repo by itself.
- `create_task` for anything that will not finish this session.
- Before stopping, `log_entry(kind:'handoff')` on every task you touched,
and `dead_end` for approaches that failed.
- Always pass your own model id.Or let the installer do it:
pnpm install:mcp claude-code --write-memoryIt is off unless asked, because that file is yours rather than ours, and it is
idempotent — the block is fenced with an HTML comment, so a second run replaces
it instead of leaving two sets of instructions where the older one wins. Add
--dry-run to see the exact block first.
The user-level file, not the project one. This is the same trap as the config above, one directory over:
Agent | The file that applies everywhere |
Claude Code |
|
Codex |
|
Cursor |
|
VS Code |
|
OpenCode |
|
A repository's own AGENTS.md, and the per-project rules files the editors also
read, apply inside that checkout only. A cross-project memory installed into one
project is the thing this whole section exists to avoid.
The token stays out of that file — it lives in your MCP config. This is the habit, not the credential.
Optional: local mode
The hosted server has no filesystem — but your agent does, and that is enough:
it sends the hash when it links a file and calls report_file_hashes with what
it finds afterwards, so staleness works over HTTP like anywhere else.
The stdio server does that part itself rather than asking. Worth running if you would rather not spend an agent's attention on it, or want the hashing to happen even when the agent forgets. There is nothing to clone:
TODOX_TOKEN=todox_… TODOX_URL=https://www.todox.dev \
npx https://github.com/beydemirfurkan/todox/releases/latest/download/todox-mcp.tgzOr as an MCP config, which is the form an agent wants:
{
"mcpServers": {
"todox": {
"command": "npx",
"args": [
"-y",
"https://github.com/beydemirfurkan/todox/releases/latest/download/todox-mcp.tgz"
],
"env": { "TODOX_TOKEN": "todox_…", "TODOX_URL": "https://www.todox.dev" }
}
}
}There is no npm package, and that is a decision rather than a to-do. A
GitHub Release needs no account and no token to publish or to install from, so
the tarball is the whole distribution and npx takes its URL directly. The URL
above always resolves to the newest release; every release also carries a
todox-mcp-<version>.tgz if you would rather pin and choose when to move.
It carries only what the stdio server actually loads — no Next, no React, no
Postgres driver, because it talks to the API over HTTP and never opens a
database. pnpm pack:mcp builds it, and fails the build if anything
server-side ever finds its way into the tool surface again.
From a clone, pnpm -C /path/to/todox mcp still works and is what to use when
you are changing the tools themselves.
Tools
tool | what it does |
| Call this first. Standing rules, project decisions and gotchas, every open task with its decisions, dead ends, questions, files and last handoff — plus stale-file warnings. Resolves a project from a slug, a name, or any path inside it. Capped so it cannot grow without bound, and it says what it left out. Pass |
| Capture work. Pass |
| Status, title, body, priority. Moving to |
| Append one of the five kinds. |
| For an entry that was wrong when it was written. One overtaken by later work is history, not an error — append instead. |
| Today / this week / any window: durations, models, importance, decisions, dead ends, open questions. |
| Attach paths with their hashes to a task or a context note. Safe to call again for the same file. |
| Hosted only: what the linked files look like on disk now. The local process does this for itself. |
| Clear a stale warning once you have read the change, or drop a link that has stopped meaning anything. Nothing else can clear it — the server never sees the file. |
| Knowledge that outlives a task; omit the project to make it account-wide. |
| One note in full, for the ones whose body the briefing capped and for reading past a search snippet. |
| What is known about one file: the tasks that touched it with their dead ends, and the notes attached to it. Absolute or repo-relative; both find a link made on another machine. |
| Correct a note that turned out wrong. A log that can only be added to stops being worth reading. |
| Across all your projects, ranked by relevance. Ask the question in words; quote a phrase to require it. Stems English and Turkish, and still matches the middle of an identifier. Words that only one of the two languages treats as noise are dropped, so a question does not match every record containing the word "a". |
| One task with its log and linked files. |
| The plain lists, when |
| Rarely needed: |
| The way back from a mistyped |
| The way back from one repo registered twice. Moves tasks, notes and paths into the surviving project; |
Every write tool takes a model, and the server instructions tell the agent to
always pass it. That is what makes the per-model breakdown real rather than
guessed.
Prompts
Three, because there are three moments this is for. They show up in your client's own menu, so you can see what the server does without reading anything:
prompt | when |
| before planning — read what earlier sessions established |
| before finishing — leave a handoff, and the dead ends especially |
| when somebody asks what got done |
Deploying
A container and a Postgres beside it. docker-compose.yml at the root is that,
assembled — the database publishes no port at all and is reachable only over
the compose network:
cp .env.example .env # set POSTGRES_PASSWORD and TODOX_PUBLIC_URL
docker compose up -d --build
docker compose exec app pnpm db:migrateThe migration is a separate line on purpose; see the note at the end of this section. todox.dev itself runs the same two containers on one host.
variable | why |
| Postgres. When the database is a neighbour on the same network this is its service name, and no certificate or public port is involved. |
| Optional, default 10. Connections this process may hold. Raise it only after checking the server's own |
| Verification links, reset links and the agent setup snippet are built from it — get it wrong and people, and their agents, land on the wrong host. |
| Optional, but the first four together. Without them mail is printed to the server log rather than sent. Port defaults to 587 (STARTTLS). What |
Run pnpm db:migrate when the schema changes. It deliberately does not run at
startup: DDL racing between instances of a rolling deploy is a bad way to
discover lock contention, and the schema is idempotent precisely so the decision
can be made after a deploy rather than during one. From the host:
docker exec <container> pnpm db:migrateThat is also why the image keeps its dev dependencies instead of using Next's
standalone output — pruning them removes tsx and everything under
scripts/, and a database that is deliberately unreachable from the internet
can only be migrated from something already inside the network.
Taking your data with you
The Account page has a Download my data button, and /api/export answers
the same file to a bearer token — so an agent can write the backup without the
result passing through a model. It carries every project you own with its
tasks, log, context notes and file hashes, and nothing about anybody else: no
credential, no collaborator, no share token, and no projects that were shared
with you, which belong to whoever made them.
Loading one into an instance you run:
pnpm db:import ./todox-export-2026-08-18.json your-usernameAdditive, never destructive: nothing is deleted or overwritten, and a project whose slug is taken arrives under the next free one. Task events come across too, so durations in a report on the restored copy say what they said on the original.
Coming from the old SQLite version? pnpm db:import-sqlite [path] copies a
~/.todox/todox.db across.
Security
Passwords are scrypt; sessions, agent tokens and email links are stored as hashes only. Ownership is enforced in one module, and a row belonging to someone else answers 404 rather than 403 so ids cannot be probed. Rate limits live in the database, so they hold across instances.
Details, and an honest list of what is not covered, in SECURITY.md.
Known gaps
Search's full-text half is indexed; its substring half is not. The two are asked separately and merged, which is what lets the first one use an index at all — measured on 110k rows, a search went from 5.7s to 0.16s. What is left is one sequential scan for the
ILIKEarm that finds identifiers full-text cannot, and indexing that needspg_trgm, which needs aCREATE EXTENSIONthis project cannot assume it is allowed to run.Staleness is per-file hash; per-symbol would be the honest version. Hosted, it depends on the agent actually sending hashes — the instructions ask, and nothing can make it.
Coverage sits around 39%, and the shape matters more than the number: the agent surface, the auth boundary and the repositories that answer "is this yours" are covered, while much of the UI is not.
No 2FA, no per-session revocation, no audit log.
Share links are unlisted, not access-controlled.
No keyboard navigation beyond
/for search.
Cutting a release
git tag v0.1.1 && git push origin v0.1.1That is the procedure. The workflow checks the tag against package.json,
runs the checks, builds the stdio package and attaches it to a GitHub Release —
no account and no credential involved, so npx <that tarball url> works from
the first tag.
Two names go up: todox-mcp-<version>.tgz, and the same bytes as
todox-mcp.tgz so that /releases/latest/download/todox-mcp.tgz is an address
worth writing into a config once. Nothing is published to npm, on purpose — see
the local-mode section above.
server.json pins the MCP registry entry to the same version and
server-json.test.ts holds it there, so the tag, the package and the registry
move together or the release stops.
Contributing
The rules the codebase actually follows, and how to run the checks: CONTRIBUTING.md.
MIT — see LICENSE.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityDmaintenanceProvides state and log management tools designed for long-lived AI agents that may be interrupted and resumed. It enables tracking agent progress and maintaining an append-only event history to ensure continuity across multiple sessions.4MIT
- AlicenseAqualityCmaintenanceAuto-captures decision context from multi-agent workflows to preserve the 'why' behind every choice. Enables task traceability, reasoning retrieval, and continuous improvement across planning and implementation sessions.17126MIT
- AlicenseCqualityCmaintenanceCaptures key development moments, enables multi-agent traceability, provides intelligent context curation, and facilitates seamless agent-to-agent handoffs.2917MIT
- AlicenseNot gradedqualityCmaintenancePersistent activity journal for AI agents - enables logging and querying decisions, changes, errors, and observations across sessions.131MIT
Related MCP Connectors
Durable agent-to-agent handoffs and shared scratchpad for multi-agent workflows.
Persistent docs and memory for AI agents — read, write, organize & search a shared workspace.
One shared brain for your AI coding agents: team memory, agent Q&A, tasks, and file claims.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/beydemirfurkan/todox'
If you have feedback or need assistance with the MCP directory API, please join our Discord server