Skip to content

feat(mcp): adopt @outfitter/mcp with createMcpServer() and defineTool()#171

Open
galligan wants to merge 1 commit into
fire-10/cli-outputfrom
fire-11/mcp-framework
Open

feat(mcp): adopt @outfitter/mcp with createMcpServer() and defineTool()#171
galligan wants to merge 1 commit into
fire-10/cli-outputfrom
fire-11/mcp-framework

Conversation

@galligan

@galligan galligan commented Feb 22, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Replace McpServer/StdioServerTransport with createMcpServer()/connectStdio()
  • All 6 tools use defineTool() with TOOL_ANNOTATIONS presets (readOnly, destructive)
  • adaptHandler() bridges domain errors to OutfitterError for JSON-RPC code mapping
  • Auth-gated write tools registered after connectStdio() with auto tools/list_changed
  • @modelcontextprotocol/sdk retained as devDependency for types (FIRE-11)

Test plan

  • bun run check passes
  • bun test passes (298 tests)
  • bun apps/mcp/bin/fw-mcp.ts starts without error

🤘🏻 In-collaboration-with: Claude Code

Greptile Summary

Migrated the MCP server from direct @modelcontextprotocol/sdk usage to the @outfitter/mcp abstraction layer. The class-based FirewatchMCPServer is replaced with functional composition using createMcpServer(), defineTool(), and adaptHandler(). All 6 tools now use standardized TOOL_ANNOTATIONS presets for readOnly/write/destructive categories, and error handling is unified through adaptHandler() which bridges domain errors to Result<T, OutfitterError> for proper JSON-RPC error code mapping. The SDK is retained as a devDependency for type compatibility (FIRE-11).

Key changes:

  • Renamed schema exports from *ParamsShape to *ParamsSchema for consistency
  • Auth-gated write tools now registered after connectStdio() with auto notifyToolsChanged()
  • Test helper updated to use createSdkServer() wrapper for SDK compatibility
  • All tool handlers wrapped in try/catch with Result-based returns

Confidence Score: 5/5

  • Safe to merge - well-structured refactoring with passing tests
  • Clean migration to abstraction layer with comprehensive test coverage (298 tests passing). The refactoring maintains all existing functionality while improving code organization through functional composition. Error handling is properly unified, and the SDK compatibility is preserved for tests.
  • No files require special attention

Important Files Changed

Filename Overview
apps/mcp/package.json Moved @modelcontextprotocol/sdk to devDependencies, added new @outfitter/* dependencies for the MCP refactor
apps/mcp/src/index.ts Refactored from class-based FirewatchMCPServer to functional approach with createMcpServer() and defineTool(), using adaptHandler() to bridge domain errors to Result types
apps/mcp/tests/integration.test.ts Updated test helper to use createSdkServer() wrapper for SDK compatibility with InMemoryTransport

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[run] --> B[initializeServer]
    B --> C[createMcpServer]
    B --> D[Create AuthGateState]
    B --> E[Register Base Tools]
    
    E --> E1[defineQueryTool]
    E --> E2[defineStatusTool]
    E --> E3[defineDoctorTool]
    E --> E4[defineHelpTool]
    
    E1 --> F[defineTool + adaptHandler]
    E2 --> F
    E3 --> F
    E4 --> F
    
    A --> G[connectStdio]
    A --> H[verifyAuthAndEnableWriteTools]
    
    H --> I{Auth Success?}
    I -->|Yes| J[registerWriteTools]
    I -->|No| K[Return Error]
    
    J --> J1[definePrTool]
    J --> J2[defineFbTool]
    
    J1 --> L[defineTool + adaptHandler]
    J2 --> L
    
    J --> M[notifyToolsChanged]
    
    F --> N[Result.ok/Result.err]
    L --> N
Loading

Last reviewed commit: 0e54a57

@linear

linear Bot commented Feb 22, 2026

Copy link
Copy Markdown

Replace direct @modelcontextprotocol/sdk usage with @outfitter/mcp framework:
- createMcpServer() + connectStdio() replace McpServer + StdioServerTransport
- defineTool() with TOOL_ANNOTATIONS replaces server.tool() registration
- adaptHandler() bridges Error -> OutfitterError for Result-based handlers
- All 6 tools (fw_query, fw_status, fw_doctor, fw_help, fw_pr, fw_fb) converted
- Auth-gated write tool pattern preserved with notifyToolsChanged()
- Integration tests updated to use createSdkServer() for InMemoryTransport

🤘🏻 In-collaboration-with: [Claude Code](https://claude.com/claude-code)
@galligan galligan force-pushed the fire-11/mcp-framework branch from c31cf2c to 0e54a57 Compare February 22, 2026 03:51
@galligan galligan marked this pull request as ready for review February 22, 2026 04:08

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0e54a578d4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/mcp/src/index.ts
* Returns both the server and the auth gate state for lifecycle management.
*/
function initializeServer(): { server: McpServer; state: AuthGateState } {
const server = createMcpServer({ name: "firewatch", version: mcpVersion });

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Restore MCP server instructions during initialization

The migrated initialization now calls createMcpServer with only { name, version }, which drops the server-level instructions string that was previously advertised to clients. In this codebase, docs/development/mcp-context-management.md explicitly treats server instructions as critical for tool-search routing; removing them means models are less likely to discover and invoke Firewatch tools unless the user gives highly explicit prompts, so behavior regresses even though tool registration still succeeds. Please pass the prior instructions text (or equivalent metadata field in @outfitter/mcp) when creating the server.

Useful? React with 👍 / 👎.

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.

1 participant