MCP tool servers
Declare a server as
[tool_servers.<name>] in config.toml. Give it exactly one transport. command spawns a process and speaks stdio. url speaks streamable HTTP over https, or over http on loopback. A declaration with both, or with neither, refuses to load.
dir, headers, oauth, timeout_ms and enabled. Every declared server connects at startup unless you set enabled = false.
Narya keeps one long-lived session per server and reconnects with backoff. When a server disconnects, Narya withdraws its tools from the registry, so the model never sees a departed server’s tools.
Set oauth = true for a remote server that signs in. Narya holds the connection open, prints the authorization URL, and listens on 127.0.0.1:7666 for the callback while the sign-in is open. A sign-in nobody answers costs that one server and nothing else. A one-shot run cannot complete a sign-in, and it says so.
OpenAPI tool trees
Declare
[tool_trees.<name>] to turn an OpenAPI document into a callable tool tree. The keys are spec, base_url, headers, timeout_ms and enabled. A relative spec path resolves against your Narya home. Set base_url when the document declares no server of its own. Narya derives the tools once at startup. No server runs, and no session reconnects.
Confined scripts
Narya runs ECMAScript in a confined engine. The engine reaches no filesystem, no network, no environment and no module loader. It has no dynamic evaluation. Call depth stops at 4,096, and source stops at 256 KiB. Three callers use it: the model’s
run_program tool, workflows, and tool discovery.
The host API
The host serves one HTTP API over a Unix socket, and every client drives it. The host API describes the transport, the event stream and the envelopes.
Agents, skills, commands and hooks
Narya reads Claude Code’s own formats without any change. Agents are markdown files with YAML frontmatter.
name is the only field a file must carry. The others are description, prompt, tools, model, mode and hidden. tools is an allowlist and never a grant: Narya intersects a child’s list with its parent’s, so a child agent can lose tools, never gain them.
Narya reads agents from your Narya home, then ~/.claude/agents, then the .claude/agents and .narya/agents of a repository you trust. Four agents ship with the binary: explore, general, plan and review.
Skills follow the Agent Skills standard: a directory that holds a SKILL.md. Narya reads the same ladder, ~/.claude/skills included, and re-reads it on each request. A skill you add mid-session reaches the next turn.
Commands come from your Narya home, from ~/.claude/commands, and from the .claude/commands and .narya/commands of a repository you trust.
Hooks come from the hooks table of ~/.claude/settings.json, and from the same file in a repository you trust. Narya reads them with the stdin keys and exit codes those scripts already use. Four events map: PreToolUse, PostToolUse, UserPromptSubmit and SessionStart. Five have no equivalent, so Narya skips them and writes a line on standard error: Stop, SubagentStop, Notification, PreCompact and SessionEnd.
Narya’s own hooks
Declare
[[hooks]] in config.toml with point, command, timeout_ms, fail and match. fail carries no default, so state it. match filters a before-tool-call hook to one tool name.
Four points decide, and a hook there can stop what it fronts:
before-tool-call, before-model-request, after-tool-call, at-permission-ask.
Eight points observe, and a hook there learns what happened without changing it:
session-started, lane-started, lane-finished, delegation-created, child-asked, skill-invoked, permission-denied, session-compacted.
A repository’s own file cannot declare at-permission-ask.
Delegation
Delegation is a tool call. Set its bounds under
[delegation] in config.toml. The max_depth key counts the levels below your conversation, and 0 turns delegation off. Set max_concurrent to bound how many lanes one conversation runs at any instant.
