Skip to content

feat(goose): Add MCP extensions support for Goose (config.yaml) #1114

@dyoshikawa

Description

@dyoshikawa

Summary

Add MCP extension configuration support for the goose tool target via Goose's ~/.config/goose/config.yaml file (global scope only).

Motivation / Purpose

Goose manages MCP server extensions through a YAML configuration file at ~/.config/goose/config.yaml. Supporting this in Rulesync enables teams to synchronize MCP server configurations across Goose and other AI tools from a unified .rulesync/mcp.json source.

Details

Goose MCP Configuration Format

  • File: ~/.config/goose/config.yaml (macOS/Linux) or %APPDATA%\Block\goose\config\config.yaml (Windows)
  • Format: YAML
  • Section: extensions: key within the config file
  • Scope: Global only (no project-level MCP config file)

Example config.yaml structure

extensions:
  github:
    name: GitHub
    cmd: npx
    args: [-y, "@modelcontextprotocol/server-github"]
    enabled: true
    envs: { "GITHUB_PERSONAL_ACCESS_TOKEN": "<TOKEN>" }
    type: stdio
    timeout: 300
  filesystem:
    name: Filesystem
    cmd: npx
    args: [-y, "@modelcontextprotocol/server-filesystem", "/path/to/dir"]
    enabled: true
    type: stdio
    timeout: 300

Extension configuration fields

Field Type Description
name string Display name for the extension
cmd string Base command (e.g., npx, uvx, docker)
args string[] Command arguments
enabled boolean Whether the extension is active
envs object Environment variables
type string Protocol type (stdio, sse)
timeout number Max seconds to wait for responses

Implementation Checklist

1. Create GooseMcp class

  • File: src/features/mcp/goose-mcp.ts
  • Extends: ToolMcp
  • Reference pattern: Review ClaudecodeMcp or GeminiCliMcp for global-only or YAML-based patterns
  • Key challenge: Goose uses YAML format while Rulesync's canonical MCP format is JSON (mcp.json). The class needs to handle conversion between Rulesync's JSON MCP schema and Goose's YAML extension config.

2. Mapping between Rulesync MCP and Goose extensions

Rulesync MCP JSON → Goose config.yaml conversion:

// Rulesync .rulesync/mcp.json
{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "<TOKEN>" }
    }
  }
}

Maps to:

# ~/.config/goose/config.yaml (extensions section)
extensions:
  github:
    name: github
    cmd: npx
    args: [-y, "@modelcontextprotocol/server-github"]
    enabled: true
    envs: { "GITHUB_PERSONAL_ACCESS_TOKEN": "<TOKEN>" }
    type: stdio

Key mapping notes:

  • commandcmd
  • argsargs
  • envenvs
  • name is derived from the server key
  • type defaults to "stdio" (Rulesync's standard transport)
  • enabled defaults to true
  • timeout can use a sensible default (e.g., 300)

3. Register in MCP processor

  • Add "goose" entry to toolMcpFactories in src/features/mcp/mcp-processor.ts:
    [
      "goose",
      {
        class: GooseMcp,
        meta: {
          supportsProject: false,
          supportsGlobal: true,
          supportsEnabledTools: false,
          supportsDisabledTools: false,
        },
      },
    ],

4. Handle YAML serialization

  • Goose uses YAML, not JSON. Consider using an existing YAML library (e.g., yaml npm package) if one is already in the project, or add one as a dependency.
  • The implementation must handle reading/writing only the extensions section of config.yaml without disrupting other configuration keys (e.g., GOOSE_PROVIDER, GOOSE_MODEL).

5. Tests

  • File: src/features/mcp/goose-mcp.test.ts
  • Follow existing test patterns (e.g., claudecode-mcp.test.ts)
  • Test scenarios:
    • JSON → YAML conversion for stdio servers
    • YAML → JSON round-trip
    • Preserving existing non-extension config in config.yaml
    • Multiple server entries
    • Environment variable handling (envenvs)
    • fromFile, fromRulesyncMcp, toRulesyncMcp, forDeletion

Design Considerations

  • Global-only support: Goose does not appear to support project-level MCP configuration. The implementation should only support global scope (supportsProject: false, supportsGlobal: true).
  • Config file coexistence: The config.yaml contains other settings beyond extensions. The implementation must merge/update only the extensions section and preserve everything else.
  • YAML dependency: Check if the project already has a YAML parsing library. If not, consider adding the yaml package.
  • SSE support: Goose supports SSE-type extensions in addition to stdio. Consider how to map Rulesync's URL-based MCP entries to Goose's SSE config if applicable.

Additional Context

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions