@justmpm/agent-runner
v0.9.0
Published
MCP Server para invocar o OpenCode CLI em modo headless (7 tools concisas, sem owner, controle por mode via sufixo de prompt).
Maintainers
Readme
@justmpm/agent-runner
MCP Server para invocar o OpenCode CLI em modo headless, com abstração unificada via Adapter Pattern.
Status: v0.8.0 — OpenCode Headless Otimizado. Catálogo limpo de 7 tools essenciais. Retornos e descrições concisos para LLMs.
idnumérico obrigatório nas tools de controle.wait_for_completionopera em ciclos de 3 minutos fixos com alerta imperativo para não fechar processos em andamento.
✨ O que faz
Permite que agentes de IA executem tarefas complexas via OpenCode CLI em modo headless — auditoria de qualidade, validação, investigação, implementação, correção, criação de testes, design de UI, geração de trackers. Tudo em modo headless (sem telão), com persistência via terminal manager.
v0.8.0: catálogo enxuto de 7 tools com descrições objetivas. Sempre usa o default_agent do opencode (configurado em ~/.config/opencode/opencode.json ou built-in build) e o model default. A IA não escolhe provider, agent ou model — para customizar, edite o opencode.json.
Diferença vs @justmpm/term-manager: enquanto o term-manager executa scripts npm pré-definidos (build, test, lint), o agent-runner delega raciocínio para o opencode, que interpreta o prompt e age sobre o código.
🚀 Instalação
Pré-requisitos
| Requisito | Versão | |-----------|--------| | Node.js | >= 18 | | OS | Windows 10 1809+ (para ConPTY) ou macOS/Linux | | OpenCode CLI | 1.x (https://opencode.ai/docs/cli) |
Opção 1: Instalação global (recomendada)
A forma mais limpa e estável. O binário agent-runner fica disponível no PATH e a versão fica fixa.
npm install -g @justmpm/agent-runnerVerificar instalação:
agent-runner --version
# Saída esperada: @justmpm/agent-runner v0.5.0Configuração do MCP Client
A configuração depende do client que você usa. Escolha o seu:
OpenCode (~/.config/opencode/opencode.json)
{
"mcpServers": {
"agent-runner": {
"command": "agent-runner"
}
}
}Vantagem do global install: funciona em QUALQUER projeto sem mudar config. A IA passa o cwd diretamente em cada chamada (ex: cwd: "${workspace}" é expandido pelo OpenCode no momento da call). Veja a Migration Guide v0.1.0 → v0.2.0+ abaixo para entender por que a env var AGENT_RUNNER_PROJECT_DIR foi removida.
Claude Desktop (%APPDATA%/Claude/claude_desktop_config.json)
{
"mcpServers": {
"agent-runner": {
"command": "agent-runner"
}
}
}Cursor (~/.cursor/mcp.json)
{
"mcpServers": {
"agent-runner": {
"command": "agent-runner"
}
}
}Windsurf (~/.codeium/windsurf/mcp_config.json)
{
"mcpServers": {
"agent-runner": {
"command": "agent-runner"
}
}
}Opção 2: npx (sem instalar)
Útil para experimentar sem comprometer o ambiente global. Mais lento (baixa o pacote a cada inicialização).
{
"mcpServers": {
"agent-runner": {
"command": "npx",
"args": ["-y", "@justmpm/agent-runner"]
}
}
}Opção 3: Desenvolvimento local
Para contribuir com o código ou rodar versão customizada.
git clone https://github.com/Just-mpm/Pacotes-Pessoais.git
cd Pacotes-Pessoais/mcps-ai/agent-runner
npm install
npm run build{
"mcpServers": {
"agent-runner": {
"command": "node",
"args": ["D:/Pictures/Pacotes-Pessoais/mcps-ai/agent-runner/dist/index.js"]
}
}
}Variáveis de ambiente úteis
| Var | Default | Descrição |
|-----|---------|-----------|
| AGENT_RUNNER_MAX_SIMULTANEOUS | 5 | Limite de terminais simultâneos (1-20) |
| AGENT_RUNNER_DEBUG | 0 | Se 1, mostra logs extras (ex: lista de adapters registrados) |
⚠️ Removido em v0.2.2: a env var
AGENT_RUNNER_PROJECT_DIRnão existe mais.cwdagora é obrigatório nos args derun_agent/ask_agent— não há fallback implícito. Veja a Migration Guide abaixo.
Troubleshooting de instalação
| Problema | Causa | Solução |
|----------|-------|---------|
| agent-runner: command not found (Linux/Mac) | npm global bin não está no PATH | Adicione $(npm config get prefix)/bin ao PATH |
| agent-runner: command not found (Windows) | npm global bin não está no PATH | Reinicie o terminal após instalar OU adicione %APPDATA%\npm ao PATH |
| Cannot find module 'node-pty' após update | native bindings desatualizados | npm install -g @justmpm/agent-runner --force |
| Permissão negada ao instalar global (Linux/Mac) | npm precisa de sudo | Use nvm ou configure npm com prefix em pasta do usuário |
| Build falha com gyp ERR! find Python (Mac/Linux) | node-pty precisa compilar native | npm install -g windows-build-tools (Win) ou xcode-select --install (Mac) |
🔄 Migration Guide v0.6.0 → v0.7.0 (BREAKING)
A v0.7.0 é uma simplificação radical: OpenCode passa a ser o único provider
e a tool run_agent é unificada (absorveu a antiga ask_agent). Não há
mais escolha de provider, agent ou model na chamada MCP.
O que mudou
| Mudança | Versão | Impacto |
|---------|--------|---------|
| Providers codex e antigravity removidos | v0.7.0 (BREAKING) | Tabela de list_providers mostra só opencode |
| Campo provider removido do schema de run_agent e ask_agent | v0.7.0 (BREAKING) | A IA não pode mais escolher provider |
| Campo agent removido do schema de run_agent | v0.7.0 (BREAKING) | OpenCode sempre usa o default_agent |
| ask_agent removida (fundida em run_agent) | v0.7.0 (BREAKING) | Use run_agent com sandbox: "read-only" para apenas conversar |
| Total de tools: 9 (eram 10) | v0.7.0 | ask_agent saiu |
Migração de chamadas MCP
ANTES (v0.6.0):
// Delegar tarefa com codex
run_agent({
provider: "codex",
agent: "code-validator",
prompt: "Audite src/",
cwd: "D:/Pictures/Projetos/meu-app",
owner: "nexus"
})
// Conversa com codex
ask_agent({
provider: "codex",
prompt: "Esse plano tá bom?",
cwd: "D:/Pictures/Projetos/meu-app",
owner: "nexus"
})DEPOIS (v0.7.0):
// Delegar tarefa (sempre usa default_agent + model default)
run_agent({
prompt: "Audite src/",
cwd: "D:/Pictures/Projetos/meu-app",
owner: "nexus"
})
// Conversa (sandbox read-only impede edição)
run_agent({
prompt: "Esse plano tá bom?",
cwd: "D:/Pictures/Projetos/meu-app",
sandbox: "read-only",
owner: "nexus"
})Forward-compat: clientes que continuam mandando provider e/ou agent
não quebram — recebem o novo contrato automaticamente (Zod strip
silencioso). Mas a recomendação é remover do cliente para ficar explícito.
Checklist pós-update
- Instale o OpenCode CLI (se ainda não tiver): https://opencode.ai/docs/cli
- Configure o model em
~/.config/opencode/opencode.json(ex:"model": "anthropic/claude-sonnet-4-20250514"). - Opcional: configure
default_agent(default =build). - Remova
providereagentdas chamadas MCP (a IA ainda vai funcionar, mas é mais limpo sem). - Migre
ask_agentpararun_agentcomsandbox: "read-only". - Rode
npm install -g @justmpm/agent-runner@latest(ounpm updateno dev-local).
Por que fizemos essa quebra?
- Decisão consciente: o opencode é maduro o suficiente para ser a escolha padrão. Manter 3 providers (Codex, Antigravity, OpenCode) com qualidades diferentes só criava confusão para a IA.
- UX da chamada: quanto mais simples o schema, mais fácil a IA usar corretamente. Sem
providere semagent, a chamada é direta:prompt+cwd+sandboxopcional. - Adapter Pattern preservado: se quiser re-adicionar Codex/Antigravity no futuro, é trivial (veja Adicionar novo provider).
🔄 Migration Guide v0.1.0 → v0.2.0+
A partir da v0.2.0, o agent-runner virou auto-suficiente (não depende mais do @justmpm/term-manager para consultar terminais) e em v0.2.2 houve uma quebra importante. Se você atualizou de uma versão < 0.2.0, ajuste sua config e calls.
O que mudou
| Mudança | Versão | Impacto |
|---------|--------|---------|
| Env var AGENT_RUNNER_PROJECT_DIR removida | v0.2.2 (BREAKING) | Não é mais consultada — cwd é obrigatório nos args |
| cwd agora é OBRIGATÓRIO em run_agent e ask_agent | v0.2.2 (BREAKING) | A IA deve passar conscientemente cada chamada |
| 6 tools de consulta/controle adicionadas | v0.2.0 | Não precisa mais do @justmpm/term-manager em outro processo |
| id OU name aceitos nas tools de consulta | v0.2.1 | Resolve o anti-padrão de esquecer ID numérico entre calls |
| wait_for_completion SEMPRE espera o processo realmente terminar | v0.5.0 (BREAKING) | timeoutMs e waitUntilExit foram removidos do schema — contrato único |
Configuração MCP (env var removida)
ANTES (v0.1.0):
{
"mcpServers": {
"agent-runner": {
"command": "agent-runner",
"env": {
"AGENT_RUNNER_PROJECT_DIR": "D:\\Pictures\\MeuProjeto"
}
}
}
}DEPOIS (v0.2.2+):
{
"mcpServers": {
"agent-runner": {
"command": "agent-runner"
}
}
}A env var
AGENT_RUNNER_PROJECT_DIRé simplesmente ignorada pelo código v0.2.2+ (não causa erro, mas também não faz nada).
Chamadas MCP (cwd agora obrigatório)
ANTES (v0.1.0): a IA podia omitir cwd e o server usava a env var como fallback.
DEPOIS (v0.7.0+): a IA sempre passa cwd explícito (sem provider/agent — v0.7.0 unificou):
// run_agent — cwd obrigatório (tool unificada em v0.7.0)
run_agent({
prompt: "Audite src/",
cwd: "D:/Pictures/MeuProjeto", // ← OBRIGATÓRIO
owner: "nexus"
})
// Para apenas conversar (sandbox read-only):
run_agent({
prompt: "Esse plano tá bom?",
cwd: "D:/Pictures/MeuProjeto",
sandbox: "read-only", // impede edit/bash
owner: "nexus"
})Tools de consulta (não precisa mais do term-manager)
ANTES (v0.1.0): para acompanhar um terminal criado por run_agent, era necessário rodar @justmpm/term-manager em outro processo — o que não funcionava (IDs são locais a cada processo).
DEPOIS (v0.2.0+): use as tools do mesmo MCP:
// Após run_agent → ID 5 (aguarda nativamente até o processo realmente terminar)
wait_for_completion({ id: 5, owner: "nexus" })
// ou por nome (v0.2.1+) — em v0.7.0 todos os terminais têm name "opencode:default"
wait_for_completion({ name: "opencode:default", owner: "nexus" })
read_output({ id: 5, lines: 50, owner: "nexus" })
search_output({ id: 5, pattern: "error", owner: "nexus" })
close_terminal({ id: 5, owner: "nexus" })Checklist pós-update
- Atualize o pacote:
npm install -g @justmpm/agent-runner@latest(ounpm updateno dev-local). - Remova
env.AGENT_RUNNER_PROJECT_DIRde TODOS os seus MCP clients (OpenCode, Claude Desktop, Cursor, Windsurf, dev-local). - Verifique que suas chamadas MCP passam
cwdexplícito em toda invocação derun_agent/ask_agent. - Se você usava
@justmpm/term-managerpara monitorar terminais do agent-runner, remova essa dependência — agora é auto-suficiente. - Rode
npm run build && npm publishse você forkou/mirrorou o pacote.
🔧 Tools MCP (7 tools, v0.8.0)
Criação (1 tool)
| Tool | Descrição |
|------|-----------|
| run_agent | Delega tarefa ao OpenCode CLI em modo headless. Sempre usa o default_agent e model default. mode: read-only (só analisa) ou workspace-write (default, pode editar) via sufixo de prompt. |
Consulta / Controle (6 tools)
| Tool | Descrição |
|------|-----------|
| wait_for_completion | Aguarda término de processo (ciclos de 3min fixos). Se running, re-chame sem cancelar. |
| read_output | Lê snapshot do output do terminal (lines e offset opcionais). |
| search_output | Busca substring no output com classificação [ERRO]/[WARN]/[INFO]. |
| list_terminals | Lista terminais registrados (filtro por status). |
| stop_terminal | Envia Ctrl+C para o processo (apenas se realmente necessário abortar). |
| close_terminal | Fecha terminal e libera recursos. Nunca feche processo com status running. |
v0.2.0: Antes era necessário o
@justmpm/term-managerem outro processo para acompanhar os terminais criados aqui — o que não funcionava (processos separados não enxergam IDs uns dos outros). Agora o agent-runner é auto-suficiente.
v0.2.1: As 5 tools de consulta (
wait_for_completion,read_output,search_output,stop_terminal,close_terminal) aceitamid(numérico) OUname(string). Em v0.7.0 todos os terminais dorun_agenttêm o mesmo nome (opencode:default) — prefira usaridpara evitar ambiguidade.// Por ID (nativamente espera até terminar) wait_for_completion({ id: 5 }) // Por NAME (esqueceu o ID? pega o mais recente com esse nome) wait_for_completion({ name: "opencode:default" })Se ambos forem passados,
idtem prioridade.
🤖 Provider Suportado (v0.7.0: único)
| Provider | CLI | Versão mínima | Auth |
|----------|-----|---------------|------|
| opencode | opencode (opencode.ai) | 1.x | Conforme provider de modelo configurado em ~/.config/opencode/opencode.json |
Instalação do OpenCode
Siga as instruções em https://opencode.ai/docs/cli. Após instalação, autentique conforme o provider de modelo que você configurar em ~/.config/opencode/opencode.json.
Configuração inicial recomendada:
// ~/.config/opencode/opencode.json
{
"model": "anthropic/claude-sonnet-4-20250514", // ou o modelo que preferir
"default_agent": "build" // ou "plan" ou um custom
}Agents custom ficam em .opencode/agents/*.md (projeto) ou ~/.config/opencode/agents/*.md (global) — frontmatter YAML opcional. Em v0.7.0 o run_agent sempre usa o default_agent (não passa --agent).
📦 Modo de execução (v0.9.0, via sufixo de prompt)
run_agent aceita mode (sem flag do CLI — controle por linguagem natural ao fim do prompt):
| Modo (enum) | Sufixo anexado ao prompt |
|-------------|--------------------------|
| read-only (use para conversas) | "Apenas analise e responda. NÃO implemente nada, NÃO edite, NÃO crie arquivos e NÃO execute comandos que alterem o código." |
| workspace-write (default do run_agent) | "Você pode fazer edições caso seja necessário para completar a tarefa." |
v0.9.0: OPENCODE_PERMISSION/sandbox removidos (não funcionavam de forma confiável). owner também removido (uso single-agent).
🎯 Como usar (exemplos)
Workflow típico (v0.7.0)
// 1. Verificar opencode instalado
list_providers()
// → opencode | ✅ sim | ? | 1.0.0
// 2. (Opcional) ver custom agents do projeto
list_agents({ provider: "opencode" })
// 3. Delegar uma auditoria (cwd é OBRIGATÓRIO)
run_agent({
prompt: "Audite src/tools/agent-runner.ts focando em SOLID, tipos, race conditions.",
cwd: "D:/Pictures/Pacotes-Pessoais", // ⚠️ obrigatório
owner: "nexus"
})
// → [ID: 1] [Nome: opencode:default]
// → Agent: default (configurado em opencode.json ou built-in build)
// → Model: default (configurado em opencode.json)
// 4. Aguardar resultado (default 3min, re-chame se precisar)
wait_for_completion(id=1, owner="nexus")
// → ✓ SUCESSO (exit 0): agente terminou | Tempo: 1m 23s
// 5. Ler output e investigar
search_output(id=1, pattern="error", owner="nexus")
read_output(id=1, owner="nexus")
// 6. Liberar recursos
close_terminal(id=1, owner="nexus")Conversa sem editar código (sandbox read-only)
run_agent({
prompt: "Esse plano de implementação de autenticação tá bom?",
cwd: "D:/Pictures/Pacotes-Pessoais",
sandbox: "read-only", // impede edit/bash — só conversa
owner: "nexus"
})
// → [ID: 2] [Nome: opencode:default]
// → Sandbox: read-only (não altera código)
// Aguardar e ler
wait_for_completion(id=2, owner="nexus")
read_output(id=2, owner="nexus")
close_terminal(id=2, owner="nexus")v0.7.0:
run_agenté a única tool de criação. Não háprovidernemagentno schema. Para customizar o agent/model, edite~/.config/opencode/opencode.json.
Workflow de monitoramento (múltiplos terminais)
// Disparar várias delegações em paralelo
const r1 = run_agent({ prompt: "...", owner: "nexus" });
const r2 = run_agent({ prompt: "...", owner: "nexus" });
// Listar seus terminais ativos
list_terminals({ owner: "nexus", status: "running" })
// Aguardar cada um conforme necessário (default 3min)
wait_for_completion(id=r1.id, owner="nexus")
wait_for_completion(id=r2.id, owner="nexus")
// Cleanup
close_terminal(id=r1.id, owner="nexus")
close_terminal(id=r2.id, owner="nexus")🏗️ Arquitetura
Adapter Pattern isola as quirks do OpenCode CLI atrás de uma interface unificada:
interface AgentAdapter {
readonly provider: ProviderId;
readonly binary: string;
readonly sandboxModes: readonly SandboxMode[];
readonly installHint: string;
detect(): Promise<DetectResult>;
listAgents(args?: { cwd?: string }): Promise<AgentDefinition[]>;
buildRunCommand(args: RunCommandArgs): string;
buildAskCommand(args: AskCommandArgs): string;
}O OpenCode é 1 arquivo (src/tools/adapters/opencode.ts) e se registra no ProviderRegistry. O ProviderRegistry permanece genérico (DIP) — se quiser re-adicionar providers no futuro, basta criar um adapter, registrar no registry e estender o enum ProviderId.
Stack
| Dependência | Versão | Uso |
|-------------|--------|-----|
| TypeScript | ^5.9.3 | Linguagem principal (strict mode, zero any) |
| Node.js | >= 18 | Runtime |
| node-pty | ^1.0.0 | Gerenciamento de terminais (ConPTY no Windows 10 1809+) |
| zod | ^3.24.0 | Validação de schemas de input |
| zod-to-json-schema | ^3.24.0 | Conversão de schemas Zod para JSON Schema (MCP) |
| @modelcontextprotocol/sdk | ^1.26.0 | MCP server e transporte stdio |
Como o prompt é passado (segurança + robustez)
- Node escreve o prompt em arquivo temporário (UTF-8).
- PowerShell lê via
Get-Content -Raw | <cli>, envia via stdin. - Bloco
try/finallydo PowerShell remove o temp file ao terminar. - Node só age em falha de spawn (não em
finallygenérico).
Isso resolve:
- Limite de argv do Windows (~8191 chars)
- Escape de aspas no prompt (vai via stdin, não argv)
- Não precisa encoding especial (UTF-8 cru)
v0.7.0: o OpenCode recebe o prompt interpolado como
"$prompt"(argv, não stdin). Para não depender do limite doCreateProcess(~32767 chars), orun_agentrejeita com erro acionável prompts >30000 chars — sem truncamento silencioso.
🧪 Desenvolvimento
npm run build # compila TypeScript → dist/
npm test # roda Vitest
npm run dev # watch mode (tsc --watch)Adicionar novo provider (v0.7+)
O ProviderRegistry permanece genérico em v0.7.0. Para re-adicionar um provider (Codex, Antigravity) ou adicionar um novo (Claude Code, Gemini CLI, etc):
- Adicionar ID em
src/tools/adapters/types.ts(ProviderId). - Criar
src/tools/adapters/<novo-provider>.tsimplementandoAgentAdapter. - Importar e registrar em
src/tools/adapters/index.ts:defaultRegistry.register(<novoProvider>Adapter); - Opcional: re-adicionar campo
providerno schema derun_agent(foi removido em v0.7.0).
📋 Requisitos
| Requisito | Detalhe | |-----------|--------| | Node.js | >= 18 | | OS | Windows 10 1809+ (necessário para ConPTY) | | OpenCode CLI | 1.x (https://opencode.ai/docs/cli) |
🐛 Troubleshooting
| Problema | Causa | Solução |
|----------|-------|--------|
| opencode não aparece em list_providers | CLI não está no PATH | Instale via https://opencode.ai/docs/cli e reinicie o shell |
| Prompt >30000 chars rejeitado | Guard de argv do Windows (~32767) | Divida a tarefa em prompts menores |
| Limite de N terminais simultâneos atingido | maxSimultaneous | Use close_terminal para liberar |
| Erro de validação: ... | argumento inválido | Veja o schema JSON da tool via tools/list |
| opencode pendurado esperando aprovação | Alguma permissão com "ask" (ex: configurada no opencode.json) | O adapter NUNCA emite "ask" via OPENCODE_PERMISSION; revise permissões do projeto |
| Race condition no temp file | (impossível) | Mitigada: cleanup só em falha de spawn (GATE-07) |
🔗 Links
- Repositório: https://github.com/Just-mpm/Pacotes-Pessoais
- Pacotes relacionados:
@justmpm/term-manager— pacote "irmão" para scripts npm. O agent-runner copia e adapta o motor (TerminalManager) do term-manager — veja a seção sobre compatibilidade noAGENTS.md.
- Koda AI Studio: https://kodaai.app
- Email: [email protected]
📄 Licença
MIT © Koda AI Studio
