@takazudo/zudotext-mcp
v0.1.1
Published
stdio MCP server exposing zudo-text documents, history, changes, assets, and agent workflows
Maintainers
Readme
@takazudo/zudotext-mcp
A stdio Model Context Protocol server for working with an encrypted zudo-text cloud workspace from Claude Code or another MCP client. It exposes direct document operations, document history and changes, a deliberately narrow asset surface, and the zudo-text cloud agent.
Install
The package is public on the npm registry. Its source repository remains private. Node.js 22.19 or newer is required.
ZUDOTEXT_MCP_VERSION=0.1.1
npm install --global "@takazudo/zudotext-mcp@${ZUDOTEXT_MCP_VERSION}"
zudotext-mcp --versionThe verification command must print the version you installed.
Install the official authoring skill
The npm package ships separate, behaviorally equivalent skill artifacts for Claude Code and Codex. Install the one for each harness you use:
zudotext-mcp-install-skill --harness claude-code
zudotext-mcp-install-skill --harness codexThe default user destinations are
$CLAUDE_CONFIG_DIR/skills/zudotext-authoring/SKILL.md (falling back to
~/.claude/skills/) and
$HOME/.agents/skills/zudotext-authoring/SKILL.md for Codex. For a
repository-local install, pass its absolute root; Claude Code uses
.claude/skills/ and Codex uses the officially discovered .agents/skills/:
zudotext-mcp-install-skill --harness claude-code --project "$PWD"
zudotext-mcp-install-skill --harness codex --project "$PWD"The skill version is the containing MCP package version. To update, install the new npm package version first, then replace and verify each artifact explicitly:
zudotext-mcp-install-skill --harness claude-code --update
zudotext-mcp-install-skill --harness claude-code --check
zudotext-mcp-install-skill --harness codex --update
zudotext-mcp-install-skill --harness codex --checkWithout --update, an existing skill is never overwritten. --check is
read-only and fails when the installed artifact differs from the current
package. Claude Code may explicitly invoke /zudotext-authoring; Codex uses
$zudotext-authoring or its /skills selector. This invocation and discovery
syntax is the only intentional harness divergence; the authoring policy is
otherwise equivalent.
The destructive defaults are intentionally owner-editable in the installed
SKILL.md. Such edits make --check fail, and --update replaces them with
the packaged policy. Before updating, back up intentional customizations, run
--update, then reapply the customizations and retain the expected
post-customization --check mismatch (or restore the packaged file for an
exact successful check).
These are external-agent skills. Do not copy them into
.zudotext/skills/, which is zudo-text's separate in-app inline-AI namespace
and does not load nested SKILL.md artifacts.
Add it to Claude Code or Codex
After installing the npm package globally:
claude mcp add zudotext \
--env ZUDOTEXT_SERVER_URL=https://your-sync-server.example.com \
--env ZUDOTEXT_PAT=your_personal_access_token \
--env ZUDOTEXT_WORKSPACE_ID=your-workspace-id \
--env ZUDOTEXT_WORKSPACE_PASSWORD_FILE=$HOME/.config/zudotext/workspace-password \
-- zudotext-mcpThen start Claude Code and ask it to call list_notes or another tool below.
Codex uses the same environment contract:
codex mcp add zudotext \
--env ZUDOTEXT_SERVER_URL=https://your-sync-server.example.com \
--env ZUDOTEXT_PAT=your_personal_access_token \
--env ZUDOTEXT_WORKSPACE_ID=your-workspace-id \
--env ZUDOTEXT_WORKSPACE_PASSWORD_FILE=$HOME/.config/zudotext/workspace-password \
-- zudotext-mcpThen run codex mcp list and ask Codex to call list_notes.
Configuration
All configuration is supplied through environment variables.
| Variable | Required | Meaning |
| --- | --- | --- |
| ZUDOTEXT_SERVER_URL | yes | Sync server origin, such as https://sync.example.com. |
| ZUDOTEXT_PAT | yes | Personal access token. See Minting a token. |
| ZUDOTEXT_WORKSPACE_ID | yes | Workspace exposed by this process. |
| ZUDOTEXT_WORKSPACE_PASSWORD | one password source | Password inline. |
| ZUDOTEXT_WORKSPACE_PASSWORD_FILE | one password source | Path to a file containing the password. |
| neither password variable | one password source | Prompt once on the controlling terminal, without echo. |
| ZUDOTEXT_WORKSPACE_SALT | no | Encryption salt in hex. This is a debugging override; workspace metadata normally supplies it. |
| ZUDOTEXT_AGENT_URL | no | Agent server origin for ask_zudo_agent; defaults to the operator-run agent server. |
| ZUDOTEXT_MCP_LOG_LEVEL | no | debug, info, warn, error, or silent; default info. Logs use stderr. |
Choosing a password source
ZUDOTEXT_WORKSPACE_PASSWORD_FILEis the recommended default for an MCP client that spawns this server. Protect the file with permissions such aschmod 600.ZUDOTEXT_WORKSPACE_PASSWORDis simpler but is visible to anything that can read the process environment, and MCP configuration is sometimes synced or committed.- The interactive prompt is the most private and least convenient. It reads from
/dev/tty, not stdin, because stdin is the MCP protocol channel. It therefore requires a controlling terminal.
The process never writes the password to disk.
Minting a token
Create a personal access token under Settings → Access Tokens in zudo-text, bind it to the configured workspace, and set an expiry. Grant only the families you intend to use:
| Scope | Tools it enables |
| --- | --- |
| documents:read | Document list/read/search, changes, versions, checkpoints, summaries, and restore manifests. |
| documents:write | Document create/update, stash, delete, move, authoring checkpoints, and version restore. |
| assets:read | Asset listing, usage, and download. |
| assets:write | Asset upload and empty-folder creation. |
| agent:invoke | ask_zudo_agent. |
For the complete direct document and asset inventory, use documents:read, documents:write, assets:read, and assets:write; add agent:invoke only when needed. A full token is not required. Workspace metadata, including the encryption salt, accepts documents:read, documents:write, agent:invoke, assets:read, or full. An asset-only token therefore needs assets:read to derive its local asset keys; assets:write alone is insufficient.
Tools
Documents and changes
| Tool | Kind | Contract |
| --- | --- | --- |
| list_notes(prefix?, limit?, cursor?) | read | Lists paths and current versions, with pagination. |
| read_note(path, maxBytes?) | read | Reads a UTF-8 window and current version. Default 1 MiB; maximum 8 MiB; truncation is explicit. |
| search_notes(query, mode?, prefix?, limit?) | read | Regex search in files, content, or count mode. |
| write_note(path, content, expectedVersion?, idempotencyKey?) | write | Creates when the version is omitted or replaces one current version optimistically. |
| stash_log(project, title, content) | write | Creates a dated, collision-safe Markdown work log under logs/. |
| delete_note(path, expectedVersion, idempotencyKey?) | destructive | Soft-deletes the live path while retaining its tombstone and version history. |
| move_note(fromPath, toPath, expectedVersion, idempotencyKey?) | destructive | Atomically moves the stable document identity and preserves history. |
| what_changed(afterCursor?, limit?) | read | Lists ordered document updates/deletions after a document cursor. |
what_changed maintains an implicit cursor only for the current MCP process. Successful implicit calls advance it; explicit afterCursor calls do not. The implicit cursor resets to zero when the process restarts.
Authoring sessions and document history
| Tool | Kind | Contract |
| --- | --- | --- |
| begin_authoring_session(label) | create | Creates the explicit document checkpoint that marks an agent's undo boundary. |
| list_note_versions(path) | read | Lists stored versions of the stable document currently at a path. |
| read_note_version(path, versionId) | read | Reads one complete historical document version. |
| restore_note_version(path, versionId, expectedVersion, idempotencyKey) | destructive | Restores one historical version as a new head with an optimistic precondition. |
| list_checkpoints() | read | Lists named document change-log cursors. |
| get_checkpoint_summary(checkpointId, fromCursor?) | read | Projects document changes ending at a checkpoint. |
| get_checkpoint_restore_manifest(checkpointId) | read | Returns the document work order for a client-orchestrated rollback. |
Call begin_authoring_session before the first document write when you need an undo boundary. A checkpoint is a change-log marker, not a workspace snapshot. Per-file version restore is server-backed; there is no one-call or atomic workspace rollback. A rollback client must read the restore manifest, verify its expected head cursor, apply its restore/delete/noop work, treat a same-fileId old-path restore plus new-path delete as a move-back, stop on conflicts, and report possible partial progress. Compacted projections remain distinguishable as HISTORY_COMPACTED.
Checkpoints, versions, restore manifests, summaries, and what_changed cover documents only. Assets are not included.
Assets
| Tool | Kind | Contract |
| --- | --- | --- |
| list_assets() | read | Lists decrypted asset paths, sizes, and modification times. |
| get_asset_usage() | read | Reports plan, quota, used/add-on bytes, and soft-lock status. |
| download_asset(path, destinationPath) | local write | Decrypts into a new absolute local file; an existing destination is never overwritten. |
| upload_asset(sourcePath, path, idempotencyKey) | create | Encrypts and creates an asset from a regular, non-symlink local file up to 25 MiB. |
| create_asset_folder(path, idempotencyKey) | create | Creates empty encrypted-folder markers without replacing an existing path. |
Asset bytes never appear in MCP tool content or structured results. Transfers use explicit local paths; failed downloads remove only the partial file they exclusively created.
The narrow asset family has no move, rename, delete, recursive delete, replace, or delete-and-recreate tool. Those irreversible operations stay on the interactive/full surface because assets have no revision history or undo, and callers must not emulate them. Document moves do not rewrite asset references.
Cloud agent
| Tool | Kind | Contract |
| --- | --- | --- |
| ask_zudo_agent(message, conversationId?) | agent | Delegates semantic, open-ended, or multi-step work to the zudo-text assistant. |
Prefer direct tools when the path and operation are already known. The cloud agent costs an LLM call, uses a shared daily quota, and is less deterministic. Calls without conversationId share one process-local default conversation; passing an id pins a specific thread. The result includes exact structured tool activity and validated edit previews. An edit preview is not automatically applied: review it and use write_note with its baseVersion as expectedVersion.
ask_zudo_agent requires agent:invoke and reuses the same server-side document key session as the direct document tools.
Concurrency and retries
Document writes use optimistic concurrency. Omit expectedVersion only to create a new path; an existing path fails with VERSION_CONFLICT. For updates, deletes, moves, and restores, first read the current version and pass it. A conflict writes nothing and preserves the server's structured current-version details.
Idempotency is operation-specific:
write_note,delete_note, andmove_noteaccept an optional key. If omitted, the client generates one for that request and preserves it across its internal key-session retry. Supply and reuse your own stable key when retrying the same MCP-level operation.restore_note_version,upload_asset, andcreate_asset_folderrequire a caller-stable key. Reuse it only for an exact retry; reusing it with a different payload is a conflict.stash_logavoids overwrites by selecting the next free dated filename.begin_authoring_sessionandask_zudo_agentare not idempotent operations.
Security model
- Document keys use a bounded server session. When a document or cloud-agent operation first needs it, this package derives workspace keys locally with PBKDF2-SHA-256 at 600,000 iterations and sends transient raw key material to the sync server's key-session endpoint. The server holds it in memory for at most one hour and does not persist it. Expired sessions are re-derived and reopened. MCP close, transport close,
SIGINT, andSIGTERMall trigger one best-effort asynchronous session deletion before process exit. - Asset plaintext stays local. Asset operations derive non-extractable local keys. The opaque
/api/assetsroutes receive encrypted path tokens and encrypted blobs, never plaintext asset names or bytes. An asset-only process does not need a document key session. - Credentials remain local. Protect the PAT, password, password file, and MCP config as you would an SSH key. Workspace binding prevents a bound PAT from being redirected to another workspace.
- Logs are protocol-safe and redacted. Logs use stderr only. Known credentials, transient key material in failures, and key-session handles are redacted; stdout is reserved for MCP framing.
Verification status
The package tests exercise every registered family against in-process fake transports, including schemas/annotations, document concurrency and history compaction errors, key-session recovery and teardown, change cursors, asset crypto/quota/filesystem safety, cloud-agent conversations/edit previews, and secret redaction.
Release verification performs a clean build, npm pack, temporary-prefix install, installed zudotext-mcp --version, and installed 21-tool inventory smoke. It rejects unintended tarball files and unresolved private @takazudo/* JavaScript or declaration imports.
A live end-to-end run against deployed sync and agent servers is not part of this package test suite. Operators should verify their own URLs, token scopes, workspace binding, and representative document/asset/agent calls before relying on it for unattended work.
Testing and maintenance
When adding or changing an MCP tool, follow the verbatim tool-change checklist and the MCP lanes. The live verification runbook contains the credentialed command, config, residue-journal, and empty-ledger contracts; dated manager evidence is archived on the linked tracking issues rather than kept in this runbook.
Development and release
pnpm --filter @takazudo/zudotext-mcp test
pnpm --filter @takazudo/zudotext-mcp typecheck
pnpm --filter @takazudo/zudotext-mcp build
pnpm --dir packages/zudotext-mcp release:verify -- --expected-tag zudotext-mcp-v0.1.1See RELEASING.md for npm bootstrap, trusted publishing, and
GitHub Release mirroring. @takazudo/cloud-crypto and
@takazudo/file-utils remain private devDependencies and are inlined into the
distributable JavaScript by tsup.
License
MIT
