camunda-mcp
by fssou
README.md
# camunda-mcp
> MCP server (Model Context Protocol) com ferramentas para modelar BPMN **Camunda 7**,
> em Node.js, **independente do Camunda Modeler**.
Construído sobre [`bpmn-moddle`](https://github.com/bpmn-io/bpmn-moddle) e
[`camunda-bpmn-moddle`](https://github.com/camunda/camunda-bpmn-moddle), os mesmos
módulos do projeto `bpmn-js` — então o XML gerado é 100% compatível com o
Camunda Modeler / `bpmn-js`. Layout/DI é regenerado pelo
[`bpmn-auto-layout`](https://github.com/bpmn-io/bpmn-auto-layout).
Namespace de extensão usada: `http://camunda.org/schema/1.0/bpmn` (Camunda 7).
---
## Instalação
```bash
git clone https://github.com/fssou/camunda-mcp.git
cd camunda-mcp
npm install
npm run build
```
## Uso em clientes MCP
### Claude Desktop / Cursor / Continue (stdio)
Adicione no `mcpServers` do seu cliente:
```json
{
"mcpServers": {
"camunda7": {
"command": "node",
"args": ["/caminho/absoluto/para/camunda-mcp/dist/index.js"]
}
}
}
```
Após salvar, o cliente lista todas as ferramentas (~40) prefixadas com `camunda7`.
### Execução standalone (debug)
```bash
node dist/index.js
# imprime no stderr: "@fssou/camunda-mcp v0.1.0 ready on stdio"
# espera mensagens MCP JSON-RPC em stdin
```
---
## Ferramentas disponíveis
### Ciclo de vida do diagrama
| Tool | Descrição |
|---|---|
| `create_diagram` | Cria um novo diagrama em memória. Retorna `diagramId`. |
| `list_diagrams` | Lista diagramas abertos. |
| `delete_diagram` | Descarta um diagrama. |
| `load_diagram_xml` | Importa um XML BPMN 2.0. |
| `load_diagram_file` | Importa um arquivo `.bpmn` do disco. |
| `get_diagram_xml` | Serializa para XML. |
| `save_diagram` | Grava `.bpmn` em disco. |
| `auto_layout` | Regenera `bpmndi:BPMNDiagram` (shapes/edges) via `bpmn-auto-layout`. |
| `validate_diagram` | Lista erros/warnings estruturais. |
### Elementos BPMN
| Tool | Descrição |
|---|---|
| `add_start_event` | StartEvent (`none|message|timer|signal|error|conditional`). |
| `add_end_event` | EndEvent (`none|message|signal|error|escalation|terminate`). |
| `add_intermediate_event` | IntermediateCatchEvent / IntermediateThrowEvent. |
| `add_boundary_event` | BoundaryEvent anexado a uma atividade (interrupting ou não). |
| `add_task` | Task / UserTask / ServiceTask / SendTask / ReceiveTask / ScriptTask / BusinessRuleTask / ManualTask. |
| `add_gateway` | Exclusive / Parallel / Inclusive / EventBased / Complex. |
| `add_subprocess` | SubProcess / Transaction / AdHocSubProcess (event sub-process via `triggeredByEvent`). |
| `add_call_activity` | CallActivity (`calledElement`). |
| `add_text_annotation` | Anotação de texto. |
| `delete_element` | Remove o elemento e os fluxos incidentes. |
| `list_elements` | Lista elementos (filtros por tipo / parentId). |
| `get_element` | Inspeciona um elemento e suas extensões Camunda. |
| `set_name`, `set_documentation` | Mutações genéricas. |
### Fluxos
| Tool | Descrição |
|---|---|
| `connect_elements` | Cria um `bpmn:SequenceFlow` (com `conditionExpression` opcional). |
| `add_message_flow` | Cria um `bpmn:MessageFlow` entre participants. |
| `add_association` | Cria uma `bpmn:Association` (anotação ↔ elemento). |
| `set_default_flow` | Marca um fluxo como default de um gateway/atividade. |
| `set_condition_expression` | Define um `bpmn:FormalExpression` em um fluxo. |
### Pools e lanes
| Tool | Descrição |
|---|---|
| `add_participant` | Cria um Participant (pool) — promove o diagrama para `bpmn:Collaboration`. |
| `add_lane` | Cria uma Lane em um Participant. |
| `assign_to_lane` | Adiciona um flow node a uma lane (`flowNodeRef`). |
### Extensões Camunda 7
| Tool | Descrição |
|---|---|
| `set_task_implementation` | `class`, `expression` (+ `resultVariable`), `delegateExpression`, `external` (`topic`). |
| `set_async` | `asyncBefore`, `asyncAfter`, `exclusive`, `jobPriority`. |
| `set_user_task_assignment` | `assignee`, `candidateUsers`, `candidateGroups`, `dueDate`, `followUpDate`, `priority`. |
| `set_form` | `formKey` ou `formRef` + `camunda:FormData/FormField` embutido. |
| `set_io_mapping` | `camunda:InputOutput` com `camunda:InputParameter` / `camunda:OutputParameter` (`value` ou `camunda:Script`). |
| `set_camunda_properties` | Substitui `camunda:Properties`. |
| `add_execution_listener` | Anexa `camunda:ExecutionListener` (`start|end|take`) com `class`, `expression`, `delegateExpression` ou `script`. |
| `add_task_listener` | Anexa `camunda:TaskListener` (`create|assignment|complete|delete|update|timeout`) a um UserTask. |
| `set_error_event_definition` | Configura `bpmn:ErrorEventDefinition` + `bpmn:Error` + `camunda:errorCodeVariable`/`errorMessageVariable`. |
| `set_timer_event_definition` | `timeDuration` / `timeCycle` / `timeDate` (FormalExpression). |
| `set_message_event_definition` | Cria/reusa `bpmn:Message` e seta `messageRef`. |
| `set_signal_event_definition` | Cria/reusa `bpmn:Signal` e seta `signalRef`. |
| `set_process_attributes` | `id`, `name`, `isExecutable`, `camunda:versionTag`, `camunda:historyTimeToLive`, `camunda:jobPriority`, `camunda:candidateStarterUsers/Groups`, `camunda:isStartableInTasklist`. |
---
## Exemplo de fluxo
Após o cliente MCP chamar as ferramentas, o XML produzido tem o seguinte formato
(Camunda 7 plenamente válido):
```xml
<bpmn:definitions xmlns:bpmn="..." xmlns:camunda="http://camunda.org/schema/1.0/bpmn">
<bpmn:process id="Approval_Process" isExecutable="true"
camunda:versionTag="1.0.0" camunda:historyTimeToLive="P30D">
<bpmn:startEvent id="Event_..." name="Pedido recebido" />
<bpmn:userTask id="Activity_..." name="Aprovar pedido"
camunda:candidateGroups="gerentes" camunda:dueDate="P1D"
camunda:asyncBefore="true" camunda:exclusive="true"
camunda:formKey="embedded:app:forms/approve.html" />
<bpmn:exclusiveGateway id="Gateway_..." name="Aprovado?" />
<bpmn:serviceTask id="Activity_..." name="Faturar"
camunda:delegateExpression="${invoiceService}">
<bpmn:extensionElements>
<camunda:inputOutput>
<camunda:inputParameter name="orderId">${execution.getVariable("orderId")}</camunda:inputParameter>
<camunda:outputParameter name="invoiceId">${result.id}</camunda:outputParameter>
</camunda:inputOutput>
<camunda:properties>
<camunda:property name="retries" value="5" />
</camunda:properties>
<camunda:executionListener event="end" expression="${endListener.notify(execution)}" />
</bpmn:extensionElements>
</bpmn:serviceTask>
<bpmn:endEvent id="Event_..." name="Pedido recusado">
<bpmn:errorEventDefinition errorRef="Error_PEDIDO_RECUSADO" />
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_..." name="Aprovado" sourceRef="Gateway_..." targetRef="Activity_...">
<bpmn:conditionExpression>${approved}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
</bpmn:process>
<bpmn:error id="Error_PEDIDO_RECUSADO" name="Pedido recusado" errorCode="PEDIDO_RECUSADO" />
</bpmn:definitions>
```
Use `auto_layout` para regenerar `bpmndi:BPMNDiagram` quando o diagrama mudar.
---
## Desenvolvimento
```bash
npm install
npm run build # compila TS → dist/
npm run typecheck # tsc --noEmit
npm run lint # eslint
npm test # vitest (smoke end-to-end)
npm run dev # roda src/index.ts via tsx (stdio)
```
A árvore do projeto:
```
src/
├── index.ts # stdio entrypoint
├── server.ts # buildServer() — factory de McpServer
├── store.ts # DiagramStore + DiagramSession
├── bpmn/
│ ├── moddle.ts # cria BpmnModdle com camunda 7 descriptor
│ ├── builder.ts # BpmnBuilder — adiciona/remove elementos
│ ├── camunda.ts # helpers de extensões Camunda 7
│ ├── layout.ts # wrapper de bpmn-auto-layout
│ ├── validate.ts # validateDiagram()
│ ├── xml.ts # fromXML / toXML / indexById
│ └── types.ts # uniões discriminadas de tipos BPMN
└── tools/
├── registry.ts # schemas Zod por tool
└── handlers.ts # dispatch(toolName, params)
test/
└── smoke.test.ts # end-to-end: criação → exportação → auto-layout → round-trip
```
---
## Licença
MIT — veja [LICENSE](LICENSE).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing