← Back to project

Using CoreDNS APIs for MCP Management



This article explores how to leverage CoreDNS’s plugin architecture and existing APIs to build an MCP‑controlled DNS server. While we previously recommended a custom server, CoreDNS remains a viable alternative if we can integrate SQLite storage and MCP management via plugins or an auxiliary control layer.

---

CoreDNS Plugin Architecture Overview



CoreDNS is built around a chain of plugins. each plugin implements the `plugin.Handler` interface and can process the DNS query/response or provide management functionality. Plugins are configured in the `Corefile` and loaded at runtime.

Key interfaces:


Plugins can also define their own configuration directives parsed from the Corefile.


---

Storing Zones in SQLite with CoreDNS



CoreDNS’s official `file` plugin reads zone files. There is no official SQLite backend. However, we have two approaches:

Option A: Write a Custom SQLite Plugin



Implement a plugin that:


The plugin would register as a `Handler` and also expose additional MCP tools via a separate registration? Not directly; MCP is external. So the plugin would primarily serve DNS from SQLite. We could also make it respond to a custom DNS query type (e.g., `TYPE255` or `TXT` under a special name) to trigger reload, but that’s hacky.


Better: the plugin watches the SQLite file or receives a signal to reload. The MCP server (separate binary) would:


But CoreDNS’s plugin system doesn’t have a built‑in hot‑reload callback. The typical way to reload CoreDNS is to send `SIGHUP` to the process; CoreDNS will re‑parse the Corefile and call plugin `Startup()` again? Actually, CoreDNS’s `caddy` base has a `Reload` mechanism: you can send `SIGUSR1` to trigger a live configuration reload without dropping connections. In that case, each plugin’s `Setup` is re‑run? Let’s check: CoreDNS uses Caddy’s `caddycmd` and `caddyhttp`. For DNS, it’s a bit different; the server can be reloaded by sending `SIGUSR1` (or using `coredns - reload`). When reloading, the new process reads the Corefile and starts fresh; the old process finishes existing queries and exits. That’s a clean new process, not an in‑memory swap. So if we want zero‑downtime, we need to keep state in shared memory or database. SQLite writes are immediate; new process will read fresh data. That works: MCP writes to SQLite, then triggers `SIGUSR1` to CoreDNS to reload config (which may be static Corefile; but the reload causes new process to re‑instantiate the SQLite plugin, which reads fresh DB). This yields a brief pause but minimal. In practice, it’s acceptable.


Thus: custom `sqlite` plugin reads zones at startup on each reload. MCP server triggers reload by sending `SIGUSR1` to CoreDNS.

Option B: Use the `dynamic` plugin



CoreDNS has a `dynamic` plugin that allows updating zone data via a `dns.db` file and a `dnsdb` update mechanism using IXFR? Not exactly. The `dynamic` plugin keeps zones in memory and can apply updates via a `dynamic.update` file? Actually, there is a `dynamic` plugin that serves zones that can be updated by sending `SIGUSR1` after editing a zone file? Not appropriate.

Option C: Wrap CoreDNS with an External MCP Server



Instead of embedding MCP, we run a separate MCP server process that:


We can also expose a tiny HTTP API on the MCP server as an alternative.


---

Designing the SQLite Plugin



A minimal `sqlite` plugin for CoreDNS:


The plugin would be compiled into CoreDNS as a third‑party plugin, and we’d use a custom build.


---

MCP Server as Separate Process



We write an MCP server (Go) that:


This design decouples MCP from CoreDNS; the MCP server can be versioned independently. CoreDNS remains a pure DNS server.


---

Example Corefile Configuration




.:53 {
sqlite /var/db/dns-server.sqlite
log
errors
}


The MCP control server runs separately, maybe started by the same systemd unit with a `Type=forking`? Or could be a separate unit that depends on CoreDNS.

---

Pros and Cons vs Custom Server



Pros of CoreDNS‑based:


Cons:

---


Implementation Steps (CoreDNS + MCP)



1. Create the SQLite plugin:

2. Build custom CoreDNS binary:
3. Write MCP control server:
4. Systemd setup:
5. Deployment package: Provide SQLite DB init script, Corefile, README.


---

Example MCP Interaction (same API as earlier)



The MCP control server implements identical tools as the custom server design. The only difference is that after `add_record`, it writes to SQLite and then sends `SIGUSR1` to the CoreDNS PID.

---

Conclusion



Using CoreDNS is feasible and may be preferable if you want to tap into its ecosystem (monitoring, advanced features). The main engineering task is writing the SQLite plugin and the MCP control wrapper. The MCP tool definitions remain the same. For a quicker MVP, the custom server approach is simpler (one binary, no plugin compilation). However, if you anticipate needing CoreDNS features later, starting with CoreDNS could save integration effort.

---

Word count: ~1,100