infoblox-ddi-mcp
by iracic82
README.md
[](https://github.com/iracic82/infoblox-ddi-mcp/actions/workflows/ci.yml)
[](https://www.python.org/downloads/)
[](LICENSE)
[](https://modelcontextprotocol.io)
[](https://pypi.org/project/infoblox-ddi-mcp/)
# Infoblox DDI — MCP Server
> **26 intent-level workflow tools** for managing Infoblox Universal DDI via the Model Context Protocol.
Any MCP-compatible AI agent can manage your entire DDI infrastructure — DNS, DHCP, IPAM, security, and federation — without being an Infoblox expert.
---
## Why Intent-Level Tools (Not 1:1 API Mapping)
The Infoblox Universal DDI platform has **300+ REST API endpoints** across DDI, Security, and Insights services. A naive MCP implementation would expose each endpoint as a separate tool. This server takes a fundamentally different approach: **26 intent-level workflow tools** backed by **303 API methods** that abstract multi-step operations into single calls.
**The problem with 1:1 mapping:**
```
# What an agent must do to provision a host with 1:1 tools (7 API calls):
1. list_ip_spaces(filter="name==prod") → resolve space name to ID
2. list_subnets(filter="space==ipam/ip_space/1") → find subnets
3. get_next_available_ip(subnet_id) → allocate IP
4. list_auth_zones(filter="fqdn==example.com") → resolve zone
5. create_ipam_host(name, addresses, ...) → create host
6. create_dns_record(type="A", ...) → create A record
7. create_dns_record(type="PTR", ...) → create PTR record
```
```
# Same operation with intent-level tool (1 call):
provision_host(hostname="web-01", space="prod", zone="example.com")
```
| Concern | 1:1 Mapping (300+ tools) | Intent Layer (26 tools) |
|---------|----------------------|------------------------|
| **LLM tool selection** | Agent must choose from 300+ tools — high hallucination rate | 26 tools with `USE THIS for X / For Y use Z` disambiguation |
| **Token efficiency** | 5-7 API calls per workflow, each consuming context window | Single call, single response |
| **Error handling** | Agent must implement rollback, partial-success, retry | Server-side orchestration with `steps[]` tracking |
| **Domain knowledge** | Agent needs to know Infoblox resource IDs, filter syntax, API paths | Agent speaks business intent: "provision host", "diagnose DNS" |
| **Safety** | Every destructive call is directly exposed | `dry_run=True` by default, input validation, filter injection protection |
| **Consistency** | Each agent builds its own workflow logic | Standardized response envelope (`status`, `summary`, `steps`, `result`, `warnings`, `next_actions`) |
**Key design principles:**
- **One tool per user intent** — "provision a host", "diagnose DNS", "investigate a threat"
- **Resolvers handle name→ID mapping** — agents pass human-readable names, not resource IDs
- **Dry-run by default** on all mutating operations — agents must explicitly opt in
- **Guided next actions** — every response suggests what to do next, reducing multi-turn back-and-forth
---
## Quick Start
### Option A: uv (recommended)
```bash
cd infoblox-ddi-mcp
# Install dependencies
uv pip install -r requirements.txt
# Configure credentials
cp .env.example .env
# Edit .env — add INFOBLOX_API_KEY
# Run (stdio)
uv run python mcp_intent.py
# Run (HTTP)
uv run python mcp_intent.py --http
```
### Option B: Docker (one command)
```bash
docker build -t infoblox-ddi-mcp .
docker run -p 4005:4005 -e INFOBLOX_API_KEY=your_key infoblox-ddi-mcp
```
Or with docker compose (reads `.env` automatically):
```bash
cp .env.example .env # add your INFOBLOX_API_KEY
docker compose up -d
```
### Option C: pip install
```bash
cd infoblox-ddi-mcp
pip install .
# Now available as a CLI command:
infoblox-ddi-mcp --http
```
## Transport Modes
| Mode | Command | Use Case |
|------|---------|----------|
| **stdio** (default) | `python mcp_intent.py` | Claude Desktop, Cursor, Windsurf, Claude Code |
| **HTTP streamable** | `python mcp_intent.py --http` | HCL AEX, LangChain, OpenAI SDK, remote clients |
| **Docker** | `docker run -p 4005:4005 ...` | Production, Kubernetes, HCL evaluation |
Stdio transport communicates via stdin/stdout JSON-RPC. HTTP transport runs a spec-compliant MCP server on port 4005 (configurable via `MCP_PORT`).
### Configuration
| Environment Variable | Default | Description |
|---------------------|---------|-------------|
| `INFOBLOX_API_KEY` | (required) | Infoblox CSP API key |
| `INFOBLOX_BASE_URL` | `https://csp.infoblox.com` | CSP portal URL |
| `MCP_HOST` | `0.0.0.0` | HTTP bind address |
| `MCP_PORT` | `4005` | HTTP port |
| `MCP_PATH` | `/mcp` | HTTP endpoint path |
| `MCP_AUTH_TOKEN` | (optional) | Bearer token for HTTP transport authentication |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | (optional) | OTLP endpoint to enable tracing (requires `[otel]` extra) |
When `MCP_AUTH_TOKEN` is set, all HTTP requests must include `Authorization: Bearer <token>`. Stdio transport is unaffected (authentication is handled by the host process).
---
## Connect to AI Frameworks
### Claude Desktop
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
```json
{
"mcpServers": {
"infoblox-ddi": {
"command": "python",
"args": ["/absolute/path/to/infoblox-ddi-mcp/mcp_intent.py"],
"env": {
"INFOBLOX_API_KEY": "your_api_key_here",
"INFOBLOX_BASE_URL": "https://csp.infoblox.com"
}
}
}
}
```
Restart Claude Desktop — the 26 tools appear in the tool picker.
### Claude Code (CLI)
```bash
# Add the MCP server (stdio — Claude Code launches the process)
claude mcp add infoblox-ddi -e INFOBLOX_API_KEY=your_api_key_here -- python /absolute/path/to/infoblox-ddi-mcp/mcp_intent.py
# Or connect to a running HTTP server
claude mcp add --transport http infoblox-ddi http://localhost:4005/mcp
```
### Anthropic Python SDK
```python
import anthropic
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
mcp_servers=[
{
"type": "url",
"url": "https://your-gateway.example.com/mcp", # must be HTTPS
"name": "infoblox-ddi",
"authorization_token": "your_mcp_auth_token", # optional, if MCP_AUTH_TOKEN is set
}
],
tools=[
{
"type": "mcp_toolset",
"mcp_server_name": "infoblox-ddi",
}
],
messages=[{"role": "user", "content": "Show me all IP spaces and their utilization"}],
betas=["mcp-client-2025-11-20"],
)
```
> **Note:** The Anthropic MCP connector requires the server to be reachable via HTTPS. For local testing, use Claude Desktop (stdio) instead.
### LangChain / LangGraph
```python
from langchain_mcp_adapters.client import MultiServerMCPClient
client = MultiServerMCPClient(
{
"infoblox-ddi-stdio": {
"command": "python",
"args": ["/path/to/infoblox-ddi-mcp/mcp_intent.py"],
"transport": "stdio",
},
# Or use HTTP (streamable_http is recommended over sse):
# "infoblox-ddi-http": {
# "url": "http://127.0.0.1:4005/mcp",
# "transport": "streamable_http",
# },
}
)
tools = await client.get_tools()
# Use with any LangChain agent or LangGraph workflow
```
### OpenAI Agents SDK
```python
from agents import Agent, Runner
from agents.mcp import MCPServerStdio, MCPServerStreamableHttp
# Option A: stdio transport
async with MCPServerStdio(
name="infoblox-ddi",
params={
"command": "python",
"args": ["/path/to/infoblox-ddi-mcp/mcp_intent.py"],
},
) as server:
agent = Agent(name="ddi-agent", mcp_servers=[server])
result = await Runner.run(agent, "Show me all IP spaces")
print(result.final_output)
# Option B: HTTP streamable transport (start server first with --http)
async with MCPServerStreamableHttp(
name="infoblox-ddi",
params={"url": "http://127.0.0.1:4005/mcp"},
) as server:
agent = Agent(name="ddi-agent", mcp_servers=[server])
result = await Runner.run(agent, "List all DNS zones")
print(result.final_output)
```
### Cursor IDE
Add to `.cursor/mcp.json` in your project root:
```json
{
"mcpServers": {
"infoblox-ddi": {
"command": "python",
"args": ["/absolute/path/to/infoblox-ddi-mcp/mcp_intent.py"],
"env": {
"INFOBLOX_API_KEY": "your_api_key_here"
}
}
}
}
```
### Windsurf IDE
Add to `~/.codeium/windsurf/mcp_config.json`:
```json
{
"mcpServers": {
"infoblox-ddi": {
"command": "python",
"args": ["/absolute/path/to/infoblox-ddi-mcp/mcp_intent.py"],
"env": {
"INFOBLOX_API_KEY": "your_api_key_here"
}
}
}
}
```
### HCL BigFix AEX
AEX has native MCP client support. In **Admin Console → Agent Studio**:
1. Add an MCP Server tool source
2. Set the endpoint to `http://<host>:4005/mcp`
3. Start the server with `python mcp_intent.py --http`
4. The 26 tools are auto-discovered and available to AEX agents
### Any HTTP Client
```bash
# Step 1: Initialize session (capture the Mcp-Session-Id header from the response)
curl -v -X POST http://127.0.0.1:4005/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {"name": "curl", "version": "1.0"}
}
}'
# Look for the response header: Mcp-Session-Id: <session-id>
# Step 2: List available tools (pass the session ID from step 1)
curl -X POST http://127.0.0.1:4005/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Mcp-Session-Id: <session-id>" \
-d '{"jsonrpc": "2.0", "id": 2, "method": "tools/list"}'
# Step 3: Call a tool
curl -X POST http://127.0.0.1:4005/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Mcp-Session-Id: <session-id>" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "explore_network",
"arguments": {"depth": "summary"}
}
}'
```
### Remote Access (HTTP Transport)
Any MCP-compatible client can connect remotely over HTTP. Start the server with `--http` and point clients to the endpoint:
```
http://<host>:4005/mcp
```
**Local network:**
```bash
# Start the server
python mcp_intent.py --http
# Any client on the network connects to:
# http://192.168.1.100:4005/mcp
```
**Docker (remote host):**
```bash
docker run -p 4005:4005 -e INFOBLOX_API_KEY=your_key infoblox-ddi-mcp
# Clients connect to:
# http://your-docker-host:4005/mcp
```
**With authentication:**
```bash
# Start with auth token
MCP_AUTH_TOKEN=my-secret-token python mcp_intent.py --http
# Clients must include the header:
# Authorization: Bearer my-secret-token
```
**Production (TLS):** For internet-facing deployments, place the server behind a reverse proxy (nginx, API gateway) that handles TLS. See [Production Deployment](#production-deployment) below.
> **Summary:** `stdio` = client launches the server locally. `HTTP` = server runs independently, clients connect to `http://host:4005/mcp`. Use `MCP_AUTH_TOKEN` to secure HTTP access.
---
## Available Tools
### Discovery & Exploration (Read-only)
| Tool | Description |
|------|-------------|
| `explore_network` | Browse the IP hierarchy tree (Spaces → Blocks → Subnets) with utilization. Use for navigating network structure |
| `search_infrastructure` | Find resources by keyword across all DDI domains (IP, hostname, domain, comment) |
| `get_network_summary` | Executive dashboard with counts and health across all DDI infrastructure |
### Provisioning (Write)
| Tool | Description |
|------|-------------|
| `provision_host` | Create host + IP + DNS in one call. Supports auto-IP from subnet and auto-DNS (atomic A/PTR via API) or manual DNS creation |
| `provision_dns` | Create a new DNS record with automatic zone discovery and validation |
| `decommission_host` | Reverse provisioning with dry-run safety — detects auto-generated DNS (system records) vs manual DNS and handles each correctly |
### Troubleshooting (Read-only)
| Tool | Description |
|------|-------------|
| `diagnose_dns` | Diagnose DNS resolution problems: zone, records, security policies, and optional cache flush |
| `diagnose_ip_conflict` | Detect overlapping subnets, duplicate reservations, DHCP usage, and host associations |
| `check_api_health` | Verify Infoblox API connectivity for all three service clients (DDI, Insights, ATCFW) with response latency |
| `check_infrastructure_health` | HA groups, DHCP hosts, DNS zones, DNS views, IP spaces, on-prem appliance and service health |
### Security (Read + Write)
| Tool | Description |
|------|-------------|
| `investigate_threat` | SOC insights with threat indicators, affected assets, and timeline events |
| `assess_security_posture` | Security policies, category filters, compliance, and analytics scorecard |
| `manage_security_policy` | CRUD for named lists (with partial add/remove items), app filters, internal domains, access codes |
| `triage_security_insight` | Update status, bulk triage by priority, get comment history |
### IPAM Management (CRUD)
| Tool | Description |
|------|-------------|
| `manage_network` | Create, update, delete, get, or list IP spaces, address blocks, subnets, and ranges |
| `manage_ip_reservation` | Reserve/release fixed IPs and DHCP static leases |
### DNS Configuration (CRUD)
| Tool | Description |
|------|-------------|
| `manage_dns_zone` | Create, delete, list, or get authoritative and forward zones |
| `manage_dns_record` | Update, delete, list, or get DNS records (smart lookup by name+zone+type) |
### DHCP Configuration (CRUD)
| Tool | Description |
|------|-------------|
| `manage_dhcp` | CRUD for HA groups, option codes, hardware/option filters, hardware entries |
| `manage_dhcp_lease` | List/search active leases, clear (wipe) leases, or resend DDNS updates |
### DNS Traffic Control (CRUD)
| Tool | Description |
|------|-------------|
| `manage_dtc` | Manage DTC/GSLB: LBDNs, pools, servers, and policies for global server load balancing and traffic steering |
### Federation (CRUD)
| Tool | Description |
|------|-------------|
| `manage_federation` | Manage realms, blocks, delegations, pools, overlapping/reserved blocks |
### Reporting (Read-only)
| Tool | Description |
|------|-------------|
| `get_ip_utilization` | Capacity planning — utilization by space, block, and subnet |
---
## Response Format
Every tool returns a standard envelope:
```json
{
"status": "success | partial | failed",
"summary": "Human-readable one-liner",
"steps": [
{"step": "Resolve IP space", "status": "success", "result": {"space_id": "ipam/ip_space/abc"}},
{"step": "Create subnet", "status": "success", "result": {"id": "ipam/subnet/xyz"}}
],
"result": { "..." : "..." },
"warnings": ["Optional warnings"],
"next_actions": ["Suggested follow-up tool calls"]
}
```
This makes it easy for any LLM to:
- **Check `status`** to know if the operation succeeded
- **Read `summary`** for a one-line answer to show the user
- **Inspect `steps`** to understand the multi-step workflow
- **Follow `next_actions`** for intelligent follow-up suggestions
---
## Example Conversations
**"Show me what's in our network"**
```
→ explore_network(depth="full")
→ Returns hierarchical tree: IP spaces → address blocks → subnets with utilization %
```
**"Create a /24 subnet in the prod space for web servers"**
```
→ manage_network(resource_type="subnet", action="create", address="10.20.3.0/24", space="prod", comment="Web servers")
→ Resolves space name → ID, validates CIDR, creates subnet
```
**"Set up a new host called web-prod-01 in the prod space"**
```
→ provision_host(hostname="web-prod-01", space="prod", subnet="10.20.3.0/24", zone="example.com", view="default")
→ Auto-assigns next available IP (10.20.3.50), creates IPAM host + DNS A/PTR atomically
```
**"Provision web-prod-02 but I want to manage DNS records separately"**
```
→ provision_host(hostname="web-prod-02", ip="10.20.3.51", space="prod", zone="example.com", auto_dns=False)
→ Creates IPAM host, then A and PTR records as separate API calls
```
**"DNS isn't working for api.example.com"**
```
→ diagnose_dns(domain="api.example.com")
→ Returns zone status, records found, security blocks, and fix recommendations
```
**"Reserve 10.20.3.100 for the new database server"**
```
→ manage_ip_reservation(action="reserve", address="10.20.3.100", space="prod", hostname="db-01", mac="AA:BB:CC:DD:EE:FF")
→ Checks availability, validates MAC, creates fixed address reservation
```
**"Close all low-priority security insights"**
```
→ triage_security_insight(action="bulk_triage", priority_filter="low", status="CLOSED", dry_run=True)
→ DRY RUN: Shows 15 insights that would be closed
→ triage_security_insight(action="bulk_triage", priority_filter="low", status="CLOSED", dry_run=False)
→ Bulk closes 15 insights
```
**"What would happen if I decommissioned web-prod-01?"**
```
→ decommission_host(identifier="web-prod-01", dry_run=True)
→ "Would delete: 1 host, 1 A record, 1 PTR, release IP 10.20.3.50"
```
---
## Docker Deployment
```bash
# Build
make docker-build # or: docker build -t infoblox-ddi-mcp .
# Run standalone
make docker-run # or: docker run --rm -p 4005:4005 -e INFOBLOX_API_KEY=... infoblox-ddi-mcp
# Run with compose (reads .env)
make docker-up # or: docker compose up -d
make docker-down # or: docker compose down
```
The Docker image:
- Uses **multi-stage build** (small final image)
- Runs as **non-root** user
- Has a **health check** built in
- Binds to `0.0.0.0:4005` by default
- Accepts all config via environment variables
## OpenTelemetry (Optional)
Distributed tracing is available as an optional extra:
```bash
pip install infoblox-ddi-mcp[otel]
```
Enable by setting `OTEL_EXPORTER_OTLP_ENDPOINT`:
```bash
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
python mcp_intent.py --http
```
All MCP tool calls are auto-traced with service name `infoblox-ddi-mcp`. Works with Jaeger, Grafana Tempo, Datadog, or any OTLP-compatible backend. If the packages aren't installed, the server runs normally without tracing.
---
## Production Deployment
### Behind an API Gateway (Recommended)
For production environments, run the MCP server behind an API gateway for TLS termination, rate limiting, and centralized authentication.

The MCP server runs plain HTTP internally. The gateway handles TLS and external auth. Set `MCP_AUTH_TOKEN` as a shared secret between the gateway and the server for an additional layer of security.
#### Kubernetes / Docker Compose
```yaml
# docker-compose.prod.yml
services:
infoblox-mcp:
image: infoblox-ddi-mcp:latest
restart: always
environment:
- INFOBLOX_API_KEY=${INFOBLOX_API_KEY}
- INFOBLOX_BASE_URL=${INFOBLOX_BASE_URL:-https://csp.infoblox.com}
- MCP_HOST=0.0.0.0
- MCP_PORT=4005
- MCP_AUTH_TOKEN=${MCP_AUTH_TOKEN}
ports:
- "127.0.0.1:4005:4005" # bind to localhost only — gateway handles external traffic
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:4005/mcp')"]
interval: 30s
timeout: 5s
retries: 3
deploy:
resources:
limits:
memory: 512M
cpus: "0.5"
```
#### Nginx Reverse Proxy Example
```nginx
upstream mcp_backend {
server 127.0.0.1:4005;
}
server {
listen 443 ssl;
server_name mcp.example.com;
ssl_certificate /etc/ssl/certs/mcp.crt;
ssl_certificate_key /etc/ssl/private/mcp.key;
location /mcp {
proxy_pass http://mcp_backend/mcp;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Authorization "Bearer ${MCP_AUTH_TOKEN}";
# Rate limiting
limit_req zone=mcp burst=20 nodelay;
}
}
```
#### AWS API Gateway
1. Create an HTTP API in API Gateway
2. Add a route: `POST /mcp` → integration to your ECS/EKS service on port 4005
3. Attach a Lambda authorizer or Cognito user pool for auth
4. Enable CloudWatch logging for audit trail
#### Kubernetes Deployment
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: infoblox-mcp
spec:
replicas: 2
selector:
matchLabels:
app: infoblox-mcp
template:
metadata:
labels:
app: infoblox-mcp
spec:
containers:
- name: mcp
image: infoblox-ddi-mcp:latest
ports:
- containerPort: 4005
env:
- name: INFOBLOX_API_KEY
valueFrom:
secretKeyRef:
name: infoblox-secrets
key: api-key
- name: MCP_AUTH_TOKEN
valueFrom:
secretKeyRef:
name: infoblox-secrets
key: mcp-token
livenessProbe:
httpGet:
path: /mcp
port: 4005
initialDelaySeconds: 10
periodSeconds: 30
resources:
limits:
memory: "512Mi"
cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
name: infoblox-mcp
spec:
selector:
app: infoblox-mcp
ports:
- port: 4005
targetPort: 4005
```
### Deployment Checklist
| Step | Action |
|------|--------|
| 1 | Set `INFOBLOX_API_KEY` via secrets manager (never in plain text) |
| 2 | Set `MCP_AUTH_TOKEN` for server-to-gateway authentication |
| 3 | Bind to `127.0.0.1` or internal network only (gateway handles external) |
| 4 | Enable TLS on the gateway (never expose plain HTTP externally) |
| 5 | Configure rate limiting (recommended: 60 req/min per client) |
| 6 | Enable access logging on the gateway for audit |
| 7 | Set resource limits (512MB RAM, 0.5 CPU is sufficient) |
| 8 | Monitor health check endpoint |
---
## Makefile Targets
```
make install Install dependencies with uv
make dev Install in editable mode
make run Run MCP server (stdio)
make run-http Run MCP server (HTTP)
make lint Run ruff linter
make format Run ruff formatter
make test Run test suite (163 tests)
make docker-build Build Docker image
make docker-run Run Docker container
make docker-up Start with docker compose
make docker-down Stop docker compose
make check Verify syntax
make clean Remove build artifacts
```
---
## Architecture

---
## Project Structure
```
infoblox-ddi-mcp/
├── mcp_intent.py ← MCP server entry point (run this)
├── services/
│ ├── infoblox_client.py ← Infoblox DDI API client (90 methods)
│ ├── insights_client.py ← SOC Insights API client (13 methods)
│ ├── atcfw_client.py ← DNS Security API client (12 methods)
│ └── metrics.py ← Internal metrics collection
├── tests/ ← 163 tests (validators, resolvers, tools, resources)
│ ├── conftest.py
│ ├── test_validation.py
│ ├── test_resolvers.py
│ ├── test_tools.py
│ └── test_resources.py
├── examples/ ← Integration examples
│ ├── anthropic_sdk.py
│ ├── openai_agents.py
│ ├── langchain_example.py
│ └── curl_test.sh
├── .github/workflows/
│ ├── ci.yml ← Lint + test (3.10-3.13) + Docker
│ └── publish.yml ← PyPI publishing on v* tags
├── pyproject.toml ← Package metadata (uv/pip install)
├── requirements.txt ← Pinned dependencies
├── Dockerfile ← Production container image
├── docker-compose.yml ← One-command deployment
├── Makefile ← Developer shortcuts
├── .pre-commit-config.yaml ← Ruff + pre-commit hooks
├── CHANGELOG.md
├── SECURITY.md
├── .env.example
└── README.md
```
---
## Troubleshooting
**"Unexpected non-whitespace character after JSON"**
→ Something is writing to stdout. This server routes all logging to stderr. If you added custom print statements, use `print(..., file=sys.stderr)`.
**"Infoblox client not initialized"**
→ `INFOBLOX_API_KEY` is missing or invalid. Check your `.env` file or environment variables.
**"IP space 'prod' not found"**
→ The space name doesn't match exactly. Use `explore_network()` to see available space names.
**"DNS zone 'example.com' not found"**
→ The zone doesn't exist in Infoblox. Use `manage_dns_zone(action="list")` to see available zones, or `manage_dns_zone(action="create", fqdn="example.com")` to create one.
**Tools not appearing in Claude Desktop**
→ Restart Claude Desktop after editing `claude_desktop_config.json`. Check the path to `mcp_intent.py` is absolute.
**HTTP server not responding**
→ Start with `python mcp_intent.py --http`. Test with: `curl -X POST http://127.0.0.1:4005/mcp -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'`
**Dry run confusion**
→ All destructive operations (delete, release, bulk triage) default to `dry_run=True`. They show what *would* happen without making changes. Set `dry_run=False` to execute.
**Token overflow / response too large**
→ Use `limit` parameters to reduce result sizes. The intent layer already truncates large results, but specific queries return less data.
TDQS
A4.3/5.0
Scored across 26 tools
Disambiguation5/5
Each tool targets a distinct domain (DHCP, DNS, IPAM, security, etc.) and descriptions include explicit cross-references, so an agent can reliably choose the correct tool without ambiguity.
Naming Consistency5/5
All tools follow a consistent snake_case verb_noun pattern with repeated prefixes like manage_, provision_, check_, and diagnose_, making the naming predictable and uniform.
Tool Count2/5
With 26 tools, the set exceeds the 25-tool threshold and feels heavy, even though the broad Infoblox DDI scope justifies many of the tools individually.
Completeness5/5
The tool surface covers IPAM, DHCP, DNS, DNSSEC, RPZ, DTC, DoH, security, provisioning, and diagnostics, providing comprehensive lifecycle operations with no major gaps.
Maintenance
ActivityInactive
ResponsivenessNo issues