Skip to main content
Glama

NextDNS MCP Server

A Model Context Protocol (MCP) server for the NextDNS API, built with FastMCP and a small set of grouped CRUD tools.

Overview

This project provides an MCP server that exposes NextDNS API operations as tools that can be used by AI assistants and other MCP clients. The server registers a small set of domain-grouped CRUD tools directly; it does not generate tools from an OpenAPI spec.

Related MCP server: Cloudflare Control

Features

  • Domain-grouped CRUD tools exposing the full NextDNS API surface through ~8 high-level tools

  • Profile Management: Full CRUD operations - create, read, update, and delete profiles

  • Profile Access Control: Fine-grained read/write restrictions per profile, with read-only mode support

  • DNS-over-HTTPS Testing: Perform DoH lookups to test DNS resolution through profiles

  • Settings Configuration: Comprehensive grouped settings management including logs, block page, and performance

  • Logs: Query log retrieval, download, and clearing

  • Analytics: Comprehensive DNS query analytics and statistics, including time-series and plotting

  • Content Lists: Manage denylist, allowlist, privacy blocklists, native tracking, security TLDs, and parental control

  • Security: Complete security settings and TLD blocking configuration

  • Privacy: Privacy settings, blocklists, and native tracking protection management

  • Parental Control: Settings management with safe search and YouTube restrictions

  • Reference OpenAPI spec: The bundled nextdns-openapi.yaml documents the NextDNS API surface for validation tooling

  • Docker Support: Containerized deployment with proper OCI labels

  • Safety Mechanisms: Write operation protections and validation

Documentation

Complete documentation can be found in docs/index.md.

Quick Start

Prerequisites

  • Python 3.12+

  • uv (for development)

  • Docker (for containerized deployment)

  • NextDNS API key (get one here)

Configuration

  1. Copy the .env.example file to .env:

    cp .env.example .env
  2. Edit .env and set your NextDNS API key:

    NEXTDNS_API_KEY=your_api_key_here
    NEXTDNS_DEFAULT_PROFILE=your_profile_id  # Optional
    
    # Optional: Profile access control (see docs/configuration.md).
    # There is no separate test-profile variable for writes: list a dedicated
    # sandbox profile in NEXTDNS_WRITABLE_PROFILES, or block writes entirely
    # with NEXTDNS_READ_ONLY.
    # NEXTDNS_READABLE_PROFILES=profile1,profile2
    # NEXTDNS_WRITABLE_PROFILES=test_profile
    # NEXTDNS_READ_ONLY=false

Running with Docker

  1. Build the Docker image:

    docker build -t nextdns-mcp:latest .
  2. Run the container with environment variables:

    Option A: Direct environment variables (simple)

    docker run -i --rm \
      -e NEXTDNS_API_KEY=your_api_key_here \
      -e NEXTDNS_DEFAULT_PROFILE=your_profile_id \
      nextdns-mcp:latest

    Option B: Docker secrets (recommended for production)

    # Create secret
    echo "your_api_key_here" | docker secret create nextdns_api_key -
    
    # Run with Docker Swarm
    docker service create \
      --name nextdns-mcp \
      --secret nextdns_api_key \
      -e NEXTDNS_API_KEY_FILE=/run/secrets/nextdns_api_key \
      nextdns-mcp:latest

    Or for non-swarm (using mounted file):

    # Create a secret file
    echo "your_api_key_here" > /tmp/api_key.txt
    chmod 600 /tmp/api_key.txt
    
    # Run with mounted secret
    docker run -i --rm \
      -v /tmp/api_key.txt:/run/secrets/nextdns_api_key:ro \
      -e NEXTDNS_API_KEY_FILE=/run/secrets/nextdns_api_key \
      nextdns-mcp:latest

    Option C: Environment file (development)

    docker run -i --rm \
      --env-file .env \
      nextdns-mcp:latest

    Note: the commands above use stdio (standard input/output), the default transport. For the opt-in streamable-HTTP transport, see HTTP Transport below.

    Alpine variant

    An Alpine Linux image is also available. To build it locally, use Dockerfile.alpine:

    docker build -f Dockerfile.alpine -t nextdns-mcp:alpine .

    The published Alpine tags use the -alpine suffix (e.g. nextdns-mcp:alpine, nextdns-mcp:2.0-alpine). The python:3.14-slim image remains the recommended default.

Running Locally (Development)

  1. Install dependencies:

    uv sync
  2. Run the server:

    uv run python -m nextdns_mcp.server

HTTP Transport (network access)

By default the server uses stdio, which is what MCP clients (Claude Desktop, CLI tools) expect. You can switch to a streamable-HTTP transport for network-based clients, but the HTTP endpoint has no built-in authentication.

Variable

Default

Description

MCP_TRANSPORT

stdio

Set to http to serve over streamable-HTTP. Any other value fails startup; see configuration

MCP_HOST

127.0.0.1

Interface to bind. Loopback-only by default

MCP_PORT

8000

Port to listen on

Because there is no authentication, the default bind is loopback-only (127.0.0.1), so the HTTP endpoint is only reachable from the same host. That keeps it off the network, but on its own it does not stop a browser on that host from being tricked into reaching it (DNS rebinding) — the header validation below is what addresses that.

FastMCP's Host/Origin header validation (FASTMCP_HTTP_HOST_ORIGIN_PROTECTION, which mitigates DNS rebinding against that unauthenticated endpoint) is not enabled by default for application runs, because on a loopback bind it also enforces a Host allowlist and would reject the name your proxy or clients present. Behind a TLS-terminating proxy, enabling it takes three steps: make the server trust that proxy's forwarded headers (the FORWARDED_ALLOW_IPS environment variable, which defaults to 127.0.0.1 and so already covers a same-host proxy — set it to the proxy's address otherwise, and never to *), then set the public host in FASTMCP_HTTP_ALLOWED_HOSTS='["mcp.example.com"]' (a JSON array, not a bare hostname), and only then set FASTMCP_HTTP_HOST_ORIGIN_PROTECTION=auto. Skipping the allowlist answers 421 Misdirected Request; skipping the trusted forwarded headers makes the server compare an http origin against the browser's https Origin and answer 403. See configuration.

In HTTP mode the server also serves GET /health, a readiness check that probes the NextDNS API with the configured key: it returns 200 only when the credentials work, and 503 with a failure class (auth or unreachable) when they do not. See the FAQ.

Binding to a non-loopback interface (explicit opt-in)

To make the endpoint reachable from other hosts you must explicitly set MCP_HOST to a non-loopback address (e.g. 0.0.0.0 or a specific IP). The server logs a prominent SECURITY warning on startup when this happens, because it exposes every tool — and the full reachability of your NextDNS API key — to anyone who can reach the port.

A non-loopback bind is only production-suitable when it is fronted by a reverse proxy (or gateway) that provides authentication and/or TLS, such that unauthenticated remote callers cannot reach the /mcp endpoint. Recommended setup:

  • Terminate TLS at the reverse proxy.

  • Require authentication (e.g. a shared secret, OAuth2/OIDC, or IP allow-listing) before forwarding to the MCP server.

  • Bind the MCP server itself to a private interface or 127.0.0.1 behind the proxy where possible.

# Loopback-only (default; see the Host/Origin validation note above):
MCP_TRANSPORT=http uv run python -m nextdns_mcp.server

# Non-loopback bind — MUST be placed behind an authenticating reverse proxy:
MCP_TRANSPORT=http MCP_HOST=0.0.0.0 uv run python -m nextdns_mcp.server

Architecture

This server uses a modern, declarative approach:

  1. OpenAPI Specification (nextdns-openapi.yaml): Complete NextDNS API documentation

  2. FastMCP Foundation: Server built from grouped CRUD tools registered in src/nextdns_mcp/tools/; the OpenAPI spec is a reference for validation only (issues #141/#146)

  3. HTTP Client: Authenticated httpx.AsyncClient with profile-level access control for NextDNS API calls

  4. MCP Protocol: Tools, resources, and prompts exposed via Model Context Protocol

Key Components

  • src/nextdns_mcp/nextdns-openapi.yaml: OpenAPI 3.0 specification for NextDNS API (reference/validation only); a Spectral lint workflow (openapi-lint.yml) enforces explicit per-operation security declarations via spectral.yaml, runnable locally with npx @stoplight/spectral lint -r spectral.yaml src/nextdns_mcp/nextdns-openapi.yaml

  • src/nextdns_mcp/server.py: FastMCP server implementation

  • Dockerfile: Container definition with OCI labels for container metadata

  • AGENT.md: Development guidelines and safety rules

Docker Tags

This project publishes official Docker images with a standardized tagging policy. The default image is based on python:3.14-slim; an Alpine Linux variant is also available and tagged with an -alpine suffix.

Primary (python:3.14-slim) tags

  • :latest: Floating tag that tracks the most recent successful build from the main branch. This tag is rebuilt on changes to main and via scheduled rebuilds.

  • :<major>: Floating tag for the most recent build in a given major series (e.g., :2). This tag is updated whenever a new image for that major line is published and may include unreleased changes if the corresponding build comes from a branch head.

  • :<major>.<minor>: Floating tag for the most recent build in a given minor series (e.g., :2.0). Like :<major>, it is updated when new images are built for that series and may include unreleased changes.

  • :<major>.<minor>.<patch>: Tags for specific application releases (e.g., :2.0.3). These are intended to be immutable once published via the release workflow.

Alpine tags

  • :alpine: Floating tag for the most recent Alpine build from main.

  • :<major>-alpine: Floating tag for the most recent Alpine build in a major series (e.g., :2-alpine).

  • :<major>.<minor>-alpine: Floating tag for the most recent Alpine build in a minor series (e.g., :2.0-alpine).

  • :<major>.<minor>.<patch>-alpine: Specific Alpine release tag (e.g., :2.0.3-alpine).

All floating tags (:latest, :<major>, :<major>.<minor> and their -alpine counterparts) are rebuilt regularly to include the latest OS security updates and any application changes present in the source commit used for that build. Consumers who require strict version pinning should use the full :<major>.<minor>.<patch> or :<major>.<minor>.<patch>-alpine tags.

License

This project is released under the MIT License.

Contributing

  1. See AGENT.md for guidelines and architecture

  2. Note that NextDNS does not provide an OpenAPI specification. This is based on their documentation and may not reflect the current state of the API.

Available Tools

8 tools
dohLookupDohlookupC

Perform a DNS-over-HTTPS lookup using a NextDNS profile.

ParametersJSON Schema
NameRequiredDescriptionDefault
domainYesThe domain name to look up (e.g., "adwords.google.com")
profile_idNoNextDNS profile ID. If not provided, uses NEXTDNS_DEFAULT_PROFILE.
record_typeNoDNS record type to query (default "A").A

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full behavioral burden. 'Lookup' implies a non-mutating read, which is useful, but nothing is said about authentication requirements, rate limits, whether the profile must pre-exist, or how the default-profile fallback behaves at runtime.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence with no waste. It is efficient, though the brevity edges toward under-specification rather than optimal conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The output schema exists, so return-value explanation is not required, and the three parameters are fully covered by the schema. However, with no annotations and no usage or behavioral context, the definition is only minimally sufficient for an agent to invoke this confidently.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

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 domain, profile_id (including the NEXTDNS_DEFAULT_PROFILE fallback), and record_type. The description adds no parameter meaning beyond what the schema provides, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (lookup) and resource (DNS-over-HTTPS via a NextDNS profile), which an agent can distinguish from the manage*/analytics siblings. It stops short of saying anything that would differentiate it from a hypothetical non-DoH DNS lookup, but the purpose is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives no indication of when to use this tool versus the sibling tools (queryAnalytics, manageLogs) or when a DoH lookup is the right approach. There are no prerequisites or exclusion conditions stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

manageListsManagelistsA

Manage allow/deny/block lists for a NextDNS profile.

List types: - allowlist / denylist: Always-allow or always-block specific domains. - privacy_blocklists: Subscribed blocklists (e.g., nextdns-recommended). - privacy_natives: Native tracking blockers (e.g., apple, facebook). - security_tlds: Dangerous top-level domains to block (e.g., zip). - parental_categories: Content categories (e.g., gambling, porn). - parental_services: Specific apps/services (e.g., tiktok, youtube).

Operations: - get: Return the current list. - add: Append one entry (pass entry as {"id": "value"} or as a plain id string). The entry must carry a string id; an entry without one is rejected locally with invalid_argument rather than sent upstream. - remove: Delete one entry by entry_id. - update: Toggle an existing entry by entry_id (pass entry={"active": True|False}). Only supported for allowlist, denylist, parental_categories, and parental_services. - replace: Replace the entire list with entries (list of dicts). Each entry must be an object with a string id; a malformed entry is rejected locally with invalid_argument naming its index, rather than sent upstream.

Examples: - get: manageLists(list_type="denylist", operation="get", profile_id="abc123") - add: manageLists(list_type="denylist", operation="add", profile_id="abc123", entry={"id": "example.com"}) - remove: manageLists(list_type="denylist", operation="remove", profile_id="abc123", entry_id="example.com") - replace: manageLists(list_type="privacy_blocklists", operation="replace", profile_id="abc123", entries=[{"id": "nextdns-recommended"}]) - add parental category: manageLists(list_type="parental_categories", operation="add", profile_id="abc123", entry={"id": "gambling"}) - update parental service: manageLists(list_type="parental_services", operation="update", profile_id="abc123", entry_id="tiktok", entry={"active": False})

ParametersJSON Schema
NameRequiredDescriptionDefault
entryNo
entriesNo
entry_idNo
list_typeYes
operationYes
profile_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does well: it discloses local validation behavior (entries lacking a string 'id' rejected with invalid_argument, named by index for replace), the destructive nature of 'replace' overwriting the entire list, and the list-type restriction on 'update'. It omits permission/auth requirements and any rate-limit or mutation-side-effect notes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the purpose, then cleanly sectioned into list types, operations, and examples, so it scans well. The six examples are largely a restatement of the operations section and add length, though each is individually compact and useful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 6-parameter, multi-operation tool with 0% schema coverage and no annotations, the description supplies everything needed to call it correctly: valid list types, per-operation argument shapes, validation failure modes, and an output schema covers return values. No meaningful gap remains.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does: 'entry' is documented as either {"id": "value"} or a plain id string, 'entries' as a list of dicts, 'entry_id' as the remove/update key, plus the accepted values for list_type and operation. The worked examples pin down exact call shapes for each operation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening states a specific verb and resource ('Manage allow/deny/block lists for a NextDNS profile') and then enumerates the exact list types and operations, which cleanly separates it from siblings like manageSettings, manageProfiles, and manageRewrites. An agent can identify what this tool covers without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Each operation is defined with its intended use ('get' returns, 'add' appends, 'remove' deletes, 'replace' overwrites the entire list), and a constraint is given for 'update' (only allowlist/denylist/parental_categories/parental_services). There is no explicit comparison against alternative tools for overlapping tasks, which keeps it short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

manageLogsManagelogsA

Manage query logs for a NextDNS profile.

Operations: - get: Return recent query log entries (use limit to cap results). Set raw=true to bypass deduplication/noise filtering. - clear: Delete all stored logs for the profile. - download: Download retained logs as CSV. from_time and to_time are ignored by the NextDNS download endpoint. The CSV is streamed to a temporary file; only the file path, size, row count, and a small capped preview are returned (the full text is never inlined). A hard total-size cap bounds how much is streamed to disk (the NEXTDNS_DOWNLOAD_MAX_BYTES environment variable, default 1 GiB); a download that would exceed it is aborted mid-stream and the partial file is removed. On success the temp file is not cleaned up: the CSV stays in the OS temp directory (mode 0600) and the returned path is the only record of it, so delete it when it is no longer needed. Failed downloads do remove the temp file and its parent directory.

Time values can be Unix timestamps or relative strings like -1d or -7d. They are only used by get.

limit is clamped server-side to the range 1-1000 entries for get (the range accepted by the NextDNS API): values above 1000 are reduced to 1000 and non-positive values to 1. The clamp is silent, so ask for at most 1000.

Examples: - get recent: manageLogs(operation="get", profile_id="abc123", limit=10) - get raw logs: manageLogs(operation="get", profile_id="abc123", raw=true) - download: manageLogs(operation="download", profile_id="abc123", from_time="-1d") - clear: manageLogs(operation="clear", profile_id="abc123")

ParametersJSON Schema
NameRequiredDescriptionDefault
rawNo
userNo
limitNo
deviceNo
to_timeNo
from_timeNo
operationYes
profile_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full behavioral burden and does so thoroughly: clear is destructive (deletes all stored logs), download is bounded by NEXTDNS_DOWNLOAD_MAX_BYTES, aborts mid-stream and deletes the partial file on overflow, and on success leaves a mode-0600 temp file that the caller must delete. It also discloses that only a path/size/row-count/preview is returned and that limit clamping is silent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose and a bulleted operation list, then examples, so it is easy to scan. It is verbose in places (the temp-file lifecycle is dwelt on at length), but each sentence conveys actionable information rather than filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter, unannotated, multi-mode tool this is well covered: operation modes, clamping, time semantics, destructive behavior, and side effects of download are all spelled out, and an output schema exists so return values need no further explanation. Only the user/device filters remain unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

At 0% schema description coverage the description must compensate, and it does for most parameters: it explains the three operation values, the 1-1000 silent clamp on limit, raw=true semantics, accepted time formats (Unix or '-1d'), and that time values apply only to get. The user and device parameters are never mentioned, leaving two of eight undocumented in both schema and description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first line names a concrete verb+resource (manage query logs for a NextDNS profile) and breaks the tool into three explicitly enumerated operations (get/clear/download), so an agent knows exactly what it does. It does not, however, distinguish itself from siblings like queryAnalytics or plotAnalytics, which also deal with log/analytics data, so the boundary is left implicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives per-operation usage: 'use limit to cap results', 'set raw=true to bypass deduplication/noise filtering', notes that from_time/to_time are ignored by the download endpoint and only used by get, and provides four concrete call examples. It lacks guidance on when to prefer this tool over the analytics siblings, so it stops short of full when/when-not coverage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

manageProfilesManageprofilesA

Manage NextDNS profiles.

NextDNS profiles are named configurations that contain DNS settings, blocklists, analytics, and logs. Most other tools require a profile_id from this tool.

Operations: - list: Return profiles the API key can access (supports cursor for pagination). - create: Create a new profile (requires name). - get: Retrieve a single profile (requires profile_id). - update: Rename a profile (requires profile_id and name). - delete: Remove a profile (requires profile_id).

Examples: - list: manageProfiles(operation="list") - list (page): manageProfiles(operation="list", cursor="j2k3zl3b4v") - create: manageProfiles(operation="create", name="Home Network") - get: manageProfiles(operation="get", profile_id="abc123")

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNo
cursorNo
operationYes
profile_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden. It does disclose useful traits beyond the schema, such as cursor-based pagination for list and that delete removes a profile, but it omits permission requirements, irreversibility of delete, and rate-limit behavior, leaving meaningful gaps for a mutation-capable tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The structure is excellent: a one-line purpose, an operations list with per-op requirements, and concrete call examples. It is slightly verbose since the examples partly restate the operations list, but every block adds routing value for a multi-operation tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no explanation, and the description covers all operations, their parameters, pagination, and upstream dependency. It is nearly complete; only safety/permission context for destructive operations is missing, which is a modest gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it largely does: it maps each operation to its required parameters (create→name, get/delete→profile_id, update→profile_id+name) and explains cursor's pagination role. All four parameters are given meaning, though name/cursor formats remain unspecified.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific resource (NextDNS profiles) and enumerates the five distinct operations it performs (list/create/get/update/delete). It also distinguishes itself from siblings by noting that most other tools require a profile_id obtained from this tool, so an agent can place it in the workflow without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly routes usage: most other tools depend on a profile_id sourced here, and each operation lists its required inputs. There is no explicit when-not-to-use guidance or exclusion of sibling tools, so it falls short of a full 5 despite the strong context provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

manageRewritesManagerewritesA

Manage DNS rewrite entries for a NextDNS profile.

Rewrites let you return a custom answer for a hostname. Typical uses:

  • Point an internal hostname to a private IP.

  • Block a domain by rewriting it to 0.0.0.0.

Operations: - list: Show existing rewrites. - add: Create a rewrite (requires name and content). - delete: Remove a rewrite (requires entry_id from list).

Examples: - list: manageRewrites(operation="list", profile_id="abc123") - add: manageRewrites(operation="add", profile_id="abc123", name="router.home", content="192.168.1.1") - delete: manageRewrites(operation="delete", profile_id="abc123", entry_id="<id-from-list>")

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNo
contentNo
entry_idNo
operationYes
profile_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description must carry behavioral burden. It discloses that add mutates by creating an entry and delete removes one, and that entry_id must be sourced from list (an ordering dependency), which is useful. However it says nothing about authorization needs, idempotency, whether deletes are reversible, or side effects on DNS resolution beyond the illustrative examples.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded one-line purpose, then a short usage rationale, then an operation list, then examples. Each block earns its place and nothing is redundant; examples directly reinforce the required-parameter rules.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, and the description covers all three operations with required inputs. The omission of any note on profile_id semantics or failure modes keeps it from being fully complete for a mutation-capable multi-operation tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does: it maps name/content to add and entry_id to delete, and the operation enum values are each explained with an example. The only gap is profile_id, which is required but never described beyond appearing in examples.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Manage DNS rewrite entries for a NextDNS profile') with clear scope, and the sibling set (manageSettings, manageProfiles, manageLists) makes it obvious this handles rewrites specifically. The enumeration of list/add/delete operations further pins down what the tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit per-operation guidance, including which parameters each operation requires (add needs name/content, delete needs entry_id from list) and concrete call examples. It stops short of when-not-to-use guidance or steering to a sibling for adjacent tasks, so it lands at 4 rather than 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

manageSettingsManagesettingsA

Manage a settings category for a NextDNS profile.

Settings categories: - general: Core profile settings (e.g., name, web3 blocking). - privacy: Privacy features such as disguised-tracker blocking and affiliate links. - security: Threat intelligence, Google Safe Browsing, typosquatting protection. - parental: Parental control enablement (safe search, YouTube restricted mode). - performance: ECS, cache boost, and other performance options. - logs: Query-logging enablement and retention. - blockpage: Whether to show a custom block page for blocked queries.

Operations: - get: Retrieve current settings for the category. - update: Apply new settings (requires settings payload).

The settings argument can be a Python dict or a JSON string. For update, first call get to see the current schema, then send only the fields you want to change.

Examples: - get: manageSettings(operation="get", category="privacy", profile_id="abc123") - update: manageSettings(operation="update", category="privacy", profile_id="abc123", settings={"disguisedTrackers": True})

ParametersJSON Schema
NameRequiredDescriptionDefault
categoryYes
settingsNo
operationYes
profile_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses that update requires a settings payload, that settings can be a dict or JSON string, and that you should retrieve first to see the schema. It doesn't describe permissions, reversibility, or rate limits, but for a settings-management tool, the get-before-update guidance and payload format are substantial behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a clear purpose statement, a bulleted category list, a bulleted operation list, and concrete examples. Every sentence earns its place; the formatting makes it easy to scan for the relevant category or operation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (4 parameters, 2 enums, no annotations, but an output schema exists), the description is complete enough. It covers all categories, both operations, the settings payload format, and the recommended workflow. The output schema handles return values, so the description doesn't need to explain them.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It does: it enumerates all category values with meanings, lists the two operations with their effects, explains the settings argument format (dict or JSON string), and provides examples showing exact parameter usage. This fully compensates for the schema gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb+resource: managing a settings category within a NextDNS profile. It enumerates all categories and operations, so the agent understands the exact scope. It doesn't explicitly distinguish from siblings like manageProfiles or manageLogs, though the category list implicitly covers some overlap.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear when-to-use guidance: 'first call get to see the current schema, then send only the fields you want to change.' It explains the get-then-update workflow, which is a strong usage guideline. It doesn't state when not to use this tool or name alternatives, but the workflow guidance is explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

plotAnalyticsPlotanalyticsA

Generate a PNG line chart for a NextDNS analytics time-series metric.

Use this to visualize query trends over time. The profile should have recent query history; otherwise the tool returns an error explaining that no data is available.

Supported metrics: status, devices, protocols, queryTypes, ipVersions, dnssec, encryption, reasons, ips.

Time values can be Unix timestamps or relative strings like -1d.

The ;series endpoint takes no limit parameter: limit is part of this tool's published surface, is rejected above 500 rather than clamped, and is never forwarded, so the requested range is the only thing that bounds the response. Three server-side limits are enforced before the request is built, and each is rejected with an invalid_argument error naming the limit rather than silently adjusted:

  • interval must be between 60 and 86400 seconds.

  • limit must not exceed 500.

  • The range must be interpretable (a Unix timestamp, an ISO 8601 timestamp, now, or a relative offset such as -7d; a relative unit letter is read case-sensitively and a timestamp with no timezone is read as UTC), must end after it starts, and spans at most 2000 intervals (at most 2000 points per series), so a wide range needs a proportionally larger interval.

Examples: - plotAnalytics(metric="status", profile_id="abc123", from_time="-1d") - plotAnalytics(metric="devices", profile_id="abc123", from_time="-7d", interval=86400) - a year of data: plotAnalytics(metric="status", profile_id="abc123", from_time="-1y", interval=43200)

Returns: An MCP ImageContent PNG chart, or an error dict if data is unavailable.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
metricYes
to_timeNonow
intervalNo
partialsNonone
timezoneNoGMT
alignmentNoend
from_timeNo-1d
profile_idNo

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so well: it discloses the failure mode (error when no data), the return type (ImageContent PNG or error dict), and the exact server-side enforcement behavior — limits rejected ('invalid_argument' naming the limit) rather than silently clamped, plus the 60–86400s interval and 2000-interval span caps. This is behavior an agent genuinely needs and could not infer from the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and metric list are front-loaded, and the bulleted limits plus concrete examples make the dense content scannable. The middle paragraph about the ';series' endpoint and the limit being 'never forwarded' is somewhat convoluted and could be tightened, but the overall structure earns its length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, but the description names the return form (PNG chart or error dict), and with no annotations it supplies the safety/behavioral context itself. Only the unexplained secondary parameters keep it from being fully complete for a 9-parameter tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 9 parameters, so the description must compensate, and it does for several: metric values, from_time/to_time timestamp and relative-offset formats, the interval range, and the limit ceiling. However, partials, alignment, and the timezone parameter are never explained, leaving a meaningful share of the surface undocumented in either place.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening states a specific verb and resource: 'Generate a PNG line chart for a NextDNS analytics time-series metric,' immediately separating it from a data-returning sibling like queryAnalytics. The follow-up 'visualize query trends over time' pins the distinct job down without ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states when to use it ('visualize query trends over time') and gives a real precondition (the profile needs recent history or it errors). It stops short of naming an alternative tool or an explicit when-not-to-use condition, so it is clear context rather than full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

queryAnalyticsQueryanalyticsA

Query NextDNS analytics metrics.

Metrics: - status: Query resolution status (default, blocked, allowed, relayed). - domains: Top domains; supports the status and root filters. - devices: Queries per device. - protocols: DNS transport protocol (DoH, DoT, Do53 UDP/TCP, DoQ). - queryTypes: DNS record types requested (A, AAAA, CNAME, etc.). - ipVersions: IPv4 vs IPv6 queries. - dnssec: DNSSEC validation results. - encryption: Encrypted vs unencrypted queries. - reasons: Why queries were blocked or allowed. - ips: Top source IPs. - destinations: Top destinations; requires destination_type such as countries or gafam.

Set series=true to fetch time-series data instead of aggregate totals. Time values can be Unix timestamps or relative strings like -1d. Note: series=true is not supported when metric="domains".

limit is clamped server-side to the range 1-500 (the range accepted by the NextDNS API): values above 500 are reduced to 500 and non-positive values to 1. The clamp is silent, so ask for at most 500.

Optional filters: - cursor: Pagination cursor from a previous response. - device: Filter analytics to a single device id. - status: For the domains metric, filter by resolution status. - root: For the domains metric, group results by root domain (boolean).

Examples: - totals: queryAnalytics(metric="status", profile_id="abc123", from_time="-1d") - time series: queryAnalytics(metric="status", profile_id="abc123", from_time="-1d", series=true) - destinations: queryAnalytics(metric="destinations", profile_id="abc123", from_time="-1d", destination_type="countries")

ParametersJSON Schema
NameRequiredDescriptionDefault
rootNo
limitNo
cursorNo
deviceNo
metricYes
seriesNo
statusNo
to_timeNo
intervalNo
partialsNo
timezoneNo
alignmentNo
from_timeNo
profile_idYes
destination_typeNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden and adds substantial detail: silent server-side limit clamping to 1-500, the series/domains incompatibility, cursor-based pagination, destination_type requirement, and time input formats. It still does not state auth requirements, error behavior, or explicitly that the operation is read-only, so it is not fully transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose and organized into metrics, notes, filters, and examples. It is fairly long, but the length is justified by the 15-parameter surface and the need to document metric semantics. Slight tightening is possible, but there is little wasted text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the high parameter count, 0% schema coverage, no annotations, and an available output schema, the description is mostly complete. It covers the core metrics, filters, and examples needed for basic calls, but the four undocumented optional parameters and the lack of sibling-tool routing leave gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explains metric values, series, limit clamping, cursor, device, status, root, destination_type, and from_time/to_time formats. However, interval, partials, timezone, and alignment are never described, leaving four parameters undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb and resource: 'Query NextDNS analytics metrics.' It then enumerates the metrics it can return, making the tool's scope concrete. It does not explicitly distinguish itself from sibling tools such as plotAnalytics, so it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear usage context: aggregate totals by default, series=true for time-series, destinations requiring destination_type, and examples for common calls. It also notes that series=true is unsupported for metric='domains'. It does not explain when to choose this tool over plotAnalytics or manageLogs, so no sibling routing is provided.

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.

  1. 1 tool updatev3.2.0
    • ChangedmanageProfiles1 field changed
      • addedInput schema / properties / cursor
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
  2. 2 tool updatesv3.1.5
    • AddeddohLookup
    • AddedmanageSettings
  3. 3 tool updatesv3.1.3
    • RemoveddohLookup
    • AddedmanageLists
    • AddedmanageRewrites
  4. 3 tool updatesv3.1.2
    • RemovedmanageLists
    • RemovedmanageRewrites
    • RemovedmanageSettings
  5. 82 tool updatesv3.0.1
    • RemovedaddPrivacyBlocklist
    • RemovedaddPrivacyNative
    • RemovedaddSecurityTLD
    • RemovedaddToAllowlist
    • RemovedaddToDenylist
    • RemovedaddToParentalControlCategories
    • RemovedaddToParentalControlServices
    • RemovedclearLogs
    • RemovedcreateProfile
    • RemoveddeleteProfile
    • ChangeddohLookup2 fields changed
      • changedInput schema / properties / profile_id / description
        Previous value: -"NextDNS profile ID (6-character alphanumeric). If not provided, uses NEXTDNS_DEFAULT_PROFILE"New value: +"NextDNS profile ID. If not provided, uses NEXTDNS_DEFAULT_PROFILE."
      • changedInput schema / properties / record_type / description
        Previous value: -"DNS record type to query. Common types:\n- A: IPv4 address (default)\n- AAAA: IPv6 address\n- CNAME: Canonical name\n- MX: Mail exchange\n- TXT: Text records\n- NS: Name servers\n- SOA: Start of authority\n- PTR: Pointer record"New value: +"DNS record type to query (default \"A\")."
    • RemovedgetAllowlist
    • RemovedgetAnalyticsDestinations
    • RemovedgetAnalyticsDestinationsSeries
    • RemovedgetAnalyticsDevices
    • RemovedgetAnalyticsDevicesSeries
    • RemovedgetAnalyticsDNSSEC
    • RemovedgetAnalyticsDNSSECSeries
    • RemovedgetAnalyticsDomains
    • RemovedgetAnalyticsEncryption
    • RemovedgetAnalyticsEncryptionSeries
    • RemovedgetAnalyticsIPs
    • RemovedgetAnalyticsIPsSeries
    • RemovedgetAnalyticsIPVersions
    • RemovedgetAnalyticsIPVersionsSeries
    • RemovedgetAnalyticsProtocols
    • RemovedgetAnalyticsProtocolsSeries
    • RemovedgetAnalyticsQueryTypes
    • RemovedgetAnalyticsQueryTypesSeries
    • RemovedgetAnalyticsReasons
    • RemovedgetAnalyticsReasonsSeries
    • RemovedgetAnalyticsStatus
    • RemovedgetAnalyticsStatusSeries
    • RemovedgetBlockPageSettings
    • RemovedgetDenylist
    • RemovedgetLogs
    • RemovedgetLogsSettings
    • RemovedgetParentalControlCategories
    • RemovedgetParentalControlServices
    • RemovedgetParentalControlSettings
    • RemovedgetPerformanceSettings
    • RemovedgetPrivacyBlocklists
    • RemovedgetPrivacyNatives
    • RemovedgetPrivacySettings
    • RemovedgetProfile
    • RemovedgetSecuritySettings
    • RemovedgetSecurityTLDs
    • RemovedgetSettings
    • RemovedlistProfiles
    • AddedmanageLists
    • AddedmanageLogs
    • AddedmanageProfiles
    • AddedmanageRewrites
    • AddedmanageSettings
    • AddedplotAnalytics
    • AddedqueryAnalytics
    • RemovedremoveFromAllowlist
    • RemovedremoveFromDenylist
    • RemovedremoveFromParentalControlCategories
    • RemovedremoveFromParentalControlServices
    • RemovedremovePrivacyBlocklist
    • RemovedremovePrivacyNative
    • RemovedremoveSecurityTLD
    • RemovedreplaceAllowlist
    • RemovedreplaceDenylist
    • RemovedreplaceParentalControlCategories
    • RemovedreplaceParentalControlServices
    • RemovedreplacePrivacyBlocklists
    • RemovedreplacePrivacyNatives
    • RemovedreplaceSecurityTLDs
    • RemovedupdateAllowlistEntry
    • RemovedupdateBlockPageSettings
    • RemovedupdateDenylistEntry
    • RemovedupdateLogsSettings
    • RemovedupdateParentalControlCategoryEntry
    • RemovedupdateParentalControlServiceEntry
    • RemovedupdateParentalControlSettings
    • RemovedupdatePerformanceSettings
    • RemovedupdatePrivacySettings
    • RemovedupdateProfile
    • RemovedupdateSecuritySettings
    • RemovedupdateSettings

TDQS

A3.9/5.0

Scored across 8 tools

Disambiguation4/5

Most tools target clearly distinct resources: profiles, settings, lists, rewrites, logs, and DNS lookup. The main ambiguity is between queryAnalytics and plotAnalytics, which both cover analytics metrics but return data versus a chart, so an agent could occasionally misselect.

Naming Consistency4/5

The dominant pattern is camelCase verb_noun (manageSettings, manageProfiles, manageLists, manageRewrites, manageLogs, queryAnalytics, plotAnalytics). dohLookup is the one mild deviation because it starts with an acronym/noun rather than a verb, but the overall convention is still predictable.

Tool Count5/5

Eight tools is well-scoped for a NextDNS management server. Each tool groups a coherent operation family, and none appear redundant or gratuitous.

Completeness5/5

The surface covers profile CRUD, per-category settings get/update, allow/deny/blocklist management, rewrites, DoH lookup, log retrieval/clear/download, and analytics querying/plotting. This provides full lifecycle coverage for the domain, with no obvious dead ends for typical NextDNS administration.

Maintenance

ActivityActive
ResponsivenessWithin a week

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    F
    maintenance
    Enables AI assistants to interact with Fastly's CDN API through the Model Context Protocol, allowing secure management of CDN services, caching, security settings, and performance monitoring without exposing API keys.
    2
    18 npm
    7
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to manage Cloudflare infrastructure including DNS records, cache purging, SSL settings, Workers, and analytics through the Cloudflare API. Eliminates dashboard context-switching by allowing natural language control of domain management and infrastructure operations.
    -
  • F
    license
    Not graded
    quality
    A
    maintenance
    Real-time DNS security analysis for AI assistants via MCP. Enables DNSSEC chain validation, email authentication posture, and registration intelligence directly from chat sessions.
    1
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables natural language management of Cloudflare services including Workers, KV, R2, D1, Queues, and more via the Model Context Protocol.
    2,408 npm
    Apache 2.0