MCP
threadle speaks MCP in two directions.
| Direction | What you get | Entry |
|---|---|---|
| Server | Hosts (Claude Code, Cursor, …) call your saved workflows as tools | threadle mcp |
| Client | A canvas node calls one tool on one discovered server (stdio · HTTP · SSE) | ◈ MCP tool |
Repo copy (Markdown + examples): docs/mcp.md · examples/mcp/
Run threadle mcp
Section titled “Run threadle mcp”Stdout is the MCP JSON-RPC channel. Logs go to stderr.
threadle mcpWhat each tool is
Section titled “What each tool is”| Field | Source |
|---|---|
| Name | wf_<graphId> |
| Title | Graph name |
inputSchema | Graph.params (text · int · float · bool · json) |
| Result | Concatenated ⇤ output node text |
Subgraphs are skipped. Calls run with approveAll: false. Workflows that need interactive splice (approval / live handoff) must be run in the UI, not via MCP.
Which workflows appear is controlled by Settings → MCP → publish allowlist: empty / unset = none (default). null = all saved workflows.
Seed a tool graph
Section titled “Seed a tool graph”threadle run examples/workflows/mcp-brief.jsonthreadle graphs # note the idmcp-brief is agent-free: one topic param → markdown brief → output. Ideal for first host calls.
Connect. Host .mcp.json
Section titled “Connect. Host .mcp.json”Claude Code / project .mcp.json
Section titled “Claude Code / project .mcp.json”{ "mcpServers": { "threadle": { "command": "threadle", "args": ["mcp"] } }}Cursor. .cursor/mcp.json
Section titled “Cursor. .cursor/mcp.json”Same shape. Reload MCP in the host after saving.
After curl install or npx threadle, command: "threadle" is enough. From a clone without a global binary:
{ "mcpServers": { "threadle": { "command": "npx", "args": ["tsx", "packages/server/src/cli.ts", "mcp"], "cwd": "/absolute/path/to/threadle" } }}| Variable | Effect |
|---|---|
THREADLE_CONFIG_DIR | Graphs root (default ~/.config/threadle. Windows %USERPROFILE%\.config\threadle) |
THREADLE_MCP_PROJECT_DIR | Project dir for agent CLIs inside tools (default cwd of the MCP process) |
Work. Call a workflow from the host
Section titled “Work. Call a workflow from the host”- Save a workflow with params for anything the model should fill (≔ on the canvas).
- Put at least one ⇤ output on the graph. That text is the tool result.
- Fix detached blockers (models on agents, context with a session or Library payload, …). Gates auto-approve under MCP.
- Reload MCP → ask the model to list tools → call
wf_<id>with args matching param names.
CLI equivalent of one call:
threadle run <graphId> --param topic="…" --approve-allGuards
Section titled “Guards”| Situation | Behavior |
|---|---|
Nested threadle mcp (THREADLE_MCP_DEPTH ≥ 1) | Refused |
| Same graph already on the call stack | Refused |
| Publish allowlist empty (default) | No wf_* tools until you list graph ids (or set null / * for all) |
| Publish allowlist set | Only listed graph ids become wf_* tools |
| Hard readiness errors | Tool fails with the readiness message |
Canvas. ◈ MCP tool node
Section titled “Canvas. ◈ MCP tool node”Drop MCP tool from the Nodes palette (or the wire-drop menu).
- Inspector → server (discovered locally) → tool.
- Optional arg port. Inbound text fills that argument name.
- Param fields follow the tool’s JSON Schema properties.
- Wire prompt → MCP tool → output (or into an agent) → ▶ Run.
Discovery paths
Section titled “Discovery paths”First match wins (project → threadle registry → user hosts):
| Path |
|---|
<project>/.mcp.json (walks up to the git root. Monorepo-safe) |
<project>/.cursor/mcp.json (same walk-up) |
project opencode.json (same walk-up) |
~/.config/threadle/mcp/servers.json (threadle-owned registry) |
~/.cursor/mcp.json |
~/.claude.json (mcpServers) |
~/.config/opencode/config.json / opencode.json |
~/.gemini/config/mcp_config.json (Antigravity) |
<project>/.codex/config.toml · ~/.codex/config.toml (mcp_servers) |
Transports
Section titled “Transports”| Transport | Config shape |
|---|---|
| stdio | command + optional args / env / cwd |
| streamable-http | url (optional headers). Bare url without a type defaults here |
| sse | url or serverUrl with type / transport: "sse" |
Unix sockets / WebSockets are not supported.
Example registry entry (~/.config/threadle/mcp/servers.json):
{ "mcpServers": { "docs": { "url": "https://example.com/mcp", "headers": { "Authorization": "Bearer …" } } }}Settings (Settings → MCP)
Section titled “Settings (Settings → MCP)”| Control | Effect |
|---|---|
| MCP client off/on | When off, canvas discovery and /api/mcp/call refuse |
| disable / enable per server | Hides that id from the client. The Settings list still shows it |
| publish allowlist | Graph ids for threadle mcp as wf_*. One per line or comma-separated. Empty = none. null = all |
| ⌘ registry | Opens ~/.config/threadle/mcp/ |
Environment
Section titled “Environment”Spawned stdio servers get the same allowlist as custom nodes (PATH, HOME, locale, temp dirs, …), then the server’s own env from .mcp.json. The threadle process’s secrets are not copied wholesale. Declare tokens in the config when a server needs them. HTTP/SSE remotes use optional headers instead.
Echo demo (client)
Section titled “Echo demo (client)”- Copy examples/mcp/mcp.json.echo.example into your project
.mcp.json, fixing the path toecho-server.mjs. threadle --dir <that-project>- Clone Hello MCP from examples, or MCP tool node → server
echo→ toolecho→ set arg portmessage→ run.
Child stderr from stdio servers shows in the Run log (prefixed ◈ <server>:). Stdout stays the MCP protocol channel.
Calling threadle’s own MCP from the canvas is fine. Calling it from inside a workflow that was started via threadle mcp is refused (depth guard).
API (local UI server)
Section titled “API (local UI server)”| Method | Path |
|---|---|
GET | /api/mcp/servers. Discovered list (transport, disabled, registry paths) |
GET | /api/mcp/servers/:id/tools |
POST | /api/mcp/call. { server, tool, args?, params?, projectDir? } |
Related
Section titled “Related”- CLI. Command table including
mcp - Settings. Client toggle, allowlist, server table
- Params. What becomes
inputSchema - Detached runs. Same executor + approve-all rules
- Custom nodes. Similar local-exec trust model
- Nodes overview. ◈ glyph
- Trust. Localhost + custom/MCP process model