Skip to content

Tools & Plugins

AgentZero ships with 50+ built-in tools and supports extension via WASM plugins, process plugins, MCP servers, skills, and dynamic tools (runtime-created tools that persist across sessions). Every tool enforces fail-closed security — capabilities are denied unless explicitly enabled. All tools implement input_schema() for structured tool-use APIs (Anthropic tool_use, OpenAI function calling).

Tools are organized into three tiers that control which tools are compiled into the binary. This is especially relevant for resource-constrained deployments (e.g., Raspberry Pi, embedded devices).

TierDescriptionIncluded Tools
CoreEssential agent tools — always includedread_file, shell, glob_search, content_search, memory_store, memory_recall, memory_forget, task_plan
ExtendedStandard tools for most deployments (default)Core + write_file, file_edit, apply_patch, git_operations, web_search, web_fetch, http_request, browser, delegate, converse, cron_*, subagent_*
FullAll 50+ tools including hardware, SOP, WASM, and integration toolsExtended + hardware_*, sop_*, wasm_*, composio, pushover, schedule

Use the embedded-minimal feature flag to build with only the Core tier, producing a significantly smaller binary suitable for edge devices:

Terminal window
cargo build -p agentzero --release --no-default-features --features embedded-minimal

The default build includes the Extended tier. To include all tools, enable the full-tools feature.

ToolDescription
read_fileRead file contents within allowed root
shellExecute allowlisted shell commands
glob_searchFind files by glob pattern
content_searchSearch file contents with regex
memory_storeStore entries in agent memory
memory_recallRecall entries from agent memory
memory_forgetRemove entries from agent memory
image_infoExtract image metadata
docx_readRead DOCX file contents
pdf_readRead PDF file contents
screenshotCapture screen screenshots
task_planCreate and manage task plans
process_toolExecute external processes
subagent_spawnSpawn background sub-agents
subagent_listList running sub-agents
subagent_manageManage sub-agent lifecycle
cli_discoveryDiscover CLI capabilities
proxy_configQuery proxy configuration
delegate_coordination_statusCheck delegate coordination status
sop_listList Standard Operating Procedures
sop_statusCheck SOP execution status
sop_advanceAdvance SOP to next step
sop_approveApprove SOP step
sop_executeExecute an SOP
hardware_board_infoQuery hardware board information
hardware_memory_mapRead hardware memory map
hardware_memory_readRead hardware memory
wasm_moduleLoad WASM modules
wasm_tool_execExecute WASM tool
ToolDescriptionConfig
write_fileWrite file contents within allowed root[security.write_file]
file_editEdit files with search/replaceEnabled with write_file
apply_patchValidate and apply structured patchesEnabled with write_file
git_operationsGit operations (status, diff, log, etc.)enable_git
http_requestMake HTTP requests to allowed domains[http_request]
web_fetchFetch and convert web pages to markdown[web_fetch]
url_validationValidate URLs against access policy[url_access]
web_searchSearch the web via DuckDuckGo/Brave/etc[web_search]
browserBrowser automation and screenshot[browser]
browser_openOpen URLs in system browser[browser]
cron_addAdd a cron schedule[cron]
cron_listList cron schedules[cron]
cron_removeRemove a cron schedule[cron]
cron_updateUpdate a cron schedule[cron]
cron_pausePause a cron schedule[cron]
cron_resumeResume a cron schedule[cron]
scheduleSchedule one-time tasks[cron]
composioComposio integrationenable_composio
pushoverPushover notificationsenable_pushover
agent_manageCreate, list, update, or delete persistent named agents. Supports create_from_description for NL agent definitions.enable_agent_manage
tool_createCreate, list, delete, export, or import dynamic tools at runtime. Supports shell, HTTP, LLM, and composite strategies.enable_dynamic_tools
proposal_createCreate autopilot proposals for agent-driven work[autopilot]
proposal_voteApprove or reject autopilot proposals[autopilot]
mission_statusQuery autopilot mission status[autopilot]
trigger_fireManually fire an autopilot trigger[autopilot]
ToolDescriptionCondition
agents_ipcInter-process communication between agentsenable_agents_ipc (default: true)
converseMulti-turn conversations between agents or with humansWhen "converse" in allowed_tools
mcp__{server}__{tool}MCP server tools (one per remote tool)[security.mcp] + mcp.json
model_routing_configQuery model routing configurationWhen router is configured
delegateSpawn sub-agent with scoped toolsWhen [agents.*] configured

All tools implement the core Tool trait:

#[async_trait]
pub trait Tool: Send + Sync {
fn name(&self) -> &'static str;
fn description(&self) -> &'static str { "" }
fn input_schema(&self) -> Option<serde_json::Value> { None }
async fn execute(&self, input: &str, ctx: &ToolContext) -> anyhow::Result<ToolResult>;
}

The input_schema() method returns a JSON Schema describing expected input parameters. When provided, this enables structured tool-use APIs (Anthropic tool_use, OpenAI function calling) and input validation before execution. All 50+ built-in tools implement this method.

Terminal window
agentzero tools list # List all registered tools
agentzero tools list --with-schema # Include JSON schemas
agentzero tools list --json # Machine-readable output
agentzero tools info read_file # Show details for a specific tool
agentzero tools schema read_file # Print the JSON schema
agentzero tools schema shell --pretty # Pretty-printed schema

The ToolContext carries workspace-scoped security state:

pub struct ToolContext {
pub workspace_root: String,
pub allow_sensitive_file_reads: bool,
pub allow_sensitive_file_writes: bool,
pub sender_id: Option<String>,
// ... additional fields omitted for brevity
}

Reads text file contents with full path-safety enforcement.

Input: Relative file path (e.g., src/main.rs)

Security controls:

  • Path traversal prevention — rejects .. components and absolute paths
  • Canonicalization — resolves symlinks and validates the final path stays within allowed_root
  • Hard-link guard (B7) — blocks files with multiple hard links to prevent symlink attacks
  • Binary detection — rejects files containing null bytes or non-UTF8 content
  • Sensitive file detection — blocks .env, .aws/credentials, .ssh/id_rsa, .gnupg/, credentials.json, etc. unless allow_sensitive_file_reads is true
  • Size cap — 64 KiB per read (configurable)
[security.read_file]
allowed_root = "." # workspace root
max_read_bytes = 65536 # 64 KiB
allow_binary = false

Writes text files with the same path-safety enforcement as read_file.

Input: JSON payload:

{
"path": "src/output.txt",
"content": "file contents here",
"overwrite": false,
"dry_run": false
}

Security controls:

  • Disabled by default — requires explicit enabled = true
  • All read_file protections apply (path traversal, canonicalization, hard-link guard, sensitive file detection)
  • Existence check — errors if file exists and overwrite: false
  • Dry-run mode — preview capability without writing to disk

Output: dry_run={bool} path={path} bytes={count} overwrite={bool}

[security.write_file]
enabled = true
allowed_root = "."
max_write_bytes = 65536 # 64 KiB

Validates and applies structured patches using a strict envelope format.

Input: Patch content with BEGIN/END markers:

*** Begin Patch
*** Update File: src/main.rs
@@ ... patch content ...
*** End Patch

Security: Validates patch structure before any file modification. Rejects malformed envelopes.


Executes shell commands with allowlist-driven security. Only explicitly permitted commands can run.

Input: Command string (e.g., ls -la src/)

Security controls:

  • Command allowlist — only commands listed in allowed_commands can execute
  • Default allowlist: ls, pwd, cat, echo
  • Quote-aware validation — metacharacters (; & | > < $) are forbidden when unquoted, but allowed inside single/double quotes
  • Always forbidden — backtick (`) and null byte are blocked even inside quotes
  • Argument limits — max 8 arguments of 128 bytes each
  • Output truncation — stdout/stderr capped at 8 KiB with truncation notice

Output: status={code}\nstdout:\n...\nstderr:\n...

Examples:

Terminal window
# Allowed — semicolon is inside single quotes
echo 'hello;world'
# Blocked — unquoted semicolon is shell injection
echo hello;world
# Blocked — backtick is always forbidden
echo `whoami`

Shell tokenizer: The command parser performs quote-aware tokenization supporting single quotes (no interpretation), double quotes (with escape handling), and backslash escapes. Each character’s quoting context is tracked for policy validation.

[security]
allowed_commands = ["ls", "pwd", "cat", "echo", "grep", "find", "git"]
[security.shell]
max_args = 8
max_arg_length = 128
max_output_bytes = 8192
forbidden_chars = ";&|><$`\n\r"

All network tools share the URL Access Policy for SSRF prevention.

[url_access]
block_private_ip = true # blocks 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
allow_loopback = false # blocks 127.0.0.0/8
enforce_domain_allowlist = false
domain_allowlist = []
domain_blocklist = []

Private IP ranges blocked:

RangeDescription
10.0.0.0/8Private Class A
172.16.0.0/12Private Class B
192.168.0.0/16Private Class C
169.254.0.0/16Link-local
100.64.0.0/10Carrier-grade NAT
0.0.0.0/8Unspecified
240.0.0.0/4Reserved
fc00::/7IPv6 unique local
fe80::/10IPv6 link-local

DNS rebinding protection: Domain names are resolved to IP addresses and checked against the private IP blocklist. This prevents attackers from registering a domain, then changing DNS to point to an internal IP.

Performs HTTP requests (GET, POST, PUT, DELETE) to allowed domains.

Input: <METHOD> <URL> [JSON_BODY]

GET https://api.example.com/data
POST https://api.example.com/items {"name": "item1"}

Security pipeline:

Input → URL Parse → Scheme Check (http/https only) →
Policy Check (blocklist) → IP Resolution → Private IP Check →
DNS Rebinding Check → Domain Allowlist Check → Execute
[http_request]
enabled = true
allowed_domains = ["api.example.com", "*.internal.dev"]
max_response_size = 1000000 # 1 MB
timeout_secs = 30

Fetches content from URLs and returns the response body.

Input: URL string

Output: status={code}\n{body}

Security: Same URL access policy as http_request. Automatic response truncation at 64 KiB default.

Searches the web via configurable provider.

[web_search]
enabled = true
provider = "duckduckgo" # duckduckgo, brave, perplexity, exa, jina
max_results = 5
timeout_secs = 15

Spawns a sub-agent with scoped tools. Prevents infinite delegation chains.

Input:

{
"agent": "researcher",
"prompt": "Find the latest Rust async runtime benchmarks"
}

Security controls:

  • Depth limitingmax_depth prevents infinite delegation chains
  • Tool blocklist — the delegate tool itself is forbidden in sub-agent tool lists (prevents recursion)
  • Scoped tool access — each delegate configuration specifies its own allowed_tools

Per-agent configuration:

[agents.researcher]
provider = "https://api.openai.com/v1"
model = "gpt-4"
max_depth = 2
agentic = true
max_iterations = 10
allowed_tools = ["read_file", "web_search", "memory"]

Multi-turn bidirectional conversations between agents or with humans via channels. Each call is one turn — the calling agent controls the flow.

Input:

{
"agent": "analyst",
"message": "What do you think about these findings?",
"conversation_id": "conv-researcher-analyst-001"
}

For human-in-the-loop:

{
"channel": "slack",
"recipient": "#engineering",
"message": "Should we proceed with approach A or B?",
"conversation_id": "conv-approval-001"
}

Parameters:

ParameterRequiredDescription
agentOne of agent/channelTarget agent ID
channelOne of agent/channelTarget channel for human conversation
recipientWith channelChannel recipient
messageYesThe message to send
conversation_idYesShared across turns (generate on first turn, reuse for follow-ups)

Safety controls:

  • Turn limit — configurable max_turns per conversation (default: 10)
  • Per-turn timeoutturn_timeout_secs (default: 120s)
  • Budget limits — inherited token/cost limits
  • Loop detection — catches repetitive conversation patterns
  • Leak guard — responses scanned for credential leaks

Configuration:

[swarm.agents.researcher.conversation]
max_turns = 15
turn_timeout_secs = 120

Inter-process communication between agents with encrypted storage.

Operations:

OperationInputDescription
send{"op":"send","from":"a1","to":"a2","payload":"msg"}Send message between agents
recv{"op":"recv","to":"agent_name"}Receive pending messages
list{"op":"list","to":"?","from":"?","limit":"?"}List messages with filters
clear{"op":"clear","to":"?","from":"?"}Clear messages

Security: All IPC data is encrypted at rest using EncryptedJsonStore. Messages include timestamps for audit trail.

Queries the model routing configuration to determine which provider/model handles a request.

Operations:

OperationDescription
list_routesReturns all model route hints
list_embedding_routesReturns all embedding route hints
resolve_hintFind route by hint name
classify_queryClassify query to appropriate hint
route_queryComplete routing decision for query

Tools are gated by the autonomy policy, which controls what requires user approval:

LevelRead ToolsWrite ToolsNetwork Tools
ReadOnlyAuto-approveBlockedBlocked
SupervisedAuto-approveRequires approvalRequires approval
FullAuto-approveAuto-approveAuto-approve

Read tools (auto-approved): read_file, glob, search, memory_read

Write tools (gated): write_file, shell, apply_patch, browser, http_request

Forbidden paths (all levels): /etc, /root, /proc, /sys, ~/.ssh, ~/.gnupg, ~/.aws

[autonomy]
level = "supervised"
workspace_only = true
forbidden_paths = ["/etc", "/root", "/proc", "/sys"]
auto_approve = ["read_file", "memory"]
always_ask = ["shell", "write_file"]
allow_sensitive_file_reads = false
allow_sensitive_file_writes = false

AgentZero runs plugins in a sandboxed WASM environment with WASI capabilities, strict resource limits, and SHA-256 integrity verification. Plugins implement the same Tool trait as native tools — the agent loop treats them identically.

MechanismIsolationOverheadUse Case
WASM pluginsSandboxed (memory + CPU + capability-gated)~1-5ms (cached)Third-party tools, community plugins
FFI pluginsHost process (not sandboxed)NativeEmbedding in Swift/Kotlin/Python/Node.js apps
Process pluginsFull (OS process)~5-50msAny-language tools via stdin/stdout JSON
MCP serversFull (separate process)NetworkTool server interoperability
use agentzero_plugin_sdk::prelude::*;
declare_tool!("my_tool", execute);
fn execute(input: ToolInput) -> ToolOutput {
let req: serde_json::Value = serde_json::from_str(&input.input)
.unwrap_or_default();
let name = req["name"].as_str().unwrap_or("world");
ToolOutput::success(format!("Hello, {name}!"))
}

Build: cargo build --target wasm32-wasip1 --release

For a complete example with typed input, az_log host calls, ToolOutput::with_warning, and WASI filesystem access, see the reference notepad plugin at plugins/agentzero-plugin-reference/notepad/.

See the Plugin Authoring Guide for the full walkthrough.

Plugins are auto-discovered from three locations (later overrides earlier):

PathScopeHot-Reload
~/.local/share/agentzero/plugins/Global (user-wide)No
$PROJECT/.agentzero/plugins/Project-specificNo
./plugins/Current working directory (development)Yes
Terminal window
agentzero plugin new --id my-tool --scaffold rust # Scaffold project
agentzero plugin test --manifest manifest.json --wasm plugin.wasm --execute # Test
agentzero plugin package --manifest manifest.json --wasm plugin.wasm # Package
agentzero plugin install --package my-tool.tar # Install from file
agentzero plugin install my-tool # Install from registry
agentzero plugin list # List installed
agentzero plugin enable <id> / disable <id> # Toggle state
agentzero plugin search <query> # Search registry
agentzero plugin remove --id my-tool # Remove
[runtime.wasm]
fuel_limit = 1000000 # execution budget
memory_limit_mb = 64 # max memory
max_module_size_mb = 50 # max .wasm file size
allow_workspace_read = false
allow_workspace_write = false
allowed_hosts = [] # network access allowlist
[runtime.wasm.security]
require_workspace_relative_tools_dir = true
reject_symlink_modules = true
reject_symlink_tools_dir = true
capability_escalation_mode = "deny"
module_hash_policy = "warn" # warn or enforce
  • Network: disabled by default
  • Filesystem write: disabled by default
  • WASI capabilities: granted per-plugin via manifest + policy
  • Bounded execution: epoch-based CPU timeout (default: 30s)
  • Bounded memory: configurable max memory (default: 256MB)
  • Capability validation: undeclared imports fail at load time (not runtime)
  • SHA-256 integrity: verified on every install and load

For the full ABI specification, host callbacks, and manifest schema, see the Plugin API Reference.


Dynamic tools are created at runtime by agents and persist across sessions. Over time, the system accumulates a library of tools it invented — each encrypted at rest in .agentzero/dynamic-tools.json.

During any agent session, the agent can call tool_create to invent a new tool:

You: "I need to transcribe audio files using Whisper"
Agent thinks: No transcription tool exists. I'll create one.
Agent calls tool_create:
{
"action": "create",
"description": "A tool that transcribes audio/video files using OpenAI Whisper CLI",
"strategy_hint": "shell"
}
→ LLM derives the tool definition automatically:
name: whisper_transcribe
strategy: shell
command_template: whisper {{input}} --output_format txt
→ Tool registered immediately — available in this session and every future session.

The agent can then use whisper_transcribe as a tool in the same conversation, without restarting.

Terminal window
# The agent calls tool_create internally, but you can also
# ask the agent to create tools via the gateway:
curl -X POST http://localhost:3000/v1/agent \
-H "Content-Type: application/json" \
-d '{
"message": "Create a tool that checks the weather using wttr.in"
}'

Each dynamic tool wraps one of four execution strategies:

Executes a shell command with {{input}} placeholder substitution.

{
"name": "youtube_download",
"description": "Download a YouTube video using yt-dlp",
"strategy": {
"type": "shell",
"command_template": "yt-dlp -o /tmp/%(title)s.%(ext)s {{input}}"
}
}

When the agent calls youtube_download with input "https://youtube.com/watch?v=abc", the system runs:

Terminal window
yt-dlp -o /tmp/%(title)s.%(ext)s https://youtube.com/watch?v=abc

Calls an HTTP endpoint with the tool input as the request body.

{
"name": "sentiment_api",
"description": "Analyze text sentiment via external API",
"strategy": {
"type": "http",
"url": "https://api.example.com/v1/sentiment",
"method": "POST",
"headers": {
"Authorization": "Bearer sk-...",
"Content-Type": "application/json"
}
}
}

Delegates to the LLM with a specialized system prompt. Useful for analysis, review, or transformation tasks that don’t need external tools.

{
"name": "code_reviewer",
"description": "Review code for bugs, security issues, and style",
"strategy": {
"type": "llm",
"system_prompt": "You are an expert code reviewer. Analyze the following code for bugs, security vulnerabilities, performance issues, and style violations. Be specific and actionable."
}
}

Chains existing tools sequentially — each step’s output becomes the next step’s input.

{
"name": "video_to_summary",
"description": "Download a video, transcribe it, then summarize",
"strategy": {
"type": "composite",
"steps": [
{ "tool_name": "youtube_download" },
{ "tool_name": "whisper_transcribe" },
{ "tool_name": "code_reviewer", "input_override": "Summarize this transcript" }
]
}
}

The tool_create tool supports five actions:

ActionDescriptionExample Input
createCreate a new tool from NL description{"action": "create", "description": "...", "strategy_hint": "shell"}
listList all dynamic tools with their strategies{"action": "list"}
deleteRemove a dynamic tool by name{"action": "delete", "name": "whisper_transcribe"}
exportExport a tool as shareable JSON{"action": "export", "name": "whisper_transcribe"}
importImport a tool from JSON (single or array){"action": "import", "json": "{...}"}

Export a tool on machine A:

You: "Export the youtube_download tool"
Agent: Here's the tool definition:
{
"name": "youtube_download",
"description": "Download a YouTube video using yt-dlp",
"strategy": { "type": "shell", "command_template": "yt-dlp -o /tmp/%(title)s.%(ext)s {{input}}" },
"created_at": 1711234567
}

Import it on machine B:

You: "Import this tool: { ... paste the JSON ... }"
Agent calls tool_create:
{"action": "import", "json": "{ ... }"}
→ Tool registered and persisted.
  1. At startup: build_runtime_execution() loads all tools from .agentzero/dynamic-tools.json into the tool list alongside built-in tools. The LLM sees them identically.
  2. Mid-session: The ToolSource trait on DynamicToolRegistry feeds newly created tools into build_tool_definitions() on each agent loop iteration. A tool created via tool_create is visible to the LLM on the very next turn.
  3. Tool selection: Both KeywordToolSelector and HintedToolSelector match against dynamic tools by name and description — they participate in tool filtering just like built-in tools.
  4. Recipe learning: When a dynamic tool is used successfully, the RecipeStore records it. Future goals matching similar patterns will boost that tool automatically.

Enable dynamic tool creation in agentzero.toml:

[agent]
enable_dynamic_tools = true
  • Only root agents (depth=0) can create tools — sub-agents cannot
  • Shell-strategy tools are validated against the ShellPolicy (command allowlists, path restrictions)
  • HTTP-strategy tools are validated against the UrlAccessPolicy (domain allowlists, private IP blocking)
  • LLM-strategy tools use the same provider and billing as the parent agent
  • All definitions are encrypted at rest via EncryptedJsonStore

The agent can write Rust source code, compile it to WASM, and load it as a sandboxed tool — all at runtime. This produces tools as capable as hand-written ones, isolated inside the WASM sandbox.

{
"name": "markdown_to_html",
"strategy": {
"type": "codegen",
"source": "use agentzero_plugin_sdk::prelude::*;\ndeclare_tool!(\"markdown_to_html\", handler);\nfn handler(input: ToolInput) -> ToolOutput { ... }",
"wasm_path": ".agentzero/codegen/markdown_to_html/target/wasm32-wasip1/release/markdown_to_html.wasm",
"wasm_sha256": "a1b2c3..."
}
}

The compilation pipeline retries up to 3 times — if cargo build fails, errors are fed back to the LLM for correction. A curated allowlist of dependencies (serde_json, regex, chrono, url, base64, sha2, hex, rand, csv) keeps compile times predictable and prevents supply-chain risk.

Dynamic tools improve themselves over time:

  • Auto-Fix: Tools with >60% failure rate and 5+ invocations are automatically repaired via LLM-based strategy correction. The evolver provides rich error context including quality stats, generation history, and multi-strategy pivot suggestions (e.g., “this Shell tool keeps failing — try HTTP instead”).
  • Auto-Improve: Tools with >80% success rate and 10+ invocations get optimized variants (tool_v2, tool_v3). The original is preserved; the variant competes on quality.
  • Anti-loop protections: One evolution per tool per session, max 5 evolutions per session, generation caps prevent infinite repair loops.

The RecipeStore monitors failure patterns across sessions. When the same goal pattern fails 3+ times with no matching successful recipe, the system detects a tool gap — a recurring need with no tool to fulfill it. This feeds into proactive tool creation: “I noticed we keep failing at PDF conversion, so I’ll create a tool for that.”

The insights_report tool lets the agent query its own performance history:

You: "How are my tools performing?"
Agent calls insights_report: {"focus": "tools"}
→ ## Tool Usage Heatmap
- **shell**: 142 uses (94% success, 9 failures)
- **web_fetch**: 87 uses (98% success, 2 failures)
- **write_file**: 63 uses (100% success, 0 failures)

Available focus modes: summary, models, tools, failures, cost.

File-mutating tools (write_file, apply_patch, file_edit) automatically snapshot the target file before modification. Checkpoints are stored as plain file copies in .agentzero/checkpoints/<session>/<timestamp>/. Pre-rollback snapshots enable “undo the undo” — restoring a file also snapshots its current state first.

Tools can be wrapped with composable pre/post interceptors — the same pattern as the provider LlmLayer pipeline. Built-in middleware includes:

  • TimingMiddleware: Logs execution duration and success/failure for every tool call
  • RateLimitMiddleware: Blocks tool execution when invoked too frequently within a configurable window
  • CheckpointMiddleware: Snapshots files before write operations (see above)

Custom middleware implements the ToolMiddleware trait with before() and after() hooks.

Dynamic tools survive restarts, updates, and reboots. The encrypted store at .agentzero/dynamic-tools.json is the system’s growing tool library — portable and backupable.


Skills are higher-level composable behaviors built on top of tools.

Terminal window
# List installed skills
agentzero skill list
# Install a skill
agentzero skill install --name my-skill --source local
# Test a skill
agentzero skill test --name my-skill
# Remove a skill
agentzero skill remove --name my-skill

MCP servers are integrated as first-class tools. Each tool exposed by an MCP server is registered individually with a namespaced name (mcp__{server}__{tool}), its real description, and its full input schema. The LLM sees and invokes them just like any built-in tool.

MCP server definitions live in dedicated mcp.json files, discovered from two locations:

LocationPathScope
Global~/.agentzero/mcp.jsonAvailable to all projects
Project{workspace}/.agentzero/mcp.jsonProject-specific servers

Both files are optional. Project servers override global ones with the same name. The AGENTZERO_MCP_SERVERS env var is supported as a final override layer.

mcp.json format (matches Claude Code / VS Code convention):

{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@anthropic/mcp-server-filesystem", "/tmp"]
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": { "GITHUB_TOKEN": "ghp_..." }
}
}
}

Enable MCP in agentzero.toml (the kill-switch):

[security.mcp]
enabled = true
allowed_servers = [] # empty = allow all configured servers

When allowed_servers is non-empty, only those named servers are loaded.

At startup, AgentZero connects to each configured MCP server, calls tools/list, and registers every discovered tool as its own Box<dyn Tool>:

  • Name: mcp__filesystem__read_file, mcp__github__create_issue, etc.
  • Description: From the MCP server’s tool metadata
  • Schema: The inputSchema from tools/list, passed directly to the LLM

Multiple tools from the same server share a single McpServerConnection (subprocess + stdin/stdout handles). The first tool call spawns the process; subsequent calls reuse it. If a connection error occurs, the session is cleared and retried once automatically.

If a server fails to connect at startup (e.g. missing binary, timeout), it is skipped with a warning — other servers and all built-in tools continue to work normally.


ComponentSettingDefault
read_file max sizemax_read_bytes64 KiB
write_file max sizemax_write_bytes64 KiB
write_file enabledenabledfalse
shell max argsmax_args8
shell max arg lengthmax_arg_length128 bytes
shell max outputmax_output_bytes8 KiB
web_fetch max sizemax_bytes64 KiB
WASM fuel limitfuel_limit1,000,000
WASM memory limitmemory_limit_mb64 MB
Private IP blockingblock_private_iptrue
Loopback accessallow_loopbackfalse
Sensitive filesallow_sensitive_file_readsfalse