Tools
Agents get tools from MCP (Model Context Protocol) servers. Settings can reference MCP sources from either user settings ($HOME/.aether/settings.json) or project settings (.aether/settings.json) via mcps, and the default project source is usually .aether/mcp.json.
MCP config files
Section titled “MCP config files”Aether accepts either servers or the mcpServers alias at the top level:
{ "servers": { "coding": { "type": "in-memory", "args": ["--rules-dir", ".aether/skills"] } }}{ "mcpServers": { "playwright": { "command": "npx", "args": ["-y", "@playwright/mcp@latest"] } }}If a server entry has a command and no type, it is treated as "type": "stdio".
Server types
Section titled “Server types”Built-in Aether servers run inside the agent process. No subprocess is launched.
{ "servers": { "coding": { "type": "in-memory", "args": ["--rules-dir", ".aether/skills"] }, "skills": { "type": "in-memory", "args": ["--dir", ".aether/skills", "--notes-dir", ".aether/notes"] }, "tasks": { "type": "in-memory" }, "subagents": { "type": "in-memory" }, "survey": { "type": "in-memory" }, "plan": { "type": "in-memory" } }}| Field | Type | Description |
|---|---|---|
type | "in-memory" | Required. |
args | string[] | Arguments passed to the registered in-memory server factory. |
input | any JSON or null | Optional factory input for in-memory servers that accept one. |
proxy | boolean | Whether to hide this server behind the MCP tool proxy. |
External MCP servers launched as subprocesses. Communication happens over JSON-RPC via stdin/stdout.
{ "servers": { "playwright": { "command": "npx", "args": ["-y", "@playwright/mcp@latest"] }, "github": { "type": "stdio", "command": "gh-mcp", "env": { "GITHUB_TOKEN": "$GITHUB_TOKEN" } } }}| Field | Type | Description |
|---|---|---|
type | "stdio" | Optional when command is present. |
command | string | Executable to run. |
args | string[] | Command arguments. |
env | object | Environment variables for the subprocess. |
proxy | boolean | Whether to expose this server through proxy__call_tool. |
Remote MCP servers over streamable HTTP.
{ "servers": { "linear": { "type": "http", "url": "https://mcp.linear.app/mcp", "headers": { "Authorization": "Bearer $LINEAR_API_KEY" } } }}| Field | Type | Description |
|---|---|---|
type | "http" | Required. |
url | string | Streamable HTTP endpoint URL. |
headers | object | Optional headers. Aether currently forwards the Authorization header to the transport. |
proxy | boolean | Whether to expose this server through proxy__call_tool. |
Remote MCP servers over HTTP with Server-Sent Events. Internally, Aether uses the same HTTP transport path.
{ "servers": { "remote-tools": { "type": "sse", "url": "https://mcp.example.com/sse", "headers": { "Authorization": "Bearer $MCP_TOKEN" } } }}| Field | Type | Description |
|---|---|---|
type | "sse" | Required. |
url | string | SSE endpoint URL. |
headers | object | Optional headers. Aether currently forwards the Authorization header to the transport. |
proxy | boolean | Whether to expose this server through proxy__call_tool. |
Built-in servers
Section titled “Built-in servers”| Server | Purpose | Args |
|---|---|---|
coding | File I/O, bash, grep/find, web fetch/search, and LSP-backed coding tools | --root-dir <path>, repeat --rules-dir <path>, --permission-mode always-allow|auto|always-ask, --disable-lsp |
skills | Skill discovery, slash-command prompts, and notes | Required: repeat --dir <path> and --notes-dir <path> |
tasks | Hierarchical task management | Optional --dir <base> for persistent storage |
subagents | Spawn child agents from loaded settings | --project-root <path> (alias: --dir, defaults to .) |
survey | Structured human-in-the-loop questions | No args |
plan | Plan prompt and markdown plan review | Optional --prompt-file <path>, plus optional trailing submit command |
MCP sources in settings
Section titled “MCP sources in settings”The mcps array in user or project settings can reference files, inline configs, optional files, or proxied files:
{ "mcps": [ ".aether/mcp.json", { "type": "file", "path": "${WORKSPACE}/.aether/local-mcp.json", "optional": true }, { "type": "file", "path": ".aether/external-mcp.json", "proxy": true }, { "type": "inline", "servers": { "coding": { "type": "in-memory", "args": ["--rules-dir", ".aether/skills"] } } } ], "agents": [ { "name": "Build", "description": "Builds features", "model": "anthropic:claude-sonnet-4-5-20250929", "userInvocable": true, "prompts": [".aether/BUILD.md"] } ]}Agent-level mcps replace the top-level list when the agent’s array is non-empty. String shorthand entries are required file sources. Use a typed file object when you need proxy or optional.
User, project, and MCP source resolution
Section titled “User, project, and MCP source resolution”Aether first merges user settings from $HOME/.aether/settings.json and project settings from .aether/settings.json. Set AETHER_HOME to use a different user settings directory. Project settings win when they define the same agent, and a non-empty project top-level mcps list replaces a user top-level mcps list. Within the selected agent, agent-level mcps replace top-level mcps when non-empty.
MCP file paths use resource path resolution:
- In project settings, plain relative paths resolve from the workspace root.
- In user settings, plain relative paths resolve from the Aether home (
$HOME/.aetherby default). ${WORKSPACE}always resolves to the current workspace root. This is the preferred way for a user-level agent to load a project’s.aether/mcp.json.- Other
$VARand${VAR}references fall through to the process environment. optional: trueskips a missing MCP file or unresolved variable instead of failing settings resolution.
{ "agents": [ { "name": "Build", "description": "Reusable coding agent", "model": "anthropic:claude-sonnet-4-5-20250929", "userInvocable": true, "prompts": ["BUILD.md"], "mcps": [ "mcp.json", { "type": "file", "path": "${WORKSPACE}/.aether/mcp.json", "optional": true } ] } ]}In this user-level example, mcp.json resolves to $HOME/.aether/mcp.json by default, while ${WORKSPACE}/.aether/mcp.json resolves to the project MCP config.
Merging and proxy behavior
Section titled “Merging and proxy behavior”Multiple MCP sources are loaded in order after settings resolution. Server names are unique keys; when two sources define the same server, the later source wins, including its proxy flag.
A server can be proxied in two ways:
- Set
"proxy": trueon the server entry in an MCP config file. - Reference a file source with
{ "type": "file", "path": "...", "proxy": true }, which marks every server loaded from that file as proxied.
proxy and optional can be combined: { "type": "file", "path": "${WORKSPACE}/.aether/external-mcp.json", "proxy": true, "optional": true }.
{ "servers": { "chrome-devtools": { "type": "stdio", "command": "npx", "args": ["-y", "chrome-devtools-mcp@latest"], "proxy": true }, "linear": { "type": "http", "url": "https://mcp.linear.app/mcp", "proxy": true } }}When any server is proxied, Aether exposes one virtual tool named proxy__call_tool, writes nested tool definitions under $HOME/.aether/tool-proxy/proxy by default, or $AETHER_HOME/tool-proxy/proxy when AETHER_HOME is set, and adds instructions telling the agent how to browse those files. The server name proxy is reserved when proxied servers are present.
Variable expansion
Section titled “Variable expansion”Variables are expanded in two places: MCP source paths in settings, and server fields inside MCP JSON files. Environment variables are expanded in stdio command, stdio args, stdio env values, in-memory args, HTTP/SSE url, and the HTTP/SSE Authorization header value. ${WORKSPACE} is also available when server configs are converted into running MCP servers.
Supported syntax:
| Syntax | Meaning |
|---|---|
$VAR | Expand VAR |
${VAR} | Expand VAR |
$$ | Literal $ |
Missing variables are errors; they are not replaced with an empty string. For MCP source paths only, optional: true skips the missing source when a variable is undefined.
{ "servers": { "github": { "command": "$HOME/.local/bin/github-mcp", "env": { "GITHUB_TOKEN": "$GITHUB_TOKEN", "PROMPT": "cost is $$5" } } }}Tool filtering
Section titled “Tool filtering”The tools field in an agent entry restricts which discovered MCP tools the model can use.
Filters can be tool name patterns or (MCP) annotation matchers. allow is applied first; deny then removes matching tools, so deny wins.
Name patterns
Section titled “Name patterns”Tool names use server__tool with a double underscore. Patterns support exact names or a trailing * prefix wildcard only.
| Pattern | Matches |
|---|---|
coding__* | All coding server tools |
coding__read_file | Only the read_file tool |
coding__web_* | web_fetch and web_search |
tasks__* | All task management tools |
plan__submit_plan | Only the plan review tool |
coding__bash | Only the coding server’s bash tool |
Wildcards are only valid at the end of a pattern.
Annotation matchers
Section titled “Annotation matchers”MCP servers can attach tool annotations and you can filter tools based on those:
| Matcher field | MCP annotation | Meaning |
|---|---|---|
readOnly | readOnlyHint | The tool should not modify its environment. |
destructive | destructiveHint | The tool may perform destructive updates. |
idempotent | idempotentHint | Repeated calls with the same arguments should not add effects. |
openWorld | openWorldHint | The tool may interact with external systems or the network. |
Annotation-first read-only agent:
{ "agents": [ { "name": "ReadOnly", "description": "Can inspect code but cannot write files or run shell commands", "model": "openai:gpt-5.5", "userInvocable": true, "prompts": [".aether/READONLY.md"], "mcps": [".aether/mcp.json"], "tools": { "allow": [{ "readOnly": true }] } } ]}Read-only tools plus explicit plan tools:
{ "agents": [ { "name": "Planner", "description": "Can inspect code and write plan files", "model": "anthropic:claude-sonnet-4-5-20250929", "userInvocable": true, "mcps": [".aether/mcp.json"], "tools": { "allow": [{ "readOnly": true }, "plan__*", "skills__*"], "deny": ["coding__web_*"] } } ]}Full coding without bash:
{ "agents": [ { "name": "NoShell", "description": "Can use coding tools except shell execution", "model": "anthropic:claude-sonnet-4-5-20250929", "userInvocable": true, "prompts": [".aether/NOSHELL.md"], "mcps": [".aether/mcp.json"], "tools": { "allow": ["coding__*"], "deny": ["coding__bash", "coding__read_background_bash"] } } ]}Deny destructive tools from mixed servers:
{ "agents": [ { "name": "SafeOps", "description": "Allows everything except tools annotated as destructive", "model": "anthropic:claude-sonnet-4-5-20250929", "userInvocable": true, "mcps": [".aether/mcp.json"], "tools": { "deny": [{ "destructive": true }] } } ]}If tools is omitted or empty, the agent can use all tools from its configured MCP servers.