Skip to content

mcp: make the version tri-lock's third leg real — read serverInfo from the live servers #9661

Description

@JSONbored

⚠️ Definition of Done: this issue must be completed in full, in a single PR. Do not split this
work across multiple PRs, and do not defer any Deliverable below to a follow-up issue. A PR that
satisfies only some of the Deliverables, stubs a required test, or leaves a checkbox
partially-done does NOT resolve this issue and will be closed.

Context

#9520 shipped a "version tri-lock across all three servers". checkVersionLock
(scripts/lib/validate-mcp/invariants.ts:60-82) documents which leg matters:

LATEST_RECOMMENDED_MCP_VERSION derives from the package.json today, so two of the three are equal
by construction -- but serverInfo.version is read independently at server construction and is
the one a client actually sees, so it is the one that can drift
.

The test never reads it from a server. It reads packages/loopover-mcp/package.json's version into
a local packageVersion, then calls checkVersionLock({ packageVersion, advertisedLatestVersion: LATEST_RECOMMENDED_MCP_VERSION, serverInfoVersion: packageVersion })serverInfoVersion is
literally the same expression as packageVersion, so the one leg the helper says is the drift-prone
one is asserted against itself. This is the exact failure mode the same file warns about six lines
later in checkWatchedPathsExist's doc: "A version lock that only compares constants to each other
stays green while the thing that is supposed to update them has stopped running."

The other two servers are unlocked entirely. The miner reads ownPackageJson.version at
packages/loopover-miner/bin/loopover-miner-mcp.ts:217 and nothing asserts it. (The remote server's
hardcoded version: "0.1.0" at src/mcp/server.ts:1204 is explicitly #9526's to fix — do not change
it here.)

The same test file also carries committed debug residue from the PR that landed it: a
for (const f of result.failures) process.stdout.write(...) loop at
test/contract/validate-mcp.test.ts:197-198 that prints RFAIL lines for the remote surface only,
and a comment block at :186-193 where an earlier and a rewritten version of the same paragraph both
survive.

Requirements

  1. The stdio leg is read from the live server: connect the client (as validateSurface already does)
    and take the version from client.getServerVersion(), then feed that into checkVersionLock as
    serverInfoVersion. It must be obtained from the connected client, never re-read from
    package.json.
  2. A second lock covers the miner server: its serverInfo.version read from a connected client must
    equal packages/loopover-miner/package.json's version.
  3. checkVersionLock gains a failure for a missing serverInfoVersion (an undefined or empty
    value from a server that advertised none), so an absent version cannot pass as an accidental
    match.
  4. test/contract/validate-mcp.test.ts:197-198's RFAIL debug loop is deleted, and the duplicated
    comment paragraph at :186-193 is reduced to the one accurate version.
  5. The remote server's serverInfo.version stays out of the lock, with a code comment naming mcp(discovery): server.json + .well-known surfaces, MCP registry publish, and the stdio gateway front door #9526
    as the issue that makes it derivable.

⚠️ Required pattern: checkVersionLock in scripts/lib/validate-mcp/invariants.ts:60-82 stays the
single pure comparator; the test's job is to supply it a value actually observed on the wire.
Comparing serverInfo.version to a second readFileSync of the same package.json, or asserting
the version inside a server module's unit test instead of over a connected client, do NOT satisfy
this issue.

Deliverables

  • test/contract/validate-mcp.test.ts's version-lock case obtains the stdio server's
    serverInfo.version from a connected Client and passes it as serverInfoVersion
  • A miner version-lock case comparing the miner server's advertised serverInfo.version to
    packages/loopover-miner/package.json's version
  • checkVersionLock returns a failure for an absent or empty serverInfoVersion, unit-tested in
    test/unit/validate-mcp-helpers.test.ts for: all three agreeing, a drifted serverInfo, a
    drifted compatibility constant, and an absent serverInfo
  • The RFAIL debug loop at test/contract/validate-mcp.test.ts:197-198 is deleted and the
    duplicated comment at :186-193 is collapsed to one paragraph
  • npm run validate:mcp green

All Deliverables above are required in a single PR. A PR that satisfies only some of them — for
example adding the miner lock while leaving the stdio leg comparing packageVersion to itself — does
not resolve this issue.

Test Coverage Requirements

99%+ Codecov patch coverage, branch-counted, applies to any src/** or packages/** file you touch
(vitest.config.ts:55-100). scripts/lib/validate-mcp/invariants.ts and test/** are outside
coverage.include, so the new checkVersionLock branch is not Codecov-gated — cover both arms in
test/unit/validate-mcp-helpers.test.ts anyway, and add a named regression test proving a
deliberately mismatched serverInfoVersion produces a failure string.

Expected Outcome

The version lock fails when the stdio or miner server advertises a version that disagrees with its
own package.json — instead of passing because it compares a value to itself.

Links & Resources

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:bugGittensor-scored bug fix — scores a 0.05x multiplier.help wantedExtra attention is needed

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions