Skip to content

feat: add GoosePlatform to AgentConfig and MCP initialization#6931

Merged
jamadeo merged 2 commits intoblock:mainfrom
Jazzcort:distinguish-desktop-and-cli
Feb 17, 2026
Merged

feat: add GoosePlatform to AgentConfig and MCP initialization#6931
jamadeo merged 2 commits intoblock:mainfrom
Jazzcort:distinguish-desktop-and-cli

Conversation

@Jazzcort
Copy link
Contributor

@Jazzcort Jazzcort commented Feb 3, 2026

Summary

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 feat(mcp): upgrade rmcp to 0.15.0 and advertise MCP Apps UI extension capability #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).

Type of Change

  • Feature
  • Bug fix
  • Refactor / Code quality
  • Performance improvement
  • Documentation
  • Tests
  • Security fix
  • Build / Release
  • Other (specify below)

Testing

For the client side, try this in the get_info function at crates/goose/src/agents/mcp_client.rs

eprintln!("Platform: {:?}", self.goose_platform);

And then launch both cli and desktop to see if the displayed platform is correct.
Screenshot 2026-02-03 at 2 05 30 PM
Screenshot 2026-02-03 at 2 10 10 PM

For the server side, just try to catch the initialize request from both goose desktop and goose cli and check if

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

exists under experimental field.

@Jazzcort Jazzcort force-pushed the distinguish-desktop-and-cli branch 2 times, most recently from 5092351 to 32f7f10 Compare February 3, 2026 22:33
@Jazzcort
Copy link
Contributor Author

Jazzcort commented Feb 3, 2026

I noticed that #6927 also addresses adding the mcp-apps capability to the initialize request and it's waiting on a PR at rmcp to add the extension field under capabilities.

@aharvard, I propose we land this PR first and then merge #6927 to handle the get_info modifications.

The main use case for differentiating between Goose Desktop and the CLI is ensuring the MCP server can provide alternative tools when it detects the client is not mcp-apps compatible. What do you think?

@aharvard
Copy link
Collaborator

aharvard commented Feb 4, 2026

@Jazzcort, I like the thinking of goose differentiating between desktop and CLI. I can imagine this will be beneficial on many fronts. The more info we can provide to MCP servers, the better end UX can be!

From what I understand, based on looking at this PR, and correct me if I'm wrong, you're introducing the ability to advertise MCP Apps under the capabilities.experimental. And from there, servers could detect if this is goose desktop or goose CLI. Is that your intent here?

It sounds like there might be two distinct problems to solve. Do you agree?

  1. Advertising if the client is goose-desktop or goose-cli
  2. Declaring MCP App support when users are using goose desktop

Now that both MCP Apps (SEP-1865) and MCP Extensions (SEP-1724) have landed, I think we should collaborate to achieve the below outcome when goose sends the initialize request (I've abbreviated the params for illustration purposes)

Do you want to pivot this PR to conditionally address prams.clientInfo.name?

Then, we can leverage your platform detection to set capabilities.extensions for goose Desktop in #6927 (or based on timing, in a follow-up PR).

// goose Desktop
{
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "capabilities": {
      "extensions": {
        "io.modelcontextprotocol/ui": {
          "mimeTypes": ["text/html;profile=mcp-app"]
        }
      }
    },
    "clientInfo": {
      "name": "goose-desktop",
      "version": "..."
    }
  }
}
// goose CLI
{
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "capabilities": { },
    "clientInfo": {
      "name": "goose-cli",
      "version": "..."
    }
  }
}

@Jazzcort
Copy link
Contributor Author

Jazzcort commented Feb 4, 2026

From what I understand, based on looking at this PR, and correct me if I'm wrong, you're introducing the ability to advertise MCP Apps under the capabilities.experimental. And from there, servers could detect if this is goose desktop or goose CLI. Is that your intent here?

You're absolutely right!

It sounds like there might be two distinct problems to solve. Do you agree?

1. Advertising if the client is goose-desktop or goose-cli
2. Declaring MCP App support when users are using goose desktop

agree!

Do you want to pivot this PR to conditionally address prams.clientInfo.name?

That sounds great! I'll pivot it to just address prams.clientInfo.name and leave the rest for #6927

@Jazzcort Jazzcort force-pushed the distinguish-desktop-and-cli branch 4 times, most recently from bf5c776 to f013d1b Compare February 5, 2026 19:07
@jamadeo
Copy link
Collaborator

jamadeo commented Feb 5, 2026

Makes sense to me that we'd need to express different capabilities depending on the client. But I think it would be cleaner if, instead of a CLI/Desktop enum, the extension manager itself were configured directly with these. Since CLI and desktop construct their agent/extension manager in different places, it would be easy enough to configure there.

@Jazzcort
Copy link
Contributor Author

Jazzcort commented Feb 6, 2026

@jamadeo Thanks for the review! I'll work on the patch! 😁

@Jazzcort
Copy link
Contributor Author

Jazzcort commented Feb 6, 2026

@jamadeo So after my investigation, I found the last place we can differentiate Desktop/Cli is when we create Agent. (Please correct me if I'm wrong) And the extension manager is created within Agent. Therefore, without passing something to the agent to differentiate the platform, I don't think there is a way to know which platform the users are using while creating the extension manager. Please let me know if you do find a way to make this work without passing the enum. 😁

@Jazzcort
Copy link
Contributor Author

@jamadeo Any updates on this? Let me know if you think of any better ways other than passing the enum when creating Agent.

@aharvard
Copy link
Collaborator

FYI @Jazzcort, we just merged #6927
Happy to review your conditional approach to advertise MCP Apps for Desktop when ready

@Jazzcort
Copy link
Contributor Author

@aharvard Thanks for the update! I will fix the conflicts. Will ping you when it's done. Does this sounds good to you?

@jamadeo
Copy link
Collaborator

jamadeo commented Feb 11, 2026

sorry for the late reply @Jazzcort - what I meant was, we could specify capabilities instead of a platform type. So instead of passing the cli/desktop enum, you'd configure the extension manager itself to be created with capabilities/name. Something like

struct ExtensionManagerCapabilities {
    mcpui: bool
}

impl ExtensionManager {
    pub fn new(
        provder: ...,
        ...
        client_name: &str,
        capabilities: ExtensionManagerCapabilities
    ) -> { ...

I see that at the Agent level, you might just want to keep the CLI/Desktop distinction, but this way you don't make that a concern of the extension manager itself

@Jazzcort
Copy link
Contributor Author

@jamadeo Got it! Sorry for the misunderstanding there. 😅 I see your point now and will modify it as you suggested!

@Jazzcort Jazzcort force-pushed the distinguish-desktop-and-cli branch 3 times, most recently from e5ce00c to 0433e7a Compare February 13, 2026 17:45
@Jazzcort
Copy link
Contributor Author

@aharvard @jamadeo
Sorry for the delay on this. I ended up adding both ExtensionManagerCapabilities and GooseMcpClientCapabilities. It just felt a bit weird to pass ExtensionManagerCapabilities straight into GooseClient, so I split them out.

They’re basically the same right now, but I see them as handling fine-grained configuration at different levels, so it might give us more flexibility later if they start to diverge.

Curious to hear what you all think — happy to tweak it if this doesn’t feel right.

…ities

This commit introduces platform-awareness to the Goose agent and MCP clients, allowing for
distinct behaviors and capabilities based on the environment (CLI vs. Desktop).

Key Changes:
  - Added GoosePlatform Enum: Introduced GooseCli and GooseDesktop variants and integrated
    them into AgentConfig.

  - Conditional UI Capabilities: Created ExtensionManagerCapabilities and
    GooseMcpClientCapabilities. The MCP UI capability (io.modelcontextprotocol/ui) is now
    properly gated and only exposed when running on GooseDesktop (mcpui: true).

  - Dynamic Client Identification: Updated GooseClient to dynamically set clientInfo.name
    in MCP initialization requests (e.g., "goose-cli" or "goose-desktop") instead of using
    a hardcoded "goose" string.

  - Architecture Plumbing: Plumbed the platform strings and capability structs through the
    initialization pipelines in Agent, ExtensionManager, and McpClient.

  - Test Maintenance: Updated execution managers, integration tests, and MCP replay files
    to explicitly pass GoosePlatform::GooseCli and assert against the updated "goose-cli"
    initialization payload.

Signed-off-by: Jazzcort <jason101011113@gmail.com>
@Jazzcort Jazzcort force-pushed the distinguish-desktop-and-cli branch from 0433e7a to 889c7e3 Compare February 13, 2026 18:03
Copy link
Collaborator

@jamadeo jamadeo left a comment

Choose a reason for hiding this comment

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

Looks great, thanks @Jazzcort

@jamadeo jamadeo enabled auto-merge February 17, 2026 13:40
@jamadeo jamadeo added this pull request to the merge queue Feb 17, 2026
Merged via the queue into block:main with commit 5328467 Feb 17, 2026
20 checks passed
@Jazzcort
Copy link
Contributor Author

@jamadeo Thanks for reviewing! 😁

zanesq added a commit that referenced this pull request Feb 17, 2026
…led-extensions-cmd

* 'main' of github.com:block/goose: (24 commits)
  Set up direnv and update flake inputs (#6526)
  fix: restore subagent tool call notifications after summon refactor (#7243)
  fix(ui): preserve server config values on partial provider config save (#7248)
  fix(claude-code): allow goose to run inside a Claude Code session (#7232)
  fix(openai): route gpt-5 codex via responses and map base paths (#7254)
  feat: add GoosePlatform to AgentConfig and MCP initialization (#6931)
  Fix copied over (#7270)
  feat(gemini-cli): add streaming support via stream-json events (#7244)
  fix: filter models without tool support from recommended list (#7198)
  fix(google): handle more thoughtSignature vagaries during streaming (#7204)
  docs: playwright CLI skill tutorial (#7261)
  install node in goose dir (#7220)
  fix: relax test_basic_response assertion for providers returning reasoning_content (#7249)
  fix: handle reasoning_content for Kimi/thinking models (#7252)
  feat: sandboxing for macos (#7197)
  fix(otel): use monotonic_counter prefix and support temporality env var (#7234)
  Streaming markdown (#7233)
  Improve compaction messages to enable better post-compaction agent behavior (#7259)
  fix: avoid shell-escaping special characters except quotes (#7242)
  fix: use dynamic port for Tetrate auth callback server (#7228)
  ...
katzdave added a commit to YusukeShimizu/goose that referenced this pull request Feb 17, 2026
* origin/main: (263 commits)
  working_dir usage more clear in add_extension (block#6958)
  Use Canonical Models to set context window sizes (block#6723)
  Set up direnv and update flake inputs (block#6526)
  fix: restore subagent tool call notifications after summon refactor (block#7243)
  fix(ui): preserve server config values on partial provider config save (block#7248)
  fix(claude-code): allow goose to run inside a Claude Code session (block#7232)
  fix(openai): route gpt-5 codex via responses and map base paths (block#7254)
  feat: add GoosePlatform to AgentConfig and MCP initialization (block#6931)
  Fix copied over (block#7270)
  feat(gemini-cli): add streaming support via stream-json events (block#7244)
  fix: filter models without tool support from recommended list (block#7198)
  fix(google): handle more thoughtSignature vagaries during streaming (block#7204)
  docs: playwright CLI skill tutorial (block#7261)
  install node in goose dir (block#7220)
  fix: relax test_basic_response assertion for providers returning reasoning_content (block#7249)
  fix: handle reasoning_content for Kimi/thinking models (block#7252)
  feat: sandboxing for macos (block#7197)
  fix(otel): use monotonic_counter prefix and support temporality env var (block#7234)
  Streaming markdown (block#7233)
  Improve compaction messages to enable better post-compaction agent behavior (block#7259)
  ...

# Conflicts:
#	crates/goose/src/providers/openai.rs
zanesq added a commit that referenced this pull request Feb 17, 2026
…ions-fallback

* 'main' of github.com:block/goose: (43 commits)
  Added cmd to validate bundled extensions json (#7217)
  working_dir usage more clear in add_extension (#6958)
  Use Canonical Models to set context window sizes (#6723)
  Set up direnv and update flake inputs (#6526)
  fix: restore subagent tool call notifications after summon refactor (#7243)
  fix(ui): preserve server config values on partial provider config save (#7248)
  fix(claude-code): allow goose to run inside a Claude Code session (#7232)
  fix(openai): route gpt-5 codex via responses and map base paths (#7254)
  feat: add GoosePlatform to AgentConfig and MCP initialization (#6931)
  Fix copied over (#7270)
  feat(gemini-cli): add streaming support via stream-json events (#7244)
  fix: filter models without tool support from recommended list (#7198)
  fix(google): handle more thoughtSignature vagaries during streaming (#7204)
  docs: playwright CLI skill tutorial (#7261)
  install node in goose dir (#7220)
  fix: relax test_basic_response assertion for providers returning reasoning_content (#7249)
  fix: handle reasoning_content for Kimi/thinking models (#7252)
  feat: sandboxing for macos (#7197)
  fix(otel): use monotonic_counter prefix and support temporality env var (#7234)
  Streaming markdown (#7233)
  ...

# Conflicts:
#	crates/goose/src/config/extensions.rs
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.

3 participants

Comments