feat: add compact MCP surface and session-init measurement - #115
Conversation
Advertise a backward-compatible FAVA_TRAILS_MCP_SURFACE=compact mode that shortens initialize instructions and tool descriptions and omits list-time outputSchema, while keeping all tools, input schemas, and authorization. Measure tokenizer-labeled session-init size via fava-trails measure-mcp-context. Closes #104.
timeleft--
left a comment
There was a problem hiding this comment.
Independent review of exact head 6527b6c4cd6ee7e50d481a084d5244e3a78c6387 found four material gaps:
- The measurement covers only the candidate checkout and labels the server serialization/MCP SDK as the client. It records neither the tested FAVA release/version/commit nor an actual client and version, so the required release-versus-candidate provenance is missing.
- The advertised same-task comparison is hardcoded metadata rather than an executed recall/save/promote comparison. Discoverability, skipped steps, permissions, and error recovery are constants, and the compact warning is emitted for the full surface too. Run and record the same task against both configurations, including recovery behavior, rather than asserting outcomes.
- The checked-in
get_usage_guidemeasurement is stale: the document says 10,077 characters / 2,520 heuristic tokens while this exact head reports 10,174 / 2,544. Make the recorded artifact reproducible from the current head. - Compact scope discovery omits the configured
FAVA_TRAILS_SCOPE_HINTfallback required by root agent guidance. Preserve that third fallback before asking the user.
The branch also currently conflicts with main; resolve those conflicts in the existing branch. Focused context/protocol tests, Ruff, git diff --check, and all current GitHub checks passed on the reviewed head.
Address PR #115 review: record tested-release vs candidate MCP session-init provenance, execute recall/save/promote on both surfaces, keep FAVA_TRAILS_SCOPE_HINT in compact scope discovery, and refresh the measured get_usage_guide artifact.
timeleft--
left a comment
There was a problem hiding this comment.
Independent re-review of exact head a411da8cfbb57dc32392ac014b8dd621c43e6bba found three material gaps:
- The documented same-task
mcp.Clientcomparison is still a direct handler exercise. It neither starts full and compact MCP sessions nor instantiates a client, forces every recall/save/promote step, cannot observe skipped client steps, and records failures without exercising recovery. Run the comparison through actual MCP sessions/client calls and distinguish observed skips from scripted steps. - Tested-release measurement is a hardcoded historical fixture. The command cannot reproduce commit
6c5278a, omits that release's enabled tool names and recurrence data, and labels it with the candidate environment's current SDK version. Keep a reproducible frozen artifact or measurement procedure with complete historical provenance, and prevent future environments from relabeling it. AGENTS_USAGE_INSTRUCTIONS.mdsays its core guidance is canonical and injected, butmcp_context.pymaintains a separate full-instructions literal that already differs: canonical recall examples include project filters while runtime full instructions omit them. Derive runtime guidance from the canonical source or state the relationship accurately and add drift prevention.
Confirmed fixed: scope-hint fallback, current guide measurement, enforced-versus-prompt boundaries, context budget/regression disclosure, and main-branch conflicts. Verification on this exact head passed 59 focused tests, the isolated workflow test, Ruff, git diff --check, and all GitHub checks.
timeleft--
left a comment
There was a problem hiding this comment.
Independent re-review of exact head 4082d298286f737a0efe4c47e12ac65e5cc831a0 found two remaining evidence gaps:
- The reported "observed skips" are still scripted inference from exact words in initialize instructions, not behavior observed from a client. This misclassifies compact
propose_truthas skipped even though compact instructions explicitly request it, merely because the word "mandatory" is absent. Label these as deterministic prompt-coverage indicators rather than observed client choices, and keep actual executed client steps separate. - Missing-scope recovery marks any successful
list_scopescall as recovered without inspecting returned paths, selecting a valid scope, or retrying the failed recall. An empty result passes. Complete the recovery by selecting an exact returned scope and retrying the failed operation, or describe the evidence honestly as discovery attempted rather than recovery achieved.
Confirmed fixed: real separate in-process mcp.Client handshakes/tool calls, frozen tested-release provenance and exact metrics, all historical tool names and recurrence/lazy-loading data, relabel protection, current measurements, scope-hint preservation, maintained-subset wording/drift tests, context budget, and unchanged authorization. Verification passed 57 focused tests, Ruff, git diff --check, and all nine GitHub checks.
Label initialize-text gaps as deterministic prompt-coverage scans instead of observed client skips, and complete missing-scope recovery by selecting an exact list_scopes path and retrying recall.
timeleft--
left a comment
There was a problem hiding this comment.
Independent re-review of exact head 768fdd8df0c9b97bcbec2fdbbee1644667885e81 found one remaining evidence-labeling defect:
naive_initialize_only.called/skipped still reports deterministic instruction substring checks as client behavior. It even places propose_truth_requested under called without calling that tool, contradicting the adjacent not_observed_client_choices label. Remove this object or rename its fields and enclosing concept strictly as instruction/prompt-coverage indicators, with no called, skipped, or client-behavior terminology.
All prior substantive findings are otherwise fixed: frozen release metrics reproduce, candidate metrics match docs, both surfaces use separate mcp.Client sessions, missing-scope recovery selects a returned path and retries recall successfully, and scope hint, drift checks, budget, permissions, and enforcement boundaries hold. Verification passed 23 focused tests, Ruff, git diff --check, and all nine GitHub checks; the branch is mergeable.
Remove naive_initialize_only.called/skipped, which treated deterministic initialize-text checks as client behavior and listed propose_truth_requested without calling the tool. Prompt coverage stays an instruction scan; actual session-start recall is recorded in scripted_steps when initialize text includes it.
timeleft--
left a comment
There was a problem hiding this comment.
The final exact-head review found one material acceptance defect in the scripted error-recovery comparison. The failed recall uses only trail_name, but the retry changes both trail_name and the operation semantics by adding query="status". Because the saved synthetic thought does not contain that term, an empty successful response is counted as recovery. Preserve the original recall arguments, change only the selected trail_name, and assert that the retry returns the saved thought or the expected result count. All earlier findings are otherwise resolved; 1,049 tests, the focused suite, Ruff, diff checks, the recorded baseline, and all nine GitHub checks passed at fb4ea5b.
Preserve original recall arguments except trail_name, and require a non-empty retry result so empty ok responses are not counted as recovery.
timeleft--
left a comment
There was a problem hiding this comment.
Independent review is clean at exact head 7e92e23. The final recovery repair preserves the original recall arguments except the selected trail name and requires the expected non-empty retry result. Issue #104 acceptance remains intact. Verification: 23 focused tests, Ruff, git diff --check, recorded full/compact measurements, and all nine GitHub checks passed.
Summary
FAVA_TRAILS_MCP_SURFACE=compactso initialize instructions and tool descriptions can shrink without dropping tools or changing read/authoring authorization. Default remainsfull.fava-trails measure-mcp-contextto record tokenizer-labeled session-init size (instructions + advertisedtools/list), lazy-loading (false), and whether the cost recurs.outputSchema; server-side validation still usesTOOL_DEFINITIONS. Full protocol stays on-demand viaget_usage_guide.Motivation
Closes #104.
Evaluator estimates of ~6000 tokens of schemas/instructions were client-specific. This PR measures this server's advertised payload and offers a backward-compatible compact surface instead of claiming a universal token figure.
Changes
src/fava_trails/mcp_context.py: surface selection, compact instructions/descriptions, measurement, 70% session-init budget vs full baseline.tools/listkeeps all 17 tools and the same input schemas.docs/mcp-context-overhead.mdrecords the measured baseline, budget, recall/save/promote comparison, and server-enforced vs prompt/client behavior.Test Plan
uv run pytest -q(864 passed, jj on PATH)uv run pytest tests/test_mcp_context.py -qfava-trails measure-mcp-context --surface both(chars/4 heuristic; compact session-init ≈ 0.52 of full, budget 0.70)Notes for Reviewers
propose_truthplus durable approval.get_usage_guidemay skip session-start recall or promotion. That is documented as a regression of prompt coverage, not a permission change.6c5278a(issue baseline).origin/mainhas moved; this PR does not rebase (no force-push).