{{ message }}
Repository navigation
feat: add MCP server for AI agent access to pull requests and issues - #9071
Open
Liora Milbaum (lmilbaum) wants to merge 1 commit into
Open
Liora Milbaum (lmilbaum) wants to merge 1 commit into
Liora Milbaum (lmilbaum) wants to merge 1 commit into
Conversation
- Register a localhost Streamable-HTTP MCP server bridging 9 existing LanguageModelTool instances to external MCP-capable agents - Server binds to 127.0.0.1 with a per-session bearer token; exposed as $GITHUB_PR_MCP_URL and $GITHUB_PR_MCP_TOKEN in integrated terminals - Write tools show a Allow/Allow-for-session/Deny confirmation modal - New command pr.copyMcpServerConfig copies a ready-to-paste config snippet - Gated behind githubPullRequests.experimental.mcpServer (default off) - Browser stub keeps web bundle clean Closes microsoft#9070 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Liora Milbaum (lmilbaum)
force-pushed
the
feat/mcp-server
branch
from
October 16, 2026 07:26
78beb37 to
4d2866a
Compare
Liora Milbaum (lmilbaum)
marked this pull request as ready for review
October 16, 2026 07:30
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved write safeguards, lifecycle races, validation gaps, and browser test failures block approval.
8 open findings
Exclude Node-only HTTP suite from browser test runner · New Preserve socket to return HTTP 413 for oversized requests · New Scope client metadata to individual MCP sessions · New Serialize startup and recheck state after awaiting · New Keep copied MCP configuration as valid JSON · New Validate tool arguments against the complete input schema · New Honor cancellation after confirmation and before invocation · New Show full write details in confirmation prompts · New
What changed in this PR
Adds an opt-in localhost MCP server for #9070, exposing existing pull request and issue tools to external agents and VS Code’s MCP client.
Changes:
- Bridges nine language-model tools with authenticated HTTP access and write confirmations.
- Adds server lifecycle management, discovery, terminal credentials, and configuration copying.
- Adds browser fallback support and MCP tests.
| File | Description |
|---|---|
| webpack.config.js | Aliases the browser server stub. |
| src/test/lm/mcpServer.test.ts | Tests catalog, protocol, bridge, and HTTP behavior. |
| src/lm/tools/tools.ts | Extracts reusable tool creation. |
| src/lm/mcp/mcpToolCatalog.ts | Maps existing tools to MCP definitions. |
| src/lm/mcp/mcpToolBridge.ts | Adapts invocation and write confirmations. |
| src/lm/mcp/mcpServerManager.ts | Manages lifecycle, discovery, and configuration copying. |
| src/lm/mcp/mcpProtocol.ts | Handles MCP protocol requests. |
| src/extension.ts | Initializes the server manager. |
| src/env/node/mcpHttpServer.ts | Provides authenticated localhost HTTP transport. |
| src/env/browser/mcpHttpServer.ts | Provides a no-op browser implementation. |
| src/common/settingKeys.ts | Adds the experimental setting key. |
| package.nls.json | Adds setting and command text. |
| package.json | Declares the setting, command, and provider. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| }); | ||
| }); | ||
|
|
||
| describe('MCP HTTP server', () => { |
| let size = 0; | ||
| req.on('data', (chunk: Buffer) => { | ||
| size += chunk.length; | ||
| if (size > MAX_BODY_BYTES) { resolve(null); req.destroy(); } |
| const protocolVersion = typeof requested === 'string' && SUPPORTED_PROTOCOL_VERSIONS.includes(requested) | ||
| ? requested | ||
| : SUPPORTED_PROTOCOL_VERSIONS[0]; | ||
| this.clientName = clientNameOf(p['clientInfo']); |
| const version: string = this.context.extension.packageJSON.version ?? '0.0.0'; | ||
| const handler = new McpProtocolHandler(bridge, version); | ||
|
|
||
| this.serverHandle = await startMcpHttpServer(handler); |
Comment on lines
+129
to
+130
| await vscode.env.clipboard.writeText(`${config}\n\n# Claude Code:\n# ${claudeCmd}`); | ||
| vscode.window.showInformationMessage('MCP server configuration copied to clipboard.'); |
Comment on lines
+51
to
+55
| const required = def.inputSchema.required ?? []; | ||
| const missing = required.filter(key => input[key] === undefined); | ||
| if (missing.length > 0) { | ||
| return toolError(`Missing required arguments: ${missing.join(', ')}`); | ||
| } |
|
|
||
| try { | ||
| // toolInvocationToken is intentionally undefined: no VS Code language model session exists in the MCP path | ||
| const result = await tool.invoke({ input, toolInvocationToken: undefined }, token); |
| private async confirmationMessage(tool: vscode.LanguageModelTool<unknown>, input: Record<string, unknown>, fallback: string, token: vscode.CancellationToken): Promise<string> { | ||
| try { | ||
| const prepared = await tool.prepareInvocation?.({ input }, token); | ||
| return prepared?.confirmationMessages?.title ?? fallback; |
Member
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Implements #9070.
vscode.LanguageModelToolinstances to any MCP-capable agent running in the integrated terminal (Claude Code, Copilot, etc.)127.0.0.1with a per-session 256-bit bearer token, exposed as$GITHUB_PR_MCP_URLand$GITHUB_PR_MCP_TOKENin integrated terminals — agents spawned there connect automaticallyvscode.lm.registerMcpServerDefinitionProviderso VS Code's own MCP client (Copilot Agent) discovers the server automatically — no manual config needed inside the editorcreate_pull_request,resolve_review_thread) show an explicit Allow / Allow for session / Deny modal before executingpr.copyMcpServerConfig) copies a ready-to-paste JSON snippet plus aclaude mcp addone-liner for external agentsgithubPullRequests.experimental.mcpServer(defaultfalse, application scope); a no-op browser stub keeps the web build cleanApproach: bridge over existing LM tools
src/lm/tools/already has 9vscode.LanguageModelToolclasses. This PR adds a thin MCP adapter layer on top — descriptions and schemas come fromcontributes.languageModelToolsinpackage.json(one source of truth). No new GitHub API calls.Tools exposed (MVP)
get_active_pull_requestget_viewed_pull_requestget_issue_or_pull_requestget_pull_request_status_checkssearch_issues_and_pull_requestslist_labelsget_notificationcreate_pull_requestresolve_review_threadSecurity
127.0.0.1only; never externally reachablecrypto.timingSafeEqual.vscode/settings.jsonfrom enabling the serverHow to test
External agent (Claude Code CLI)
"githubPullRequests.experimental.mcpServer": trueand a trusted workspace.echo $GITHUB_PR_MCP_URLprintshttp://127.0.0.1:<port>/mcp.curl -s -X POST "$GITHUB_PR_MCP_URL" -H "Content-Type: application/json" -H "Authorization: Bearer $GITHUB_PR_MCP_TOKEN" -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'returns 9 tools.claude mcp add --transport http github-pr "$GITHUB_PR_MCP_URL" --header "Authorization: Bearer $GITHUB_PR_MCP_TOKEN", then/mcpshows 9 tools.get_active_pull_requestand surfaces review threads and CI status.Copilot Agent (VS Code-internal)
mcpServerDefinitionProviders— no manual config required.Lifecycle
Open questions
@modelcontextprotocol/servervs hand-rolled? Currently hand-rolled to avoid touchingpackage-lock.json. Happy to switch if preferred.context.secretsand/or add a port setting?mcpServerDefinitionProviderswired up, Copilot Chat may show each tool twice (once as a native LM tool, once over MCP). Worth filtering one set out, or is the duplication acceptable?Closes #9070
🤖 Generated with Claude Code