MCP Workflow Orchestration Server
Permite que agentes de IA descubram, criem e executem fluxos de trabalho complexos e de múltiplas etapas definidos em arquivos YAML simples.
Documentação
@cyanheads/workflows-mcp-server
Armazene, consulte e crie playbooks de workflow YAML para agentes de LLM via MCP. STDIO ou Streamable HTTP.
Visão geral
Uma biblioteca de workflows declarativos para agentes de LLM, apoiada por arquivos YAML locais. Armazene, liste e recupere playbooks nomeados e versionados de múltiplas etapas — cada um uma sequência de chamadas de servidor/ferramenta MCP — para reutilização permanente ou execuções temporárias de uso único. Executa como um processo stdio ou um servidor HTTP Streamable local; um índice em memória é reconstruído automaticamente conforme os arquivos mudam.
Ferramentas
| Ferramenta | Descrição |
|---|---|
workflow_list | Lista todos os workflows permanentes no índice, com filtros opcionais de palavra-chave, categoria e tag. |
workflow_get | Recupera uma definição completa de workflow por nome, com instruções globais anexadas no início. |
workflow_create | Grava um novo workflow permanente em YAML na biblioteca. |
workflow_create_temp | Grava um rascunho de workflow temporário, indexado mas excluído dos resultados de listagem, mantido até ser excluído. |
workflow_delete | Remove um workflow permanente ou um rascunho temporário por nome e versão opcional, após o usuário confirmar o alvo resolvido. |
Referência de capacidades
workflow_list ferramenta
- Filtro opcional de palavra-chave
query(substring sem diferenciar maiúsculas/minúsculas no nome e na descrição do workflow) - Filtro opcional de categoria (correspondência de substring sem diferenciar maiúsculas/minúsculas)
- Filtro opcional de tag (correspondência AND sem diferenciar maiúsculas/minúsculas — todas as tags listadas devem estar presentes)
- Os valores dos filtros são aparados de espaços iniciais e finais antes da correspondência; um
queryoucategoryem branco não aplica filtro - Defina
includeTools: truepara exibir os pares únicos deserver/toolusados nas etapas de cada workflow - Workflows temporários são excluídos; os resultados são ordenados por nome e, em seguida, por precedência semver decrescente (uma versão de lançamento antes de suas pré-lançamentos)
- Resultados vazios ecoam os filtros aplicados com uma dica para ampliar a busca
workflow_get ferramenta
- Ciente de semver: omita
versionpara obter a correspondência mais alta disponível; especifique uma versão para uma consulta exata - Um
versionque não seja semver válido é rejeitado como argumentos inválidos antes de qualquer consulta; uma grafia tolerada (v1.0.0, espaços ao redor, metadados de build) resolve para sua forma canônica (1.0.0) nameé aparado antes da consulta, correspondendo a como as ferramentas de criação o armazenam; umnameem branco é rejeitado como argumentos inválidos- Retorna a estrutura YAML completa do workflow com todas as etapas e metadados
- Injeta o conteúdo de
global_instructions.mdcomoglobalInstructions— aplique-os ao executar o workflow;nullquando o arquivo estiver ausente - Workflows temporários são acessíveis aqui, mesmo excluídos de
workflow_list - Placeholders de modelo (
{{input.foo}},{{steps.X.output.Y}}) são retornados literalmente — o servidor nunca os interpola
workflow_create ferramenta
- Workflow armazenado em
categories/<slugified-category>/<slugified-name>-<slugified-version>-<hash>-workflow.yaml, onde<hash>são os primeiros 8 caracteres hexadecimais de SHA-256 sobrename@version— um arquivo porname@version, então múltiplas versões coexistem e chaves cujos slugs coincidem (Deploy/deploy,Café Plan/Caf Plan) nunca compartilham um arquivo - Qualquer nome com conteúdo visível é aceito; um sem letras ou dígitos ASCII (por exemplo,
Рабочий процесс) usaworkflowcomo a parte do nome em seu nome de arquivo - Rejeita se
name@versionjá existir, como workflow permanente ou rascunho temporário — aumente a versão para criar uma nova revisão, ou exclua o rascunho comworkflow_deletepara armazená-lo permanentemente - Criações concorrentes de um
name@versionproduzem um workflow e umalready_exists, mesmo entre categorias versioné armazenado na forma semver canônica: umvinicial, espaços ao redor e metadados de build são removidos, entãov1.0.0+build.5é armazenado, indexado e recuperado como1.0.0- Rejeita um
name,description,author,categoryou etapaserver/toolapenas com espaços cominvalid_input - Rejeita um
namecom mais de 200 caracteres ou umcategorycom mais de 255 caracteres após a slugificação cominvalid_input, para que todo nome de arquivo e diretório caiba no limite de 255 bytes - O servidor carimba
created_dateelast_updated_dateautomaticamente - Índice e snapshot reconstruídos após a gravação; o observador do sistema de arquivos também dispara (idempotente, com debounce)
- Uma falha do sistema de arquivos é relatada como
write_failedcom o código de erro e a descrição apenas, nunca o caminho absoluto
workflow_create_temp ferramenta
- Gravar um
name@versionque já tem um rascunho sobrescreve esse rascunho no lugar:statusé"created"para um novo rascunho e"overwritten"para um substituído, e uma sobrescrita mantém ocreated_dateoriginal do rascunho - Rejeita um
name@versionmantido por um workflow permanente comalready_exists - Armazenado sob
temp/com o mesmo esquema de nome de arquivo, armazenamento canônico deversione rejeição de campos apenas com espaços comoworkflow_create - Indexado e acessível via
workflow_get, mas excluído dos resultados deworkflow_list; um camponoticeinformando isso acompanha tanto emstructuredContentquanto na saída de texto - Rascunhos persistem: um rascunho permanece sob
temp/entre reinicializações até queworkflow_deleteo remova — nada expira rascunhos ou os limpa - Útil para planos de uso único, andaimes ou rascunhos ainda não prontos para a biblioteca permanente
workflow_delete ferramenta
- Exclui workflows permanentes e rascunhos temporários igualmente; o
sourceda saída ("permanent"ou"temp") indica qual foi removido - Ciente de semver: omita
versionpara excluir a correspondência mais alta disponível entre workflows permanentes e rascunhos; especifique uma versão para mirar exatamente uma - Mesmas regras de
versionenamequeworkflow_get: entrada não-semver é rejeitada antes de qualquer exclusão, uma grafia tolerada mira sua forma canônica e umnamecom espaços é aparado - Pergunta ao usuário primeiro: a chamada retorna um prompt de confirmação nomeando o
name@versionresolvido, sua origem e seu caminho de arquivo relativo aWORKFLOWS_DIR, e exclui apenas quando o usuário respondeconfirm: true. Responderfalse, recusar ou cancelar falha comcancellede não exclui nada - O servidor mantém o registro de cada prompt e entrega ao cliente apenas um id aleatório para ele. Uma resposta deve chegar em até 10 minutos e funciona uma vez; uma resposta a um prompt que o servidor nunca emitiu, já respondido ou emitido há muito tempo falha com
confirmation_invalide não exclui nada - O arquivo é excluído apenas se ainda for o que o usuário viu: se o nome resolver para um workflow ou arquivo diferente, ou o conteúdo do arquivo mudou, quando a resposta chega, a chamada falha com
target_changede não exclui nada - Precisa de um cliente que possa exibir o prompt (elicitação); um cliente sem isso não pode excluir, e não há como contornar o prompt
- Irreversível: o arquivo é removido e o workflow não aparece mais em
workflow_listouworkflow_get— a menos que outro arquivo escrito manualmente declare o mesmoname@version. Essa cópia então toma seu lugar, e o resultado carrega umnoticenomeando seu caminho relativo aWORKFLOWS_DIR - Excluir um rascunho libera seu
name@version, entãoworkflow_createpode armazená-lo permanentemente - Excluir o último workflow em um diretório
categories/<slug>/remove esse diretório esvaziado; um diretório que ainda contém qualquer arquivo permanece
Recursos
Construído sobre @cyanheads/mcp-ts-core: transportes stdio e Streamable HTTP, autenticação plugável (none / jwt / oauth), armazenamento intercambiável (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), registro estruturado com rastreamento OpenTelemetry opcional.
Biblioteca de workflows:
- Arquivos de workflow YAML validados contra um esquema no momento da indexação; arquivos inválidos (incluindo um
name,description,author,categoryou etapaserver/toolapenas com espaços) são ignorados e registrados, nunca derrubam o servidor - Versões indexadas na forma semver canônica — um arquivo escrito como
version: v1.0.0é indexado comoname@1.0.0 - Uma entrada de índice por
name@version: um workflow permanente tem precedência sobre um rascunho temporário com a mesma chave (o rascunho é ignorado com um aviso nomeando ambos os arquivos), e dois arquivos de um tipo que compartilham uma chave registram um aviso de duplicata, com o último lido vencendo - Índice em memória chaveado por
name@version, construído na inicialização a partir deworkflows-yaml/categories/eworkflows-yaml/temp/recursivamente, mantido atualizado por um observador recursivo do sistema de arquivos com debounce em qualquer adição/alteração/remoção - O índice lê a identidade de cada workflow do conteúdo de seu arquivo, nunca de seu nome de arquivo, então arquivos nomeados sob qualquer esquema — incluindo o
<name>-<version>-workflow.yamlanterior — são listados, recuperados e excluídos como qualquer outro - Criações e exclusões são executadas uma de cada vez dentro do servidor, então a verificação de existência de cada uma é mantida até que sua gravação seja concluída
- Consulta ciente de semver — versão mais recente retornada quando
versioné omitido - Snapshot
_index.jsongravado em cada reconstrução para ferramentas externas e depuração WORKFLOWS_DIR,GLOBAL_INSTRUCTIONS_PATHe intervalo de debounce configuráveis
Saída amigável ao agente:
- Saída discriminada —
source: "permanent" | "temp"em cada resposta deworkflow_gete códigos dereasontipados (not_found,version_not_found,already_exists,cancelled,confirmation_invalid,target_changed,index_unavailable, …) em falhas, para que os chamadores ramifiquem com base em dados em vez de analisar strings de erro - Sem ida e volta extra —
workflow_getsempre retornaglobalInstructionsjunto com a definição do workflow na mesma resposta - Modelagem de resposta — o sinalizador opcional
includeToolsdeworkflow_listpré-deriva os pares únicos deserver/toolusados por um workflow, e um resultado vazio ecoa os filtros aplicados com uma dica de ampliação em vez de retornar nada
Começando
Nenhuma chave de API necessária. O servidor lê de um diretório local workflows-yaml/ por padrão.
Adicione o seguinte ao seu arquivo de configuração do cliente MCP:
{
"mcpServers": {
"workflows-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/workflows-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"WORKFLOWS_DIR": "/absolute/path/to/your/workflows-yaml"
}
}
}
}
Ou com npx (sem Bun necessário):
{
"mcpServers": {
"workflows-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/workflows-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"WORKFLOWS_DIR": "/absolute/path/to/your/workflows-yaml"
}
}
}
}
Ou com Docker:
{
"mcpServers": {
"workflows-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"-v", "/absolute/path/to/your/workflows-yaml:/workflows-yaml",
"-e", "WORKFLOWS_DIR=/workflows-yaml",
"ghcr.io/cyanheads/workflows-mcp-server:latest"
]
}
}
}
Para Streamable HTTP, defina o transporte e inicie o servidor:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
Workflows de semente
O repositório inclui um diretório workflows-yaml/ com exemplos de workflows organizados sob categories/. Eles estão prontos para uso como ponto de partida. O arquivo workflows-yaml/global_instructions.md contém instruções que o servidor anexa ao início de cada resposta de workflow_get — edite-o para definir orientações globais para seu agente.
Pré-requisitos
- Bun v1.4.0 ou superior (ou Node.js v24+).
- Um diretório local contendo arquivos de workflow YAML (ou use a semente
workflows-yaml/incluída).
Instalação
- Clone o repositório:
git clone https://github.com/cyanheads/workflows-mcp-server.git
- Navegue para o diretório:
cd workflows-mcp-server
- Instale as dependências:
bun install
- Configure o ambiente:
cp .env.example .env
# edit .env if needed — most settings have defaults
Configuração
| Variável | Descrição | Padrão |
|---|---|---|
WORKFLOWS_DIR | Caminho absoluto ou relativo para o diretório raiz dos workflows. | ./workflows-yaml |
GLOBAL_INSTRUCTIONS_PATH | Caminho para o arquivo markdown de instruções globais. Deriva de WORKFLOWS_DIR quando não definido. | <WORKFLOWS_DIR>/global_instructions.md |
WATCHER_DEBOUNCE_MS | Milissegundos para debounce de eventos de alteração no sistema de arquivos antes de reconstruir o índice. | 500 |
MCP_TRANSPORT_TYPE | Transporte: stdio ou http. | stdio |
MCP_HTTP_PORT | Porta para o servidor HTTP. | 3010 |
MCP_SESSION_MODE | Sessões HTTP: auto ou stateful. O prompt de confirmação de workflow_delete precisa de uma sessão ativa, então a inicialização HTTP com stateless falha com um erro de configuração. Ignorado via stdio. | stateful, declarado em src/index.ts |
MCP_AUTH_MODE | Modo de autenticação: none, jwt ou oauth. | none |
MCP_LOG_LEVEL | Nível de log (RFC 5424). | info |
OTEL_ENABLED | Habilita instrumentação OpenTelemetry (spans, métricas, logs de conclusão). | false |
Consulte .env.example para a lista completa de sobrescritas opcionais.
Executando o servidor
Desenvolvimento local
-
Compilar e executar:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:http -
Executar verificações e testes:
bun run devcheck # Lint, format, typecheck, security bun run test # Vitest test suite bun run lint:mcp # Validate MCP definitions against spec
Docker
docker build -t workflows-mcp-server .
docker run --rm \
-v /path/to/workflows-yaml:/workflows-yaml \
-e WORKFLOWS_DIR=/workflows-yaml \
-p 3010:3010 \
workflows-mcp-server
O Dockerfile usa por padrão transporte HTTP, modo de sessão com estado (obrigatório — veja MCP_SESSION_MODE acima) e registra logs em /var/log/workflows-mcp-server. Dependências de pares do OpenTelemetry são instaladas por padrão — compile com --build-arg OTEL_ENABLED=false para omiti-las.
Estrutura do projeto
| Diretório | Finalidade |
|---|---|
src/index.ts | Ponto de entrada do createApp() — registra ferramentas e inicializa o serviço de índice de workflows. |
src/config/ | Análise e validação de variáveis de ambiente específicas do servidor com Zod. |
src/mcp-server/tools/ | Definições de ferramentas (*.tool.ts). |
src/services/workflow-index/ | WorkflowIndexService — análise YAML, construção de índice, observador, consulta semver, auxiliares de escrita. |
tests/ | Testes unitários e de integração espelhando src/. |
workflows-yaml/ | Biblioteca de workflows de exemplo — categories/ para workflows permanentes, temp/ para rascunhos temporários, global_instructions.md para orientação global de agentes. |
Guia de desenvolvimento
Consulte CLAUDE.md para diretrizes de desenvolvimento e regras arquiteturais. A versão resumida:
- Handlers lançam exceções, o framework captura — sem
try/catchna lógica de ferramentas - Use
ctx.logpara registro de logs com escopo de requisição - Registre novas ferramentas via o barrel em
src/mcp-server/tools/definitions/index.ts - Operações de sistema de arquivos passam por
WorkflowIndexService, não diretamente nos handlers de ferramentas
Contribuindo
Issues são bem-vindas. Execute verificações e testes antes de enviar:
bun run devcheck
bun run test
Licença
Apache-2.0 — veja LICENSE para detalhes.