Skip to content

CTX7-3522: Docs feedback score and required comment, with a feedback request in the server instructions - #3617

Merged
enesgules merged 5 commits into
masterfrom
CTX7-3522/docs-feedback-score
Nov 2, 2026
Merged

enesgules merged 5 commits into
masterfrom
CTX7-3522/docs-feedback-score

Conversation

@enesgules

@enesgules enesgules commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • submit-docs-feedback takes score (whole number 0 to 5) in place of helpful. comment is required. author is removed. The tool asks for issue only when the score is below 5.
  • With research preview on, the server instructions end with one line: after you answer with docs from query-docs, call submit-docs-feedback once with a score and a short comment.
  • With research preview on, every API call sends X-Context7-Research-Preview: 1, so the app can count how many people use the preview (app Refresh request for /websites/developers_facebook_marketing-api #1599).
  • Nothing changes when research preview is off.

Deploy order

Deploy the app PR first: https://github.com/upstash/context7app/pull/1599. The route must accept score before this MCP sends it.

Benchmark

10 tasks taken from real query-docs queries, each ending with "use context7". The MCP was the local build with research preview on, behind a local proxy. The proxy sent docs queries to production and kept all feedback local.

Feedback calls per 10 runs:

Agent / model No hint Hint in query-docs result Hint in server instructions
Claude Opus 0 6 10
Claude Sonnet 0 0 (10 answers told the user it was an injection) 10
Claude Haiku 0 0 (9 answers told the user it was an injection) 9
Codex gpt-6-astra 0 0 0 (6 tries blocked by approval)
Codex gpt-6.1-sol 0 0 0 (7 tries blocked by approval)
OpenCode DeepSeek V4.1 Flash 0 7 7
OpenCode Gemini 3.1 Pro / 3.8 Flash 5 / 10 - -
OpenCode GLM 5.3 / Grok 4.7 4 / 10 - -
  • A hint in the tool result is a bad idea. Sonnet and Haiku treat it as a prompt injection and tell the user.
  • With the server instructions, the average score is 4.2 to 4.4. Several agents found the same real docs gaps independently: expo-router setParams pages disagree, the Tailwind v4 install snippet comes from the alpha blog (@next), and Next.js has no reverse-proxy redirect guide.
  • Codex asks for approval before it calls a tool that is not read-only. The benchmark used approval "never". Real Codex users get an approval prompt.

Part of CTX7-3522

@vercel

vercel Bot commented Nov 2, 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 2, 2026 10:30am UTC

Request Review

@linear-code

linear-code Bot commented Nov 2, 2026

Copy link
Copy Markdown

CTX7-3522

@fahreddinozcan fahreddinozcan 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.

Code quality review. I found no correctness bugs, and the behavior matches the description. I ask for one structural change before merge: remove the toolClientContext wrapper. The other comments are smaller.

The app side review is on upstash/context7app#1599.

Comment thread packages/mcp/src/index.ts Outdated
const server = mcpInstrumentation
? mcpInstrumentation.createServer(serverInfo, serverOptions, mcpContext)
: new McpServer(serverInfo, serverOptions);
const toolClientContext = (toolCtx: ServerContext): ClientContext => ({

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.

This wrapper is not necessary. ClientContext is already built in exactly two places: the HTTP context object (const context: ClientContext = {...} in the request handler) and the stdio fallback in getClientContext.

Suggestion: set researchPreview there.

  • HTTP: read it from the same research_preview query parameter (isResearchPreviewValue).
  • stdio: use a module-level flag, like stdioSessionId.

Then this wrapper, the 3 changed call sites, the changed registerResearchPreviewTools signature and the ...(x ? { researchPreview: true } : {}) spread all go away.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in fa3d031. The HTTP context reads research_preview from the query with isResearchPreviewValue, and stdio uses a module-level stdioResearchPreview next to stdioSessionId. The wrapper is gone, the call sites use getClientContext again, and registerResearchPreviewTools has its old signature.

import type { ClientContext, DocsFeedback } from "./types.js";

/** Added to the server instructions with research preview on, so agents remember the feedback tool. */
export const DOCS_FEEDBACK_INSTRUCTIONS = `After you answer a question with documentation from 'query-docs', call '${SUBMIT_DOCS_FEEDBACK_TOOL}' once for that library with a score from 0 to 5 and a short comment on the docs. The user turned on this research preview to collect this feedback.`;

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.

'query-docs' is a literal string here, but QUERY_DOCS_TOOL exists and the next tool name already uses its constant. Use ${QUERY_DOCS_TOOL}.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in fa3d031. It uses ${QUERY_DOCS_TOOL} now.

),
author: z
.enum(["agent", "user"])
.min(1)

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.

This does not match the app contract. The app trims the text, requires at least 1 character after the trim, and rejects more than 1,000 characters. Here " " passes and there is no maximum, so the agent gets a 400 from the app and not a schema error. Suggestion: .trim().min(1).max(1000).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in fa3d031. The comment is .trim().min(1).max(1000) now, the same as the app.

Comment thread packages/mcp/src/lib/types.ts Outdated
libraryId: string;
query?: string;
helpful: boolean;
score: number;

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.

DocsFeedback copies the zod input schema by hand (the issue enum is in both places). Suggestion: move the schema to a constant and use export type DocsFeedback = z.infer<typeof docsFeedbackSchema>.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in fa3d031. The schema is the docsFeedbackSchema constant, and DocsFeedback is z.infer<typeof docsFeedbackSchema>. I removed the copy from types.ts.

@fahreddinozcan fahreddinozcan 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.

All review comments are addressed, and CI passes. Deploy after upstash/context7app#1599, as the description says. Thanks.

@enesgules
enesgules merged commit 18d6f5d into master Nov 2, 2026
4 checks passed
@enesgules
enesgules deleted the CTX7-3522/docs-feedback-score branch November 2, 2026 10:46
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