pi-delegate-mcp
██████╗ ██╗ ██████╗ ███████╗██╗ ███████╗ ██████╗ █████╗ ████████╗███████╗
██╔══██╗██║ ██╔══██╗██╔════╝██║ ██╔════╝██╔════╝ ██╔══██╗╚══██╔══╝██╔════╝
██████╔╝██║ ██║ ██║█████╗ ██║ █████╗ ██║ ███╗███████║ ██║ █████╗
██╔═══╝ ██║ ██║ ██║██╔══╝ ██║ ██╔══╝ ██║ ██║██╔══██║ ██║ ██╔══╝
██║ ██║ ██████╔╝███████╗███████╗███████╗╚██████╔╝██║ ██║ ██║ ███████╗
╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚══════╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝
███╗ ███╗ ██████╗██████╗
████╗ ████║██╔════╝██╔══██╗
██╔████╔██║██║ ██████╔╝
██║╚██╔╝██║██║ ██╔═══╝
██║ ╚═╝ ██║╚██████╗██║
╚═╝ ╚═╝ ╚═════╝╚═╝
Servidor MCP que expone el agente de codificación pi como un trabajador delegable y dirigible.
Apunta Claude Code (o cualquier host MCP) hacia él y delega trabajo en cualquiera de los ~38 proveedores de pi (DeepSeek, Grok, GLM, Kimi, Qwen, Codex, OpenRouter, llama.cpp local) con el contexto del subagente manteniéndose fuera de tu conversación principal.
Para qué sirve
Tu arnés principal se ejecuta en un modelo caro, con una ventana de contexto que te importa. Mucho de lo que hace no necesita ese modelo, y daña activamente ese contexto: buscar en un repositorio cada punto de llamada, leer un archivo de 2000 líneas para responder una pregunta, auditar lo que dejó una refactorización.
Encomienda ese trabajo a un delegado en su lugar:
Coste. El trabajo pesado se ejecuta en DeepSeek, GLM, Kimi, Qwen o un llama.cpp local. Pagas precios de frontera solo por el razonamiento que de verdad los necesita.
Contexto. El delegado lee los archivos por su cuenta y devuelve un resultado. Los 200 KB que leyó nunca entran en tu conversación.
Radio de impacto. Los delegados son de solo lectura por defecto (
read, grep, find, ls), aplicado en la construcción de la sesión. Un modelo barato haciendo trabajo exploratorio no puede tocar tu árbol salvo que lo habilites.
El delegado es siempre el agente pi. Codex, Grok, DeepSeek y el resto aportan el modelo detrás de él; esto no es un envoltorio de sus CLIs.
Related MCP server: handoff-mcp
¿Por qué pi, y no opencode o un envoltorio CLI?
Un delegado solo es dirigible si dos canales permanecen abiertos: debes poder redirigirlo a mitad de tarea, y debe poder preguntarte algo y bloquearse hasta que respondas. La mayoría de las formas de conducir un agente de codificación desde otro programa cierran ambos.
| opencode SDK | este servidor | |
Se ejecuta en proceso | no (subproceso) | no (cliente HTTP a | sí ( |
Redirigir un turno en curso | no | solo |
|
El agente puede preguntarte algo | no ( | no en la API de sesión |
|
Modelo por llamada | no | sí | argumento |
pi -p y --mode json establecen ctx.hasUI = false. Un delegado iniciado así es de disparar y olvidar
por construcción: no puede plantear una pregunta y no puedes redirigirlo.
El SDK de opencode es un cliente tipado para un proceso de servidor separado: createOpencode() arranca
opencode serve y le habla por HTTP. Diseño limpio, pero implica un segundo proceso que supervisar,
y la superficie de sesión que expone (prompt, abort, revert, messages) no tiene
dirección a mitad de turno ni vía para que el agente pregunte nada a quien lo llama.
pi incluye createAgentSession como biblioteca embebible. Este servidor mantiene el objeto de sesión
en proceso, de modo que session.steer() puede colocar un mensaje después de la llamada de herramienta actual y antes de la
siguiente llamada al modelo, y un uiContext sintético captura las preguntas del agente y las aparca para
answer. No se lanza nada a un shell; no hay nada que supervisar.
* Las preguntas provienen de las extensiones de pi, por lo que ese canal está abierto solo para delegados creados con
extensions: true. Consulta Búsqueda web y otras herramientas de extensión.
(La tabla compara el canal de delegación, no el sandboxing; opencode tiene su propia configuración de permisos. Consulta Solo lectura por defecto para ver qué hace y qué no hace este servidor.)
Herramientas
Tool | Propósito |
| Llámalo primero. Informa de los modelos alcanzables, las herramientas permitidas y cómo dirigir un delegado. Cualquier otra herramienta se niega hasta que se ha ejecutado una vez. |
| Delega en segundo plano. Devuelve |
| Lanza hasta 10 delegados en una sola llamada. Se valida como lote, así que nada se inicia si una tarea es incorrecta. |
| Delega y bloquea hasta terminar. Solo para preguntas rápidas. |
| Estado, turnos, herramientas usadas, último texto y preguntas pendientes. |
| Redirige a un agente en ejecución. Se aplica después de su llamada de herramienta actual. |
| Da otro turno a un delegado ya terminado. Conserva todo lo que leyó, así no tienes que volver a explicar la tarea. |
| Responde a una pregunta mostrada por |
| Detiene una sesión; la salida parcial sigue siendo legible. |
| Lista los modelos que puede usar este delegado. |
| Lista sesiones, en ejecución y terminadas. Filtra por |
| Elimina una sesión terminada del historial, liberando su id. |
Instalación
Requiere Node.js 22.19+ y una instalación funcional de pi en la que se haya iniciado sesión una vez
(pi, y luego /login).
Claude Code
claude mcp add pi -e PI_DELEGATE_MODEL=openrouter/stealth/ox-alpha -- npx -y pi-delegate-mcpCualquier host MCP, mediante .mcp.json
{
"mcpServers": {
"pi": {
"command": "npx",
"args": ["-y", "pi-delegate-mcp"],
"env": { "PI_DELEGATE_MODEL": "openrouter/stealth/ox-alpha" },
"timeout": 1800000
}
}
}npx resuelve el paquete en cada lanzamiento. Para fijarlo, instálalo globalmente y llama al binario
directamente:
npm install -g pi-delegate-mcp{ "mcpServers": { "pi": { "command": "pi-delegate-mcp", "timeout": 1800000 } } }Mantén la clave del servidor corta, ya que prefija cada nombre de herramienta (mcp__pi__spawn).
Desde el código fuente
git clone https://github.com/howznguyen/pi-delegate-mcp && cd pi-delegate-mcp
npm install && npm run build && npm linkPrimera ejecución
Pide a tu agente que delegue algo. Llama a init una vez para saber qué puede alcanzar este servidor,
y luego a spawn:
{ "id": "audit-01", "label": "who still imports onnxruntime",
"prompt": "Search this repo for anything still importing onnxruntime and list the files.",
"cwd": "/path/to/repo" }{ "sessionId": "audit-01", "state": "running", "model": "opencode-go/deepseek-v4-flash",
"activeTools": ["read", "grep", "find", "ls"] }spawn devuelve inmediatamente. Consulta con status el rastro ordenado de herramientas y la respuesta, o
sessions cuando haya varias en vuelo. Si init falla, dice exactamente qué falta: pi no
instalado, ningún proveedor con sesión iniciada o un ámbito de modelos que no coincide con nada.
Los nombres de modelo en los ejemplos siguientes son ilustrativos. Ejecuta models para ver qué puede alcanzar realmente
tu propia instalación de pi.
Trazabilidad
spawn y run aceptan tu propio id y una label de texto libre:
{
"id": "search-audit-01",
"label": "what ONNX removal left behind",
"prompt": "...",
"model": "opencode-go/deepseek-v4-flash"
}Los Ids son [A-Za-z0-9._:-], de 1 a 64 caracteres, deben empezar alfanuméricos y ser únicos entre las
sesiones activas. Omítelo para obtener un UUID.
Las sesiones terminadas siguen siendo legibles mediante status y sessions en lugar de desaparecer, para que puedas
volver y comprobar qué hizo realmente un delegado. Se conservan las PI_DELEGATE_HISTORY (50 por defecto) más recientes;
forget elimina una antes de tiempo.
status devuelve un rastro ordenado toolCalls: cada herramienta que ejecutó el delegado, con argumentos y
tiempos. Añade verbose: true para los ids de llamada y los resultados:
{
"seq": 1,
"id": "call_467b4bb4…",
"name": "bash",
"state": "ok",
"ms": 10,
"args": "{\"command\":\"echo hello-trace\"}",
"result": "hello-trace\n"
}Los argumentos y resultados se recortan (PI_DELEGATE_TRACE_ARGS, PI_DELEGATE_TRACE_RESULT) con la
longitud descartada registrada, de modo que un read de un archivo grande no puede inundar tu contexto.
Dar otro turno a un delegado
Un delegado terminado no está agotado. pi conserva su sesión en memoria, así que follow_up vuelve a preguntar
al mismo agente con todo lo que ya leyó aún en contexto:
{ "sessionId": "search-audit-01", "prompt": "Now check whether the build files reference it too" }{ "sessionId": "search-audit-01", "state": "running", "turnsSoFar": 1 }El delegado continúa donde lo dejó. Todavía conserva los archivos que leyó en el primer turno, así que la segunda pregunta cuesta una llamada al modelo en lugar de una sesión nueva releyendo el repositorio.
Esta es la forma barata de mantener una conversación con un delegado. Crear uno nuevo significa re-explicar la tarea y pagar para que vuelva a leer los mismos archivos, y su respuesta llega sin nada del razonamiento que llevó hasta ella.
follow_up rechaza a un delegado que todavía está trabajando, porque redirigirlo a mitad de tarea es
para lo que sirve steer. Los dos no son intercambiables: steer aterriza entre llamadas de herramienta en un
agente en ejecución; follow_up inicia un nuevo turno en uno terminado.
Desplegar en abanico
spawn_batch inicia un lote completo en una llamada. Las tareas heredan el model, cwd,
tools y extensions a nivel de lote, y los sobrescriben individualmente donde lo necesiten:
{
"idPrefix": "audit",
"model": "opencode-go/deepseek-v4-flash",
"cwd": "/repo",
"tools": ["ls"],
"tasks": [
{ "prompt": "What still imports onnxruntime?", "label": "imports" },
{ "prompt": "Which build files still reference ONNX?", "label": "build" },
{
"prompt": "Any ONNX model files left on disk?",
"label": "artifacts",
"model": "opencode-go/ox-alpha-free"
}
]
}Eso las nombra audit-01, audit-02, audit-03 y devuelve en pocos milisegundos, ya que
lanzar un delegado no espera a que piense.
El lote se valida antes de que empiece nada: formato de id, ids duplicados dentro del lote, ids ya activos, herramientas bloqueadas y cada nombre de modelo. Una tarea incorrecta hace fallar la llamada y no lanza nada. Un abanico a medias es el peor resultado, porque pagas por los delegados que sí se iniciaron y aun así tienes que averiguar cuáles no lo hicieron.
Consulta todo el lote con una sola llamada a sessions en lugar de un status por delegado. Baja a
status solo para el delegado que realmente quieras leer. steer y abort siguen siendo por sesión.
Elegir un modelo por llamada
model en cualquier llamada sobrescribe PI_DELEGATE_MODEL. Un nombre irresoluble es un error grave, nunca una
retirada silenciosa al modelo por defecto, porque una retirada silenciosa es como terminas facturando un modelo
que nunca pediste.
Qué nombres se resuelven lo decide el ámbito enabledModels propio de pi, que este servidor aplica
en lugar de limitarse a mostrar:
opencode-go/deepseek-v4-flash -> ok (listed in enabledModels)
opencode-go/glm-5.3 -> refused (out of scope)
knowns-hub/claude-opus -> ok (custom provider, see below)Los proveedores personalizados omiten el ámbito. Cualquier modelo servido por un proveedor declarado en
~/.pi/agent/models.json se ofrece incluso cuando enabledModels no lo nombra, con el argumento
de que declarar un proveedor a mano ya es una intención de usarlo. Por eso la lista puede ser
mucho más larga que enabledModels: tres entradas en el ámbito más dos proveedores personalizados pueden fácilmente
significar quince modelos ofrecidos. init lo dice explícitamente en models.scopeNote cuando aplica.
Dos interruptores cambian eso:
Efecto | |
| Respeta |
| Elimina el ámbito por completo. Todo modelo autenticado es usable. |
Llama a models para ver qué es realmente alcanzable según la configuración vigente.
Línea de estado
Claude Code permite exactamente un comando statusLine, así que pi-delegate-statusline envuelve lo que
ya ejecutes y añade un segmento que muestra los delegados de este espacio de trabajo:
{
"statusLine": {
"type": "command",
"command": "PI_DELEGATE_STATUSLINE_WRAP=ccstatusline pi-delegate-statusline",
"refreshInterval": 10
}
}Elimina PI_DELEGATE_STATUSLINE_WRAP para imprimir solo el segmento de pi.
π ▸ audit engine·t1·12s audit index·t2·8s running, with turn counts and elapsed time
π ▸ migrate·t7·3m04s ?1 waiting one delegate is blocked on a question
π ✓2 finished, nothing runningQué delegados pertenecen a cada sesión
Filtrar por directorio no basta: dos sesiones de Claude Code abiertas en el mismo repositorio mostrarían los delegados de la otra. La atribución usa en su lugar el linaje de procesos.
El host MCP crea un servidor por sesión, así que el servidor registra process.ppid, el pid del
host. La línea de estado, creada por ese mismo host, recorre su propia ascendencia y conserva solo los
archivos de estado cuyo hostPid encuentra ahí. Mismo repositorio, dos sesiones, sin interferencias. El
filtro de directorio sigue como respaldo para archivos de estado escritos antes de que esto existiera.
El estado vive en $XDG_STATE_HOME/pi-delegate-mcp/<pid>.json (PI_DELEGATE_STATE_DIR para
reubicarlo). Los archivos se podan cuando su proceso desaparece, solo con ESRCH, ya que EPERM significa que el
proceso está vivo bajo otro usuario. Los servidores también salen por sí solos cuando stdin se cierra o el
pid del host desaparece, así que un host que muere sin cerrar el transporte no deja nada atrás.
Solo lectura por defecto
Las herramientas están bloqueadas a read, grep, find, ls en la construcción de la sesión. Cualquier otra cosa se rechaza
antes de que siquiera se cree una sesión.
Para ampliar eso, nombre las herramientas adicionales en el servidor:
"env": { "PI_DELEGATE_ALLOW_TOOLS": "bash" }o PI_DELEGATE_ALLOW_WRITE=1 para permitir todo.
bash no es un término medio. pi no incluye un sistema de permisos, así que un delegado que tenga bash
puede escribir archivos, borrarlos y alcanzar la red sin importar si write y edit están
en su lista. Rechazar esos dos mientras se permite bash registra su intención; no hace cumplir
nada. Los avisos de permisos y los hooks de Claude Code nunca ven lo que hace pi. Si necesita un límite
real, ejecute este servidor dentro de un contenedor.
Búsqueda web y otras herramientas de extensión
Las herramientas propias de pi son read, grep, find, ls, bash, powershell, write, edit. No hay
búsqueda ni fetch entre ellas. Esas vienen de las extensiones de pi, que registran sus propias herramientas, y un
delegado puede usarlas.
Establezca extensions: true en la llamada y permita los nombres de las herramientas en el servidor:
"env": { "PI_DELEGATE_ALLOW_TOOLS": "web_search,fetch_content" }{ "prompt": "Find the current Node LTS version and tell me just the number",
"extensions": true, "tools": ["read", "grep", "find", "ls", "web_search"] }{ "seq": 1, "name": "web_search", "state": "ok", "ms": 2568,
"args": "{\"query\":\"latest stable Node.js LTS version\",\"numResults\":5}" }Así es como se le da a un delegado alcance de red sin entregarle bash. web_search puede buscar
y nada más, y pasa por la misma lista de permitidos que cualquier otra herramienta, así que el valor por defecto
de solo lectura no cambia para las llamadas que no lo piden.
Qué herramientas existen depende de lo que tenga instalado el usuario que ejecuta el servidor. pi-web-access proporciona
web_search, fetch_content, source_check y get_search_content. pi-mcp-adapter conecta los
servidores MCP en ~/.pi/agent/mcp.json y los expone como mcp. pi no tiene un cliente MCP propio, así que
esa extensión es la única ruta hacia uno.
extensions: true confía en todas las extensiones instaladas, no solo en la que quería. Se cargan como un
conjunto, se ejecutan con los privilegios completos del proceso de este servidor, y algunas abren sockets y temporizadores
que sobreviven a la sesión. Actívelo por llamada, para los delegados que lo necesiten, en lugar de dejarlo
activado por defecto. También cuesta tiempo de arranque real, por eso está desactivado a menos que se pida.
Configuración
Variable de entorno | Por defecto | Significado |
| el propio de pi | Modelo usado cuando una llamada omite |
| sin definir | Lista separada por comas de herramientas adicionales a permitir, p. ej. |
| sin definir |
|
|
| Sesiones terminadas que se conservan para revisión |
|
| Máximo de caracteres de los argumentos de herramientas guardados en el rastro |
|
| Máximo de caracteres de los resultados de herramientas guardados en el rastro |
|
| Límite de tareas por llamada a |
|
| Por encima de esto, |
| directorio de estado XDG | Dónde se publica el estado de la línea de estado |
| sin definir | Comando de línea de estado para envolver y añadir |
| sin definir | Archivo al que añadir una marca de tiempo en cada render de la línea de estado, para depuración |
|
| Intervalo de notificación de progreso durante |
| sin definir |
|
| sin definir |
|
|
| Dónde se leen |
Trabajo de larga duración
El SDK de MCP TypeScript tiene por defecto un tiempo de espera de solicitud de 60 segundos, que una tarea real superará. Tres defensas, en orden de preferencia:
Use
spawn+status. Nada se bloquea, así que no aplica ningún tiempo de espera.runemite notificaciones de progreso periódicas, que reinician el tiempo de espera del host.Suba el límite con
"timeout"en.mcp.jsonoMCP_TOOL_TIMEOUTen el entorno.
CLAUDE_AUTO_BACKGROUND_TASKS=1 hace que Claude Code ponga en segundo plano las llamadas MCP largas después de ~2 minutos.
Tenga en cuenta que las notificaciones de progreso se descartan una vez que una llamada se pone en segundo plano, así que elija (1) o (3),
no ambos.
Autenticación
El servidor no maneja credenciales. pi se autentica desde ~/.pi/agent/auth.json,
luego variables de entorno. Los hosts MCP a menudo lanzan servidores con un entorno reducido, así que
prefiera auth.json (ejecute pi una vez y /login) sobre exportar claves en un perfil de shell.
Desarrollo
npm install
npm run build # tsc, src/*.ts -> dist/
npm run typecheck # tsc --noEmit, strict
npm run test:ci # offline: boots the server over stdio and lists its tools
npm test # full suite: needs a logged-in pi, makes real model callstest:ci es lo que ejecuta CI y lo que prepublishOnly exige, porque no necesita credenciales ni
red. npm test maneja delegados reales contra proveedores reales, así que cuesta dinero y solo
funciona donde pi ha iniciado sesión.
Ruta | Qué vive allí |
| Cada variable de entorno, leída en un solo lugar |
| La lista de permitidos de herramientas y la puerta que la hace cumplir |
| Mapa de sesiones, reclamación de ids, expulsión de historial |
| Un módulo por grupo de herramientas MCP |
| Todo lo que toca el SDK de pi |
| Publicación de archivos de estado y el binario de línea de estado |
Los lanzamientos están impulsados por etiquetas. npm version patch && git push --follow-tags ejecuta la compilación y las pruebas,
luego publica mediante publicación confiable OIDC, así que no se almacena ningún token npm en el repositorio.
Las incidencias y las solicitudes de extracción son bienvenidas. Si está informando de un delegado que se comportó mal, el
rastro toolCalls de status con verbose: true es lo útil para adjuntar.
Trabajo previo
abatilo/pi-mcp-bridge toma la ruta más simple:
genera pi --mode json -p --session-id <uuid> y deja que pi persista las sesiones en disco, así que el puente
no mantiene ningún estado. Elegante, y vale la pena leerlo. Cambia el control de dirección, preguntas y
control de herramientas para llegar allí.
Licencia
MIT
Maintenance
Related MCP Servers
- AlicenseCqualityBmaintenanceEnables MCP hosts to delegate coding tasks to Pi CLI as a programmable sub-agent with session tracking and process management.72MIT
- AlicenseAqualityCmaintenanceEnables Claude to delegate tasks to external coding agents (Codex or Antigravity) for independent reviews, separate quota usage, and async processing.6MIT
- AlicenseNot gradedqualityBmaintenanceEnables Hermes agents to delegate bounded coding tasks to persistent oh-my-pi sessions with isolated git worktrees, live steering, and durable follow-ups, requiring explicit user confirmation before each task.AGPL 3.0
- AlicenseAqualityBmaintenanceEnables delegating asynchronous coding tasks and DAG workflows to local Oh My Pi (OMP) CLI sub-agents, with topological orchestration, path isolation, and supervised resumption.91MIT
Related MCP Connectors
Stop re-explaining yourself to Agents. Give it the right context, right when needed.
The team layer for AI coding agents: shared contracts, collision alerts, E2EE sessions.
Human-as-a-Service for AI agents. Delegate tasks that need a real human, get results via API.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/howznguyen/pi-delegate-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server