wraft-mcp
# wraft-mcp
[](https://www.npmjs.com/package/wraft-mcp)
[](https://github.com/salsabeeljamal/wraft-mcp/actions/workflows/ci.yml)
[](LICENSE.md)
The mcp server for [Wraft](https://wraft.co), the open-source document lifecycle platform. It gives Cursor, Claude Code, Claude Desktop, and any other MCP client a curated tool set for running the document lifecycle end to end:
- **Scaffold the pipeline** — create themes, layouts, approval flows, and content types (variants) with their fillable fields
- **Author templates** — write a document body in markdown; `[Field Name]` placeholders become fillable fields
- **Produce documents** — fill a template with values, build the PDF, and move the document through its approval flow
- **Automate** — wire adaptor steps (build document, email, HTTP, conditions) into workflow DAGs with conditional edges
One shared tool set, two ways to run it:
- **stdio** (`wraft-mcp`) — your MCP client spawns the server locally; auth via env vars
- **Streamable HTTP** (`wraft-mcp-http`) — a hosted, stateless service at `/mcp`; auth via per-request `x-api-key` header
## Setup
**Local (stdio)** — recommended for individuals. Add to your MCP client config:
```json
{
"mcpServers": {
"wraft": {
"command": "npx",
"args": ["-y", "wraft-mcp@0"],
"env": {
"WRAFT_BASE_URL": "https://app.your-wraft.example",
"WRAFT_API_KEY": "wraft_..."
}
}
}
}
```
**Remote (hosted HTTP)**:
```json
{
"mcpServers": {
"wraft": {
"url": "https://mcp.your-domain.example/mcp",
"headers": { "x-api-key": "wraft_..." }
}
}
}
```
**Client timeouts:** `build_document` can run up to 120 s. Raise your MCP client's tool-call timeout accordingly (Cursor: `"timeout"` per server entry) or builds will appear to fail while still completing server-side.
During development (before npm publish): `"command": "node", "args": ["/ABS/PATH/wraft-mcp/dist/index.cjs"]`.
## Tools
### Documents
| Tool | What it does |
|------|--------------|
| `list_documents` / `get_document` | Documents in the organisation |
| `create_document_from_template` | **Preferred create path**: fills a template's placeholders from a field-values map and creates the document |
| `create_document` | Raw-payload create (escape hatch) |
| `update_document` | Update content (creates a version) |
| `build_document` | Generate the PDF (synchronous, up to ~2 min) |
| `transition_document_state` | Move a document through its approval flow |
| `list_data_templates` / `get_data_template` | Pre-authored templates with fillable fields |
| `create_data_template` | Author a template from markdown — `[Field Name]` placeholders become fillable holder fields (must match the content type's fields) |
### Scaffolding
| Tool | What it does |
|------|--------------|
| `list_content_types` | Content types (document variants) with their fields |
| `create_content_type` | Create a variant with fields, wired to a layout, flow, and theme |
| `list_field_types` | Field types (String, Text, Date, …) for `create_content_type` fields |
| `list_flows` / `get_flow` / `list_flow_states` | Approval flows and their states |
| `create_flow` | Create a flow (default Draft → Publish states; custom states/approvers need the Wraft UI) |
| `list_themes` / `create_theme` | Themes: font + colors (font-file assets must pre-exist; pass ids) |
| `list_layouts` / `list_engines` / `create_layout` | Layouts: engine, page-template slug (`pletter` / `contract` / `gantt_chart`), dimensions (no letterhead upload via MCP) |
| `list_assets` | Uploaded assets by type (theme fonts, layout letterheads) — source of ids for `create_theme` |
| `list_workflows` / `get_workflow` | Automation workflows (DAGs of adaptor steps) and their full structure |
| `create_workflow` | Create a workflow: steps (adaptor + config, referenced by key) connected by edges; triggers need the Wraft UI |
| `execute_workflow` | Run a workflow with trigger data and get per-step results (synchronous) |
| `list_workflow_runs` / `get_workflow_run` | Run history and per-step results of a run |
| `whoami` | Verify the key: user, email, organisation, roles |
### Notes for agents
- **Pagination:** `list_*` tools accept `page` and return `page_number` / `total_pages` / `total_entries` — paginate before concluding something doesn't exist. Exceptions: `list_flow_states` and `list_field_types` return plain arrays.
- **Field machine names:** `create_document_from_template` takes `fields` keyed by machine name — the field's name lowercased, apostrophes stripped, spaces → `_`, other characters removed (`"Client Name"` → `client_name`). Get field names from `get_data_template` (under `content_type.fields`).
- **Writes are not idempotent:** a timed-out `create_*` or `build_document` call may still have completed. **List or fetch before retrying** — a blind retry creates a duplicate.
- **No update/delete for scaffolding:** themes, layouts, flows, content types, and workflows can be created but not modified or removed via MCP — clean up mistakes in the Wraft web UI. Workflow triggers also need the UI (execution is available via `execute_workflow`).
## API keys
- **Keys are unscoped.** A Wraft API key carries its owner's full role permissions — the curated tool list limits what the *agent* can reach, not what the *credential* could do elsewhere. Create a dedicated least-privilege user for MCP keys.
- **IP-whitelisted keys don't work via the hosted server.** Wraft sees the MCP server's IP, not yours, so whitelisted keys get `403 ip_not_whitelisted`. Use a key without an IP whitelist for hosted access, or run stdio from an allowed machine. Do **not** whitelist the MCP server's egress IP — that nullifies the control for everyone behind the proxy.
- Keys are never logged by this server; redaction of `x-api-key` / `authorization` must also be configured in any logging/APM middleware added around it.
## Hosted deployment
See [`deploy/README.md`](deploy/README.md) — Docker image, env reference, ready-made compose + nginx edge, and the hosting checklist.
## Development
```
npm install
npm test # unit tests
npm run typecheck
npm run build # dist/index.cjs (stdio) + dist/http.cjs (HTTP)
# live smoke against a running Wraft (runs whoami by default; exits non-zero on tool errors):
WRAFT_BASE_URL=http://localhost:4000 WRAFT_API_KEY=wraft_... npm run smoke
# or pass tool calls:
node scripts/smoke.mjs dist/index.cjs '{"name":"list_flows","arguments":{}}'
# optional pre-push gate (typecheck + tests + build before every push):
git config core.hooksPath .githooks
```
## License
AGPL-3.0-only — see [LICENSE.md](LICENSE.md).
TDQS
Scored across 15 tools
Most tools target distinct resources and actions (documents, templates, flows, content types), with clear verb-prefixed names. The main potential confusion is between create_document_from_template and create_document, and between get_flow and list_flow_states, but the descriptions clarify their respective purposes well.
The majority follow a consistent verb_noun pattern: get_, list_, create_, update_, build_, transition_. The only outlier is 'whoami', a common utility convention, so it doesn't disrupt overall readability.
With 15 tools, the server sits at the upper end of the ideal range but every tool serves a distinct necessary function for document management, template authoring, and approval flows. No redundant or superfluous tools are present.
Core document lifecycle is covered: create (two ways), read, update, build PDF, and transition states. Missing delete operations for documents/templates and an update for data templates are minor gaps that agents can work around, but they don't prevent primary workflows.