gitbutlerapp/gitbutler · error

MCP Apps capability is an object

Error message

MCP Apps capability is an object

What it means

When the MCP server advertises itself (ServerHandler::get_info), but inserts the MCP Apps UI capability into ExtensionCapabilities by deserializing a hardcoded JSON literal ({"mimeTypes":[MCP_APP_MIME_TYPE]}) into rmcp's capability value type. Since the input is a compile-time constant, the expect can only fail when the installed rmcp crate's extension-capability type no longer accepts that shape — i.e. a dependency upgrade changed the schema.

Source

Thrown at crates/but/src/command/mcp/mod.rs:245

        Ok(match result {
            Ok(result) => result,
            Err(err) => CallToolResult::error(vec![Content::text(format!(
                "Could not mark the review as ready: {err:#}"
            ))]),
        })
    }
}

#[tool_handler]
impl ServerHandler for Mcp {
    fn get_info(&self) -> ServerInfo {
        let mut extensions = ExtensionCapabilities::new();
        extensions.insert(
            "io.modelcontextprotocol/ui".to_owned(),
            serde_json::from_value(json!({
                "mimeTypes": [MCP_APP_MIME_TYPE]
            }))
            .expect("MCP Apps capability is an object"),
        );

        ServerInfo {
            instructions: Some(
                "Use gitbutler_workspace to inspect a repository's current GitButler workspace. Pass the active repository path when it is available; omit it only when the client is known to expose that repository as a filesystem root. After `but pr new`, call gitbutler_review_card with the returned review numbers so the user can see the created reviews."
                    .into(),
            ),
            capabilities: ServerCapabilities::builder()
                .enable_extensions_with(extensions)
                .enable_resources()
                .enable_tools()
                .build(),
            server_info: Implementation {
                name: "gitbutler".into(),
                title: Some("GitButler".into()),
                version: option_env!("VERSION").unwrap_or("dev").into(),
                description: Some("GitButler workspace tools and views".into()),
                icons: None,

View on GitHub (pinned to 2497b8007a)

Solutions

  1. Align rmcp with the version but was built against — check Cargo.lock for the pinned rmcp and restore it (e.g. git checkout Cargo.lock or cargo update -p rmcp --precise <ver>)
  2. If the upgrade is intentional, update the json! literal to the capability shape the new rmcp expects
  3. Pin rmcp exactly (rmcp = "=x.y.z") so silent drift cannot reintroduce this
  4. Add a smoke test asserting get_info() completes without panicking after dependency changes

Example fix

// before — Cargo.toml allows drift
rmcp = "0.x"

// after — exact pin so the capability literal and the type stay in sync
rmcp = "=0.x.y"
Defensive patterns

Strategy: validation

Validate before calling

// after any rmcp/cargo update, verify server info construction before shipping
#[test]
fn mcp_server_info_smoke() {
    let mcp = /* construct Mcp handler */;
    let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| mcp.get_info()));
    assert!(result.is_ok(), "get_info panicked — extension capability schema drifted");
}

Try / catch

// degrade gracefully: serve without extensions if the capability literal no longer parses
let extensions = std::panic::catch_unwind(AssertUnwindSafe(build_extensions))
    .unwrap_or_default(); // proceed with no advertised UI capability

Prevention

When it happens

Trigger: Starting but's MCP server mode (an MCP client spawning `but mcp`, or any path calling Mcp::get_info) after the rmcp dependency was upgraded/changed so that ExtensionCapabilities::insert's value type rejects an object with a mimeTypes array.

Common situations: cargo update or a version bump of the rmcp SDK in the workspace; building against a fork/patched rmcp; drift between rmcp and the MCP Apps (io.modelcontextprotocol/ui) spec revision.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@2497b8007a (2026-08-17). Data as JSON: /api/errors/a806f3a59e427ac0. Report an issue: GitHub.