Skip to content

CTX7-3712: A/B test the server instructions on the hosted MCP server - #3733

Open
fahreddinozcan wants to merge 5 commits into
CTX7-3596/direct-mcp-server-instructionsfrom
CTX7-3712/instructions-ab-test
Open

fahreddinozcan wants to merge 5 commits into
CTX7-3596/direct-mcp-server-instructionsfrom
CTX7-3712/instructions-ab-test

Conversation

@fahreddinozcan

@fahreddinozcan fahreddinozcan commented Nov 10, 2026 •

Copy link
Copy Markdown
Collaborator

Adds an off-by-default A/B test of the server instructions to the hosted MCP server, so #3665's text can be measured in production.

  • CONTEXT7_INSTRUCTIONS_CONTROL_PERCENT (0-100) sends that share of callers the previous instructions without alwaysLoad; the rest get CTX7-3596: Make the MCP server instructions direct so agents call Context7 more often #3665's text with alwaysLoad. 0 (default) is off; stdio is never part of it.
  • lib/instructions-experiment.ts owns the test behind one object (assign, sessionConfig, observeRequest); index.ts calls it once in the HTTP middleware and once in createMcpServer.
  • Each caller keeps one arm: bucket = first 4 bytes of sha256("<salt>:<identity>") mod 100. Identity is key:<sha256 hex of the ctx7sk key> (the hash context7app stores), user:<JWT sub>, token:<hash>, or ip:<client IP>.
  • While the test runs, tools/list and server/discover use the private cache hint. API calls send X-Context7-Instructions-Variant, -Unit (salted caller hash, the randomization unit) and -Control-Percent, for the admin page in context7app (CTX7-3724).
  • Metrics: context7.mcp.instructions_experiment.instruction_requests by arm and client; tool calls carry context7.mcp.instructions.variant on mcp.server.operation.duration (all tools, research preview included).
  • Checked live with Claude Code against the real API: control got the old text, deferred tools, and no lookup; treatment got the new text, loaded tools, and resolve + query calls; the metrics matched.

Stacked on #3665. Closes CTX7-3712

@vercel

vercel Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
context7-admin-mcp Ignored Ignored Nov 10, 2026 11:09am UTC

Request Review

@linear-code

linear-code Bot commented Nov 10, 2026

Copy link
Copy Markdown

CTX7-3712

@enesgules enesgules left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. The test is off by default and stdio gets an empty env. The arm comes from a salted hash of a stable identity, so a stateless server gives the same arm on each request. req.ip is correct here because trust proxy is set. The list cache hints are private while the test runs, so one arm cannot get the cached tool list of the other. Client labels on the new counter are capped at 50.

Notes, none is a blocker:

  • Set CONTEXT7_INSTRUCTIONS_EXPERIMENT_SALT in production. The default salt is in this public repository, so for anonymous callers the X-Context7-Instructions-Unit value is a hash of the IP that can be computed again by anyone who has the salt. The header goes only to our API, which already gets the IP, so the risk is small.
  • The control arm changes two things together (old text and no alwaysLoad). The result shows the effect of #3665 as a whole, not of each part. That agrees with the goal in the description.
  • A caller that moves from anonymous to an API key can change arm. The admin page (upstash/context7app#1682) must count by unit, not by user.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants