Skip to content

feat(mcp): upgrade rmcp to 0.15.0 and advertise MCP Apps UI extension capability#6927

Merged
aharvard merged 5 commits intomainfrom
feat/mcp-apps-ui-extension
Feb 11, 2026
Merged

feat(mcp): upgrade rmcp to 0.15.0 and advertise MCP Apps UI extension capability#6927
aharvard merged 5 commits intomainfrom
feat/mcp-apps-ui-extension

Conversation

@aharvard
Copy link
Collaborator

@aharvard aharvard commented Feb 3, 2026

Summary

This PR updates the MCP client to advertise support for the io.modelcontextprotocol/ui extension during capability negotiation, as required by the MCP Apps specification.

Changes

  • Upgrade rmcp 0.14.0 → 0.15.0 — unblocks the extensions field on ClientCapabilities
  • Import ExtensionCapabilities from rmcp::model
  • Update GooseClient::get_info() to build and advertise the UI extension capability
  • Add test to verify the capability is correctly advertised
  • Address all rmcp 0.15.0 breaking changes across 15 files:
    • Implementation: new description field
    • ServerCapabilities: new extensions field
    • Tool: new execution field
    • SamplingMessage.content: ContentSamplingContent<SamplingMessageContent>
    • CreateElicitationRequestParams: struct → enum (FormElicitationParams/UrlElicitationParams)

Capability Advertised

{
  "capabilities": {
    "extensions": {
      "io.modelcontextprotocol/ui": {
        "mimeTypes": ["text/html;profile=mcp-app"]
      }
    }
  }
}

Verification

  • cargo build — compiles cleanly
  • cargo fmt — no formatting issues
  • ./scripts/clippy-lint.sh — all baseline checks pass
  • cargo test -p goose --lib — 532 passed (4 pre-existing snapshot failures unrelated)
  • cargo test -p goose-mcp --lib — 182 passed
  • ✅ All 44 tests in affected modules pass

Related

WIP: Depends on rmcp PR #643 being merged and released.

This change updates the MCP client to advertise support for the
io.modelcontextprotocol/ui extension during capability negotiation,
as required by the MCP Apps specification.

The client now advertises:
  {
    "capabilities": {
      "extensions": {
        "io.modelcontextprotocol/ui": {
          "mimeTypes": ["text/html;profile=mcp-app"]
        }
      }
    }
  }

Blocked by:
- modelcontextprotocol/rust-sdk#643

Related:
- https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/2026-01-26/apps.mdx
@aharvard
Copy link
Collaborator Author

aharvard commented Feb 4, 2026

note: Depending on timing, we might be able to leverage conditional declaration based off platform detection: #6931

Jazzcort added a commit to Jazzcort/goose that referenced this pull request Feb 5, 2026
Introduces a GoosePlatform enum to distinguish between GooseCli and GooseDesktop environments.
This allows the MCP client to conditionally advertise capabilities based on the active
platform.

Changes:
  - Core: Added GoosePlatform enum to crates/goose/src/agents/agent.rs and included it in
    AgentConfig.

  - MCP Integration: Updated GooseClient to include platform info. Now, the client
    advertises its client name as "goose-desktop" while using Goose Desktop and "goose-cli"
    for Goose Cli. Leave params.capabilities.extension part for
    block#6927.

  - Plumbing: Updated ExtensionManager, McpClient, and Agent constructors across the codebase
    to propagate the platform type.

  - Defaults:
    - goose-acp and goose-cli default to GoosePlatform::GooseCli.
    - AgentManager (used by the desktop execution flow) defaults to
      GoosePlatform::GooseDesktop.

  - Testing: Updated scenario runners and integration tests to explicitly pass a platform
    variant (typically GooseCli).

Signed-off-by: Jazzcort <jason101011113@gmail.com>
Jazzcort added a commit to Jazzcort/goose that referenced this pull request Feb 5, 2026
Introduces a GoosePlatform enum to distinguish between GooseCli and GooseDesktop environments.
This allows the MCP client to conditionally advertise capabilities based on the active
platform.

Changes:
  - Core: Added GoosePlatform enum to crates/goose/src/agents/agent.rs and included it in
    AgentConfig.

  - MCP Integration: Updated GooseClient to include platform info. Now, the client
    advertises its client name as "goose-desktop" while using Goose Desktop and "goose-cli"
    for Goose Cli. Leave params.capabilities.extension part for block#6927

  - Plumbing: Updated ExtensionManager, McpClient, and Agent constructors across the codebase
    to propagate the platform type.

  - Defaults:
    - goose-acp and goose-cli default to GoosePlatform::GooseCli.
    - AgentManager (used by the desktop execution flow) defaults to
      GoosePlatform::GooseDesktop.

  - Testing: Updated scenario runners and integration tests to explicitly pass a platform
    variant (typically GooseCli).

Signed-off-by: Jazzcort <jason101011113@gmail.com>
…vertisement

Upgrades rmcp to 0.15.0 which adds the 'extensions' field on ClientCapabilities,
enabling goose to advertise io.modelcontextprotocol/ui support during MCP initialize.

Breaking changes addressed:
- Implementation: added description field
- ServerCapabilities: added extensions field
- Tool: added execution field
- SamplingMessage.content: Content → SamplingContent<SamplingMessageContent>
- SamplingMessage: added meta field (handled by constructor)
- CreateElicitationRequestParams: struct → enum (FormElicitationParams/UrlElicitationParams)
@aharvard aharvard changed the title WIP: feat(mcp): advertise MCP Apps UI extension capability feat(mcp): advertise MCP Apps UI extension capability Feb 10, 2026
@aharvard aharvard changed the title feat(mcp): advertise MCP Apps UI extension capability feat(mcp): upgrade rmcp to 0.15.0 and advertise MCP Apps UI extension capability Feb 10, 2026
- Resolve Cargo.lock conflicts by regenerating lockfile
- Accept deletion of skills_extension.rs (replaced by summon_extension.rs on main)
- Add missing 'description' field to Implementation structs in summon_extension.rs and tom_extension.rs
- Add missing 'extensions' field to ServerCapabilities structs in summon_extension.rs and tom_extension.rs
@aharvard aharvard marked this pull request as ready for review February 11, 2026 13:17
Copilot AI review requested due to automatic review settings February 11, 2026 13:17
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR upgrades the MCP SDK dependency (rmcp) from version 0.14.0 to 0.15.0 and adds support for advertising the MCP Apps UI extension capability during client capability negotiation, as specified in the MCP Apps specification.

Changes:

  • Upgraded rmcp dependency from 0.14.0 to 0.15.0 in Cargo.toml
  • Updated GooseClient to advertise the io.modelcontextprotocol/ui extension capability with support for text/html;profile=mcp-app MIME type
  • Addressed rmcp 0.15.0 breaking changes across all affected files: added description field to Implementation structs, added extensions field to ServerCapabilities, added execution field to Tool constructs, updated SamplingMessage API usage, and adapted CreateElicitationRequestParams enum handling

Reviewed changes

Copilot reviewed 15 out of 16 changed files in this pull request and generated no comments.

Show a summary per file
File Description
Cargo.toml Upgraded rmcp dependency from 0.14.0 to 0.15.0
Cargo.lock Updated dependency lock file with new rmcp version and transitive dependencies
crates/goose/src/agents/mcp_client.rs Added MCP Apps UI extension capability advertisement, updated SamplingMessage and CreateElicitationRequestParams usage, added test coverage
crates/goose/src/agents/tom_extension.rs Added description and extensions fields for rmcp 0.15.0 compatibility
crates/goose/src/agents/todo_extension.rs Added description and extensions fields for rmcp 0.15.0 compatibility
crates/goose/src/agents/summon_extension.rs Added description and extensions fields for rmcp 0.15.0 compatibility
crates/goose/src/agents/extension_manager_extension.rs Added description and extensions fields for rmcp 0.15.0 compatibility
crates/goose/src/agents/extension_manager.rs Added execution field when constructing Tool instances
crates/goose/src/agents/code_execution_extension.rs Added description and extensions fields for rmcp 0.15.0 compatibility
crates/goose/src/agents/chatrecall_extension.rs Added description and extensions fields for rmcp 0.15.0 compatibility
crates/goose/src/agents/apps_extension.rs Added description and extensions fields for rmcp 0.15.0 compatibility
crates/goose-mcp/src/tutorial/mod.rs Added description field to Implementation for rmcp 0.15.0 compatibility
crates/goose-mcp/src/memory/mod.rs Added description field to Implementation for rmcp 0.15.0 compatibility
crates/goose-mcp/src/developer/rmcp_developer.rs Added description field to Implementation for rmcp 0.15.0 compatibility
crates/goose-mcp/src/computercontroller/mod.rs Added description field to Implementation for rmcp 0.15.0 compatibility
crates/goose-mcp/src/autovisualiser/mod.rs Added description field to Implementation for rmcp 0.15.0 compatibility

The PR added MCP Apps UI extension capability advertisement in the
client's initialize request, but the recorded replay files still had
the old initialize message without the extensions field. This caused
all 4 replay tests to fail because the playback comparison found a
mismatch and closed the connection.

Updated all 4 replay files to include:
  extensions: { io.modelcontextprotocol/ui: { mimeTypes: [text/html;profile=mcp-app] } }
in the capabilities of the initialize STDIN line.
The rmcp 0.15.0 upgrade added an execution field to Tool that references
ToolExecution and TaskSupport types. These were missing from the OpenAPI
schema definitions, causing @hey-api/openapi-ts to fail with a missing
$ref pointer error.
Copilot AI review requested due to automatic review settings February 11, 2026 14:25
@alexhancock alexhancock self-requested a review February 11, 2026 14:25
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 23 out of 24 changed files in this pull request and generated 4 comments.

Comment on lines +226 to 229
match msg.content.first().and_then(|c| c.as_text()) {
Some(text) => base.with_text(&text.text),
None => base.with_content(msg.content.clone().into()),
None => base,
}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

create_message drops non-text sampling message content (and even text beyond the first part), producing provider messages with empty content when the incoming MCP message contains images/resources; this is a behavioral regression from the previous with_content(msg.content.clone().into()) path and can lead to invalid/empty prompts being sent to providers. Convert each SamplingMessageContent item into MessageContent (text/image/resource) and add it to the base message (or at least preserve the first non-text part via a placeholder) instead of returning base unchanged.

Copilot uses AI. Check for mistakes.
Comment on lines 321 to +323
derive_utoipa!(ToolAnnotations as ToolAnnotationsSchema);
derive_utoipa!(ToolExecution as ToolExecutionSchema);
derive_utoipa!(TaskSupport as TaskSupportSchema);
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

The schemars→utoipa conversion used by derive_utoipa! currently ignores JSON Schema enum values, so rmcp enums like TaskSupport degrade into meaningless oneOf entries of plain string (as seen in the generated OpenAPI), which in turn makes the generated TypeScript type just string. Extend the converter (e.g., in convert_typed_schema/convert_json_object_to_utoipa) to preserve enum (and collapse redundant oneOf) so the OpenAPI accurately constrains allowed values.

Copilot uses AI. Check for mistakes.
Comment on lines +6759 to +6769
"oneOf": [
{
"type": "string"
},
{
"type": "string"
},
{
"type": "string"
}
]
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

TaskSupport is emitted as oneOf with three identical { "type": "string" } schemas, which loses the underlying enum/variant information and provides no validation constraints to clients. Regenerate this schema after fixing the schemars→OpenAPI conversion to preserve enum values (or, if it really is unconstrained, simplify it to a single type: string).

Suggested change
"oneOf": [
{
"type": "string"
},
{
"type": "string"
},
{
"type": "string"
}
]
"type": "string"

Copilot uses AI. Check for mistakes.
@@ -1,4 +1,4 @@
STDIN: {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{"sampling":{},"elicitation":{}},"clientInfo":{"name":"goose","version":"0.0.0"}}}
STDIN: {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{"elicitation":{},"extensions":{"io.modelcontextprotocol/ui":{"mimeTypes":["text/html;profile=mcp-app"]}},"sampling":{}},"clientInfo":{"name":"goose","version":"0.0.0"}}}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

leading zeros in decimal integer literals are not permitted; use an 0o prefix for octal integers (in Python 3).

Copilot uses AI. Check for mistakes.
@aharvard aharvard added this pull request to the merge queue Feb 11, 2026
Merged via the queue into main with commit 544bc1b Feb 11, 2026
26 checks passed
@aharvard aharvard deleted the feat/mcp-apps-ui-extension branch February 11, 2026 14:42
tlongwell-block added a commit that referenced this pull request Feb 11, 2026
* origin/main: (107 commits)
  feat: Allow overriding default bat themes using environment variables (#7140)
  Make the system prompt smaller (#6991)
  Pre release script (#7145)
  Spelling (#7137)
  feat(mcp): upgrade rmcp to 0.15.0 and advertise MCP Apps UI extension capability (#6927)
  fix: ensure assistant messages with tool_calls include content field (#7076)
  fix(canonical): handle gcp_vertex_ai model mapping correctly (#6836)
  Group dependencies in root Cargo.toml (#6948)
  refactor: updated elevenLabs API module and `remove button` UX (#6781)
  fix: we were missing content from langfuse traces (#7135)
  docs: update username in authors.yml (#7132)
  fix extension selector syncing issues (#7133)
  fix(acp): per-session Agent for model isolation and load_session restore (#7115)
  fix(claude-code): defensive coding improvements for model switching (#7131)
  feat(claude-code): dynamic model listing and mid-session model switching (#7120)
  Inline worklet source (#7128)
  [docs] One shot prompting is dead - Blog Post (#7113)
  fix: correct spelling of Debbie O'Brien's name in authors.yml (#7127)
  docs: GCP Vertex AI org policy filtering & update OnboardingProviderSetup component (#7125)
  feat: replace subagent and skills with unified summon extension (#6964)
  ...

# Conflicts:
#	Cargo.lock
#	Cargo.toml
zanesq added a commit to Abhijay007/goose that referenced this pull request Feb 11, 2026
* upstream/main: (109 commits)
  [docs] Skills Marketplace UI Improvements (block#7158)
  More no-window flags (block#7122)
  feat: Allow overriding default bat themes using environment variables (block#7140)
  Make the system prompt smaller (block#6991)
  Pre release script (block#7145)
  Spelling (block#7137)
  feat(mcp): upgrade rmcp to 0.15.0 and advertise MCP Apps UI extension capability (block#6927)
  fix: ensure assistant messages with tool_calls include content field (block#7076)
  fix(canonical): handle gcp_vertex_ai model mapping correctly (block#6836)
  Group dependencies in root Cargo.toml (block#6948)
  refactor: updated elevenLabs API module and `remove button` UX (block#6781)
  fix: we were missing content from langfuse traces (block#7135)
  docs: update username in authors.yml (block#7132)
  fix extension selector syncing issues (block#7133)
  fix(acp): per-session Agent for model isolation and load_session restore (block#7115)
  fix(claude-code): defensive coding improvements for model switching (block#7131)
  feat(claude-code): dynamic model listing and mid-session model switching (block#7120)
  Inline worklet source (block#7128)
  [docs] One shot prompting is dead - Blog Post (block#7113)
  fix: correct spelling of Debbie O'Brien's name in authors.yml (block#7127)
  ...
jh-block added a commit that referenced this pull request Feb 12, 2026
* origin/main: (33 commits)
  fix: replace panic with proper error handling in get_tokenizer (#7175)
  Lifei/smoke test for developer (#7174)
  fix text editor view broken (#7167)
  docs: White label guide (#6857)
  Add PATH detection back to developer extension (#7161)
  docs: pin version in ci/cd (#7168)
  Desktop: - No Custom Headers field for custom OpenAI-compatible providers  (#6681)
  feat: edit model and extensions of a recipe from GUI (#6804)
  feat: MCP support for agentic CLI providers (#6972)
  docs: keyring fallback to secrets.yaml (#7165)
  feat: load provider/model specified inside the recipe config (#6884)
  fix ask-ai bot hitting tool call limits (#7162)
  fix flatpak icon (#7154)
  [docs] Skills Marketplace UI Improvements (#7158)
  More no-window flags (#7122)
  feat: Allow overriding default bat themes using environment variables (#7140)
  Make the system prompt smaller (#6991)
  Pre release script (#7145)
  Spelling (#7137)
  feat(mcp): upgrade rmcp to 0.15.0 and advertise MCP Apps UI extension capability (#6927)
  ...
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

Comments