facebook pixel

enpilink 2.1.0: MCP SDK v2, Built-In Testing and a Secured Admin Plane

By Liran Koren · Senior Product Developer, Enpitech
enpilink 2.1.0: MCP SDK v2, Built-In Testing and a Secured Admin Plane
Newsletter

Get the next post in your inbox

Frontend, AI and how teams ship. No spam, ever.

You shipped an MCP App on 1.x. Then the spec moved.

Your tools render React views in Claude and ChatGPT, the demo landed, and real users depend on it. Then the MCP spec gets a new revision, the SDK ships a v2, and the auth requirements tighten.

You can patch each change into your server yourself, or upgrade the framework that already absorbed them. enpilink 2.1.0 is that upgrade.

enpilink is Enpitech's open-source, MIT-licensed, full-stack TypeScript framework for MCP Apps and ChatGPT Apps: MCP tools that render interactive React views inside Claude, ChatGPT, VS Code and other hosts.

2.1.0 is the first published 2.x release. 2.0.0 was never published to npm, so everything in both changelog entries ships together, and 1.2.0 upgrades straight to 2.1.0.

Read this before you upgrade

2.1.0 is a major upgrade with breaking changes. Most apps need a handful of small edits, but check each of these before you bump the version:

  • zod 4.2 or later is required. zod v3 schemas are no longer accepted, and zod@^4.2 is now a peer dependency you install in your app.
  • Raw SDK members are gone from McpServer. server.server, the tool / resource / prompt aliases, isConnected and the send*ListChanged methods are removed. Use registerTool, registerResource and registerPrompt.
  • Token audience is always validated. If you validate or proxy tokens from an identity provider that issues a different audience, Clerk for example, set auth.audience.
  • An unset runtime mode now means production. The mode comes from ENPILINK_ENV, not NODE_ENV. If you start a dev server with your own script instead of enpilink dev, set ENPILINK_ENV=development.
  • The admin plane is on by default and sign-in gated, in development and production. The Console and its data APIs need a Console session or the static bearer token.
  • Templates require Vite ^8.0.16.

The full list, including smaller API changes to mountAdmin and devtoolsStaticServer, is in the changelog on GitHub.

What's new

MCP SDK v2 and the 2026-07-28 spec, same API

enpilink now runs on the official MCP TypeScript SDK v2 and speaks the 2026-07-28 MCP spec. The same /mcp endpoint still answers clients on the 2025 protocol versions, so older hosts keep working.

The McpServer API you register tools, resources and prompts with is unchanged. If you already use registerTool and its siblings, the protocol move needs no changes to your tool code.

Auth that matches the current spec

  • Client registration by metadata document (CIMD), with an SSRF-safe fetch and a choice of redirect policy: allowlist or document.
  • Dynamic client registration now works.
  • Authorization responses carry the iss parameter from RFC 9207, so a client can confirm which authorization server answered.

@enpilink/test: evals and view tests

The new @enpilink/test package covers two failures that unit tests do not catch: the model picking the wrong tool, and a view that looks right in one host and wrong in another.

  • Evals check that a natural prompt reaches the right tool. Anthropic is the default provider, and an OpenAI adapter is included.
  • View tests in @enpilink/test/views run Playwright across host, theme and device, with screenshot baselines. Run them with enpilink test views.

A Console that debugs OAuth and previews real hosts

  • An OAuth debugger tab runs the sign-in flow step by step and checks each response against the spec.
  • Realistic ChatGPT, Claude and mobile previews, chosen with URL params.
  • A fullscreen inspector, token warnings, and auto-run links (?tool=&args=&run=1) that block destructive tools unless you opt in with allowDestructive=1.

New view hooks

Views get useHostInfo, useDeepLink, useModelContext, useOpenFile and useFileResource. Follow-up messages can now be titled and targeted.

ChatGPT features

requestFormInput and ChatGPT settings through registerSettings, plus ChatGPT tool metadata for entrypoints, display modes, mentions and file viewers.

Experimental: Agent Skills and webhook events

Two experimental features track proposals that are still moving. Agent Skills over MCP (SEP-2640) arrive through discoverSkills. Webhook events (SEP-3415) arrive through deliverEvent, with an always-on SSRF guard. Expect both APIs to change as the proposals do.

Agent-layer adapters for the app you already run

The agent surface layer detects AI agents fetching your site, serves them a self-sufficient response, and measures whether they got what they came for. It now has adapters for Express (enpilink/express), Hono (enpilink/hono), Cloudflare Workers (enpilink/cloudflare) and Next.js edge middleware (enpilink/next). The detection ruleset ships with your instance, so nothing is fetched from us.

What it fixes

Security hardening

This release closes several auth gaps. If you run enpilink in production, these are the reason to schedule the upgrade now rather than later.

  • Per-tool auth now checks every tool call in a batched request.
  • Request bodies that weren't parsed as JSON are rejected, which closes a path where an unusual content type skipped the auth check.
  • Invalid or expired tokens get a proper 401, and unexpected errors in tool auth fail closed.
  • Authorization codes and refresh tokens are bound to the client they were issued to.
  • The dev Console and the dev tunnel are no longer open to anyone who can reach the port. Tunnel and LAN requests need a token.
  • The admin guard normalizes the request path, so variations in case, slashes or encoding no longer slip past it.

Notable bug fixes

  • Old view URIs still resolve after a redeploy.
  • Tool handlers without a schema receive (args, extra).
  • useCallTool callbacks stay stable across renders.
  • Servers without views build.
  • A crashed dev server child process is now reported.
  • CSS asset URLs are no longer rewritten with the JS runtime expression.

Why it's worth the migration

Your server keeps up with the spec without you tracking it. The protocol, SDK and auth changes land in the framework. Your tool code stays the same, and older clients keep connecting.

What you checked by hand now runs in CI. Tool selection and view rendering across hosts used to mean clicking through a chat window. Evals and view tests turn both into checks a pipeline can fail.

Production is safer by default. Production is the default mode, the admin plane needs sign-in, and the auth fixes close gaps you would otherwise have to find yourself.

Auth problems get a diagnosis. The OAuth debugger shows which step of the flow failed and what the spec expected, instead of a generic error inside a host.

How to upgrade

  1. Read the 2.1.0 and 2.0.0 entries in the changelog.
  2. Install zod 4.2 or later and move any zod v3 schemas.
  3. Bump enpilink and @enpilink/console to ^2.1.0. If your app came from a template, move Vite to ^8.0.16.
  4. Replace raw SDK members on McpServer with registerTool, registerResource and registerPrompt.
  5. If you validate tokens from an external IdP such as Clerk, set auth.audience.
  6. Set ENPILINK_ENV=development anywhere you start a dev server without enpilink dev.
  7. On a deployed server, sign in to the Console with a one-time token from enpilink admin token (on localhost under enpilink dev it opens without one), or set ENPILINK_ADMIN=0 if you don't want the admin plane.
bash
# Existing app
npm install "enpilink@^2.1.0" "@enpilink/console@^2.1.0" "zod@^4.2"
# New app
npm create enpilink@latest

Try it

enpilink is open source and account-free: local dev, tunneling and deploy need no account and send no telemetry. Try it on your next MCP App, open an issue when something doesn't fit, and star it on GitHub if it saves you time.

Building an MCP App into your product and want a team that has shipped one? That is our Frontend AI work. See what we build with Frontend AI →

Read next

All posts →