Skip to main content
Glama

add_local_a_record

Add a local A record to map a hostname to an IP address. Existing entries for the same host are automatically replaced.

Instructions

Add a local A record (host -> IP). Replaces any existing entry for the same host.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
hostYes
ipYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The `add_local_a_record` tool handler: fetches current DNS config, filters out any existing entry for the same host, appends the new `ip host` record, and PATCHes the config.
    async def add_local_a_record(host: str, ip: str) -> dict:
        """Add a local A record (host -> IP). Replaces any existing entry for the same host."""
        dns = await _current_dns_config(client)
        hosts = [h for h in dns.get("hosts", []) if not h.endswith(f" {host}")]
        hosts.append(f"{ip} {host}")
        return await _patch_dns(client, {"hosts": hosts})
  • The `register` function uses `@mcp.tool()` decorator to register `add_local_a_record` (and 4 other tools) on the FastMCP instance.
    def register(mcp: FastMCP, client: PiholeClient) -> int:
        @mcp.tool()
        async def list_local_dns() -> dict:
            """List local DNS entries (hosts and CNAME records)."""
            dns = await _current_dns_config(client)
            return {"hosts": dns.get("hosts", []), "cnameRecords": dns.get("cnameRecords", [])}
    
        @mcp.tool()
        async def add_local_a_record(host: str, ip: str) -> dict:
            """Add a local A record (host -> IP). Replaces any existing entry for the same host."""
            dns = await _current_dns_config(client)
            hosts = [h for h in dns.get("hosts", []) if not h.endswith(f" {host}")]
            hosts.append(f"{ip} {host}")
            return await _patch_dns(client, {"hosts": hosts})
    
        @mcp.tool()
        async def remove_local_a_record(host: str) -> dict:
            """Remove any local A record matching the given host."""
            dns = await _current_dns_config(client)
            hosts = [h for h in dns.get("hosts", []) if not h.endswith(f" {host}")]
            return await _patch_dns(client, {"hosts": hosts})
    
        @mcp.tool()
        async def add_local_cname_record(host: str, target: str, ttl: int = 300) -> dict:
            """Add a local CNAME record (host -> target). Replaces any existing CNAME for the same host."""
            dns = await _current_dns_config(client)
            records = [r for r in dns.get("cnameRecords", []) if not r.startswith(f"{host},")]
            records.append(f"{host},{target},{ttl}")
            return await _patch_dns(client, {"cnameRecords": records})
    
        @mcp.tool()
        async def remove_local_cname_record(host: str) -> dict:
            """Remove any local CNAME record for the given host."""
            dns = await _current_dns_config(client)
            records = [r for r in dns.get("cnameRecords", []) if not r.startswith(f"{host},")]
            return await _patch_dns(client, {"cnameRecords": records})
    
        return 5
  • Helper `_current_dns_config` fetches the current DNS config from Pi-hole API.
    async def _current_dns_config(client: PiholeClient) -> dict:
        payload = await client.get("/config/dns")
        config = payload.get("config") or {}
        dns = config.get("dns") or {}
        return dns
  • Helper `_patch_dns` sends a PATCH request to update DNS config.
    async def _patch_dns(client: PiholeClient, dns_delta: dict) -> dict:
        return await client.patch("/config/dns", json={"config": {"dns": dns_delta}})
  • `register_all` iterates all tool modules (including `local_dns`) and calls their `register` function, wiring tools to the MCP server.
    def register_all(mcp: FastMCP, client: PiholeClient) -> int:
        """Register every tool module against the FastMCP instance. Returns tool count."""
        count = 0
        for module in (stats, queries, blocking, domains, local_dns, maintenance):
            count += module.register(mcp, client)
        return count
Behavior3/5

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

Discloses that the tool replaces any existing entry for the same host, which is a key behavioral trait. However, with no annotations, the description could also mention side effects, required permissions, or failure modes.

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?

Two succinct sentences with no redundancy. Purpose is front-loaded, and every word contributes to understanding.

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?

With an output schema present, the description is fairly complete for a simple mutation tool. It could mention that changes take effect immediately or require admin privileges, but overall it covers the essential operation.

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?

Adds meaning to the 'host' parameter by noting it uniquely identifies the record and references replacement. The 'ip' parameter is left as basic. With 0% schema description coverage, the description provides some context but not detailed format expectations.

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?

Clearly states the action 'Add' and the resource 'local A record', with the mapping 'host -> IP'. Distinguishes from sibling tools like add_local_cname_record, and includes a key behavioral note about replacement.

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?

Implicitly guides usage by specifying that it replaces existing entries, indicating idempotent behavior. Lacks explicit alternatives or when-not-to-use guidance, but the context is clear given the tools name and siblings.

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

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/chris2ao/pihole-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server