Work MCP Server
Introduction
The Work MCP server lets AI assistants and other Model Context Protocol (MCP) clients work with the Flowable Work runtime. Through it, an assistant can browse work (process and case) definitions, read and act on running work instances and tasks, look up users, groups and master data, discover and invoke service-backed form fields, and discover and invoke action definitions using natural language, instead of working in the Flowable Work user interface.
Working through the MCP server is equivalent to working in Flowable Work itself: every tool enforces the same permissions and tenant scoping as the Work REST API. A user can only do through the MCP server what they are allowed to do in Flowable Work.
The read and action tools return the same representations the Flowable Work REST API returns, so the data an assistant sees matches what the UI and the REST API show.
The Work MCP server is disabled by default and must be explicitly enabled per deployment. It also requires a valid AI Connector license. 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.platform.mcp.server.enabled | Enables the Work MCP server. | false |
flowable.platform.mcp.server.path | Path the MCP endpoint is exposed at, relative to the Work platform REST API (/platform-api). | /mcp |
Set flowable.platform.mcp.server.enabled=true to turn the server on. The endpoint is mounted into the Flowable Work platform REST dispatcher, relative to the Work platform REST API base path. With the default path the full URL is:
<your-work-base-path>/mcp
where <your-work-base-path> is the base URL of your Flowable Work platform REST API, including the context path (for example https://your-host/flowable-work/platform-api). If you change flowable.platform.mcp.server.path, replace /mcp accordingly.
In addition to being enabled, the server requires a valid AI Connector license. Tool calls are gated behind a shared license check: if no AI Connector license is present, calls fail with a structured error rather than executing.
These properties are also listed under the Work properties reference.
Connecting a client
The Work MCP server is a remote MCP server that uses a stateless Streamable HTTP transport. Once it is enabled, point your MCP client at the endpoint URL (<your-work-base-path>/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 Work platform REST API. You authenticate your MCP client the same way you would authenticate any call to the Work REST API, and the permissions of the authenticated user apply: a user with read-only access cannot start instances, complete tasks or invoke actions through the MCP server.
Two common options are:
- Bearer token: send a Flowable Work access token in an
Authorization: Bearer <token>header. This is the recommended option for AI assistants and automation. See Flowable Access Tokens for how to create one. - HTTP Basic authentication: send Work credentials in an
Authorization: Basic <base64 of user:password>header, for example using a dedicated technical user.
For the authentication mechanisms Flowable Work supports (HTTP Basic, OAuth2 / SSO and access tokens), see the Flowable security documentation.
Configuring your MCP client
Most MCP clients are configured with a small JSON file listing the servers to connect to. Add the Work MCP server as an HTTP server with the endpoint URL, and pass your credentials in a header. Replace the URL and credentials in the examples below with your own values.
The examples below use an access token (Bearer <your-work-access-token>). To use HTTP Basic authentication instead, 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-work": {
"type": "http",
"url": "<your-work-base-path>/mcp",
"headers": {
"Authorization": "Bearer <your-work-access-token>"
}
}
}
}
claude mcp add --transport http flowable-work <your-work-base-path>/mcp \
--header "Authorization: Bearer <your-work-access-token>"
Cursor: .cursor/mcp.json in your project, or ~/.cursor/mcp.json for all projects:
{
"mcpServers": {
"flowable-work": {
"url": "<your-work-base-path>/mcp",
"headers": {
"Authorization": "Bearer <your-work-access-token>"
}
}
}
}
VS Code (GitHub Copilot): .vscode/mcp.json in your project:
{
"servers": {
"flowable-work": {
"type": "http",
"url": "<your-work-base-path>/mcp",
"headers": {
"Authorization": "Bearer <your-work-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-work]
url = "<your-work-base-path>/mcp"
bearer_token_env_var = "FLOWABLE_WORK_TOKEN"
Set the token in your environment before starting Codex, for example export FLOWABLE_WORK_TOKEN=<your-work-access-token>.
Claude Desktop: Claude Desktop connects to a remote server through a local bridge. In claude_desktop_config.json:
{
"mcpServers": {
"flowable-work": {
"command": "npx",
"args": [
"mcp-remote",
"<your-work-base-path>/mcp",
"--header",
"Authorization: Bearer <your-work-access-token>"
]
}
}
}
Tools and operations
The server provides ten tools. For each tool, a single operation argument selects what the tool does, and the other arguments depend on that choice. List operations support paging.
Read tools are advertised to the client as read-only; the action and invoke tools are advertised as non-read-only (state-changing).
| Tool | Operations |
|---|---|
work_definition_read | list, get, get_start_form, list_deployments |
work_instance_read | list, list_historic, get, variables, identity_links (optional linkType), candidate_users, comments |
task_read | list, get, form, variables, identity_links (optional linkType), candidate_users, comments |
work_instance_action | start, add_comment, update_status, assign, change_due_date |
task_action | complete, save_form, claim, add_comment |
idm_read | list_users, get_user, list_groups, get_group, user_groups, group_members |
master_data_read | list, get, get_by_key |
action_read | scoped (actions available on an object), get_form (an action's form model) |
service_invoke | invoke a service-backed form field across seven scopes |
action_invoke | execute an action definition by key, or execute an active action instance by id |
Work definitions and instances
A work definition is a process (bpmn) or case (cmmn) definition; a work instance is a running or historic process or case. Where a tool needs to know which engine a definition or instance belongs to, it takes a type argument with the value bpmn or cmmn. The work-instance representation keeps this engine scope type on its output so it matches the tool input vocabulary.
Resources are addressed by their natural identifiers:
work_definition_readgetresolves a definition by itskey.work_instance_readandwork_instance_actionoperations address a running or historic instance by itsinstanceId.task_readandtask_actionoperations address a task by itstaskId.
Permission-checked access
Every tool enforces the same permissions and tenant scoping as the Work REST API. A caller can only read or do through the MCP server what they are allowed to read or do in Flowable Work.
Read tools are permission-filtered: task_read list returns only the tasks the caller may see, idm_read returns only the users the caller may access, and action_read scoped returns only the actions the caller may execute on an object. The action and invoke tools enforce the same access checks before changing anything, including the form-field access check when an action runs in a form context.
Discovering and invoking actions
Actions are the runtime behind a Form Engine Action button (workAction). The action_read and action_invoke tools mirror how the Flowable Work frontend drives them:
action_readscopeddiscovers the active actions available on a scoped object — the actions that can currently be executed withaction_invoke. The list is flat and mixes action definitions and active action instances (instance-backed entries carry anactionInstanceId). It takes ascopeType(such asbpmn,cmmnoruser) and the object'sscopeId, and supports optional filters:key,nameLike,supportsChannelsandglobal.action_readget_formreturns the form model an action expects. Provide exactly one ofactionDefinitionKey(the action's input form) oractionInstanceId(an active instance's form).action_invokeexecutes an action. Provide exactly one ofactionDefinitionKey(execute a definition) oractionInstanceId(execute an active action instance). An action instance can only be executed once. When the action lives on a form, supply theformIdand theformFieldIdof the action button; the action's form-field access is then verified.
service_invoke scopes
service_invoke invokes a service-backed form field (Service Select, Service Data Table or Service Button) within a Work form context. The scope argument selects the form context and determines how scopeId is interpreted. It must be one of:
task, process_instance, case_instance, process_definition, case_definition, case_page, page.
For a Service Select or Service Data Table, pass an operationType of search or lookup; omit it for a Service Button (a plain invoke). The input argument carries the field's service input parameters as a name → value map.
Error handling
Tool calls return structured errors instead of raw stack traces. Flowable engine exceptions are mapped to a small set of error codes carried in the error text:
| Code | Meaning |
|---|---|
NOT_FOUND | The referenced definition, instance, task, user, group or master data could not be found (or is not accessible). |
FORBIDDEN | The caller is not allowed to perform the operation. |
INVALID_ARGUMENT | A required argument is missing or has an invalid value (for example an unknown operation, scope or type). |
CONFLICT | The operation conflicts with the current state of the resource. |
ENGINE_ERROR | An unexpected engine error occurred. |
An unknown or missing operation yields a coaching INVALID_ARGUMENT error that lists the operations the tool supports.
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.
Reading definitions
Get a work definition by its key:
{
"name": "work_definition_read",
"arguments": {
"operation": "get",
"key": "oneTaskProcess"
}
}
Starting a work instance
Start a process (bpmn) or case (cmmn) instance from a definition key:
{
"name": "work_instance_action",
"arguments": {
"operation": "start",
"definitionKey": "oneTaskProcess",
"type": "bpmn"
}
}
Other work_instance_action operations act on a running instance by instanceId, for example:
{
"name": "work_instance_action",
"arguments": {
"operation": "assign",
"instanceId": "<instance id>",
"userId": "admin"
}
}
{
"name": "work_instance_action",
"arguments": {
"operation": "change_due_date",
"instanceId": "<instance id>",
"dueDate": "2026-07-01T00:00:00Z"
}
}
Working on a task
Claim a task, add a comment and complete it with an outcome:
{
"name": "task_action",
"arguments": {
"operation": "claim",
"taskId": "<task id>"
}
}
{
"name": "task_action",
"arguments": {
"operation": "complete",
"taskId": "<task id>",
"outcome": "approve"
}
}
Reading master data
List master data instances of a given type, then resolve one by its key:
{
"name": "master_data_read",
"arguments": {
"operation": "list",
"definitionKey": "md-country",
"search": "Atlan"
}
}
{
"name": "master_data_read",
"arguments": {
"operation": "get_by_key",
"definitionKey": "md-country",
"key": "ATL"
}
}
Looking up users and groups
{
"name": "idm_read",
"arguments": {
"operation": "group_members",
"groupKey": "<group key>"
}
}
Invoking a service-backed form field
Invoke a Service Select / Data Table field within a case instance form context:
{
"name": "service_invoke",
"arguments": {
"scope": "case_instance",
"scopeId": "<case instance id>",
"fieldId": "<form field id>",
"input": {
"personInput": { "name": "Homer", "age": 1 },
"dateInput": "2026-01-19"
}
}
}
Discovering actions on an object
List the actions available on a running process (bpmn) instance:
{
"name": "action_read",
"arguments": {
"operation": "scoped",
"scopeType": "bpmn",
"scopeId": "<instance id>"
}
}
Read the form an action expects:
{
"name": "action_read",
"arguments": {
"operation": "get_form",
"actionDefinitionKey": "form-action"
}
}
Invoking an action
Execute an action definition by its key, passing a payload:
{
"name": "action_invoke",
"arguments": {
"actionDefinitionKey": "start-one-task-process",
"payload": {
"customer": "Kermit the Frog"
}
}
}
When an action is invoked in a form context, supply the formId and the formFieldId of the action button.
Alternatively, execute an active action instance by its id:
{
"name": "action_invoke",
"arguments": {
"actionInstanceId": "<action instance id>"
}
}
