Design MCP Server
Introduction
The Design MCP server lets AI assistants and other Model Context Protocol (MCP) clients work with Flowable Design. Through it, an assistant can browse workspaces and packages, read and edit models, validate them, and publish them using natural language, instead of working in the Design user interface.
Working through the MCP server is equivalent to working in Design itself: the same permissions, validation and versioning apply. A user can only do through the MCP server what they are allowed to do in Design.
All tools use the same keys you see in Design (workspaceKey, modelKey, and, where relevant, packageType + packageKey) rather than internal identifiers, so requests stay readable.
The Design MCP server is disabled by default and must be explicitly enabled per deployment. See Enabling the server below.
Enabling the server
The server is gated behind a single property and is off by default:
| Property | Description | Default |
|---|---|---|
flowable.design.mcp.server.enabled | Enables the Design MCP server. | false |
flowable.design.mcp.server.path | Path the MCP endpoint is exposed at, relative to the Design API (/design-api). | /mcp |
Set flowable.design.mcp.server.enabled=true to turn the server on. The endpoint is exposed under the Flowable Design API, so with the default path the full URL is:
https://<your-design-host>/design-api/mcp
If you change flowable.design.mcp.server.path, replace /mcp in the URL accordingly.
These properties are also listed under the Design properties reference.
Connecting a client
The Design MCP server is a remote MCP server that uses the Streamable HTTP transport. Once it is enabled, point your MCP client at the endpoint URL (for example https://your-host/design-api/mcp) and authenticate as described below. The server exposes the tools listed further down; your client decides when to call them.
Authentication
The MCP endpoint is protected in exactly the same way as the rest of the Flowable Design REST API. You authenticate your MCP client the same way you would authenticate any call to the Design REST API, and the permissions of the authenticated user apply: a user with read-only access cannot create or change models through the MCP server.
Two common options are:
- Bearer token: send a Flowable Design access token in an
Authorization: Bearer <token>header. This is the recommended option for AI assistants and automation. See Access Tokens for how to create one. - HTTP Basic authentication: send Design credentials in an
Authorization: Basic <base64 of user:password>header, for example using a dedicated technical user.
For the authentication mechanisms Flowable Design supports (HTTP Basic, OAuth2 / SSO and access tokens), see the Flowable Design security documentation.
Configuring your MCP client
Most MCP clients are configured with a small JSON file listing the servers to connect to. Add the Design MCP server as an HTTP server with the endpoint URL, and pass your credentials in a header. Replace the URL and token in the examples below with your own values.
To use HTTP Basic authentication instead of a token, replace the header value with Basic <base64 of user:password>.
Claude Code: add an .mcp.json file to your project root (or run the command below):
{
"mcpServers": {
"flowable-design": {
"type": "http",
"url": "https://your-host/design-api/mcp",
"headers": {
"Authorization": "Bearer <your-design-access-token>"
}
}
}
}
claude mcp add --transport http flowable-design https://your-host/design-api/mcp \
--header "Authorization: Bearer <your-design-access-token>"
Cursor: .cursor/mcp.json in your project, or ~/.cursor/mcp.json for all projects:
{
"mcpServers": {
"flowable-design": {
"url": "https://your-host/design-api/mcp",
"headers": {
"Authorization": "Bearer <your-design-access-token>"
}
}
}
}
VS Code (GitHub Copilot): .vscode/mcp.json in your project:
{
"servers": {
"flowable-design": {
"type": "http",
"url": "https://your-host/design-api/mcp",
"headers": {
"Authorization": "Bearer <your-design-access-token>"
}
}
}
}
Codex CLI: MCP servers are configured in ~/.codex/config.toml. For a remote server, Codex reads the bearer token from an environment variable:
[mcp_servers.flowable-design]
url = "https://your-host/design-api/mcp"
bearer_token_env_var = "FLOWABLE_DESIGN_TOKEN"
Set the token in your environment before starting Codex, for example export FLOWABLE_DESIGN_TOKEN=<your-design-access-token>.
Claude Desktop: Claude Desktop connects to a remote server through a local bridge. In claude_desktop_config.json:
{
"mcpServers": {
"flowable-design": {
"command": "npx",
"args": [
"mcp-remote",
"https://your-host/design-api/mcp",
"--header",
"Authorization: Bearer <your-design-access-token>"
]
}
}
}
Tools and operations
The server provides ten tools. For most tools, a single operation argument (or, for validate_model, a mode argument) selects what the tool does, and the other arguments depend on that choice. List operations support paging through start (default 0), size (default 50), sort and order (asc / desc).
| Tool | Operations |
|---|---|
workspace_read | list, get, palette_categories |
workspace_write | create, update, delete |
package_read | list, get, palette_definitions, translations, list_revisions, get_revision |
package_write | create, update, delete, duplicate, lock, unlock, create_revision |
model_read | list, get, content, data_model, palette, palette_translations, relations, outline, history |
model_write | create, update_content, update_key, update_metadata, delete, duplicate, lock, unlock, restore_version |
model_edit | incremental structural edits; action vocabulary depends on the model type (see below) |
validate_model | stored, inline (selected via mode) |
publish_read | targets, requests, request, request_comments |
publish_write | publish, create_request, resolve_request, comment_request |
Identifying models and packages
Tools address resources by natural key:
workspaceKey: the workspace the resource lives in.modelKey: the model's key (unique within its scope).packageType(apporplugin) together withpackageKey: used when a model or operation is scoped to a specific package.
Where a tool needs to know the kind of model, it takes a modelType argument. The shared model-type vocabulary includes bpmn, cmmn, dmn, form, page, app, agent, channel, event, dataObject, dataDictionary, service, decisionService, knowledgeBase, and others.
Creating and updating models
When creating models with model_write create, note:
paletteDefinitionKeyis required forbpmn,cmmn,form,page,agent,channelanddecisionServicemodels.- For
package_writecreate,paletteDefinitionCategoryis required and must match a category configured for the tenant. Useworkspace_readpalette_categoriesandpackage_readpalette_definitionsto discover valid values.
The model_write content argument (raw model JSON) is rejected for bpmn, cmmn, dmn, form and page models. For those types, content must be changed with model_edit. Other model types still accept update_content.
Incremental editing with model_edit
model_edit applies a list of small, ordered, layout-free structural edits to a model. It takes workspaceKey, modelType, modelKey (plus optional packageType / packageKey) and an edits array, where each entry has a type selecting the action and action-specific parameters.
The available action vocabulary depends on the model type:
| Model type(s) | Actions |
|---|---|
bpmn, cmmn (canvas) | addNode, addEdge, updateNodeParameters, removeNode, removeEdge, changeParentNode |
dmn | addColumn, removeColumn, moveColumn (each with kind = input | output), addRuleRow, removeRuleRow, moveRuleRow |
form, page | addFormField, removeFormField, updateFormFieldParameters, resizeFormField, moveFormField |
dataObject | addProperty, removeProperty, updateProperty |
event | addEventPayloadItem, removeEventPayloadItem, updateEventPayloadItem |
dataDictionary | addType, removeType, updateType |
service | addOperation, removeOperation, updateOperation |
agent | addOperation, removeOperation, updateOperation |
For bpmn, cmmn, dmn, form and page, model_edit is the only way to change model content; model_write update_content is rejected for these types. The remaining model_edit-capable types additionally still accept update_content.
Automatic layout
Diagram layout is handled automatically. Actions reference elements by id only; you never supply coordinates. When you add or remove nodes and edges, the diagram is laid out for you.
The applied / warnings contract
model_edit reports what it did honestly. The response distinguishes:
applied: the edits that actually changed the model.warnings: edits that were dropped or were no-ops, with the reason. For example, an edit referencing an unknown element id, or removing an element that does not exist, is reported inwarningsand excluded fromapplied; it is not silently echoed back as if it succeeded.
Always inspect warnings after an edit to confirm every intended change landed.
Examples
The examples below show the arguments passed to each tool. In practice your AI assistant builds these calls for you from your natural-language requests; the arguments are shown here to illustrate what each tool does.
Discovering ids and valid stencils
Before editing a model, an assistant typically reads the model's structure to learn the element ids it can reference, and reads the palette to learn which stencils are valid for that model. This "discovery loop" avoids guessing ids or stencil types.
Read the outline to discover element ids:
{
"name": "model_read",
"arguments": {
"operation": "outline",
"workspaceKey": "claims_workspace",
"modelKey": "claim_intake_process"
}
}
Read the palette to discover the valid stencils for the model type:
{
"name": "model_read",
"arguments": {
"operation": "palette",
"workspaceKey": "claims_workspace",
"modelKey": "claim_intake_process"
}
}
Editing a BPMN model
With the ids and stencils known, apply incremental edits. The example adds a user task and wires it after an existing task. No coordinates are supplied; the layout is computed automatically:
{
"name": "model_edit",
"arguments": {
"workspaceKey": "claims_workspace",
"modelType": "bpmn",
"modelKey": "claim_intake_process",
"edits": [
{
"type": "addNode",
"id": "reviewTask",
"stencilId": "UserTask",
"name": "Review claim"
},
{
"type": "addEdge",
"id": "flowToReview",
"source": "registerTask",
"target": "reviewTask"
}
]
}
}
The response reports the edits under applied, and any dropped or no-op edits (for example, an addEdge whose source id does not exist) under warnings.
Validating a model
Validate a stored model with the model validator:
{
"name": "validate_model",
"arguments": {
"mode": "stored",
"workspaceKey": "claims_workspace",
"modelType": "bpmn",
"modelKey": "claim_intake_process"
}
}
Use "mode": "inline" with a content argument to validate a draft model definition that has not been stored yet. The response returns the list of validation issues.
Publishing
List the available deployment targets for an app, then publish:
{
"name": "publish_read",
"arguments": {
"operation": "targets",
"workspaceKey": "claims_workspace",
"appKey": "claims_app"
}
}
{
"name": "publish_write",
"arguments": {
"operation": "publish",
"workspaceKey": "claims_workspace",
"packageType": "app",
"packageKey": "claims_app",
"targetEndpointId": "production"
}
}
Where deployments go through an approval workflow, an assistant can instead create a publish request, and an approver can resolve it. Resolving a request with APPROVED triggers the deployment automatically:
{
"name": "publish_write",
"arguments": {
"operation": "create_request",
"workspaceKey": "claims_workspace",
"appKey": "claims_app",
"title": "Publish claim intake updates",
"deploymentTarget": "production"
}
}
{
"name": "publish_write",
"arguments": {
"operation": "resolve_request",
"workspaceKey": "claims_workspace",
"publishRequestId": "<id from publish_read requests>",
"resolution": "APPROVED",
"resolutionMessage": "Looks good."
}
}
Use publish_read with requests, request and request_comments to inspect the publish request inbox, a single request, and its comments.
