The most complete Dify MCP server + CLI — 192 tools that let any AI agent build, test & ship Dify workflows autonomously.
Overview
Let any AI agent build, test, and ship Dify workflows autonomously — everything a human can do in the UI, now scriptable. Works with — Claude Code, Codex, Gemini CLI, Cursor, Cline, Windsurf, Roo Code, Continue, Zed, Aider, OpenCode, Antigravity, GitHub Copilot, Goose, Trae, Kilo Code, Warp, Crush, Droid, Amp, OpenHands, Cody, Augment, and Amazon Q Developer — plus any other MCP-compatible or shell-capable agent. Dify is a powerful open-source LLM app platform — but its workflow builder is a . What if you want an AI agent to programmatically create workflows, wire up nodes, test them, iterate, and publish — without a browser? is the bridge. It exposes the as a unified tool registry with : a CLI any shell-capable agent can drive, and an MCP server (stdio or Streamable HTTP) any MCP-compatible host can attach. Same 192 tools, same JSON contract, same safety guarantees. dify-mcp is agent-agnostic by design — no SDK lock-in, no proprietary protocol.
README
What is this?
Dify is a powerful open-source LLM app platform — but its workflow builder is a visual drag-and-drop editor. What if you want an AI agent to programmatically create workflows, wire up nodes, test them, iterate, and publish — without a browser?
dify-mcp is the bridge. It exposes the entire Dify console API as a unified tool registry with two surfaces: a CLI any shell-capable agent can drive, and an MCP server (stdio or Streamable HTTP) any MCP-compatible host can attach. Same 192 tools, same JSON contract, same safety guarantees.
┌──────────────────────────────────────────────────────────┐
│ dify-mcp │
│ │
│ ┌──────────┐ ┌────────────────────┐ ┌─────────┐ │
│ │ CLI │───▶│ 192-tool │───▶│ Dify │ │
│ │ difywf │ │ registry │ │ API │ │
│ └──────────┘ │ │ └─────────┘ │
│ ┌──────────┐ │ app · workflow │ ▲ │
│ │ MCP │───▶│ knowledge · rag │─────────┘ │
│ │ stdio │ │ agent · snippet │ │
│ └──────────┘ │ workspace · ... │ │
│ └────────────────────┘ │
└──────────────────────────────────────────────────────────┘
Works with your favorite agents
dify-mcp is agent-agnostic by design — no SDK lock-in, no proprietary protocol. If your agent can run a shell command, it can use the CLI. If it speaks MCP, it can attach the server. Most popular agents do both:
| Agent | MCP | CLI | Quick setup |
|---|---|---|---|
| Claude Code | ✅ | ✅ | claude mcp add dify -- difywf mcp serve |
| Codex | ✅ | ✅ | [mcp_servers.dify] in ~/.codex/config.toml |
| Gemini CLI | ✅ | ✅ | mcpServers.dify in ~/.gemini/settings.json |
| Cursor | ✅ | ✅ | .cursor/mcp.json |
| Cline | ✅ | ✅ | Same JSON shape as Cursor |
| Windsurf | ✅ | ✅ | MCP server config in Windsurf settings |
| Roo Code | ✅ | ✅ | MCP server config in Roo Code settings |
| Continue | ✅ | ✅ | experimental.mcpServer in config.json |
| Zed | ✅ | ✅ | context_servers in ~/.config/zed/settings.json |
| Aider | - | ✅ | Run difywf commands directly in chat |
| OpenCode | ✅ | ✅ | mcp.dify in opencode.json |
| Antigravity | ✅ | ✅ | Common mcpServers JSON |
| GitHub Copilot | ✅ | ✅ | servers.dify in .mcp.json |
| Goose | ✅ | ✅ | extensions.dify in config.yaml |
| Trae | ✅ | ✅ | Common mcpServers JSON |
| Kilo Code | ✅ | ✅ | Common mcpServers JSON |
| Warp | ✅ | ✅ | Common mcpServers JSON |
| Crush | ✅ | ✅ | mcp add dify --command difywf --args mcp serve |
| Droid | ✅ | ✅ | Common mcpServers JSON |
| Amp | ✅ | ✅ | Common mcpServers JSON |
| OpenHands | ✅ | ✅ | mcpServers.dify in ~/.openhands/mcp.json |
| Cody | ✅ | ✅ | Common mcpServers JSON |
| Augment | ✅ | ✅ | Common mcpServers JSON |
| Amazon Q Developer | ✅ | ✅ | Common mcpServers JSON |
Don’t see your agent? If it supports MCP or can run shell commands, it works. The connect section below has copy-paste configs for each host.
Why you’ll star this
-
Complete coverage. Not a subset. Not a wrapper around the public API alone. This talks to the internal console API — the same surface the Dify web UI uses. Create apps, author graphs node-by-node, validate, test-run, publish, manage versions, triggers, providers, plugins, RAG pipelines, snippets, agent configs, comments, annotations, audio, stats. If the UI can do it, so can your agent.
-
Agent-agnostic by design. No SDK lock-in. The CLI works with any agent that can run a shell command. The MCP server works with any MCP host. Both return structured JSON —
{ ok, data }or{ ok: false, error: { code, message, retryable } }— so agents never scrape human-readable text. For large drafts and exports, the CLI’s--output-filekeeps the full UTF-8 result off size-limited stdout transports. -
Cookie auth, handled. Dify’s console uses cookie + CSRF double-submit, not Bearer tokens. dify-mcp captures, stores (keychain on macOS, else
0600file), and auto-refreshes the session — including server-side refresh-token rotation. That same session now covers draft and published run/stop, file upload, dependency checks, and workspace switch. MCP hosts can callauth.import_cookies/auth.login_consolewithout the CLI.DIFY_CONSOLE_COOKIEand--console-cookiework for non-interactive bootstrap. -
Safe by default. Destructive operations require explicit
confirm=true/--yes. Graphs are validated offline before sync (iteration/loop sub-graphs, sticky notes, and modern multi-case if-else included). Every mutation is audit-logged.--dry-runshows diffs without saving. -
Zero build step. Runs directly on Node 23.6+ native TypeScript. No compiler, no bundler, no transpiler. Clone, install, go.
What’s new in v0.4.0
- Workspace MCP tool providers (
mcp.*). Connect external MCP servers to your Dify workspace:mcp.list,mcp.get,mcp.create,mcp.update,mcp.delete(confirm-gated), andmcp.refresh_tools. - App MCP Server access points (
app.mcp_server_*). Expose any Dify workflow/agent app as an MCP server:app.mcp_server_get,app.mcp_server_set, andapp.mcp_server_rotate(confirm-gated token regeneration). - Workspace Skills (
skill.*). Full skill lifecycle and agent skill bindings:skill.list,skill.get,skill.versions,skill.references,skill.import,skill.publish,skill.delete(confirm-gated),skill.agent_bindings, andskill.set_agent_bindings. - Dify 1.17.1 compatibility & fixes. Verified compatibility against Dify
1.17.1upstream console routes; fixed input validation ordering insnippet.import.
What’s new in v0.3.0
- Classic knowledge bases (
knowledge.*). Dataset CRUD, document create fromfile.uploadids (or full KnowledgeConfig), rename/delete, indexing status, hit-testing, and segment add/update/delete — confirm-gated where destructive. - Workspace member admin.
workspace.invite_members,workspace.update_member_role, andworkspace.remove_member(confirm-gated). - MCP progress notifications. Long SSE runs (
workflow.run_draft, chat, …) emitnotifications/progresswhen the host supplies aprogressTokenintools/call_meta. - Local backup and migration.
app.backupbulk-exports DSLs plus a manifest;app.restoredry-runs conflicts and imports to another configured Dify instance. - Explicit compatibility matrix. Dify
1.17.xand1.16.xare supported; older versions are intentionally unsupported.
What’s new in v0.2.0
- Cookie-complete authoring. Run, stop, upload, check deps, and switch workspaces with the same console session. MCP hosts authenticate without dropping to the CLI.
- Safer HTTP MCP. Binds
127.0.0.1by default. Binding0.0.0.0(Docker) requiresDIFYWF_MCP_TOKEN. Host allowlist + 2MB body cap;/healthstays open for probes. - Workflow-as-tool providers. Get, refresh, or delete the published-tool
binding after you ship a version (
workflow.tool_get/workflow.tool_refresh_provider/workflow.tool_delete). - Verified app tags.
app.ensure_tag/app.remove_tagbind or unbind an exact tag name and read it back. Confirm-gated. - Smarter graph validation. Iteration/loop inner nodes, canvas
custom-notestickies, and moderncases[]if-else branches no longer fail offline checks. - Large payloads.
--yaml @filefor DSLs that exceed OS argument limits;--output-filekeeps big results off size-limited stdout. - Starter graphs. Ready-made templates in
examples/(echo, LLM, RAG).sync_draftno longer wipes omitted env/conversation secrets.
Live verified
Authoring loop verified against cloud.dify.ai 1.17.0 with console cookie auth:
- ✅ Create app → sync draft (echo graph) → run draft → delete (MCP Streamable HTTP)
- ✅ MCP transport:
tools/callover stdio and Streamable HTTP - ✅ Example templates in
examples/validate clean (echo, LLM, RAG) - ✅ Unit tests · typecheck clean · MCP smoke (192 tools)
Dify compatibility
| dify-mcp | Dify | DSL | Graphon | Support |
|---|---|---|---|---|
| 0.4.x | 1.17.x | 0.7.0 | 0.7.0 | Supported; cloud 1.17.0 live-verified; 1.17.1 offline-verified |
| 0.3.x | 1.17.x | 0.7.0 | 0.7.0 | Supported; cloud 1.17.0 live-verified |
| 0.3.x | 1.16.x | 0.7.0 | 0.6.0 | Best-effort; not live-verified |
| <=0.3.x | <=1.15.x and 0.x | varies | varies | Unsupported; no legacy adapter |
Cloud and self-hosted Dify releases can expose different console contracts even
within a minor series. When reporting an issue, include the response header
x-version (or your deployment version), the difywf --version output, and the
exact command/tool call. DSL version drift is a hard failure
(DSL_VERSION_MISMATCH), not something the agent should edit around.
Not every one of the 192 tools is live-probed on every release. Coverage is densest on the authoring path (apps, workflow draft/run/publish, auth, MCP guardrails). Surfaces such as knowledge bases, RAG pipelines, snippets, agents, annotations, and audio are implemented against the console API contract and unit-tested; treat them as best-effort until you exercise them on your instance.
Known gaps vs the full Dify UI
Still deferred (not blocking for workflow authoring):
- External knowledge / connector-specific ingest UIs beyond the classic dataset APIs
- Fine-grained dataset permission member pickers in the UI sense (API body passthrough only)
Quickstart
Prerequisites: Node >= 23.6 (native TypeScript type stripping — no build step).
git clone https://github.com/alexjiaguo/dify-mcp.git
cd dify-mcp
npm install
npm link # puts `difywf` on your PATH (optional)
Authenticate
The Dify console uses cookie + CSRF auth. The easiest path:
# 1. Export cookies from your browser (cookie-editor extension → Export → JSON)
# 2. Save as cookies.json, then:
difywf auth import-cookies --base-url https://cloud.dify.ai --file cookies.json
# Or self-hosted with email/password (no browser needed):
difywf auth login-console --base-url https://your-dify --email you@x --password '***'
# Non-interactive bootstrap can keep credentials out of process arguments:
DIFY_CONSOLE_EMAIL=you@x DIFY_CONSOLE_PASSWORD='***' \
difywf auth login-console --base-url https://your-dify
# Deployments whose login endpoint expects the legacy encoded payload:
DIFY_CONSOLE_EMAIL=you@x DIFY_CONSOLE_PASSWORD='***' \
DIFY_CONSOLE_PASSWORD_ENCODING=base64 \
difywf auth login-console --base-url https://your-dify
difywf auth status # confirm: shows base URL + cookie names (values masked)
# Non-interactive cookie bootstrap (Cookie header or cookie-editor JSON):
# DIFY_CONSOLE_COOKIE='console_token=...; csrf_token=...; refresh_token=...' \
# difywf auth status --base-url https://cloud.dify.ai
Build a workflow
difywf agent guide # self-onboarding playbook for agents
difywf app list # see your apps
difywf app create --mode workflow --name "my-agent-workflow"
difywf wf node defaults llm # get the schema for an LLM node
difywf wf validate --graph examples/llm-workflow.json # offline: structure, refs, cycles
difywf wf draft sync --graph examples/llm-workflow.json --dry-run
difywf wf draft sync --graph examples/llm-workflow.json
difywf wf test --input query="hello" # test-run the draft
difywf app import --yaml @workflow.yml --yes # file channel for large DSLs
difywf app ensure-tag production --yes # bind + verify exact tag name
difywf wf publish --yes # ship it
difywf workflow tool refresh-provider --yes # rebind workflow-as-tool to the published version
Starter graphs live in examples/: minimal-workflow.json (echo),
llm-workflow.json (start → LLM → answer), rag-workflow.json (knowledge
retrieval). All three pass difywf wf validate with no error-level issues.
Back up and migrate
# Source instance: writes one DSL per app plus manifest.json (secrets excluded)
difywf app backup ./dify-backup
# Target instance: authenticate or set DIFY_API_BASE first, then preview
difywf app restore ./dify-backup --dry-run
# Import after reviewing name conflicts; skip is the default
difywf app restore ./dify-backup --yes
Filters are available for larger workspaces: --app-ids , --mode workflow,
--name production, and --limit 50. Backups are local files with mode 0600.
include_secret=true and overwrite=true both require --yes. Scheduled jobs,
Git, and S3-compatible storage are intentionally not bundled; use dify-dsl-pipe
when you need a dedicated backup service.
Connect your agent (MCP)
Same binary, same 192 tools. Copy-paste the config for your host:
There is no single universal MCP filename. What every host needs is the same
local stdio launch command: difywf mcp serve. The examples below show the
wrapper your host expects.
No
difywfon PATH? Use the absolute path:node /path/to/dify-mcp/bin/difywf.js mcp serve.
Tools
192 tools across 21 namespaces. Run difywf --help for the full live list, or
difywf agent guide for the agent-oriented playbook.
| Namespace | Tools | What it does |
|---|---|---|
app |
22 | List, create, update, verified tags, delete, export, bulk backup, import/restore, MCP server access points, copy, rename, convert, chat, complete |
workflow |
29 | Get/sync drafts, validate (incl. iteration/loop sub-graphs), run, publish, workflow-as-tool providers, node last-run, variables, versions, HITL, features, triggers |
mcp |
6 | List, get, create, update, delete, refresh tools for workspace MCP tool providers |
skill |
9 | Workspace skills lifecycle: list, get, versions, references, import, publish, delete, agent skill bindings |
provider |
3 | List providers, list models, set credentials |
plugin |
4 | List, get, install, uninstall plugins |
trigger |
4 | Create, enable, list, webhook triggers; run triggers |
workspace |
7 | List, get, switch workspaces; list / invite / role-update / remove members |
file |
1 | Upload files for use in runs (multipart {name, content_b64}) |
runs |
4 | List, get, node executions, export run traces |
stats |
5 | Daily conversations/terminals, token costs, app interactions, online users |
comment |
3 | List, add, resolve workflow comments |
annotation |
11 | List, add, delete, reply, settings, export, batch import, hit histories |
audio |
3 | Transcribe (STT), synthesize (TTS), list voices |
knowledge |
16 | Classic knowledge-base datasets, documents, segments, indexing status, hit-testing |
rag |
18 | Full RAG pipeline lifecycle: datasets, templates, draft, sync, run, publish, versions |
snippet |
22 | Customized snippet lifecycle: create, import, draft, sync, run, publish, versions |
agent |
17 | Agent guide, config skills/files, drive files/skills, sandbox read/upload |
explore |
2 | Run and stop installed apps |
archive |
2 | List and download workflow run archives |
auth |
4 | Status, import cookies, console login, set tokens |
Safety
| Mechanism | How it works |
|---|---|
| Confirm gates | Destructive ops (delete, publish, restore, app.restore, set_credentials, plugin install, trigger create/enable, tag bind/unbind, workflow-tool refresh/delete, …) require confirm=true / --yes. Without it: exit code 4. app.backup also gates include_secret=true and overwrite=true. Graphs with code nodes need confirm unless DIFYWF_CODE_NODES=allow. |
| Offline validation | sync_draft validates structure, variable refs, connectivity, and cycles before hitting the API — including iteration/loop inner nodes, custom-note stickies, and modern multi-case if-else. Errors abort with exit 5. Stale hashes are VALIDATION_FAILED and retryable. Omitting env vars keeps current draft values. |
| Dry-run | --dry-run on sync_draft returns a structural diff without saving; app.restore --dry-run lists imports and name conflicts without writing to Dify. |
| Private URLs | http-request nodes targeting private/loopback hosts warn (PRIVATE_URL). yaml_url imports to private hosts are rejected unless DIFYWF_ALLOW_PRIVATE_URL=1. |
| Audit log | Every action appends to ~/.difywf/audit.jsonl (nested secrets/graphs redacted, mode 0600). |
| Auto-refresh | Cookie sessions auto-refresh on 401 via the refresh-token cookie, with server-side rotation persisted. Console cookies cover run/stop/upload/deps/workspace; OpenAPI is fallback. |
| HTTP MCP lock | Streamable HTTP binds 127.0.0.1 by default. Non-loopback binds require DIFYWF_MCP_TOKEN. Host allowlist + 2MB body cap. |
| Secret store | ~/.difywf/hosts.json is 0600. On macOS, cookies/tokens prefer the OS keychain unless DIFYWF_HOME is set. |
Error/exit codes: USAGE_ERROR(2), AUTH_REQUIRED(3), CONFIRM_REQUIRED(4),
VALIDATION_FAILED(5), RBAC_DENIED(6), NOT_FOUND(7), DSL_VERSION_MISMATCH(8),
RATE_LIMITED(9), SERVER_ERROR(10), NETWORK_ERROR(11). Check error.retryable
before retrying.
Environment
See .env.example. Common knobs:
| Variable | Purpose |
|---|---|
DIFY_API_BASE |
Dify instance URL (default https://cloud.dify.ai) |
DIFY_CONSOLE_COOKIE |
Cookie header or cookie-editor JSON for non-interactive bootstrap |
DIFY_CONSOLE_EMAIL / DIFY_CONSOLE_PASSWORD |
Headless auth login-console |
DIFY_CONSOLE_PASSWORD_ENCODING |
plain (default) or base64 for legacy login payloads |
DIFYWF_HOME |
Config + audit directory (default ~/.difywf) |
DIFYWF_MCP_TRANSPORT / DIFYWF_MCP_HOST / DIFYWF_MCP_PORT / DIFYWF_MCP_TOKEN |
Streamable HTTP MCP |
DIFYWF_CODE_NODES |
confirm (default), allow, or forbid |
DIFYWF_ALLOW_PRIVATE_URL |
Set 1 to allow yaml_url imports to private hosts |
Develop
npm test # 122 unit tests
npm run typecheck # tsc --noEmit
npm run smoke:mcp # MCP stdio smoke (192 tools, JSON-RPC handshake)
npm run smoke:mcp:http # MCP Streamable HTTP smoke (stateless POST /mcp)
No build step. Source runs directly via Node’s type stripping. GitHub Actions
runs typecheck, unit tests, and both MCP smokes on every push to main.
Contributions welcome — see CONTRIBUTING.md.
License
Apache-2.0 — see LICENSE.
Install
docker run -d --name dify-mcp \Configuration
{
"mcpServers": {
"dify": {
"command": "difywf",
"args": ["mcp", "serve"]
}
}
}