Saltar al contenido principal
Extiendes Narya con recursos que declaras en archivos, paquetes que instalas, extensiones que registras y scripts confinados. Un cliente que escribes maneja la API del host.

Servidores de herramientas MCP


Declara un servidor como [tool_servers.<name>] en config.toml. Dale exactamente un transporte. command lanza un proceso y habla stdio. url habla HTTP streamable sobre https, o sobre http en loopback. Una declaración con ambos, o sin ninguno, se niega a cargar.
env reemplaza el entorno del hijo. No se suma a él. El hijo no hereda nada, ni siquiera PATH y HOME. Declara ambos para cualquier servidor npx o uvx, o el hijo termina antes de servir una herramienta.
Las demás claves son dir, headers, oauth, timeout_ms y enabled. Cada servidor declarado se conecta al arrancar a menos que definas enabled = false. Narya mantiene una sesión de larga vida por servidor y se reconecta con backoff. Cuando un servidor se desconecta, Narya retira sus herramientas del registro, así que el modelo nunca ve las herramientas de un servidor que se fue. Define oauth = true para un servidor remoto que inicia sesión. Narya mantiene la conexión abierta, imprime la URL de autorización y escucha en 127.0.0.1:7666 el callback mientras el inicio de sesión está abierto. Un inicio de sesión que nadie responde cuesta ese único servidor y nada más. Una ejecución de un solo turno no puede completar un inicio de sesión, y lo dice.
Un servidor de herramientas declarado se ejecuta bajo la regla tool, que el conjunto incluido permite. Las reglas de escritura y de secretos de Narya no se aplican a lo que el propio servidor lee o escribe. Acótalo con ask tool <name> o deny tool <name>.

Servidores de herramientas de un repositorio de confianza


Narya lee el .mcp.json en la raíz de un repositorio en el que confías, en el formato de Claude Code, e inicia los servidores que declara. Solo las sesiones de ese repositorio reciben sus herramientas.
  • Un servidor sin type, o con type definido como stdio, lee command, args y env.
  • Un servidor con type definido como http o streamable-http lee url y headers, e inicia sesión cuando el servidor lo pide.
  • Narya expande ${VAR} y ${VAR:-default}. Un servidor que nombra una variable no definida y sin valor predeterminado, o una de las variables propias de Narya, no se inicia.
  • Narya ignora cualquier otra clave y lo indica en su log.
Un servidor de comando se ejecuta en la raíz del repositorio, con CLAUDE_PROJECT_DIR definido como esa raíz. Recibe el entorno que recibe un hook de repositorio, más su propio env. Narya no inicia un servidor cuyo nombre el host ya tiene, y el host mantiene su propia fuente con ese nombre. El .mcp.json que Narya lee primero bajo tu respuesta de confianza se inicia con esa respuesta. Un .mcp.json cambiado no inicia nada hasta que una persona lo permite en una conversación atendida. Un cambio demasiado largo para mostrarse completo en una pregunta no se inicia. Narya detiene los servidores de un repositorio cuando retiras la confianza, y después de una hora sin uso. En un contenedor que clonó un repositorio, solo los servidores de comando del archivo del repositorio clonado se ejecutan, dentro del contenedor. Cada repositorio inicia sesión en sus servidores por su cuenta, con el nombre <name> in <repository>. Cuando servidores con un mismo nombre en dos repositorios definen una herramienta de forma distinta, Narya ofrece una definición. narya host status lista estos servidores con su repositorio y nombra las herramientas que las sesiones de un repositorio no reciben.

Árboles de herramientas de OpenAPI


Declara [tool_trees.<name>] para convertir un documento OpenAPI en un árbol de herramientas invocable. Las claves son spec, base_url, headers, timeout_ms y enabled. Una ruta spec relativa se resuelve contra tu home de Narya. Define base_url cuando el documento no declara un servidor propio. Narya deriva las herramientas una vez al arrancar. No se ejecuta ningún servidor, y ninguna sesión se reconecta.

Scripts confinados


Narya ejecuta ECMAScript en un motor confinado. El motor no alcanza ningún sistema de archivos, ninguna red, ningún entorno ni ningún cargador de módulos. No tiene evaluación dinámica. La profundidad de llamadas se detiene en 4,096, y el código fuente se detiene en 256 KiB. Tres llamadores lo usan: la herramienta run_program del modelo, los workflows y el descubrimiento de herramientas.

La API del host


El host sirve una API HTTP, y cada cliente la maneja. La API del host describe el transporte, el stream de eventos y los envelopes.

Paquetes


narya ext add <source> instala un paquete desde una ruta local o una referencia de módulo Go. narya ext list, remove, enable y disable gestionan lo que instalaste. Un paquete que declara solo recursos agrega agentes, skills, comandos y hooks, y se instala por copia. Un paquete con código Go se compila en tu binario de Narya, así que necesita un toolchain de Go local. Narya te pide confiar en un paquete que lleva código o hooks antes de instalarlo. Agrega --yes para omitir esa pregunta en un script.

Extensiones registradas


Para agregar una extensión que se ejecuta como su propio servicio HTTPS, regístrala con POST /v1/extensions. Eso exige el permiso extensions:manage. El cuerpo exige dos campos: name, con la forma publisher/extension, y endpoint. Los demás campos son opcionales: description, points, slots, position, grants, models y enabled. El endpoint debe ser una URL https://, y esto también vale para las direcciones de loopback. El host resuelve la dirección antes de guardar el registro. Rechaza una dirección de loopback o privada, a menos que allow_private_endpoints en la tabla [extensions] de config.toml admita ese rango. Ninguna configuración admite otra dirección fuera de internet pública, como una dirección link-local o multicast. Un slot exclusivo admite una extensión. Un registro que reclama un slot exclusivo que otra extensión ocupa recibe 409 con NRY-0006. Para admitir ambos, indica el ganador de ese slot en prefer dentro de la tabla [extensions]. La respuesta lleva el secreto de la extensión, una sola vez. Ninguna lectura lo devuelve otra vez. Para cambiar el secreto, llama a POST /v1/extensions/{publisher}/{name}/secret. La respuesta lleva el nuevo secreto y el momento en que el anterior deja de funcionar. El host firma cada llamada a la extensión con el secreto. Hasta que el secreto anterior deje de funcionar, Narya-Signature lleva una firma por cada secreto, separadas por un espacio. Acepta la llamada cuando una de ellas se verifica con el secreto que guardas. La extensión firma sus propias llamadas de la misma forma, y solo puede llamar al stream de eventos. La extensión sirve sus propias operaciones en su endpoint. El host llama a /transform en los puntos de decisión donde la extensión actúa. Llama a /models y /supply cuando la extensión suministra modelos, a /tools cuando publica herramientas y a /invoke para ejecutar una operación con nombre. El host no sigue una redirección de la extensión. Un cliente llega a una extensión a través del host con POST /v1/extensions/{name}/invoke. El token de un miembro común es suficiente. El host firma la llamada reenviada, así que el cliente no necesita el secreto. Una respuesta de /invoke de más de 1 MiB hace fallar la llamada. El modelo lee como máximo los primeros 30,000 bytes del texto de una respuesta de herramienta de una extensión. Un aviso antes de ese texto le dice al modelo que el resto no se puede alcanzar, y el modelo lee la llamada como fallida. La parte estructurada machine de la respuesta pasa sin cambios.

Agentes, skills, comandos y hooks


Narya lee los formatos propios de Claude Code sin ningún cambio. Los agentes son archivos markdown con frontmatter YAML, y el cuerpo es el prompt. Las claves son name, description, tools, disallowedTools, model y effort, y un archivo sin name toma el nombre del archivo. Un agente en tu home de Narya o en .narya/agents también lee mode y hidden. Narya ignora cualquier otra clave. tools es una lista de permitidos y nunca una concesión: Narya intersecta la lista de un hijo con la de su padre, así que un agente hijo puede perder herramientas, nunca ganarlas. disallowedTools quita las herramientas que nombra, y una entrada con una regla entre paréntesis quita la herramienta entera. effort define el nivel de razonamiento de los turnos del agente: low, medium, high o max. Narya lee los agentes desde tu home de Narya, luego ~/.claude/agents, luego los .claude/agents y .narya/agents de un repositorio en el que confías. Cuatro agentes vienen con el binario: explore, general, plan y review. Las skills siguen el estándar Agent Skills: un directorio que contiene un SKILL.md. Narya lee la misma jerarquía, ~/.claude/skills incluido, y la vuelve a leer en cada solicitud. Una skill que agregas a mitad de sesión llega al siguiente turno. Los comandos vienen de tu home de Narya, de ~/.claude/commands, y de los .claude/commands y .narya/commands de un repositorio en el que confías. Los hooks vienen de la tabla hooks de ~/.claude/settings.json, y del mismo archivo en un repositorio en el que confías. Una tabla hooks cambiada entra en vigor solo después de que una persona la permite en una conversación atendida. Consulta Cuándo entra en vigor un cambio de configuración. Narya los lee con las claves de stdin y los códigos de salida que esos scripts ya usan. Cuatro eventos tienen equivalencia: PreToolUse, PostToolUse, UserPromptSubmit y SessionStart. Otros eventos, como Stop, SubagentStop, Notification, PreCompact y SessionEnd, no tienen equivalente. Narya los omite y lo indica en su log.
Estas diferencias no tienen solución alternativa. Narya lee la salida de un hook para obtener un veredicto y, antes de una llamada a herramienta, un updatedInput que reescribe la llamada. additionalContext nunca llega al contexto del modelo. systemMessage no va a ninguna parte. Un hook leído desde settings.json que agota su timeout, sale con un código distinto de 0 o 2 o imprime una salida que Narya no puede leer deja pasar la llamada. Este formato no tiene ningún campo para cambiar eso. Su tool_response llega como una cadena, no como un objeto.

Los hooks propios de Narya


Declara [[hooks]] en config.toml con point, command, timeout_ms, fail y match. fail no tiene valor predeterminado, así que decláralo. Un cambio en ellos entra en vigor en el siguiente inicio del host después de que una persona permite el nuevo config.toml. match filtra nombres de herramientas en before-tool-call y after-tool-call. Usa un nombre de herramienta o una expresión regular Go que coincida con el nombre completo, como read|write. Un valor vacío o * coincide con todas las herramientas. Otros puntos de hook no aceptan un match no vacío. Cuatro puntos deciden, y un hook ahí puede detener lo que tiene delante: before-tool-call, before-model-request, after-tool-call, at-permission-ask. Ocho puntos observan, y un hook ahí se entera de lo que pasó sin cambiarlo: session-started, lane-started, lane-finished, delegation-created, child-asked, skill-invoked, permission-denied, session-compacted. El archivo propio de un repositorio no puede declarar at-permission-ask.

Delegación


La delegación es una llamada a herramienta. Define sus límites en [delegation] en config.toml. La clave max_depth cuenta los niveles por debajo de tu conversación, y 0 desactiva la delegación. Define max_concurrent para acotar cuántas lanes ejecuta una conversación en cualquier instante.