Skip to content
Theme:

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.

Aether accepts either servers or the mcpServers alias at the top level:

.aether/mcp.json
{
"servers": {
"coding": {
"type": "in-memory",
"args": ["--rules-dir", ".aether/skills"]
}
}
}
mcpServers alias
{
"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".

Built-in Aether servers run inside the agent process. No subprocess is launched.

.aether/mcp.json
{
"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" }
}
}
FieldTypeDescription
type"in-memory"Required.
argsstring[]Arguments passed to the registered in-memory server factory.
inputany JSON or nullOptional factory input for in-memory servers that accept one.
proxybooleanWhether to hide this server behind the MCP tool proxy.
ServerPurposeArgs
codingFile 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
skillsSkill discovery, slash-command prompts, and notesRequired: repeat --dir <path> and --notes-dir <path>
tasksHierarchical task managementOptional --dir <base> for persistent storage
subagentsSpawn child agents from loaded settings--project-root <path> (alias: --dir, defaults to .)
surveyStructured human-in-the-loop questionsNo args
planPlan prompt and markdown plan reviewOptional --prompt-file <path>, plus optional trailing submit command

The mcps array in user or project settings can reference files, inline configs, optional files, or proxied files:

.aether/settings.json
{
"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.

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/.aether by 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 $VAR and ${VAR} references fall through to the process environment.
  • optional: true skips a missing MCP file or unresolved variable instead of failing settings resolution.
$HOME/.aether/settings.json
{
"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.

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:

  1. Set "proxy": true on the server entry in an MCP config file.
  2. 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 }.

.aether/external-mcp.json
{
"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.

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:

SyntaxMeaning
$VARExpand 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.

.aether/mcp.json
{
"servers": {
"github": {
"command": "$HOME/.local/bin/github-mcp",
"env": {
"GITHUB_TOKEN": "$GITHUB_TOKEN",
"PROMPT": "cost is $$5"
}
}
}
}

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.

Tool names use server__tool with a double underscore. Patterns support exact names or a trailing * prefix wildcard only.

PatternMatches
coding__*All coding server tools
coding__read_fileOnly the read_file tool
coding__web_*web_fetch and web_search
tasks__*All task management tools
plan__submit_planOnly the plan review tool
coding__bashOnly the coding server’s bash tool

Wildcards are only valid at the end of a pattern.

MCP servers can attach tool annotations and you can filter tools based on those:

Matcher fieldMCP annotationMeaning
readOnlyreadOnlyHintThe tool should not modify its environment.
destructivedestructiveHintThe tool may perform destructive updates.
idempotentidempotentHintRepeated calls with the same arguments should not add effects.
openWorldopenWorldHintThe tool may interact with external systems or the network.

Annotation-first read-only agent:

.aether/settings.json
{
"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:

.aether/settings.json
{
"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:

.aether/settings.json
{
"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:

.aether/settings.json
{
"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.