mcp-legacy-lane

mcp-legacy-lane

Monitors MCP protocol traffic across legacy and modern lanes, records usage evidence in a durable SQLite ledger, and recommends when the legacy fallback can safely be removed.

Category
访问服务器

README

Instrument the old path before you delete it

CI

MCP is an open protocol for LLM apps to call tools over JSON-RPC.

Kent's homework: you have a legacy path still wired in, and you have not counted whether anyone still uses it. Measure before you delete.

This repo runs one dual-era MCP server and a SQLite ledger that survives a restart. You keep the fallback while any legacy operation remains.

The versioning page names the two lanes. Legacy is 2025-11-25 and earlier: the session starts with initialize. Modern is 2026-07-28 and later: each request carries version and identity in _meta.

Count completed work

A reconnecting client changes the request count. Five legacy tool calls cost fifteen requests if the client opens a new connection each time, and seven if it holds one connection. The legacy handshake spends initialize and notifications/initialized once per connection, so a reconnecting client looks like heavy legacy traffic. Each row is the same five tool calls per lane:

Five tool calls per lane Legacy requests Modern requests Legacy share
Client reconnects for each call 15 10 60.0%
Client holds one connection 7 6 53.8%
Completed operations 5 5 50.0%

You count 5 and 5 on the operations row. The request rows differ by six points because the client chose to reconnect. recommend() reads the operations row. Count the unit that still matches after a transport rewrite or a client that changes how it connects.

Run it

Node 24 or newer. You store the ledger with node:sqlite.

Start the collector first, then the server, then generate traffic:

pnpm install

pnpm collector   # http://127.0.0.1:3000, OTLP (the metric export format) and agent tools
pnpm server      # http://127.0.0.1:8787, dual-era MCP server
pnpm traffic     # legacy and modern tool calls, plus DCR and CIMD hits

DCR is Dynamic Client Registration: the client POSTs metadata to /register on each connect. Deprecated in 2026-07-28. CIMD is Client ID Metadata Documents: the client id is an HTTPS URL to static metadata, the replacement for DCR.

Then read the two stores:

pnpm report      # verdict from .data/migration-evidence.db
pnpm proof       # lane series from the collector

Wait six seconds after pnpm traffic before pnpm proof so the scrape lands.

The first run prints this:

Migration readiness: MCP protocol lanes
=======================================
window            : 7 days
active days       : 1/7 required
legacy operations : 5
modern operations : 3
total operations  : 8/100 required
legacy %          : 62.50%
raw requests      : 15 legacy / 6 modern
legacy methods    : initialize x5, notifications/initialized x5, tools/call x5
legacy clients    : legacy-dashboard@0.9.4
modern clients    : modern-agent@2.1.0
auth DCR          : 2 attempts (1 success, 1 failure)
auth CIMD         : 3 attempts (2 success, 1 failure)

recommendation    : keep_both

A legacy client completed an operation. Keep the fallback and check next week.
Ask these clients to upgrade: legacy-dashboard@0.9.4.

pnpm traffic sends five legacy clients and three modern ones, the mix Kent describes a few weeks after a spec release. Each client reconnects for its one call, so the requests row reads 15 against 6. The report names legacy-dashboard@0.9.4, so you know who to email.

The policy

Defaults: a seven-day window, seven active traffic days, 100 completed operations.

Evidence Verdict
No operations no_traffic
One or more legacy operations keep_both
Zero legacy operations, sample below the guards collect_more_data
Zero legacy operations, both guards passed safe_to_plan_removal

recommend() returns keep_both after one legacy operation, even against two hundred modern ones. That call still belongs to a client. Modern volume does not tell you whether anyone still needs the old path.

Deprecation window

The deprecated features registry lists DCR, roots, sampling, and logging as deprecated in 2026-07-28. Earliest removal is the first revision on or after 2027-07-28. A clean local report does not move that date. Clients that follow the spec still have the promised window.

Ask your agent

Leave the collector and server running. .mcp.json points autotel at http://127.0.0.1:3000/mcp and migration at http://127.0.0.1:8787/mcp. migrationStatus reads the durable window.

List mcp.protocol.lane.operations in autotel and compare the lane=legacy and lane=modern series. Call migrationStatus on the migration server. Can we remove the 2025-11-25 fallback? Cite the operation counts, active days and policy guardrails.

Run that prompt on a weekly cron and you get Kent's answer.

Signals

Signal Storage Purpose
mcp.protocol.lane.requests OTLP Request volume, one series per lane and mcp_method
mcp.protocol.lane.operations OTLP Comparable operations, one series per lane
mcp.auth.registration.attempts OTLP DCR and CIMD attempts, one series per mode and outcome
mcp.protocol.legacy.days_since_last_operation OTLP Days of silence on the old lane, -1 when it never ran
.data/migration-evidence.db SQLite The report window, client names, across restarts

list_metrics returns one series per attribute set, so the agent groups by lane. You need autotel-mcp 0.5.1 or newer for those attributes to survive ingest.

Kent averages 125 DCR registrations per user because each reconnect writes another record. A CIMD client writes none. Count both modes and you can see when DCR has gone quiet.

Decisions to copy

Count volume, then measure silence. Read the counters for how much legacy traffic arrived. You need the last arrival to decide on removal. mcp.protocol.legacy.days_since_last_operation reads the ledger when the collector scrapes, so you do not recompute it on the request path. Alert when the gauge crosses 30.

Put method names on the metric. Put client names in the ledger. mcp_method is a label, so each new value creates another series, and an unauthenticated caller chooses the value. STANDARD_METHODS in factory.ts is an allow-list: anything unrecognised records as unknown. Client names have no bound, so they go to SQLite. One more name costs a row.

Keep both guards. A minimum sample stops you approving removal on a quiet afternoon. A minimum of active days stops you approving it on one busy Tuesday that missed the weekly batch job.

Serve both eras without a session. createMcpHandler runs with legacy: 'stateless'. One factory serves both eras and ctx.era names the lane. Any instance can answer any request, so you write the counter. You do not need a session table or sticky routing. A stateful fallback would have you instrument sessions. The report would then depend on the load balancer.

Client names per era

A modern request names its caller. A legacy request names the caller once, during initialize.

Legacy (2025-11-25 and earlier) Modern (2026-07-28)
Method name JSON-RPC body MCP-Method header
clientInfo initialize only _meta on every request

The modern envelope repeats clientInfo in params._meta on every request, so any instance can serve it. The legacy lane puts the name on the handshake. A stateless server has nowhere to keep it for the tool call that follows. factory.ts reads both. The report can name legacy-dashboard@0.9.4 because that name arrived on initialize, not on the tool call that gets counted.

You can route a gateway on MCP-Method because the request describes itself. You attribute traffic without a session for that reason too.

activeDays buckets by UTC date, so a client whose users work US evenings can land in two buckets. The auth routes write DCR and CIMD attempts. They mint no tokens and fetch no CIMD documents.

Configuration

Variable Effect
MIGRATION_EVIDENCE_PATH Ledger location
MIGRATION_WINDOW_DAYS Report window
MIGRATION_RETENTION_DAYS Ledger retention
MIGRATION_MIN_OPERATIONS Sample-size guard
MIGRATION_MIN_ACTIVE_DAYS Active-days guard

GET /metrics/lanes?windowDays=30 takes the same window, up to 90 days.

To see the ledger survive a restart: run traffic, stop the server, start it again, run pnpm report. The counts remain.

pnpm collector keeps telemetry in autotel.db for 30 days. The server keeps evidence in .data/migration-evidence.db for 90. Git ignores both.

Dual-era server

The server is dual-era because createMcpHandler runs with legacy: 'stateless', and ctx.era names the lane you count. See the changelog for the rest of the 2026-07-28 change set.

autotel-mcp-instrumentation adds spans and duration histograms on both sides. You answer the removal question from the counters and the ledger.

Code map

File Responsibility
src/server/factory.ts Dual-era tools; reads era, method and client per request
src/server/serve.ts Parses the body once, shares it with the factory
src/telemetry/legacy-metrics.ts OTel counters and windowed snapshots
src/telemetry/evidence-store.ts Indexed SQLite ledger, plus a memory store for tests
src/report/recommend.ts The guards and the report copy
src/server/oauth-routes.ts DCR and CIMD attempt evidence
src/proof/autotel-proof.ts Reads the lane series back out of OTLP
src/client/generate-traffic.ts Two named clients, one per lane

Verify

pnpm typecheck
pnpm test

Thirteen tests cover the ratio bias, window filtering, restart persistence, auth outcomes, client attribution, legacy method counts and both removal guards.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选