Skip to content

[Agent Chat feedback] - Step 1: Let agents reach a Copilot-hosted feedback tool - #3593

Merged
zeroliu merged 2 commits into
masterfrom
zeroliu/agent-feedback-mcp
Oct 15, 2026
Merged

zeroliu merged 2 commits into
masterfrom
zeroliu/agent-feedback-mcp

Conversation

@zeroliu

@zeroliu zeroliu commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

Relates to Brevilabs/obsidian-copilot-private#672

Why

When an Agent Chat turn goes wrong, the user usually says so in the chat, and that complaint is the best bug report we will ever get. The agent cannot help send it, because Agent Chat gives agents no Copilot-owned tools: every session opens with mcpServers: [] for Codex and OpenCode, and the Claude SDK adapter registers none. The feedback card in the next step needs agents to be able to call one Copilot tool, send_feedback, and a tool that drafts a report must be reachable only by the chat it belongs to.

What

Agent Chat sessions can now carry Copilot-hosted MCP servers, and Copilot can host one. Nothing starts or attaches the server yet, so chats behave exactly as today.

Situation Result
A chat is opened, resumed or loaded with Copilot's MCP server, on an ACP agent that advertises HTTP MCP (Codex, OpenCode) The agent receives the server as an HTTP MCP server with its auth header
Same, on an ACP agent that never advertised HTTP MCP The chat opens without the server instead of risking a rejected session
Same, on Claude The server is registered on every turn and its tools are pre-approved, so no permission prompt appears
A request reaches the loopback server with the chat's bearer token initialize, ping, tools/list and tools/call send_feedback are answered; a valid call is handed to that chat only
A request has no token, another chat's revoked token, the wrong path, a GET, malformed JSON, a body that is not a single JSON object (including a batch array), or a body over 64 KiB of UTF-8 401, 404, 405, a parse error or an invalid-request error; no card is raised
Copilot is shut down while the server is still starting The pending start fails at once instead of hanging teardown
A session request carrying the server is attached to Report an issue in the Copilot log or the full-frame activity log The existing report redaction replaces the Bearer token with <token>, so a chat's token never leaves the machine

Non goal

  • Starting the server or attaching it to chats (next steps).
  • The feedback card, its setting and the system-prompt pointer.
  • Any Copilot MCP tool other than send_feedback.
  • Server-initiated MCP messages (the optional SSE stream is declined).

Screenshot

Not applicable: this PR adds plumbing with no rendered change; nothing starts the server until a later step.

Risk

High

Criterion Status Reason
No behavior change, or a cosmetic/copy/docs/config change visible where it renders, or deterministic tests cover the changed behavior ✅ No caller passes servers yet; AcpBackendProcess tests cover new/resume/load with and without HTTP MCP, ClaudeSdkBackendProcess tests cover registration and pre-approval, feedbackMcpServer tests cover handshake, auth, errors, size limits, disconnect and dispose
A defect would fail CI or be obvious on first use ✅ The tests above run in CI against a real loopback HTTP server
A revert fully restores prior state, including persisted data ✅ Nothing is persisted
No auth, permissions, secrets, or input-handling surface changes ❌ Adds a loopback HTTP endpoint that parses agent-written JSON behind a per-session bearer token, and pre-approves its tools for Claude
No public API, plugin API, message, or on-disk contract changes ❌ ACP session/new, session/resume and session/load can now carry MCP servers
No core-path concurrency, async-lifecycle, or state-machine changes ✅ Opening a session is unchanged until a caller passes servers
No hot-path behavior lacks deterministic coverage ✅ Every new branch has a test
No new dependency ✅ Dependency manifests are unchanged
Human-only behavior stays in one feature area and surfaces quickly ✅ Confined to Agent Chat

Review: inspect createFeedbackMcpServer, handleHttpRequest, reply, callTool, parseDraft and readBody in src/agentMode/session/feedback/feedbackMcpServer.ts; mcpServersField in src/agentMode/acp/AcpBackendProcess.ts; and the MCP server block in prompt() in src/agentMode/sdk/ClaudeSdkBackendProcess.ts, line by line. Review the tool text in SEND_FEEDBACK_TOOL. Then run Verification.

Verification

  1. Install this build in a test vault with Claude, Codex and OpenCode configured.
  2. Open a new Agent Chat with each backend, send a message, and confirm the reply arrives as before with no new permission prompt.
  3. Reopen one of those chats from history and send another message; it resumes as before.

@vercel

vercel Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated
obsidian-copilot-docs Ignored Ignored Oct 15, 2026 4:22pm UTC

Request Review

@zeroliu

zeroliu commented Oct 13, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-14T19:28:56.789787Z 168faa2 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6ee1ac8095

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agentMode/session/feedback/feedbackMcpServer.ts
Comment thread src/agentMode/session/feedback/feedbackMcpServer.ts
Comment thread src/agentMode/session/feedback/feedbackMcpServer.ts
Comment thread src/agentMode/acp/AcpBackendProcess.ts Outdated
Comment on lines +237 to +239
for await (const chunk of request) {
body += chunk;
if (body.length > MAX_REQUEST_BYTES) throw new Error("Request body is too large.");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Count the request limit in bytes

MAX_REQUEST_BYTES is enforced with JavaScript string length after UTF-8 decoding, so it counts UTF-16 code units rather than received bytes. For example, a body containing 30,000 CJK characters is about 90 KiB but has length 30,000 and is accepted, contradicting the advertised 64 KiB input bound. Accumulate raw buffer lengths or use Buffer.byteLength() while reading so non-ASCII agent output cannot bypass the limit.

Useful? React with 👍 / 👎.

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 2eab740. readBody now counts chunk.byteLength and decodes with a streaming TextDecoder. The size test now sends 30,000 CJK characters (about 90 KB in UTF-8) and expects a 400.

@zeroliu
zeroliu added this pull request to stack #3595 October 13, 2026 02:07
@zeroliu
zeroliu force-pushed the zeroliu/agent-feedback-mcp branch from 6ee1ac8 to 2eab740 Compare October 13, 2026 02:24
@github-actions github-actions Bot added size/L and removed size/M labels Oct 13, 2026
@zeroliu
zeroliu force-pushed the zeroliu/agent-feedback-mcp branch from 2eab740 to 168faa2 Compare October 13, 2026 21:26
@zeroliu
zeroliu marked this pull request as ready for review October 14, 2026 19:19

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 168faa2222

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

async connect(sessionKey: string, onOffer: FeedbackOfferHandler): Promise<AgentMcpServer> {
if (disposed) throw new Error("The feedback MCP server is closed.");
urlPromise ??= start();
const url = await urlPromise;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Recheck disposal after awaiting server startup

When a new session connects while plugin teardown races it after the server has already started, this await still yields even though urlPromise is fulfilled. dispose() can therefore close the listener and clear both maps before the continuation resumes; the continuation then installs a fresh token and resolves with a dead MCP URL. The session may proceed with an endpoint that cannot accept connections, while the supposedly disposed server retains the new handler and token. Check disposed again immediately after the await before creating the channel.

Useful? React with 👍 / 👎.

Comment on lines +96 to +98
const next = http.createServer((request, response) => {
void handleHttpRequest(request, response, handlersByToken);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Handle request rejection before discarding the promise

If a valid send_feedback request reaches an onOffer callback that throws—for example, because constructing the feedback card fails—handleHttpRequest() rejects. This listener explicitly discards that promise, so Node sends no JSON-RPC response, the MCP client can wait indefinitely, and the failure becomes an unhandled rejection instead of an internal-error reply. Attach a rejection handler here or catch callback failures inside the request handler and complete the response.

AGENTS.md reference: AGENTS.md:L64-L66

Useful? React with 👍 / 👎.

@zeroliu
zeroliu force-pushed the zeroliu/agent-feedback-mcp branch from 168faa2 to 205f23c Compare October 14, 2026 22:11
zeroliu and others added 2 commits October 15, 2026 09:22
A loopback streamable-HTTP MCP server on 127.0.0.1 exposes one
send_feedback tool, and each chat connects with its own bearer token so a
call reaches only that chat's offer handler. Session new, resume and load
accept HTTP MCP servers: ACP backends pass them on only when the agent
advertises HTTP MCP, and the Claude SDK adapter registers them and
pre-approves their tools. Nothing starts the server yet.

Relates to Brevilabs/obsidian-copilot-private#672

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rver

Report an issue already runs every attached log through redactLogText, which
strips Bearer tokens, so the debug-tap redaction repeated it. The 64 KiB
request cap already bounds a draft, so the per-field cap is gone too. A JSON
array body now gets an invalid-request error instead of a silent 202.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@zeroliu
zeroliu force-pushed the zeroliu/agent-feedback-mcp branch from 205f23c to 6cb4384 Compare October 15, 2026 16:22
@zeroliu
zeroliu merged commit b25474e into master Oct 15, 2026
18 checks passed
@zeroliu
zeroliu deleted the zeroliu/agent-feedback-mcp branch October 15, 2026 16:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant