workflowy-mcp
Allows AI-powered operations like proposing edits and smart search via any OpenAI-compatible chat-completions API, including OpenAI's own models.
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., "@workflowy-mcpsearch for weekly review"
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.
wf — WorkFlowy CLI
╦ ╦╔═╗╦═╗╦╔═╔═╗╦ ╔═╗╦ ╦╦ ╦
║║║║ ║╠╦╝╠╩╗╠╣ ║ ║ ║║║║╚╦╝
╚╩╝╚═╝╩╚═╩ ╩╚ ╩═╝╚═╝╚╩╝ ╩wf is the WorkFlowy command-line and agent toolkit: a local-first CLI, cache, automation layer, and MCP server that lets humans, scripts, and AI agents safely read, search, organize, and edit a WorkFlowy account.
Install in one command
macOS and Linux
Copy and paste this into your terminal:
curl -fsSL https://github.com/rodolfo-terriquez/workflowy-cli/releases/latest/download/install.sh | bashWindows PowerShell
Copy and paste this into PowerShell:
irm https://github.com/rodolfo-terriquez/workflowy-cli/releases/latest/download/install.ps1 | iexThen connect your WorkFlowy account:
wf login
wf cache:sync
wf doctorThe interactive login prompt hides the key. For automation, pipe it over stdin instead of placing it in shell history:
printf %s "$WORKFLOWY_API_KEY" | wf login --stdinThat’s it. The installer auto-detects your OS and CPU architecture, downloads the latest prebuilt binary, installs wf, and adds it to your PATH when possible.
This project is WorkFlowy-native:
everything is a node in a single tree
@targetsare WorkFlowy bookmarks or built-in locationsreads are cache-first through local SQLite
writes go through the WorkFlowy APIs
agent mode returns machine-readable JSON and structured errors
Related MCP server: WorkFlowy MCP Server
Status
Current version: 3.3.0
Implemented today:
cache-first reads, search, path lookup, and subtree context
smart search with FTS, fuzzy fallback, and optional AI reranking
todos, tags, history, templates, bulk operations
REPL shell, shell completions, clipboard copy support, command aliases
multi-account config
watch daemon, webhooks, workflows, MCP server
compiled binary build via Bun
Install details
To install a specific version or custom location:
curl -fsSL https://github.com/rodolfo-terriquez/workflowy-cli/releases/latest/download/install.sh | \
WF_VERSION=v3.3.0 WF_INSTALL_DIR="$HOME/.local/bin" bashBuild from source
Requires Bun.
git clone https://github.com/rodolfo-terriquez/workflowy-cli.git
cd workflowy-cli
bun install
bun run buildThat produces a standalone binary at dist/wf.
If you installed wf from this git checkout, you can update it later with:
wf self:updateYou can also run it directly from source:
bun run cli/wf.ts --helpQuick Start
# authenticate
wf login
# sync the local cache
wf cache:sync
# inspect your tree
wf node:read @inbox
wf search "campaign"
wf targetsQuick Demos
wf login
wf cache:sync
wf search "weekly review"
wf node:read @inbox --depth 2
wf node:add @inbox "Follow up with Jane" --type todo
wf ai:propose "Clean up my inbox and group related items"
wf ai:preview
wf ai:apply
wf mcpFor agent workflows:
wf search "project roadmap" --agent
wf node:read @today --depth 3 --agent
wf doc:edit @inbox < nested-outline.json --agentCommand Surface
Node commands
wf node:read [target]
wf node:add <target> <text>
wf node:move <node> <target>
wf node:complete <node>
wf node:update <node>
wf node:delete <node>
wf node:find <path-or-name>
wf node:context <target>
wf node:todos
wf node:bulk complete|delete|move
wf node:template list|save|apply|delete
wf node:export <target>
wf doc:edit <root> < ops.jsonTop-level commands
wf search <query>
wf tags
wf targets
wf history
wf batch
wf doc:edit <root> < ops.json
wf mcp
wf completions install
wf doctor
wf login
wf self:updateCache, AI, automation, and account commands
wf cache:sync
wf cache:diff
wf ai:propose <instruction>
wf ai:preview [id]
wf ai:apply [id]
wf ai:reject [id]
wf ai:list
wf watch:start
wf watch:stop
wf watch:status
wf webhook:create
wf webhook:list
wf webhook:delete <id>
wf webhook:test <id>
wf workflow:list
wf workflow:create <name>
wf workflow:run <name>
wf config:get <key>
wf config:set <key> <value>
wf config:alias set|list|remove
wf account:list
wf account:switch <name>
wf account:currentCommon Usage
Read and navigate
wf node:read @today --depth 4
wf node:read "@inbox/Projects" --live
wf node:find "campaign 94"
wf node:context @today
wf node:export @today --format markdownSearch
wf search "campaign"
wf search "campain 94"
wf search "pricing bug" --smart
wf search "launch" --target "@inbox/Projects"
wf search "q2" --format jsonSearch behavior:
tier 1: SQLite FTS
tier 2: fuzzy fallback
tier 3: optional AI reranking with
--smart
Todos, tags, and history
wf node:todos --target @today
wf node:todos --completed --since 7d
wf tags --target @today
wf history --limit 50Write operations
wf node:add @inbox "Draft Q3 plan" --type todo
wf node:move "@today/Fix release notes" @inbox
wf node:complete "@inbox/Follow up with vendor"
wf node:update "@inbox/Follow up with vendor" --text "Follow up with billing vendor" --note "Waiting on response"
wf node:delete "Old scratch item"Templates and bulk operations
wf node:template save standup --from @today
wf node:template apply standup --to @inbox
wf node:bulk complete --filter "type:todo completed:false" --target @today
wf node:bulk move --filter "tag:#archive" --to @inbox --dry-runNested outline edits
WorkFlowy is an outline, so content that has sections, subpoints, or related bullets should usually be written as child nodes, not packed into notes. Use notes for metadata or true note fields. For nested outline content, prefer doc:edit with nested c children; it creates the whole shape in one API call and maps directly to the MCP edit_doc tool.
Use batch for flat grouped operations such as several independent adds, moves, completes, or deletes. batch converts Markdown-style text to WorkFlowy rich text, but it does not expand indented markdown into child bullets.
cat > nested-outline.json <<'JSON'
[
{
"op": "insert",
"under": "@inbox",
"items": [
{
"n": "Project brief",
"l": "h2",
"c": [
{
"n": "Draft outline",
"c": [
{ "n": "Problem" },
{ "n": "Proposed approach" },
{ "n": "Open questions" }
]
},
{
"n": "Source links",
"c": [
{ "n": "https://workflowy.com" }
]
}
]
}
],
"position": "top"
}
]
JSON
wf doc:edit @inbox < nested-outline.json
wf doc:edit @inbox < nested-outline.json --agentdoc:edit also supports insert-after, richer line types, layout changes, updates, moves, and deletes.
Batch mode
wf batch reads a JSON array from stdin and executes grouped operations.
echo '[
{"op":"add","text":"Item 1","to":"@inbox"},
{"op":"complete","ref":"abc123def456"},
{"op":"move","ref":"def456abc123","to":"@today"}
]' | wf batchTargets and Paths
Commands that accept a target support:
built-in locations like
@inbox,@today,@tomorrow,@calendar,@next-weekuser bookmarks returned by
wf targetsraw node IDs
path traversal such as
@today/Meetings/Launch review
Examples:
wf node:read "@today/Meetings"
wf node:complete "@inbox/Buy groceries"
wf node:move "@today/Fix bug" @inboxCache Model
wf cache:sync stores a local SQLite copy of your tree and powers fast reads.
wf cache:sync
wf cache:sync --status
wf cache:sync --watch
wf cache:sync --stop
wf cache:diff --since 30mMost read commands use the cache automatically. node:read and search can bypass it with --live.
Rate Limiting
wf now self-throttles WorkFlowy API traffic by default:
45requests per minute across normal API calls65seconds minimum between fullnodes-exportcalls such aswf cache:syncandwf watch:start
You can adjust those defaults if needed:
wf config:get api.rateLimit.requestsPerMinute
wf config:get api.rateLimit.exportMinIntervalSeconds
wf config:set api.rateLimit.requestsPerMinute 50
wf config:set api.rateLimit.exportMinIntervalSeconds 70REPL, Completions, and Clipboard
Run wf with no arguments to enter the interactive shell.
Features:
command history
tab completion for commands,
@targets, and common flagsalias expansion
wf
wf> node:read @today
wf> search "campaign"
wf> exitShell completions:
wf completions install
wf completions install --shell zsh
wf completions install --shell fishGit-based install update:
wf self:update
wf self:update --checkMany output commands also support --copy:
wf node:read @today --copy
wf search "launch" --copy
wf tags --copyAI Commands
ai:propose generates a structured proposal using an LLM. Review it, then apply or reject it.
wf ai:propose "move uncompleted todos from @today to @tomorrow"
wf ai:list
wf ai:preview
wf ai:apply
wf ai:rejectLLM config:
printf %s "$OPENROUTER_API_KEY" | wf config:set llm.apiKey --stdin
wf config:set llm.model google/gemini-flash-2.5Other providers:
# Any OpenAI-compatible chat-completions provider
wf config:set llm.provider openai-compatible
wf config:set llm.baseUrl https://api.openai.com/v1
printf %s "$PROVIDER_API_KEY" | wf config:set llm.apiKey --stdin
wf config:set llm.model <model-id>
# Anthropic Messages API
wf config:set llm.provider anthropic
printf %s "$ANTHROPIC_API_KEY" | wf config:set llm.apiKey --stdin
wf config:set llm.model <claude-model-id>Automation and Integration
Watch daemon
wf watch:start --interval 2m
wf watch:status
wf watch:stopwatch:start streams newline-delimited JSON events when running non-interactively. Its interval must be at least the configured export minimum, which defaults to 65s.
Webhooks
wf webhook:create --url https://example.com/hook --filter "tag:#urgent"
wf webhook:list
wf webhook:test <id>Workflows
Workflows are YAML files stored under ~/.workflowy/workflows/.
wf workflow:create daily-review
wf workflow:list
wf workflow:run daily-reviewMCP server
wf mcp
wf mcp --port 3399wf mcp supports stdio transport by default and loopback-only Streamable HTTP at /mcp when --port is provided, with the legacy SSE endpoints retained for compatibility. HTTP mode binds to 127.0.0.1; set WORKFLOWY_MCP_AUTH_TOKEN to require Authorization: Bearer <token> on every HTTP request. --tools is enforced for both discovery and direct tool calls.
MCP client config example:
{
"mcpServers": {
"workflowy": {
"command": "/absolute/path/to/wf",
"args": ["mcp"]
}
}
}Run wf login and wf cache:sync first. The MCP server uses the same local config and cache as the CLI.
Start an account-pinned server with wf --account work mcp, or pass the optional account field on any MCP tool call to select a configured account per operation. This allows one agent session to read from one account and write to another while each account keeps its own cache.
MCP exposes friendly tools for common tasks (read, search, add, batch) plus edit_doc for structured nested outline edits. Prefer edit_doc when writing sections, subpoints, or multi-bullet content; use batch for flat grouped changes. edit_doc maps back to the CLI doc:edit command, so the CLI remains the canonical implementation.
MCP instructions
wf mcp always sends built-in bootstrap instructions during MCP initialize so agents know how to use the server well. On first MCP use for an account, it will also try a best-effort cache warmup when the active account has no usable cache yet, or when a configured instructions node cannot be resolved from cache.
For clickable WorkFlowy date chips, agents must use literal time tags in node text or notes, for example <time startYear="2026" startMonth="6" startDay="3">Jun 3, 2026</time>. startYear must be 4 digits; startMonth and startDay must be numeric without leading zeroes. Plain-text dates will not render as chips.
You can also append your own custom instructions from a WorkFlowy node or subtree:
wf config:set mcp.instructionsNode "@inbox/Agent instructions"
# or use a stable node id instead of a path
wf config:set mcp.instructionsNode <node-id>Those instructions are loaded from the local cache when the MCP session starts, so run wf cache:sync after editing that subtree if you want the latest content reflected in new MCP sessions.
Agent Mode
Use --agent for JSON output. Agent mode is also enabled when:
WF_AGENT=1CI=trueTERM=dumb
Examples:
wf node:read @inbox --agent
wf search "campaign" --agent
wf node:todos --agentTypical response shapes:
Read-oriented output
{
"meta": {
"command": "node:read",
"wf_version": "3.3.0"
},
"node": {},
"children": []
}List/query output
{
"meta": {
"command": "search",
"wf_version": "3.3.0"
},
"nodes": []
}Write/status output
{
"meta": {
"command": "node:add",
"wf_version": "3.3.0"
},
"message": "..."
}Errors
{
"error": {
"code": "node_not_found",
"message": "Node not found",
"hint": "Run `wf cache:sync` first."
}
}Configuration
Config is stored under ~/.workflowy/config.json. On Unix-like systems, wf keeps the directory private (0700) and the config file, which may contain API keys, at 0600. Sensitive values are redacted by config:get unless --show-secret is explicitly provided.
Common keys:
wf config:get llm.provider
wf config:get llm.model
wf config:set llm.provider openrouter
wf config:set llm.model google/gemini-flash-2.5
printf %s "$LLM_API_KEY" | wf config:set llm.apiKey --stdin
wf config:set llm.baseUrl <openai-compatible-base-url>Aliases:
wf config:alias set today-todos "node:todos --target @today"
wf config:alias list
wf config:alias remove today-todosAccounts:
wf login --account personal
wf login --account work
wf account:list
wf account:switch work
wf account:currentEach account keeps its own SQLite cache under ~/.workflowy/db/accounts/. Switching accounts no longer discards another account's synced tree or requires an immediate re-sync.
Use --account <name> to select an account for one command without changing the configured default:
wf --account personal cache:sync
wf --account work cache:sync
wf cache:sync --all-accounts
wf --account personal read @projects --format json
wf --account work add @inbox "Follow up from personal account"This makes cross-account automations explicit: read from one retained cache, then write with the destination account's token. Account-qualified sync and watch daemons also use separate PID files, so multiple accounts can stay warm concurrently.
Development
bun install
bun run typecheck
bun run release:check
bun test
bun run build
bun run smokeHelpful local checks:
./dist/wf --help
./dist/wf self:update --check
./dist/wf doctor
./dist/wf cache:sync --status --agentCI runs those core checks on Linux, macOS, and Windows on push and pull request.
Release steps are documented in RELEASE.md.
License
MIT
Project Layout
cli/
wf.ts entry point and command registration
agent.ts agent-mode detection
targets.ts @target resolution
commands/ command implementations
shared/ cache, config, clipboard, history, REPL, API helpers
output/ JSON and outline formatters
dist/
wf compiled binary after bun run buildThis 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.
Latest Blog Posts
- 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/gijs-epping/workflowy-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server