Files
3c8578e9f4 feat(mcp): add Streamable HTTP transport (#736)
* feat(mcp): add Streamable HTTP transport

Add a modern MCP 2026-07-28 HTTP endpoint for standalone and Web modes, with shared listener configuration, authentication, schema, tests, and bilingual documentation.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(tests): support Python 2 HTTP assertions

Normalize response header names and call handler methods through their underlying functions so the HTTP tests behave consistently on Python 2.7 and Python 3.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(mcp): harden HTTP request handling

Validate mirrored request IDs, align Config Studio listener checks, bound socket reads, and accept the binary wrapper's documented SIGINT exit status.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(mcp): align HTTP negotiation validation

Reject unavailable Accept media types by quality and keep schema host validation consistent with runtime listener checks.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(tests): validate host schema behavior

Assert accepted and rejected host samples instead of comparing Unicode escape representations that differ on Python 2.7.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(tests): avoid cross-engine schema regex

Keep the schema pattern contract without executing its ECMA-262 Unicode escape through Python 2's incompatible regex engine.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(mcp): validate HTTP request boundaries

Reject empty tokens and malformed JSON-RPC request shapes, and keep Config Studio bracket validation aligned with runtime listener handling.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(mcp): tighten HTTP input validation

Reject legacy notifications, nested host brackets, and document the required JSON content type so validation remains consistent across runtime, schema, and Config Studio.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(mcp): validate Origin before method errors

Apply the existing Origin policy to non-POST MCP requests and return CORS headers for configured allowed origins.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* docs(mcp): clarify proxy Origin allowlist

Explain that browser clients behind TLS termination must allowlist the public HTTPS origin even when the public page appears same-origin.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* docs(mcp): add standalone server guide

Move MCP client setup, transports, tools, security, and protocol limits into dedicated Chinese and English pages with matching navigation and index links.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(mcp): reject duplicate routing headers

Reject repeated MCP protocol, method, and name headers before body consistency checks across Python 2 and Python 3.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(mcp): validate named request headers

Validate Mcp-Name for tools/call, prompts/get, and resources/read before dispatching unsupported methods.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-08-23 21:36:26 +08:00

4.4 KiB

title, description
title description
DDNS MCP Server Connect DDNS status and synchronization tools to MCP clients over stdio or Streamable HTTP

MCP Server

DDNS provides a standard-library-only MCP server so clients such as GitHub Copilot can inspect local cached status or run one complete DDNS synchronization after user approval. Provider credentials are never returned in protocol arguments or results.

Configuration path precedence is -c/--config > DDNS_CONFIG > the conventional local config paths. MCP mode accepts exactly one local file; remote URLs and multiple -c values are rejected.

stdio (default)

ddns mcp -c /etc/ddns/config.json

stdio mode opens no network listener. stdout is reserved for one JSON-RPC message per line, while runtime logs go to stderr.

Add the server directly to GitHub Copilot CLI:

copilot mcp add ddns -- ddns mcp -c /etc/ddns/config.json

Alternatively, add the following to an MCP client configuration:

{
  "mcpServers": {
    "ddns": {
      "command": "ddns",
      "args": ["mcp", "-c", "/etc/ddns/config.json"]
    }
  }
}

Escape Windows path backslashes as \\ in JSON, or replace command with the absolute path to the ddns executable.

Streamable HTTP

Start a standalone HTTP MCP server:

ddns mcp -c /etc/ddns/config.json --transport http

The default endpoint is http://127.0.0.1:9876/mcp. The Web console also exposes /mcp on its listener.

Standalone mode and Web share these options:

Option Description
--host Bind host; defaults to 127.0.0.1 and accepts a LAN address or 0.0.0.0 / ::
--port Listener port, default 9876; use 0 to let the OS select one
--http-token Shared Web API and HTTP MCP token; visible ASCII without spaces
--http-origin ORIGIN Exact HTTP(S) origin allowed to access /mcp; repeatable

Listener precedence is command line > root JSON http > DDNS_HTTP_* environment variables > 127.0.0.1:9876.

When loopback has no token, the Web APIs (including full configuration and provider credentials) and /mcp are unauthenticated. A non-loopback or wildcard listener requires a non-empty token. MCP clients send it as Authorization: Bearer <token>.

DDNS does not provide TLS. Put LAN listeners behind a trusted HTTPS reverse proxy that preserves Authorization, Host, and Origin. Browser access through a TLS-terminating proxy must list the exact public HTTPS origin in http.origins or --http-origin, even when the public page appears same-origin; native MCP clients may omit Origin.

HTTP supports MCP 2026-07-28 only. Each message is a separate POST to /mcp using Content-Type: application/json with MCP-Protocol-Version and Mcp-Method; tool calls also require Mcp-Name. Accept must list both application/json and text/event-stream.

This tools-only implementation returns plain JSON and does not provide SSE, sessions, legacy HTTP, resources, prompts, or subscriptions.

Available tools

Tool Arguments Behavior
get_ddns_status None Read local configuration, cached addresses and records, provider summaries, and the latest sync time; it does not query providers live
update_dns_records None Resolve current addresses using the configuration, synchronize every configured record once, and return the resulting status

update_dns_records changes external DNS state, so clients should retain user confirmation before invoking it. The tool accepts no domain, address, provider, or credential arguments, preventing a model from bypassing the local configuration to write arbitrary records.

Protocol and runtime limits

  • stdio supports MCP 2026-07-28 and the 2025-11-25 initialize lifecycle.
  • HTTP supports MCP 2026-07-28 only.
  • When a stdio client cancels an update, the server stops before subsequent IP rules, domain records, or providers.
  • HTTP provides no SSE cancellation; work may continue after a client disconnects.
  • A provider API request already sent cannot be rolled back.
  • Status comes from the local cache. With caching disabled, a later request in another process cannot reconstruct previous sync history, although the update call still returns its own result.
  • Do not let multiple Web, MCP, or system-task processes update the same configuration concurrently.