Skip to content

Schema cache serves stale tool schema after upstream contract bump (no invalidation on version change) #58

Description

@rodaddy

Problem

mcp2cli's per-credential/per-service schema cache is not invalidated when an upstream MCP server changes its contract. It only expires on a 24h TTL, so for up to a day after an upstream deploy, mcp2cli schema and generate-skills emit the old tool shape — silently. Agents/Claude then form calls against an outdated schema even though live tool calls (transport) already work against the new contract.

This surfaced during the Open Brain memory-tools.v11 rollout (open-brain #228, adds append_session_event.create_if_missing + exact-scope fields). It is the staleness counterpart to #55: #55 is about nested-field discoverability in the schema view; this is about the schema view being stale entirely after a version bump. They should be worked together.

Evidence / repro (verified live 2026-06-28)

# Hosted OB already serving v11:
mcp2cli open-brain get_contract --params '{}' | grep contract_version
#  -> "contract_version":"2026-06-28.memory-tools.v11"   (correct, live)

# But the cached schema view is stale:
mcp2cli schema open-brain.append_session_event | grep create_if_missing
#  -> (nothing — old 9-field schema served from cache)

# Manually clearing the stale per-client cache fixes it:
rm ~/.cache/mcp2cli/schemas/open-brain.json
mcp2cli schema open-brain.append_session_event | grep create_if_missing
#  -> "create_if_missing"  (now present; refetched from v11 daemon)

Root cause

The schema cache is stored in two layers and keyed per credential AND per bare service, none of which invalidate on contract change:

  • Client: ~/.cache/mcp2cli/schemas/open-brain.json
  • Daemon (CT216): /var/lib/mcp2cli/schemas/open-brain.json plus per-credential keys, e.g. credential:WyJvcGVuLWJyYWluIiwidXNlcjpyaWNvIl0.json (base64 of ["open-brain","user:rico"]), credential:...c2tpcHB5...json.

A version bump must invalidate all of these or it looks refreshed in one place and stale in another (observed: client cache stale while daemon-side appeared empty to cache status).

Second bug found while diagnosing: cache warm broken on the daemon

On CT216 (daemon mcp2cli v0.3.10), warming through the running daemon fails:

mcp2cli cache warm open-brain
#  -> open-brain: failed (Failed to communicate with daemon: Daemon failed to start within 10000ms)

This is a self-call conflict (warming a service whose calls route through the same running daemon). The refresh command documented in open-brain/docs/downstream-rollout.md (mcp2cli cache diff/warm open-brain) is therefore currently non-functional on the hub. Note: cache warm/cache diff exist on daemon v0.3.10 but NOT on older client builds (e.g. v0.3.7), which is an additional version-skew gotcha.

Why the existing design assumption fails

rtech-mcps #11 and mcp2cli #55 both state "no static cache to update / live discovery." That holds for transport (tool calls reach the live daemon) but is false for the schema cache view, which is what schema/generate-skills/help render. The cache is the source of the stale view.

Proposed fix (maintainer's call)

  1. Invalidate-on-version-change. Open Brain publishes an authoritative contract_version and a deterministic schema_hash (excludes generated_at) via get_contract. mcp2cli should record the version/hash alongside the cached schema and refetch when the live value differs — across both cache layers and all credential keys. (Generalizable: any server that publishes a version/hash; fall back to TTL otherwise.)
  2. Fix cache warm on the daemon so the hub can refresh without a manual rm of cache files (avoid the self-call deadlock).
  3. Ensure generate-skills regenerates from the current contract after invalidation.

Acceptance

  • After an upstream contract bump, mcp2cli schema <svc>.<tool> reflects the new schema without a manual cache delete (invalidation triggered by contract_version/schema_hash change for servers that publish it).
  • Invalidation covers ~/.cache/mcp2cli/schemas/ AND daemon /var/lib/mcp2cli/schemas/, including all credential:* keys.
  • mcp2cli cache warm open-brain succeeds on the CT216 daemon.
  • generate-skills open-brain emits the v11 schema (incl. create_if_missing and the nested metadata fields from Schema view doesn't expose nested object sub-fields (e.g. Open Brain metadata.share_candidate) #55).
  • No regression for servers that don't publish a version/hash (TTL behavior preserved).

Related

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions