> ## Documentation Index
> Fetch the complete documentation index at: https://botmesh.afaya.com.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Servidor MCP

`@botmesh/mcp` es un servidor **MCP** (Model Context Protocol) por stdio. Le da a un agente de código (o a un editor) las piezas deterministas del proyecto para escribir, validar, compilar, dibujar, lintear, migrar y comparar un documento de flujo **sin arrancar un bot**: sin teléfono, sin credenciales, sin red.

Cada herramienta es una función de sus argumentos. El servidor **no tiene dependencias de terceros** (el transporte JSON-RPC está implementado en el paquete), nunca evalúa código y nunca escribe en disco.

## Arrancarlo

Los clientes MCP lo arrancan con `npx`; no hay que instalar nada antes:

```bash theme={null}
npx -y @botmesh/mcp --help        # uso; --version imprime la versión
```

### Registrarlo en tu cliente

**Claude Code**:

```bash theme={null}
claude mcp add botmesh -- npx -y @botmesh/mcp
```

o, compartido con el proyecto, `.mcp.json`:

```json theme={null}
{ "mcpServers": { "botmesh": { "command": "npx", "args": ["-y", "@botmesh/mcp"] } } }
```

**Cursor** (`.cursor/mcp.json`) y **Claude Desktop** (`claude_desktop_config.json`) usan la misma forma `mcpServers`. **VS Code** (`.vscode/mcp.json`):

```json theme={null}
{ "servers": { "botmesh": { "type": "stdio", "command": "npx", "args": ["-y", "@botmesh/mcp"] } } }
```

En Windows, un cliente que no puede arrancar `npx` directamente necesita `"command": "cmd", "args": ["/c", "npx", "-y", "@botmesh/mcp"]`.

### Herramientas de documentación

`--docs <dir>` (o `BOTMESH_DOCS_DIR`; el nombre anterior, `BOTWA_DOCS_DIR`, se sigue leyendo) apunta a un árbol Markdown local, como la carpeta `docs/` de un clon del repositorio; las guías no van dentro del paquete. Sin él las dos herramientas de docs **no** se anuncian en `tools/list`, así que un cliente nunca ve una herramienta que no puede funcionar.

### Desde el repositorio

```bash theme={null}
pnpm build                                     # los paquetes se resuelven por lib/

node packages/mcp/lib/bin.js --docs docs       # herramientas de flujo + docs_search / docs_page
node packages/mcp/lib/bin.js                   # solo herramientas de flujo
```

En VS Code el repo ya trae `.vscode/mcp.json`: ejecuta `pnpm build` una vez y arranca el servidor *botmesh* desde la vista MCP.

### Por programa

```ts theme={null}
import { createMcpServer, serveStream } from '@botmesh/mcp'

const server = createMcpServer({ docsDir: 'docs' })
await serveStream(process.stdin, { server, write: (line) => { process.stdout.write(`${line}\n`) } })
```

La entrada principal (`createMcpServer`, `serveStream`, `runStdio`, las revisiones del protocolo, la identidad del servidor y `EXAMPLE_FLOW_DOCUMENT`) sigue semver; el framing JSON-RPC, el catálogo de herramientas y la búsqueda en la documentación viven en `@botmesh/mcp/internal`, sin garantía semver.

## Herramientas

| Herramienta | Entrada | Devuelve |
| - | - | - |
| `flow_validate` | `document` | `{ valid, issues: [{ path, message }], summary? }` — cada issue trae el JSON Pointer del nodo que falla. |
| `flow_analyze` | `document`, `subflows?`, `format?`, `direction?` | Valida, compila, dibuja el grafo (`mermaid` por defecto, `graph` con `format: "json"`) y devuelve los diagnósticos de `lintFlows`. |
| `flow_migrate` | `document`, `target?` | `{ document, from, to, applied, issues }`. Un documento sin `version` se lee como 0. |
| `flow_diff` | `left`, `right` | `{ changed, metadata, added, removed, changedSteps, before, after }` (los dos últimos son digests). |
| `flow_digest` | `document` | `{ digest, version }` — `sha256` sobre JSON canónico, así que el orden de claves y el formato no lo cambian. |
| `flow_schema` | — | El esquema draft 2020-12, sus `limits` y `stepKinds` (derivados del propio esquema). |
| `flow_example` | — | Un documento canónico que valida y lintea limpio. |
| `docs_search` | `query`, `limit?` | Secciones con `path`, `title`, `heading`, `snippet` y `score` (solo con directorio de docs). |
| `docs_page` | `path` | El markdown de una página (solo con directorio de docs). |

`flow_analyze` ejecuta **las mismas** `describeFlows()` y `lintFlows()` que usan `bot.describe()` y `bot.lint()`, y `flow_*` envuelve `@botmesh/flow-schema`, así que el servidor no puede contradecir al runtime ni al gate de despliegue.

### «Válido» o «inválido» es un resultado, no un error

Un documento inválido es una llamada **correcta** cuyo payload dice `valid: false` con los problemas:

```json theme={null}
{ "jsonrpc": "2.0", "id": 2, "result": { "content": [{ "type": "text", "text": "{\n  \"valid\": false,\n  \"issues\": [{ \"path\": \"/steps/0/text\", \"message\": \"must be a string of 1-4096 characters\" }]\n}" }] } }
```

`isError: true` queda reservado para la **petición** (argumentos ausentes o mal tipados, una versión que no se puede migrar, una ruta fuera del directorio de docs), así que un agente distingue «mi documento necesita trabajo» de «mi llamada estaba mal».

Los argumentos se comprueban contra el `inputSchema` que anuncia `tools/list` antes de ejecutar la herramienta: una clave desconocida, una obligatoria que falta, un valor fuera de un `enum` o de un rango (`format`, `direction`, `target` hasta la versión actual del documento, `limit` de 1 a 25) o un valor anidado a más de 64 niveles falla con una frase que lo nombra, por ejemplo `invalid arguments for flow_validate: unknown argument "doc" (accepted: "document")`. Los textos de error nunca llevan rutas absolutas: una página que no existe contesta `page not found: guide/x.md`.

## Protocolo

* `initialize` responde con `capabilities: { tools: { listChanged: false } }`, la versión del paquete y un bloque `instructions` con las reglas caras de equivocar (la API v1 no existe, los documentos son datos, un handler no debe hacer `await` de la conversación que inicia, los ids son opacos).
* Revisiones soportadas: `2025-06-18`, `2025-03-26`, `2024-11-05`. A un cliente que pide otra se le contesta `2025-06-18` y él decide qué hacer.
* Cada herramienta lleva `annotations` (`readOnlyHint: true`, `destructiveHint: false`, `idempotentHint: true`, `openWorldHint: false`), así que un cliente puede ejecutarlas sin pedir confirmación.
* `ping`, `tools/list` y `tools/call`; cualquier otra cosa (`resources/*`, `prompts/*`, `logging/setLevel`) contesta `-32601`, porque esas capabilities no se anuncian.
* **Las notificaciones nunca se contestan** (JSON-RPC lo prohíbe), incluida `notifications/initialized`.
* Una respuesta enviada por el cliente (un mensaje con `result` o `error` y sin `method`) se ignora; nunca se contesta.
* Un mensaje JSON por línea. Una línea malformada contesta `-32700`, una línea más larga que `maxMessageLength` (16 Mi caracteres por defecto, `DEFAULT_MAX_MESSAGE_LENGTH`) contesta `-32600` sin acumularse en memoria, y la sesión sigue. Un array JSON es un batch (revisión `2025-03-26`): se contesta con un array de respuestas, sin las notificaciones.
* Por stdout solo salen mensajes del protocolo; los diagnósticos van a stderr. Si el cliente cierra la tubería, el servidor deja de escribir y termina cuando acaba stdin, sin un `EPIPE` sin manejar. Un directorio `--docs` que no existe se avisa por stderr al arrancar.

## Búsqueda en la documentación

Con `--docs`, `docs_search` indexa cada `.md` del directorio salvo la salida generada (`api/`, `dist/`, `.vitepress/`) y las notas de diseño internas (`superpowers/`), y las parte en secciones por heading (un `#` dentro de un bloque de código no es un heading).

El ranking es determinista y deliberadamente simple: términos sin acentos ni mayúsculas, **frecuencia inversa de documento** para que un identificador raro (`appendLog`) gane a una palabra que aparece en todas las páginas (`durabilidad`), presencia en vez de conteos brutos, doble peso si el término está en el heading, bonus por cobertura y por frase exacta. Las páginas en inglés y en español se indexan juntas, así que una consulta alcanza a las dos.

`docs_page` solo lee archivos `.md` y rechaza cualquier ruta que se salga del directorio de docs.

## Tests

`pnpm --filter @botmesh/mcp test` cubre el framing (mensajes partidos entre chunks, `\r\n`, una última línea sin salto, chunks en UTF-8, batches, líneas demasiado largas, un fuzz con semilla de chunks crudos), la comprobación de argumentos, cada herramienta con entrada válida e inválida, los 14 tipos de paso, la resolución de subflows, la migración de un documento sin versión, una búsqueda bilingüe sobre un árbol temporal (incluido el rechazo de `../`) y la sincronización de la versión con `package.json`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.