From 2ebda9db61bef1ea752aa7c8091f430fa0e49f13 Mon Sep 17 00:00:00 2001 From: jimcody1995 Date: Thu, 2 Jul 2026 16:42:07 +0000 Subject: [PATCH 1/2] feat(mcp): classify supported-but-outdated MCP clients as stale Co-authored-by: Cursor --- src/services/mcp-compatibility.ts | 3 +++ test/unit/mcp-compatibility.test.ts | 14 ++++++++++++-- test/unit/mcp-server-telemetry.test.ts | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/services/mcp-compatibility.ts b/src/services/mcp-compatibility.ts index 12e38a9bfb..270f2e1e30 100644 --- a/src/services/mcp-compatibility.ts +++ b/src/services/mcp-compatibility.ts @@ -59,6 +59,9 @@ export function classifyMcpClientVersion(version: string | null | undefined): Mc const minimumComparison = compareMcpSemver(version, MINIMUM_SUPPORTED_MCP_VERSION); if (minimumComparison === null) return "unknown"; if (minimumComparison < 0) return "incompatible"; + const recommendedComparison = compareMcpSemver(version, LATEST_RECOMMENDED_MCP_VERSION); + if (recommendedComparison === null) return "unknown"; + if (recommendedComparison < 0) return "stale"; return "current"; } diff --git a/test/unit/mcp-compatibility.test.ts b/test/unit/mcp-compatibility.test.ts index 346d0239da..8565db7f44 100644 --- a/test/unit/mcp-compatibility.test.ts +++ b/test/unit/mcp-compatibility.test.ts @@ -8,9 +8,19 @@ describe("MCP compatibility telemetry", () => { expect(classifyMcpClientVersion("0.2.1")).toBe("incompatible"); expect(classifyMcpClientVersion("0.3.0")).toBe("incompatible"); expect(classifyMcpClientVersion("0.4.0")).toBe("incompatible"); - expect(classifyMcpClientVersion("0.5.0")).toBe("current"); + expect(classifyMcpClientVersion("0.5.0")).toBe("stale"); + expect(classifyMcpClientVersion("0.5.9")).toBe("stale"); + expect(classifyMcpClientVersion("0.6.0")).toBe("current"); + expect(classifyMcpClientVersion("0.7.0")).toBe("current"); expect(classifyMcpClientVersion("not-a-version")).toBe("unknown"); expect(classifyMcpClientVersion(undefined)).toBe("unknown"); + expect(classifyMcpClientVersion(null)).toBe("unknown"); + }); + + it("treats prerelease builds below the minimum or recommended cutoffs as incompatible or stale", () => { + expect(classifyMcpClientVersion("0.4.9-rc.1")).toBe("incompatible"); + expect(classifyMcpClientVersion("0.5.0-rc.1")).toBe("incompatible"); + expect(classifyMcpClientVersion("0.6.0-rc.1")).toBe("stale"); }); it("builds bounded telemetry from allowlisted MCP headers", () => { @@ -50,7 +60,7 @@ describe("MCP compatibility telemetry", () => { clientVersion: "0.5.0", metadata: { packageName: "@example/custom-mcp", - compatibilityStatus: "current", + compatibilityStatus: "stale", }, }); }); diff --git a/test/unit/mcp-server-telemetry.test.ts b/test/unit/mcp-server-telemetry.test.ts index f8e6dc5960..be49e01d74 100644 --- a/test/unit/mcp-server-telemetry.test.ts +++ b/test/unit/mcp-server-telemetry.test.ts @@ -57,7 +57,7 @@ describe("MCP server telemetry", () => { clientVersion: "0.5.0", metadata: expect.objectContaining({ toolName: "gittensory_local_status", - compatibilityStatus: "current", + compatibilityStatus: "stale", }), }), ]); From 5ebf57485973dbefc6e844d8300db35493f5636c Mon Sep 17 00:00:00 2001 From: jimcody1995 Date: Thu, 2 Jul 2026 16:57:08 +0000 Subject: [PATCH 2/2] test(mcp): cover recommended-version boundary branches for patch coverage Co-authored-by: Cursor --- src/services/mcp-compatibility.ts | 4 ++-- test/unit/mcp-compatibility.test.ts | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/services/mcp-compatibility.ts b/src/services/mcp-compatibility.ts index 270f2e1e30..91f77d1b3e 100644 --- a/src/services/mcp-compatibility.ts +++ b/src/services/mcp-compatibility.ts @@ -59,8 +59,8 @@ export function classifyMcpClientVersion(version: string | null | undefined): Mc const minimumComparison = compareMcpSemver(version, MINIMUM_SUPPORTED_MCP_VERSION); if (minimumComparison === null) return "unknown"; if (minimumComparison < 0) return "incompatible"; - const recommendedComparison = compareMcpSemver(version, LATEST_RECOMMENDED_MCP_VERSION); - if (recommendedComparison === null) return "unknown"; + // The client semver already parsed for the minimum check, so this comparison cannot return null. + const recommendedComparison = compareMcpSemver(version, LATEST_RECOMMENDED_MCP_VERSION)!; if (recommendedComparison < 0) return "stale"; return "current"; } diff --git a/test/unit/mcp-compatibility.test.ts b/test/unit/mcp-compatibility.test.ts index 8565db7f44..8a90a9e7f7 100644 --- a/test/unit/mcp-compatibility.test.ts +++ b/test/unit/mcp-compatibility.test.ts @@ -23,6 +23,14 @@ describe("MCP compatibility telemetry", () => { expect(classifyMcpClientVersion("0.6.0-rc.1")).toBe("stale"); }); + it("classifies the exact recommended version and newer releases as current", () => { + expect(classifyMcpClientVersion("0.6.0")).toBe("current"); + expect(classifyMcpClientVersion("0.6.1")).toBe("current"); + expect(classifyMcpClientVersion("1.0.0")).toBe("current"); + expect(compareMcpSemver("0.6.0", "0.6.0")).toBe(0); + expect(compareMcpSemver("0.7.0", "0.6.0")).toBe(1); + }); + it("builds bounded telemetry from allowlisted MCP headers", () => { const telemetry = buildMcpClientTelemetry( new Headers({