oxidized-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@oxidized-mcplist devices with failed backups"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Oxidized MCP Server
Oxidized MCP Server is a Python-based Model Context Protocol (MCP) server that gives AI assistants access to Oxidized, the network device configuration backup tool. It talks to the oxidized-web REST API to list devices, check backup health, read and search device configurations, browse and diff configuration history, and queue backups. It supports read-only mode, tag-based tool filtering, and bearer token authentication for HTTP transports.
Features
Core Features
List and filter managed devices by group, model and last backup status
Find devices by partial name, full name (
group/name) or IP addressSummarise backup health: failures, devices never backed up and stale backups
Read the latest backed-up configuration of any device, paged for large configs
Search all configurations for a regular expression or literal text, with matching lines and context
Configuration History
List the stored configuration versions of a device (git output)
Read a device's configuration as it was at any version (full oid or short prefix)
Diff two versions, or just see the most recent change, as a unified diff
Operations
Queue an immediate backup of a device, optionally with a commit message and author
Reload the node list from its source (router.db, SQL, HTTP, ...)
Read-only mode hides every operation for safe monitoring
Advanced Capabilities
Node vars (often device credentials) are redacted in tool output by default
HTTP Basic auth for oxidized-web behind a reverse proxy
Rate limiting, SSL/TLS verification and configurable timeouts
Tag-based tool filtering and an optional tool-search transform
Bearer token authentication for HTTP transports
Related MCP server: network-mcp-server
Installation
Prerequisites
Python 3.11 or higher
A running Oxidized instance with oxidized-web enabled
For version history and diffs: the Oxidized
git(orgitcrypt) output
Quick Install from PyPI
The easiest way to get started is to install from PyPI:
# Using UV (recommended)
uvx oxidized-mcp
# Or using pip
pip install oxidized-mcpRemember to configure the environment variables for your Oxidized instance before running the server:
# Create environment configuration
export OXIDIZED_URL=http://localhost:8888For more details, visit: https://pypi.org/project/oxidized-mcp/
Install from Source
Clone the repository:
git clone https://github.com/mhajder/oxidized-mcp.git
cd oxidized-mcpInstall dependencies:
# Using UV (recommended)
uv sync
# Or using pip
pip install -e .Configure environment variables:
cp .env.example .env
# Edit .env with your Oxidized URL (and Basic auth credentials if needed)Run the server:
# Using UV (recommended)
uv run oxidized-mcp
# Or using the installed command directly
oxidized-mcpDevelopment Setup
For development with additional tools:
# Clone and install with development dependencies
git clone https://github.com/mhajder/oxidized-mcp.git
cd oxidized-mcp
uv sync --group dev
# Run tests
uv run pytest
# Run with coverage
uv run pytest --cov=src/
# Run linting and formatting
uv run ruff check .
uv run ruff format .
# Run type checking
uv run ty check .
# Setup prek hooks
uv run prek installConfiguration
Environment Variables
# Oxidized Connection Details
# Base URL of oxidized-web (include the url_prefix if one is configured)
OXIDIZED_URL=http://localhost:8888
# Optional HTTP Basic auth, e.g. for a reverse proxy in front of oxidized-web
# OXIDIZED_USERNAME=
# OXIDIZED_PASSWORD=
# SSL Configuration
OXIDIZED_VERIFY_SSL=true
OXIDIZED_TIMEOUT=30
# Timeout for search_configs (oxidized-web reads every configuration)
OXIDIZED_SEARCH_TIMEOUT=300
# Redact node vars (often device credentials) in tool output
OXIDIZED_REDACT_NODE_VARS=true
# Read-Only Mode
# Set READ_ONLY_MODE true to disable operations (trigger_node_backup, reload_nodes)
READ_ONLY_MODE=false
# Disabled Tags
# Comma-separated list of tags to disable tools for (empty by default)
# Example: OXIDIZED_DISABLED_TAGS=search,diff
OXIDIZED_DISABLED_TAGS=
# Logging Configuration
LOG_LEVEL=INFO
# Rate Limiting (requests per minute)
# Set RATE_LIMIT_ENABLED true to enable rate limiting
RATE_LIMIT_ENABLED=false
RATE_LIMIT_MAX_REQUESTS=60
RATE_LIMIT_WINDOW_MINUTES=1
# Tool Search Transform (Optional)
# Set TOOL_SEARCH_ENABLED true to replace full tool listings with search_tools + call_tool
TOOL_SEARCH_ENABLED=false
# Search strategy: bm25 (natural language) or regex (pattern match)
TOOL_SEARCH_STRATEGY=bm25
# Maximum number of tools returned by search_tools
TOOL_SEARCH_MAX_RESULTS=5
# Sentry Error Tracking (Optional)
# Set SENTRY_DSN to enable error tracking and performance monitoring
# SENTRY_DSN=https://your-key@o12345.ingest.us.sentry.io/6789
# Optional Sentry configuration
# SENTRY_TRACES_SAMPLE_RATE=1.0
# SENTRY_SEND_DEFAULT_PII=false
# SENTRY_ENVIRONMENT=production
# SENTRY_RELEASE=1.2.3
# SENTRY_PROFILE_SESSION_SAMPLE_RATE=1.0
# SENTRY_PROFILE_LIFECYCLE=trace
# SENTRY_ENABLE_LOGS=true
# MCP Transport Configuration
# Transport type: 'stdio' (default), 'sse' (Server-Sent Events), or 'http' (HTTP Streamable)
# MCP_TRANSPORT=stdio
# HTTP Transport Settings (used when MCP_TRANSPORT=sse or MCP_TRANSPORT=http)
# Host to bind the HTTP server (default: 127.0.0.1)
# MCP_HTTP_HOST=127.0.0.1
# Port to bind the HTTP server (default: 8000)
# MCP_HTTP_PORT=8000
# Optional bearer token for authentication (leave empty for no auth)
# MCP_HTTP_BEARER_TOKEN=Sentry Error Tracking & Monitoring (Optional)
The server optionally supports Sentry for error tracking, performance monitoring, and debugging. Sentry integration is completely optional and only initialized if configured.
Installation
To enable Sentry monitoring, install the optional dependency:
# Using UV (recommended)
uv sync --extra sentryConfiguration
Enable Sentry by setting the SENTRY_DSN environment variable in your .env file:
# Required: Sentry DSN for your project
SENTRY_DSN=https://your-key@o12345.ingest.us.sentry.io/6789
# Optional: Performance monitoring sample rate (0.0-1.0, default: 1.0)
SENTRY_TRACES_SAMPLE_RATE=1.0
# Optional: Include personally identifiable information (default: false).
# Keep it off: with the MCP integration it records tool results, which are
# full device configurations including secrets.
SENTRY_SEND_DEFAULT_PII=false
# Optional: Environment name (e.g., "production", "staging")
SENTRY_ENVIRONMENT=production
# Optional: Release version (auto-detected from package if not set)
SENTRY_RELEASE=1.2.2
# Optional: Profiling - continuous profiling sample rate (0.0-1.0, default: 1.0)
SENTRY_PROFILE_SESSION_SAMPLE_RATE=1.0
# Optional: Profiling - lifecycle mode for profiling (default: "trace")
# Options: "all", "continuation", "trace"
SENTRY_PROFILE_LIFECYCLE=trace
# Optional: Enable log capture as breadcrumbs and events (default: true)
SENTRY_ENABLE_LOGS=trueFeatures
When enabled, Sentry automatically captures:
Exceptions & Errors: All unhandled exceptions with full context
Performance Metrics: Request/response times and traces
MCP Integration: Detailed MCP server activity and interactions
Logs & Breadcrumbs: Application logs and event trails for debugging
Context Data: Environment, client info, and request parameters
Getting a Sentry DSN
Create a free account at sentry.io
Create a new Python project
Copy your DSN from the project settings
Set it in your
.envfile
Disabling Sentry
Sentry is completely optional. If you don't set SENTRY_DSN, the server will run normally without any Sentry integration, and no monitoring data will be collected.
Available Tools
Node Tools
list_nodes: List devices with optional filters (group, model, last run status, name/IP substring) and paging; group/model are filtered by Oxidized itself (/nodes/<group|model>/<value>.json), so large inventories are not transferred in fullget_node: Get a single device's details and last backup run (accepts name or IP)find_nodes: Find devices by partial name, full name or IP, exact matches firstget_backup_stats: Backup health summary - counts per status, group and model, success rate, failed / never backed up / stale devices; optionally for a single group or model
Configuration Tools
get_node_config: Get the latest backed-up configuration of a device (by name or IP), paged by lines (offset/max_lines)search_configs: Search all configurations for a regex or literal text; returns matching lines with line numbers and optional context
Version History Tools
Require the Oxidized git or gitcrypt output.
list_node_versions: List stored configuration versions (oid, date, author, message), newest firstget_node_version: Get the configuration at a given version (full oid or unique prefix), paged by linesdiff_node_versions: Unified diff between two versions; defaults to the most recent change
Operation Tools
Hidden when READ_ONLY_MODE=true.
trigger_node_backup: Queue an immediate backup of a device, optionally recording a commit message and authorreload_nodes: Reload the whole node list from its source (a per-node reload is deliberately not offered: oxidized-web's/reload?node=Xreplaces the entire in-memory node list with the matching nodes)
Security & Safety Features
Read-Only Mode
The server supports a read-only mode that disables all write operations for safe monitoring:
READ_ONLY_MODE=trueWhen enabled, only tools tagged read-only are exposed: trigger_node_backup and reload_nodes are hidden, while every node, configuration and history tool stays available.
Tag-Based Tool Filtering
You can disable specific categories of tools by setting disabled tags:
OXIDIZED_DISABLED_TAGS=search,diffAvailable tags include:
node- Node listing and lookup tools (and the backup/reload operations)stats- Backup health statisticsconfig- Configuration read toolssearch- Configuration search and node search toolsversion- Version history toolsdiff- Version diff toolbackup- Backup trigger operationreload- Node list reload operationread-only- Every tool that does not change Oxidized state
Rate Limiting
The server supports rate limiting to control API usage and prevent abuse. If enabled, requests are limited per client using a sliding window algorithm.
Enable rate limiting by setting the following environment variables in your .env file:
RATE_LIMIT_ENABLED=true
RATE_LIMIT_MAX_REQUESTS=60 # Maximum requests allowed per window
RATE_LIMIT_WINDOW_MINUTES=1 # Window size in minutesIf RATE_LIMIT_ENABLED is set to true, the server will apply rate limiting middleware. Adjust RATE_LIMIT_MAX_REQUESTS and RATE_LIMIT_WINDOW_MINUTES as needed for your environment.
Tool Search for Large Toolsets
FastMCP tool search can reduce prompt size for servers with many tools.
When enabled, list_tools returns two synthetic tools:
search_tools: Finds matching tools and returns their full schemascall_tool: Executes any discovered tool by name
Enable it with:
TOOL_SEARCH_ENABLED=true
TOOL_SEARCH_STRATEGY=bm25 # bm25 or regex
TOOL_SEARCH_MAX_RESULTS=8 # optional, default is 5bm25 supports natural language queries, while regex uses a regex
pattern input for deterministic matching.
Tool search respects existing visibility controls (read-only mode and disabled tags).
SSL/TLS Configuration
The server supports SSL certificate verification and custom timeout settings:
OXIDIZED_VERIFY_SSL=true # Enable SSL certificate verification
OXIDIZED_TIMEOUT=30 # Request timeout in secondsUpstream Authentication
oxidized-web has no authentication of its own and is usually published behind a reverse proxy with HTTP Basic auth. Set both variables to send Basic auth with every request:
OXIDIZED_USERNAME=oxidized
OXIDIZED_PASSWORD=your-passwordNode Vars Redaction
Node vars from the Oxidized source (router.db, SQL, HTTP) often contain per-device credentials, and oxidized-web returns them unredacted from /nodes.json. The server replaces every var value with <redacted> (keeping the keys) unless you opt out:
OXIDIZED_REDACT_NODE_VARS=falseTransport Configuration
The server supports multiple transport protocols for different deployment scenarios:
STDIO Transport (Default)
The default transport uses standard input/output for communication. This is ideal for local usage and integration with tools that communicate via stdin/stdout:
MCP_TRANSPORT=stdioHTTP SSE Transport (Server-Sent Events)
For network-based deployments, you can use HTTP with Server-Sent Events. This allows the MCP server to be accessed over HTTP with real-time streaming:
MCP_TRANSPORT=sse
MCP_HTTP_HOST=127.0.0.1 # Localhost
MCP_HTTP_PORT=8000 # Port to listen on
MCP_HTTP_BEARER_TOKEN=your-secret-token # Optional authentication tokenWhen using SSE transport with a bearer token, clients must include the token in their requests:
curl -H "Authorization: Bearer your-secret-token" http://localhost:8000/sseHTTP Streamable Transport
The HTTP Streamable transport provides HTTP-based communication with request/response streaming. This is ideal for web integrations and tools that need HTTP endpoints:
MCP_TRANSPORT=http
MCP_HTTP_HOST=127.0.0.1 # Localhost
MCP_HTTP_PORT=8000 # Port to listen on
MCP_HTTP_BEARER_TOKEN=your-secret-token # Optional authentication tokenWhen using streamable transport with a bearer token:
curl -H "Authorization: Bearer your-secret-token" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' \
http://localhost:8000/mcpNote: The HTTP transport requires proper JSON-RPC formatting with jsonrpc and id fields. The server may also require session initialization for some operations.
Oxidized Notes
Version history (
list_node_versions,get_node_version,diff_node_versions) needs thegitorgitcryptoutput. With thefileoutput Oxidized reports no versions.Groups: node names should be unique. Tools accept an optional
groupto disambiguate;get_node_configand the history tools look the group up automatically when it is omitted (with the git output'ssingle_repothe group is part of the stored path, so it is required by oxidized-web). Nodes without a group are shown as groupdefault, and passingdefaultback is treated as "no group".search_configsfilters groups the same way aslist_nodes(exact match).trigger_node_backuptakes no group because Oxidized queues backups by node name or IP only.Filtering large inventories:
groupandmodelinlist_nodes/get_backup_statsare filtered by Oxidized itself. The group must match exactly (case-sensitive, as shown bylist_nodes), so a misspelt group returns nothing instead of downloading the whole inventory. Built-in model names are case-insensitive (iosand theIOSXEalias are sent asIOS, from a catalog of Oxidized's models); custom models must be spelled exactly. Neither filter ever falls back to downloading the whole inventory.Search runs in two steps: oxidized-web's
conf_searchfinds matching devices (it reads every configuration server-side, so it can be slow on large installations), then only those configurations are fetched to extract matching lines.max_nodescaps the fetches; nodes that were never backed up (whose placeholder text can match) are skipped without counting. The server-side step usesOXIDIZED_SEARCH_TIMEOUT(default 300 s) instead ofOXIDIZED_TIMEOUT. Patterns run as Ruby regexps on the server and Python regexps locally, line by line, so stick to common syntax.Backups are asynchronous:
trigger_node_backupmoves the device to the head of the queue. Checkget_nodefor the result.Errors: oxidized-web answers unknown node names with HTTP 500. When it runs with
RACK_ENV=productionthe reason is hidden, so a 500 on a node route is reported with a hint that it may be an unknown node name.
Using Docker
A Docker image is available on GitHub Packages for easy deployment.
docker pull ghcr.io/mhajder/oxidized-mcp:latest
docker run --rm -p 8000:8000 \
-e OXIDIZED_URL=http://oxidized:8888 \
-e MCP_HTTP_BEARER_TOKEN=your-secret-token \
ghcr.io/mhajder/oxidized-mcp:latestThe image defaults to the HTTP Streamable transport on port 8000 (http://localhost:8000/mcp).
Contributing
Fork the repository
Create a feature branch (
git checkout -b feature/amazing-feature)Make your changes
Run tests and ensure code quality (
uv run pytest && uv run ruff check .)Commit your changes (
git commit -m 'Add amazing feature')Push to the branch (
git push origin feature/amazing-feature)Open a Pull Request
License
MIT License - see LICENSE file for details.
Available Tools
11 toolsdiff_node_versionsDiff Node VersionsARead-onlyIdempotent
Show what changed in a node's configuration between two versions.
Returns a unified diff from 'base_oid' (older) to 'oid' (newer). With no arguments besides the node it shows the most recent change.
| Name | Required | Description | Default |
|---|---|---|---|
| oid | No | Newer version oid (full or prefix); defaults to the latest version | |
| node | Yes | Node name or IP address (e.g. 'core-sw01') | |
| group | No | Node group; looked up automatically when omitted | |
| base_oid | No | Older version oid to compare against; defaults to the version before 'oid' | |
| max_lines | No | Maximum diff lines to return (0 = whole diff) | |
| context_lines | No | Unchanged lines of context around each change |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate a safe read-only, idempotent operation. The description adds meaningful behavioral detail: output is a unified diff with a defined ordering, and default behavior when only the node is supplied. This goes beyond the annotation-provided safety profile.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences deliver the core purpose and defaults with no filler. The most important information is front-loaded, and every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only diff tool with full schema coverage, an output schema, and safety annotations, the description covers the essential behavior and default invocation. There is no critical information an agent needs to call it correctly that is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all six parameters, including defaults and meanings. The description reinforces the base_oid-to-oid direction, but does not add significant meaning beyond what the schema provides, so the baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the operation: showing what changed in a node's configuration between two versions, specifically via a unified diff. It distinguishes itself from siblings like get_node_version and get_node_config by focusing on comparison rather than retrieval.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for use, including the diff direction (base_oid older to oid newer) and the no-argument behavior of showing the most recent change. It does not explicitly name alternatives or exclusion cases, but the usage context is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_nodesFind NodesARead-onlyIdempotent
Find nodes by partial name, full name or IP address.
Useful to resolve an ambiguous device name before calling other tools. Exact matches are listed first, then prefix matches, then other substring matches (all case-insensitive).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum nodes to return | |
| query | Yes | Part of a node name, full name (group/name) or IP address |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly and idempotent, so the description adds value by disclosing result ordering (exact, prefix, then substring) and case-insensitive matching. These are meaningful behavioral traits not visible in the schema or annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences with no filler. The core lookup behavior is first, the workflow use is second, and the ordering/case details close it out efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter read-only search tool with an output schema and full schema coverage, the description provides everything needed: what to search, why to use it, and how results are ordered. No critical gap remains.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%: both query and limit are documented there, including the full set of query forms (part of a name, full name, IP address). The description mostly restates the query semantics rather than adding new parameter-level detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Find nodes' by partial name, full name, or IP address. The phrase 'resolve an ambiguous device name before calling other tools' clearly distinguishes it from siblings like list_nodes or get_node.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context: use it to resolve ambiguous node names before invoking other tools. It does not explicitly name alternatives or give when-not-to-use guidance, but the intended placement in a workflow is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_backup_statsGet Backup StatsARead-onlyIdempotent
Summarise backup health across Oxidized nodes.
Computed from the node list (oxidized-web's own stats JSON is not usable): counts per last-run status, per group and per model, the success rate, and lists of failed nodes, nodes never backed up and stale nodes. Optionally limited to one group or model, filtered by Oxidized itself.
"Stale" means Oxidized has not attempted a backup within the threshold (e.g. it is not polling the node); nodes that are attempted but keep failing are listed under failed_nodes instead. Oxidized does not expose the time of the last successful backup, and its run history is kept in memory only (reset on restart). Right after trigger_node_backup a node briefly shows as never backed up, because Oxidized clears its last run while it is queued.
| Name | Required | Description | Default |
|---|---|---|---|
| group | No | Only include nodes in this group (exact, case-sensitive name) | |
| model | No | Only include nodes of this Oxidized model (e.g. 'IOS') | |
| max_listed | No | Maximum nodes listed in each of the failed/never/stale lists | |
| stale_hours | No | Report nodes whose last backup attempt (successful or not) is older than this many hours |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds significant context beyond the readOnly/idempotent annotations: it defines 'stale' precisely (last backup attempt, not success), explains that Oxidized does not expose last successful backup time, notes that run history is in-memory and resets on restart, and warns that a node may briefly show as never backed up right after trigger_node_backup. These are critical behavioral quirks an agent must know to interpret results correctly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a bit long but every sentence carries useful information. It is front-loaded with the core summary, then explains the stale definition and important caveats. While it could be trimmed slightly, the length is justified by the need to convey data-source limitations and behavioral quirks. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (multiple optional filters, nuanced data-source limitations) and that an output schema exists, the description covers all essential context: data source, what counts are computed, the stale definition, and known edge cases (after trigger_node_backup). The output schema handles return format, so no need to describe it. An agent has everything needed to call it correctly and interpret results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters are fully documented in the schema. The description does not add parameter-specific details beyond what the schema provides; it only mentions 'optionally limited to one group or model' and clarifies the stale threshold concept, which is already in the schema. Baseline of 3 is appropriate since the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Summarise backup health across Oxidized nodes.' It specifies the exact resource (backup health across nodes) and the action (summarise). It also lists the specific outputs (counts, success rate, lists of failed/never/stale nodes), distinguishing it from sibling tools that handle node listing, config retrieval, or backup triggering.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implicitly tells the agent when to use this tool: when backup health metrics are needed, explicitly noting that oxidized-web's own stats JSON is not usable. It does not name alternatives or give explicit when-not-to-use conditions, but the unique purpose among siblings makes the usage context clear. It also explains filtering by group/model, giving a sense of optionality.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_nodeGet NodeARead-onlyIdempotent
Get details of a single Oxidized node.
Returns the node's name, full name, IP, group, model, vars and details of its last backup run (start, end, status, duration).
| Name | Required | Description | Default |
|---|---|---|---|
| node | Yes | Node name or IP address (e.g. 'core-sw01') |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is clear. The description adds value by specifying the exact return fields (name, full name, IP, group, model, vars, last backup run details), which is useful behavioral context. However, it doesn't disclose potential errors (e.g., node not found) or any rate limits, but given the annotations, a 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no waste. The first sentence states the core function, and the second lists the return fields. It is front-loaded and every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (1 parameter, no nested objects, output schema present), the description is complete enough. It covers what the tool does and what it returns. The only minor gap is not mentioning error cases, but for a read-only single-node fetch, this is acceptable. The output schema likely covers return structure, so the description doesn't need to.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents the 'node' parameter with an example. The description doesn't add much beyond what the schema provides, but it does mention that the node can be identified by name or IP, which aligns with the schema. Baseline 3 is correct since the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Get details of a single Oxidized node.' It specifies the resource (a single node) and the verb (get), and distinguishes it from siblings like list_nodes and find_nodes by focusing on a single node's details. The description also enumerates the returned fields, making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for retrieving details of a single node, which is distinct from listing or searching nodes. It doesn't explicitly state when not to use it or name alternatives, but the context signals and sibling names provide enough clarity. The description could be improved by explicitly mentioning that this is for a single node, not a list, but the 'single' qualifier already does that.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_node_configGet Node ConfigARead-onlyIdempotent
Get the latest backed-up configuration of a node.
Large configurations are paged by lines: when 'truncated' is true, call again with offset set to 'next_offset' to read the rest.
| Name | Required | Description | Default |
|---|---|---|---|
| node | Yes | Node name or IP address (e.g. 'core-sw01') | |
| group | No | Node group, to disambiguate nodes with the same name in different groups | |
| offset | No | Zero-based first line to return | |
| max_lines | No | Maximum lines to return (0 = whole configuration) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses a non-obvious pagination behavior: large configurations are paged by lines, and the caller must follow 'truncated' and 'next_offset' to fetch all data. This adds meaningful behavioral context beyond the readOnly/idempotent annotations and explains exactly how to handle partial results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences: the first states the core purpose, the second gives the necessary paging detail. No wasted words and the most important behavioral information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple, read-only nature of the tool, the fully documented input schema, the output schema, and annotations, the description covers everything needed to invoke it correctly. The pagination caveat is the main non-obvious detail, and it is included.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so parameters are already documented. The description adds value by clarifying how 'offset' interacts with 'truncated' and 'next_offset', giving the agent a fuller mental model of pagination than the schema alone provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the resource ('latest backed-up configuration of a node') and the action ('Get'), so an agent can understand what the tool returns. It does not explicitly distinguish itself from sibling tools like get_node or get_node_version, though the phrase 'backed-up configuration' narrows the scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives no guidance on when to use this tool versus siblings such as get_node, list_node_versions, or get_node_version. The intended use case is only implied by the name and subject matter, with no exclusions or alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_node_versionGet Node VersionARead-onlyIdempotent
Get the configuration of a node as it was at a specific version.
Large configurations are paged by lines: when 'truncated' is true, call again with offset set to 'next_offset' to read the rest.
| Name | Required | Description | Default |
|---|---|---|---|
| oid | Yes | Version oid from list_node_versions (full or unique prefix) | |
| node | Yes | Node name or IP address (e.g. 'core-sw01') | |
| group | No | Node group; looked up automatically when omitted | |
| offset | No | Zero-based first line to return | |
| max_lines | No | Maximum lines to return (0 = whole configuration) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only and idempotent, so the description only needs to add operational behavior. It adds the paging mechanism (truncated/next_offset), which is critical for large configurations. It also clarifies that it returns a historical snapshot. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, each earning its place. The purpose is stated first, followed by a critical operational detail about pagination. No fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only historical retrieval tool with an output schema, the description covers the key operational caveat (pagination) and the purpose. It doesn't explain error conditions or version lookup specifics, but those are likely in the output schema or parameter descriptions. Given the complexity, it's adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema descriptions cover all parameters at 100%, so the baseline is 3. The description adds context about paging that relates to offset and max_lines, but doesn't add new semantic meaning to the parameters beyond what the schema already provides. It doesn't explain the 'group' optional behavior beyond the schema's auto-lookup note.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states it retrieves the configuration of a node at a specific version, distinguishing it from get_node_config (current config) and list_node_versions (version list). The verb 'get' and resource 'configuration of a node' are specific.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies it's for historical config retrieval but does not explicitly state when to use this over get_node_config or diff_node_versions. It lacks explicit alternatives or exclusion conditions, leaving the agent to infer the use case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_nodesList NodesARead-onlyIdempotent
List nodes (network devices) managed by Oxidized.
Returns each node's name, full name (group/name), IP, group, model, last run status and time, and last run details. Node vars are redacted unless redaction is disabled in the server configuration. Pass a group or model on large installations: they are filtered by Oxidized itself, so only matching nodes are transferred. The group must match exactly; use find_nodes when unsure of the name.
| Name | Required | Description | Default |
|---|---|---|---|
| group | No | Only nodes in this group - exact, case-sensitive name as shown by list_nodes (e.g. 'core'); 'default' selects nodes without a group | |
| limit | No | Maximum nodes to return | |
| model | No | Only nodes of this Oxidized model (e.g. 'IOS', 'JunOS', 'RouterOS'); built-in model names are case-insensitive | |
| offset | No | Number of matching nodes to skip | |
| status | No | Only nodes whose last run had this status (e.g. 'success', 'no_connection', 'fail', 'never') | |
| name_contains | No | Only nodes whose name, full name or IP contains this text (case-insensitive) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, covering the mutation profile. The description adds meaningful behavioral detail: node vars are redacted unless server redaction is disabled, and filtering is done server-side so only matching nodes are transferred. This goes beyond annotations and helps the agent set expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a tight two-sentence paragraph. It front-loads the core purpose and return fields, then delivers usage advice and a pointer to an alternative. Every sentence earns its place; no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only listing tool with an output schema already present, the description covers the return shape, filtering behavior, redaction caveat, and large-installation recommendations. Nothing an agent needs to decide when and how to call it is missing. The combination of schema, annotations, and description is fully self-sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so parameters are already documented. The description enriches semantics by explaining when to pass group/model ('on large installations') and clarifies that group matching is exact and case-sensitive, with 'default' selecting nodes without a group. This practical guidance adds value beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with a clear verb-resource pair: 'List nodes (network devices) managed by Oxidized.' It then enumerates the exact fields returned (name, full name, IP, group, model, last run status/time, details), making the tool's function unambiguous. It also implicitly distinguishes from siblings by pointing to find_nodes for fuzzy group name lookup.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly recommends passing group or model filters on large installations and explains why (server-side filtering reduces transfer). It also gives a precise when-not: 'use find_nodes when unsure of the name' for groups, directing the agent to the correct alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_node_versionsList Node VersionsARead-onlyIdempotent
List the stored configuration versions of a node, newest first.
Each version has its git oid, date, author and commit message. Requires the Oxidized 'git' (or 'gitcrypt') output.
| Name | Required | Description | Default |
|---|---|---|---|
| node | Yes | Node name or IP address (e.g. 'core-sw01') | |
| group | No | Node group; looked up automatically when omitted | |
| limit | No | Maximum versions to return |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds meaningful behavioral context: it lists what each version includes (git oid, date, author, commit message) and the ordering ('newest first'). It also discloses the backend requirement (git/gitcrypt output), which is beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the main purpose is stated in the first sentence, and the second sentence adds useful detail about the version contents and a prerequisite. Every sentence earns its place, with no fluff or repetition of the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has a clear purpose, a complete schema, and an output schema, so the description does not need to explain return values. The description covers the key behavioral details (ordering, version contents, backend requirement). It could have explicitly mentioned pagination or the default limit, but the schema already covers the limit parameter, so the description is sufficiently complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all three parameters. The description adds a bit of context by mentioning the git oid, date, author, and commit message, which indirectly clarifies what the 'limit' parameter controls, but it does not add significant new meaning beyond the schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('List'), a specific resource ('stored configuration versions of a node'), and a clear ordering ('newest first'). It also distinguishes itself from siblings like get_node_version and diff_node_versions by focusing on the list of stored versions rather than a single version or a diff.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly implies when to use this tool: when you need the list of stored configuration versions for a node. It also notes a prerequisite ('Requires the Oxidized 'git' (or 'gitcrypt') output'), which is useful context. It does not explicitly name alternatives or exclusions, but the sibling list and the description's focus make the usage context clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reload_nodesReload NodesAIdempotent
Reload the Oxidized node list from its source (router.db, SQL, HTTP, ...).
Use after devices were added, removed or changed in the source so Oxidized picks up the change without waiting for its next refresh. Always reloads every node: oxidized-web's per-node reload (/reload?node=X) replaces the whole in-memory node list with just the matching nodes, so it is deliberately not offered.
Returns: Dictionary with Oxidized's response message
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover idempotency (idempotentHint=true) and non-destructiveness (destructiveHint=false). The description adds context by explaining that it reloads every node from the source, replacing the whole in-memory list, and clarifies that per-node reload would be misleading. It also states the return type (Dictionary with response message). This goes beyond annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise (three sentences) and front-loaded: it states the primary action and source, then provides usage context, then a caveat, then the return value. Every sentence adds value, with no redundancy or fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tool with no parameters and an output schema, the description fully covers purpose, usage timing, behavior, and return type. It also addresses a potential point of confusion (per-node reload) explicitly. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, and schema coverage is 100% (vacuously true). According to the rubric, 0 parameters gives a baseline of 4. The description doesn't add parameter details (there are none), but it does provide context about the operation's scope, which is sufficient.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Reload'), resource ('Oxidized node list'), and source ('from its source (router.db, SQL, HTTP, ...)'). It distinguishes itself from the per-node reload by explicitly noting that per-node reload replaces the entire list and is deliberately not offered. This clearly differentiates from siblings like list_nodes or trigger_node_backup.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use: 'Use after devices were added, removed or changed in the source' and explains the benefit ('without waiting for its next refresh'). It also notes that it always reloads every node, implying it is not suitable for single-node reloads, and explains why per-node reload is not available. It does not explicitly list alternative tools, but the per-node caveat serves as an implicit exclusion.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_configsSearch ConfigsARead-onlyIdempotent
Search the latest configurations of all nodes for a pattern.
oxidized-web first finds the nodes whose configuration matches, then those configurations are fetched to return the matching lines with line numbers. Use this to answer questions such as "which devices still have telnet enabled" or "where is VLAN 42 configured".
The pattern must be valid in both Ruby (oxidized-web) and Python regular expressions - stick to common syntax. Lines are matched one at a time, so patterns spanning several lines find nodes but no lines.
| Name | Required | Description | Default |
|---|---|---|---|
| group | No | Only search nodes in this group - exact, case-sensitive name as shown by list_nodes; 'default' selects nodes without a group | |
| literal | No | Treat the pattern as literal text | |
| pattern | Yes | Regular expression (or literal text with literal=true) to search for, e.g. 'snmp-server community' | |
| max_nodes | No | Maximum matching nodes whose configurations are searched (nodes without a stored configuration are skipped and not counted) | |
| max_matches | No | Maximum matching lines to return in total | |
| context_lines | No | Lines of context to include before and after each match | |
| case_sensitive | No | Match case-sensitively |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag read-only, idempotent, and non-destructive behavior. The description adds meaningful behavioral detail beyond those flags: it explains the two-phase search process, that matching lines come with line numbers, that patterns must be valid in both Ruby and Python regex, and that multi-line patterns will find nodes but produce no matching lines. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured: a one-sentence summary comes first, followed by the operational flow, concrete usage examples, and then an important cross-language regex caveat. Every sentence earns its place without unnecessary padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for an agent to use this tool correctly. It explains the search behavior, the regex constraint, the line-matching limitation, and when to reach for the tool. The input schema fully documents all seven parameters, and an output schema exists, so return-value details are not the description's responsibility.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds parameter-level value by warning that the pattern must be valid in both Ruby and Python regex and that lines are matched one at a time, which directly affects how the pattern parameter should be authored. This goes beyond the schema's short parameter descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Purpose is stated with a specific verb and resource: "Search the latest configurations of all nodes for a pattern." It clarifies the two-step process (find matching nodes, then fetch and return matching lines), distinguishing it from sibling tools like get_node_config, which fetches a single config, or list_nodes, which enumerates nodes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives concrete, recognizable use cases: "which devices still have telnet enabled" and "where is VLAN 42 configured". This tells an agent when this tool is appropriate, though it does not explicitly contrast it with alternatives or state when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
trigger_node_backupTrigger Node BackupAIdempotent
Queue an immediate configuration backup of a node.
Oxidized moves the node to the head of its queue; the backup itself runs asynchronously. Check get_node afterwards for the run result, and list_node_versions for a new version if the configuration changed. Oxidized picks the node by name or IP only (no group), so node names must be unique - otherwise the first node with that name is queued.
| Name | Required | Description | Default |
|---|---|---|---|
| node | Yes | Node name or IP address (e.g. 'core-sw01') | |
| user | No | Author name recorded if this backup produces a new version | |
| message | No | Commit message recorded if this backup produces a new version |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only indicate readOnlyHint=false, idempotentHint=true, and destructiveHint=false. The description adds crucial behavioral context beyond those: the node moves to the head of the queue, the backup runs asynchronously, and name/IP matching is group-less with a uniqueness requirement. It also explains the consequence of a changed configuration (a new version appears), giving the agent a full picture of the tool's runtime behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the primary purpose. The first sentence states the action immediately, followed by two sentences that earn their place by covering async behavior, follow-up steps, and a critical uniqueness constraint. No fluff or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with three parameters, an output schema, and annotations, the description covers everything an agent needs to invoke it correctly: what happens (queued async backup), how to verify the result (get_node, list_node_versions), and a key constraint (unique node names). The output schema handles return-value details, so no critical context is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with clear descriptions for node, user, and message. The tool description adds no additional meaning about parameters beyond what the schema already states. Since the schema fully documents each parameter, the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Queue an immediate configuration backup of a node.' It clearly distinguishes this from sibling retrieval tools like get_node_config or list_node_versions by focusing on triggering a backup rather than reading data. The follow-up references to get_node and list_node_versions further disambiguate its role.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use the tool: when an immediate backup is needed. It also provides post-invocation guidance ('Check get_node afterwards... list_node_versions for a new version') and a uniqueness prerequisite. It does not explicitly state when not to use it or name direct alternatives, but the usage context is strong enough for an agent to select it correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
11 tool updates
v0.1.0- First observed
diff_node_versions - First observed
find_nodes - First observed
get_backup_stats - First observed
get_node - First observed
get_node_config - First observed
get_node_version - First observed
list_node_versions - First observed
list_nodes - First observed
reload_nodes - First observed
search_configs - First observed
trigger_node_backup
TDQS
Scored across 11 tools
Each tool has a clearly distinct purpose: listing vs searching nodes, fetching node metadata vs configuration, viewing versions vs diffs, and explicit actions like triggering backups and reloading. Even overlapping tools like get_node and get_node_config are separated by their outputs (device details vs configuration content).
All 11 tools follow a consistent verb_noun snake_case pattern (e.g., list_nodes, get_node_config, diff_node_versions). Verbs are descriptive and uniform, with no style mixing or vague generic names.
11 tools is well-scoped for an Oxidized MCP server. Each tool serves a distinct function in the backup management workflow—discovery, inspection, search, versioning, and operational triggers—without redundancy or excessive granularity.
The surface covers the full lifecycle of Oxidized operations: discovering nodes (list/find), checking backup health (stats), retrieving configs (current and historical), comparing versions, triggering backups, and refreshing the node list. No obvious dead ends or missing operations for the stated purpose.
Maintenance
Related MCP Connectors
Protocol-native energy infrastructure orchestration for AI data centers. Provides 46 MCP tools across 8 grid protocols (IEC-61850, DNP3, Modbus, OCPP, OpenADR, IEEE 2030.5, IEC 60870-5-104, ICCP) with 5 core API primitives: connect, dispatch, settle, comply, and intel. Enables AI agents to programmatically interact with substations, grid interfaces, and energy assets for real-time workload-grid coordination.
Your org's AI agents, tasks, runs, search, and brain files as MCP tools and resources.
The Cortex MCP server provides read-only access to real-time engineering context from the Cortex developer portal, allowing AI coding assistants to answer natural language questions about your organization's catalog (microservices, libraries, domains, teams, infrastructure), scorecards (engineering standards and best practices), initiatives (goals and deadlines), and Engineering Intelligence metrics. It includes tools for querying documentation, tracking personal entities, and accessing AI-assisted insights across the entire Cortex ecosystem.
Zero-setup MCP gateway securely connecting AI to your tools with authentication and workflows
Related MCP Servers
- AlicenseBqualityDmaintenanceExposes Cisco Network Services Orchestrator (NSO) operations and data as MCP tools and resources, enabling AI-powered network automation through natural language. It supports tasks like retrieving device configurations, checking sync status, and managing services via the NSO RESTCONF API.914MIT
- AlicenseNot gradedqualityDmaintenanceMCP server for network operations that lets AI assistants interact with Cisco/Juniper network devices through safe, well-defined tools like compliance audits and configuration backups.MIT
- AlicenseAqualityAmaintenanceProvides MCP tools for governed multi-vendor network device operations, including configuration management (backup, diff, merge, replace, rollback) and read-only queries (facts, interfaces, BGP, LLDP, ARP) via NAPALM, with optional NetBox source-of-truth integration.33MIT
- FlicenseNot gradedqualityCmaintenanceProvides MCP tools for Cisco Meraki Dashboard API, enabling management of networks, configuration templates, and health checks via natural language commands.-