---
summary: MCP_PUBLIC_URL override for TLS-terminating proxies; design-mcp-server v2.7 — flexible tool naming, tiered subsections, server-as-service coverage, diversified examples; changelog/unreleased.md → template.md
breaking: false
---

# 0.6.6 — 2026-04-22

HTTP-mode servers deployed behind a TLS-terminating reverse proxy (Cloudflare Tunnel, Caddy, nginx, ALB) previously emitted `http://` self-referential URLs from the landing page, SEP-1649 Server Card, and RFC 9728 protected-resource metadata — because every handler derived `baseUrl` from the inbound request, which reflected the proxy-to-container hop rather than the public `https://` edge. Every copy-paste connect snippet was a dead link. This release adds an `MCP_PUBLIC_URL` override that is used verbatim as the base URL when set.

The `design-mcp-server` skill steps up to v2.6 with a codified 3-word `{server}_{verb}_{noun}` tool naming convention, a simplified shape taxonomy (Workflow and Instruction as explicit variants with distinct design pressures, single-action tools as the implicit default), documented workflow safety patterns (elicit-guarded destructive modes, safe defaults on blast-radius parameters), an "irreversible operations stay in the UI" principle distinct from `destructiveHint`, and a surface-audit pass. The `add-tool`, `field-test`, and `polish-docs-meta` skills update in lock-step — all tool-name examples follow the 3-word shape.

Closes [#43](https://github.com/cyanheads/mcp-ts-core/issues/43) and [#44](https://github.com/cyanheads/mcp-ts-core/issues/44).

## Added

- **`MCP_PUBLIC_URL` env var** — optional public-facing origin override (e.g. `https://mcp.example.com`). When set, the landing page connect snippets, SEP-1649 Server Card `endpoints.streamable_http`, and RFC 9728 `resource` fallback use this origin instead of the inbound request URL. Required behind TLS-terminating reverse proxies where the container sees `http://` but users reach the server over `https://`. Leave unset for direct (non-proxied) deployments; behavior is unchanged in that path. Surfaced on `AppConfig.mcpPublicUrl` (Zod-validated URL, empty-string → `undefined`) and on `ManifestTransport.publicUrl` (only present when configured). Wired through `CloudflareBindings` and `CORE_ENV_BINDINGS` in `createWorkerHandler()` so a plain `MCP_PUBLIC_URL` binding activates the override in Worker deployments without manual `extraEnvBindings` wiring. [#43](https://github.com/cyanheads/mcp-ts-core/issues/43)

## Changed

- **`skills/design-mcp-server/SKILL.md` → v2.7** — covers the full range of MCP servers: simple/complex API wrappers, no-API utilities, and stateful server-as-service designs. Tool naming relaxed from a strict 3-word rule: 3-segment `{server}_{verb}_{noun}` remains the strong default, 2 is valid when canonical (`git_pull`), 4 is valid for compound nouns (`patentsview_search_patent_families`). Step 4's situational subsections (Instruction tools, Workflow tool safety, Batch input, Convenience shortcuts) and checklist items tagged with `**Applies when:**` / `**If X:**` triggers so smaller models don't treat every subsection as mandatory. Mode consolidation collapsed from a subsection into a one-line tip (affects naming → noun-led, handler → dispatch by mode). Step 1 tagged conditional (internal-only servers skip it); research lead flipped to inline-by-default, with parallel agents reserved for genuinely parallelizable multi-API cases. Step 7 adds a Server-as-service paragraph pointing stateful designs at `ctx.state`. Granularity row accepts single API call, workflow, or internal-only. Examples diversified across DB migrations, deploy/release (canary/promote/rollback), observability, cloud infra, identity, and internal-only tools — previously clustered on email/notifications. ASCII diagrams replaced with markdown tables. [#44](https://github.com/cyanheads/mcp-ts-core/issues/44)
- **`skills/add-tool/SKILL.md` → v1.8** — new Naming section codifying the `{server}_{verb}_{noun}` convention with examples and the "name resists the schema → scope is fuzzy" diagnostic, cross-referencing `design-mcp-server` for shape selection (Workflow or Instruction variants).
- **`skills/field-test/SKILL.md` → v1.3** — sample report tool names updated to the 3-word convention (`acme_search_items`, `acme_get_item`).
- **`skills/polish-docs-meta/SKILL.md` → v1.7** — fictional README example tool names updated to the 3-word convention with `acme_` prefix.
- **`changelog/unreleased.md` → `changelog/template.md`** — renamed the pristine format reference to match its actual role. `unreleased.md` implied a worksheet; `template.md` makes it clear the file is copy-source-only and never edited. `scripts/build-changelog.ts`, `scripts/split-changelog.ts`, and `scripts/tree.ts` updated to match. `skills/polish-docs-meta/SKILL.md` and `skills/release/SKILL.md` updated to reference the new name. Same rename applied under `templates/changelog/` and reflected in `templates/CLAUDE.md` / `templates/AGENTS.md`.

## Fixed

- **Landing page, Server Card, and RFC 9728 protected-resource metadata now honor `MCP_PUBLIC_URL`** — `createLandingPageHandler`, `createServerCardHandler`, and `protectedResourceMetadataHandler` prefer the configured public URL over the inbound request origin. Trailing slash on `MCP_PUBLIC_URL` is stripped. Tests cover the proxied-deployment path (inbound `http://internal.container` + configured `https://mcp.example.com` → emitted URL carries the public origin) for all three surfaces, plus the trailing-slash normalization for the `resource` fallback. [#43](https://github.com/cyanheads/mcp-ts-core/issues/43)
- **Worker: `MCP_PUBLIC_URL` binding propagates to `process.env`** — the binding is now injected into `process.env` at Worker request time so the config layer's env-var read sees it correctly. Without this propagation, a bound `MCP_PUBLIC_URL` variable was invisible to the URL-override logic shipped above.
