Visitar URL original
[FEATURE]: Full MCP client capabilities · Issue #28567 · anomalyco/opencode · GitHub
Skip to content

[FEATURE]: Full MCP client capabilities #28567

Closed

Description

@Arcadi4

Feature hasn't been suggested before.

  • I have verified this feature I'm about to request hasn't been suggested before.

Describe the enhancement you want to request

OpenCode's MCP client features are way behind the latest MCP standard. The gaps below were touched across many issues and PRs (see list below). I myself also encountered many difficulties due to the incomplete capability while developing MCP extensions for OpenCode. A one-time implementation is probably the cleanest fix to all of them and leaves no technical debt. This should also bring architectural advantages by flattening skills and tasks into the MCP layer.

I know this proposal for a project of this size might be a bit unrealistic. Rewriting the MCP client would definitely break loads of plugins and dependencies, and the migration wouldn't be easy. Even so, the count of issues on this is large enough that I think the discussion is at least worth having.

Behavioral gaps

Missing entirely:

  • ❌ sampling/createMessage and the sampling capability1
  • ❌ elicitation/create (form + URL modes), notifications/elicitation/complete, URLElicitationRequiredError -32042, and the elicitation capability2
  • ❌ roots/list, notifications/roots/list_changed, and the roots capability3
  • ❌ resources/subscribe / resources/unsubscribe / notifications/resources/updated / notifications/resources/list_changed4
  • ❌ resources/templates/list5
  • ❌ completion/complete6
  • ⚠️ logging/setLevel and notifications/message7 — inbound notifications/message is now handled; outbound logging/setLevel is still missing
  • ❌ ping8
  • ❌ The entire experimental tasks/* system from 2025-11-259
  • ❌ No capabilities object passed to new Client(...) — opencode advertises nothing at initialize10

Partial or incorrect:

  • ✅ Progress: resetTimeoutOnProgress: true is passed to callTool and works at the SDK level for timeout resets, but onprogress is never wired through, so no progress token is sent and progress events are not surfaced to the user. 11 Progress reports now reset the tool call timeout timer. Long-running MCP tools that report progress will not be timed out. fix(mcp): enable progress timeout resets #32477
  • ❌ Cancellation: notifications/cancelled is never sent when a user aborts a tool call12
  • ✅ Pagination: tools/list, resources/list, prompts/list are called without cursors; large lists silently truncate — resolved: generic paginate() with cursor support, cycle detection, and 1000-page max is implemented13
  • ✅ Tool results: structuredContent is ignored — resolved: now JSON-stringified to text content14
  • ❌ outputSchema is tolerated during tools/list fallback by stripping it rather than validated or consumed15
  • ✅ resource_link content type is dropped — resolved: handled as 'resource' content type in session/tools.ts16
  • ❌ audio content type is dropped17
  • ❌ isError flag in tool results is not checked
  • ❌ Tool annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint)18 and icons[]19 are not consumed
  • ❌ tools/list_changed is the only notification handled; resources/list_changed and prompts/list_changed are missing20
  • ❌ The server's InitializeResult.instructions does not appear to be captured from MCP initialization or threaded into the LLM context, so the server's own usage hints are lost21

Authorization:

  • ✅ Token refresh: refreshToken is stored but never executed — tokens silently expire — resolved: SDK v1.29.0 executes token refresh via refreshAuthorization()22
  • ✅ RFC 8707 resource indicators: not sent — resolved: implemented by SDK23
  • ✅ RFC 9728 protected resource metadata: no explicit WWW-Authenticate resource_metadata parsing — resolved: implemented by SDK24
  • ✅ OpenID Connect Discovery 1.0: not implemented — resolved: SDK falls back from RFC 8414 to OIDC Discovery25
  • ⚠️ Client ID Metadata Documents: SDK supports it, but OpenCode's McpOAuthProvider does not supply clientMetadataUrl26
  • ✅ Step-up authorization (insufficient_scope re-auth): not implemented — resolved: SDK handles with loop protection27
  • ❌ OAuth callback server (port 19876) is not stopped after auth completes
  • ❌ OAuth callback page has unescaped error query parameter (XSS / CWE-79)
  • ✅ headers config is not sent during mcp auth / mcp debug — resolved

Networking:

  • ✅ Streamable HTTP Accept header doesn't always list both application/json and text/event-stream — resolved: SDK sends correct Accept header28
  • ⚠️ MCP-Protocol-Version header: SDK dynamically negotiates correctly during normal operation, but opencode mcp debug still hardcodes protocolVersion: "2024-11-05" (three revisions behind)29
  • ✅ Mcp-Session-Id is not handled; session loss permanently breaks the connection — resolved: SDK stores and sends session ID30
  • ✅ Last-Event-ID resumption is not implemented — resolved: SDK implements resumption31
  • ✅ No transport-level auto-reconnect on socket errors — resolved: SDK auto-reconnects with exponential backoff28
  • ⚠️ Local stdio servers still have incomplete lifecycle cleanup coverage on disconnect / replace / rollback32
  • ❌ Origin header validation, SSRF protection, and session-hijacking mitigations from the spec's Security Best Practices are not implemented33

Related issues and PRs

Sampling:

Elicitation / roots / initialize instructions:

Resources and resource content:

Prompts:

Progress and cancellation:

Tool result schemas, structured content, and content types:

OAuth / auth:

Transport / Streamable HTTP / SSE:

Connection lifecycle / reconnect / stdio:

Custom / dynamic headers:

Tool invocation and tool management:

Server notifications, _meta, logging, and schema compatibility:

TLS / mTLS / certificate validation:

Stdio / platform transport compatibility:

Footnotes

  1. https://modelcontextprotocol.io/specification/2025-11-25/client/sampling ↩

  2. https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation ↩

  3. https://modelcontextprotocol.io/specification/2025-11-25/client/roots ↩

  4. https://modelcontextprotocol.io/specification/2025-11-25/server/resources#subscriptions ↩

  5. https://modelcontextprotocol.io/specification/2025-11-25/server/resources#resource-templates ↩

  6. https://modelcontextprotocol.io/specification/2025-11-25/server/utilities/completion ↩

  7. https://modelcontextprotocol.io/specification/2025-11-25/server/utilities/logging ↩

  8. https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/ping ↩

  9. https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks ↩

  10. https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle#capability-negotiation ↩

  11. https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/progress ↩

  12. https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/cancellation ↩

  13. https://modelcontextprotocol.io/specification/2025-11-25/server/utilities/pagination ↩

  14. https://modelcontextprotocol.io/specification/2025-11-25/server/tools#structured-content ↩

  15. https://modelcontextprotocol.io/specification/2025-11-25/server/tools#output-schema ↩

  16. https://modelcontextprotocol.io/specification/2025-11-25/server/tools#tool-result ↩

  17. https://modelcontextprotocol.io/specification/2025-11-25/server/tools#tool ↩

  18. https://modelcontextprotocol.io/specification/2025-11-25/basic#icons ↩

  19. https://modelcontextprotocol.io/specification/2025-11-25/server/tools#list-changed-notification ↩

  20. https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle#initialization ↩

  21. https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization ↩

  22. https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#resource-parameter-implementation ↩

  23. https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#authorization-server-discovery ↩

  24. https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#authorization-server-metadata-discovery ↩

  25. https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#client-id-metadata-documents ↩

  26. https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#scope-challenge-handling ↩

  27. https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#streamable-http ↩ ↩2

  28. https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#protocol-version-header ↩

  29. https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#session-management ↩

  30. https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#resumability-and-redelivery ↩

  31. https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#stdio ↩

  32. https://modelcontextprotocol.io/specification/2025-11-25/basic/security_best_practices ↩

Activity

  1. changed the title [-][FEATURE]: Complete MCP client implementation[/-] [+][FEATURE]: Full MCP client capabilities[/+] on May 21, 2026
  2. Arcadi4 commented on May 27, 2026

    @Arcadi4
    ContributorAuthor

    Edit: update according to the latest dev branch (at a1a401dc9b69).

    • Added a few related PRs and issues.
    • Items edited:
      • Removed: configured oauth.scope not being threaded into client metadata. Current source now passes configured scope through OAuth provider/client metadata.
      • outputSchema: discovery failures are now tolerated by a fallback that strips outputSchema, but schemas still are not validated or consumed.
      • Local stdio cleanup: finalizer cleanup has improved, but disconnect / replace / rollback lifecycle coverage still looks incomplete.
  3. rekram1-node commented on May 28, 2026

    @rekram1-node
    Collaborator

    yeah mcp needs a major pass, thanks for aggregating all this

  4. romanilyin commented on May 31, 2026

    @romanilyin

    Adding a concrete use case here because this issue tracks the broader MCP client capability gap. I do not want to create duplicate issues; I plan to keep the detailed write-up in the main elicitation issue (#23066), but I think this use case is also relevant to this umbrella tracker. If maintainers prefer a separate issue, I can open one and link it from both places.

    Important context: the MCP server below, Unity MCP Gateway, is not a published public tool yet. It is currently an internal/private tool in my workflow, so this is not a runnable public reproduction. I am sharing the implementation shape because it depends on the exact MCP client capabilities discussed here.

    The Gateway uses CanonicalPath, a cross-language, cross-platform path canonicalization library, so it can ask the user to approve a canonicalized, scoped operation rather than raw/ambiguous path input.

    The relevant capability gap is elicitation/create nested inside tools/call.

    My internal MCP server exposes a wrapper-style tool surface like:

    sgg_unity_call(project, command, args_json, mode)
    

    A broad pre-call prompt for the wrapper tool is not enough, because the Gateway only knows whether a command needs human approval after it has:

    - parsed the command-specific args;
    - resolved the Unity project;
    - canonicalized path inputs through CanonicalPath/CanonicalFs;
    - rejected traversal/symlink/reparse/scope escapes;
    - evaluated policy as allow/ask/deny;
    - computed the canonical scope summary;
    - computed an args_hash;
    - created a one-shot pending approval request.
    

    The desired flow is:

    OpenCode calls tools/call
    → MCP server validates/canonicalizes/evaluates policy
    → MCP server sends elicitation/create
    → OpenCode renders a human approve/decline/cancel prompt
    → MCP server receives accept/decline/cancel
    → original tool call continues once or fails cleanly
    

    For MCP 2025-06-18, the client should advertise:

    {
      "capabilities": {
        "elicitation": {}
      }
    }

    The Gateway-side implementation already has this shape for capable clients:

    - official SDK transports where possible;
    - `extra.sendRequest` used for server-to-client elicitation;
    - boolean-only `approve` field;
    - `accept + approve: true` creates a one-shot approval and retries the original call once;
    - `decline`, `cancel`, error, or unsupported elicitation returns the existing confirmation_required fallback;
    - no model-callable approve tool is exposed.
    

    This use case also touches the Streamable HTTP/session part of this issue: capable clients should preserve the MCP session and support nested server-to-client requests during tools/call. Compatibility paths that call tools/list / tools/call without session support can still work for ordinary tools, but they cannot provide this native prompt UX.

    The key requirement from this use case: OpenCode should support real MCP elicitation semantics rather than mapping this to a model-callable question tool or to coarse pre-call tool approval.

    References:

  5. rekram1-node commented on Jun 9, 2026

    @rekram1-node
    Collaborator

    Started chipping away at all this, should have a lot of it knocked out soon

  6. Arcadi4 commented on Jun 13, 2026

    @Arcadi4
    ContributorAuthor

    Update (dbbe67f066fe)

    13 items are now resolved (mostly via SDK v1.29.0), 5 are partially resolved, and the rest confirmed still missing.

    Resolved

    • Pagination is fully implemented — generic paginate() with cursors, cycle detection, 1000-page cap
    • Most auth/transport items (token refresh, RFC 8707/9728, OIDC, step-up, session-id, reconnect, Last-Event-ID) are handled by the SDK now
    • structuredContent and resource_link are handled
    • headers config is now sent in mcp auth/mcp debug
    • Cancellation IS working — signal: options.abortSignal is passed through, SDK sends notifications/cancelled on abort

    Still missing

    • Core capabilities: sampling, elicitation, roots, subscriptions, templates, completion, ping, tasks — all still completely missing
    • No capabilities object at initialize
    • InitializeResult.instructions not captured
    • Progress: onprogress callback never wired to callTool, so no progressToken sent and no events surfaced
    • isError not checked, audio dropped, tool annotations ignored
    • OAuth callback server leak + XSS still present
    • Security mitigations (Origin validation, SSRF) not implemented
    • mcp debug still hardcodes protocol version 2024-11-05
    • No per-agent MCP tool filtering (model tool limits)

    Clean up

    Removed 56 resolved closed issues/PRs from the related list. Re-added 17 that were closed but never actually implemented (sampling, elicitation, roots, instructions, resource subscriptions, progress).

  7. rekram1-node commented on Jun 14, 2026

    @rekram1-node
    Collaborator

    Idk if we wanna add anything experimental like tasks but everything else will be added i believe, at least till we hit parity with other coding agents

  8. Arcadi4 commented on Jun 14, 2026

    @Arcadi4
    ContributorAuthor

    Idk if we wanna add anything experimental like tasks but everything else will be added i believe, at least till we hit parity with other coding agents

    Is elicitation planned? If so, will we reuse the current form UI? And would it just reject subagents right away?

  9. Arcadi4 commented on Jun 14, 2026

    @Arcadi4
    ContributorAuthor

    Idk if we wanna add anything experimental like tasks but everything else will be added i believe, at least till we hit parity with other coding agents

    Resource notifications also need more consideration if ever planned. Currently, there's no suitable UI component to fit it, which can be a gap. Introducing a new UI primitive for it should also benefit the plugin ecosystem, given that many plugins are using user messages as a workaround (I opened an issue to justify this #29633).

  10. Nomadcxx commented on Jun 14, 2026

    @Nomadcxx
    Contributor

    This is excellent

  11. rekram1-node commented on Jun 15, 2026

    @rekram1-node
    Collaborator

    Is elicitation experimental? My understanding was that it wasnt maybe im wrong but elicitation is planned yes

  12. rekram1-node commented on Jun 15, 2026

    @rekram1-node
    Collaborator

    im prioritizing the lowest hanging fruit in terms of easy fixes / additions and then I do fixes on critical existing paths, and then I do the bigger newer features like elicitation. Making progress almost there

  13. Arcadi4 commented on Jun 15, 2026

    @Arcadi4
    ContributorAuthor

    im prioritizing the lowest hanging fruit in terms of easy fixes / additions and then I do fixes on critical existing paths, and then I do the bigger newer features like elicitation. Making progress almost there

    Sounds like a good prioritization strategy. I’ve also noticed there are already several smaller UX PRs from the community that may not need much review.

    On elicitation: it is new (introduced in version 2025-06-18) but not experimental. For the TODOs/skills, do you think it would make sense to merge them into a built-in MCP? MCP-based skill seems to be trending. That might also expose more capability for plugins to extend or modify them over time.

  14. Nomadcxx commented on Jun 15, 2026

    @Nomadcxx
    Contributor

    I had a good look at this today and I think @rekram1-node small-fixes-first path makes sense.

    What's landed so far:

    Parallel to that resource work, #32480 is open for progress/status plumbing. I reworked it after feedback on the thread so mcp progress uses session.next.tool.progress.report instead of the partial-output path. Happy to defer broader UI if that's not the shape you want.

    After #32478, the resource chain is stacked in order:

    Still on the roadmap after that:

    • initialize instructions — thread InitializeResult.instructions into model context
    • elicitation — needs its own design pass (UI, permissions, accept/decline/cancel, subagents)
    • sampling — policy, visibility, and budget boundaries

    This split keeps the early PRs low-risk while still giving a path toward fuller MCP client support.

  15. Arcadi4 commented on Jun 16, 2026

    @Arcadi4
    ContributorAuthor

    Also created a small PR #32490 on MCP server instructions. There are already many issues complaining that server instructions are not being injected. PRs with the same fix were opened as well, but they might be stale.

  16. rekram1-node commented on Jun 16, 2026

    @rekram1-node
    Collaborator

    thx yall prolly gonna tweak these, not so sure about that mcp tool progress ideally if u make ui changes there is also a video attached

  17. Nomadcxx commented on Jun 17, 2026

    @Nomadcxx
    Contributor

    I have a little more to do on another project but can return to this soon @rekram1-node so let me know if you want me to finish with the split PRs above and/or whether you are happy with that split or not.

  18. Nomadcxx commented on Jun 19, 2026

    @Nomadcxx
    Contributor

    yeah makes sense.

    I reworked #32480 so it no longer pushes mcp progress into the existing session.next.tool.progress output path. It now uses session.next.tool.progress.report, so mcp progress stays as status/report data rather than partial tool output.

    I also avoided making a bigger UI call there for now. If you already have a preferred progress/status surface from the video, I’m happy to keep #32480 as the event/plumbing slice and leave the UI shape for your tweak or a follow-up.

  19. Nomadcxx commented on Jun 25, 2026

    @Nomadcxx
    Contributor

    quick update @rekram1-node: I rebased the split mcp PRs onto current dev and cleaned up the conflicts from the recent event/schema moves.

    Checks are green on all four now. After this stack, the next pieces I had in mind are initialize instructions, elicitation, and sampling. Elicitation probably needs the most care because it touches UI, permissions, accept/decline/cancel behaviour, and subagents.

  20. Nomadcxx commented on Jun 25, 2026

    @Nomadcxx
    Contributor

    Opened the first MCP elicitation slice here: #33748

    I looked at the earlier attempts before cutting this down:

    I kept #33748 to the smallest useful MCP path:

    • handle MCP elicitation/create during tool calls
    • support form mode only
    • support flat boolean schemas only
    • show the requesting MCP server in the TUI
    • preserve accept, decline, and cancel through MCP, events, HTTP, SDK, and TUI
    • return cancel for URL mode, unsupported schemas, auth probe clients, timeouts, disconnects, and shutdown cleanup
    • advertise elicitation.form only for normal clients with the handler wired
    • avoid model-callable approval tools

    Left out on purpose: URL mode, web/desktop UI, plugin UI primitives, broader schema forms, and sampling.

    Manual dev-build check: I started the rebuilt TUI from this branch, connected a repo-local stdio MCP demo server, called elicitation-demo_request_approval, confirmed the live prompt rendered with the requesting server and checkbox label, accepted the prompt, and verified the MCP tool returned {"action":"accept","content":{"allowDemo":false}}.

    Live TUI prompt from the dev build:

    MCP elicitation TUI prompt

    Manual round trip with a repo-local stdio MCP demo server:

    MCP elicitation accepted result

    Review before opening caught one cleanup bug: cancel paths could resolve the MCP request without sending the TUI a mcp.elicitation.replied event. #33748 fixes that. Timeout, interrupt, instance disposal, server close, disconnect, and client replacement now publish cancel replies so the TUI clears the prompt.

    Checks run locally:

    • bun run typecheck
    • cd packages/opencode && bun test --timeout 30000 test/mcp/elicitation.test.ts test/mcp/lifecycle.test.ts test/mcp/oauth-auto-connect.test.ts test/mcp/oauth-browser.test.ts test/server/httpapi-mcp-elicitation.test.ts test/server/httpapi-mcp-oauth.test.ts
    • cd packages/tui && bun test --timeout 30000 test/cli/cmd/tui/sync.test.tsx
    • bun run --filter @opencode-ai/tui typecheck
    • bun run --cwd packages/opencode build
    • manual dev-build test with elicitation-demo_request_approval
    • git diff --check

    If this direction looks okay, I’d expect follow-up PRs in this order:

    1. Add the next schema shape maintainers want after boolean approval lands.
    2. Add web/desktop handling once the TUI interaction model is settled.
    3. Add URL-mode elicitation separately, since it needs different display and trust rules.
    4. Add queue/count or dedupe behavior if repeated elicitations get noisy.

    Sampling should stay separate from elicitation.

    Also @rekram1-node for the next elicitation slice after #33748 if it lands would you prefer:

    • keep form mode TUI-only and add single-select enum support first;
    • keep the schema boolean-only and add web/desktop handling;
    • do a small hardening PR first for reply validation / required-key checks.
  21. venkman-del commented on Jun 27, 2026

    @venkman-del

    Any updates on these? @rekram1-node above approach seems reasonably solid.

  22. rekram1-node commented on Jun 29, 2026

    @rekram1-node
    Collaborator

    I already stated for bigger UI things we won't accept prs so while I appreciate it, I will be doing a separate pr.

  23. rekram1-node commented on Jul 8, 2026

    @rekram1-node
    Collaborator

    All core mcp functionality that we hope to support is there on dev/v2 branches

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions