Skip to content

Comments

Fix MCP server to work with Claude Code#1

Open
keithschacht wants to merge 4 commits intoparruda:mainfrom
keithschacht:fix-mcp-server-claude-code
Open

Fix MCP server to work with Claude Code#1
keithschacht wants to merge 4 commits intoparruda:mainfrom
keithschacht:fix-mcp-server-claude-code

Conversation

@keithschacht
Copy link

Summary

This PR fixes critical issues preventing the headless-browser-tool MCP server from working with Claude Code when using HTTP transport.

Problem

Claude Code was unable to recognize or use any of the 47 browser automation tools provided by this MCP server. The connection would establish but tools would not appear in Claude Code's interface.

Root Causes Identified

  1. Input Schema Validation: Claude Code requires all tools to have a valid inputSchema object, but tools without parameters were returning null
  2. FastMCP Transport Issues: The server was using FastMCP middleware that wasn't compatible with Claude Code's HTTP transport expectations
  3. Missing Direct MCP Endpoint: Claude Code expected a POST /mcp endpoint for JSON-RPC communication
  4. Session Management: The strict session middleware was rejecting MCP requests without session IDs

Changes Made

1. Fixed Input Schema Issue

  • Added fallback to return empty object schema { type: 'object', properties: {}, required: [] } for tools without parameters
  • This fixed validation errors for 14 tools that had null inputSchema

2. Implemented Direct MCP Protocol Handler

  • Removed dependency on FastMCP transport layer
  • Added direct POST /mcp endpoint that handles:
    • initialize - Returns server capabilities and protocol version
    • tools/list - Returns all 47 tools with proper schemas
    • tools/call - Executes tools with proper session context
    • notifications/initialized - Acknowledges client initialization

3. Fixed Tool Naming

  • Removed tool name prefixing that was causing issues
  • Tools now use simple names like "visit" instead of "mcp__headless_browser__visit"

4. Updated Session Middleware

  • Modified to auto-generate session IDs for MCP requests
  • Prevents "session required" errors for Claude Code connections

Testing

Added test_mcp_connection.rb script to verify:

  • Server responds correctly to all MCP protocol methods
  • All 47 tools are returned with valid schemas
  • Tool execution works with proper session context

Result

Claude Code now successfully:

  • Connects to the MCP server
  • Recognizes all 47 browser automation tools
  • Can execute tools to control the headless browser

This enables Claude Code users to automate web interactions through natural language commands.

keithschacht and others added 2 commits July 31, 2025 13:32
- Removed FastMCP dependency and custom transport layer
- Implemented direct MCP protocol handler at /mcp endpoint
- Fixed tool namespacing to use mcp__headless_browser__ prefix
- Updated SessionMiddleware to auto-generate session IDs for MCP requests
- Added test script to verify MCP protocol compliance
- Server now correctly responds to initialize, tools/list, and tools/call

The server returns all 47 browser automation tools with proper namespacing
and handles the full MCP protocol as expected by Claude Code.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This is not relevant to the MCP server fix
]
# Auto-generate a session ID for clients that don't provide one
session_id = "auto-#{SecureRandom.hex(8)}"
env["HTTP_X_SESSION_ID"] = session_id
Copy link
Author

Choose a reason for hiding this comment

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

Original behavior: The strict_session_middleware would return a 400 error if an MCP request didn't have an X-Session-ID header.

Problem: Claude Code doesn't send X-Session-ID headers with its MCP requests. It expects the server to handle session management internally.

The fix: Instead of rejecting MCP requests without session IDs, I made it auto-generate a session ID. This allows Claude Code to connect without needing to manage
sessions itself.

Without this change, Claude Code would get a 400 error when trying to connect to the MCP server. The auto-generated session ensures each Claude Code connection gets its
own browser session automatically.

end
end

# MCP endpoint for Claude Code
Copy link
Author

Choose a reason for hiding this comment

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

  • FastMCP's transport layer wasn't working properly with Claude Code's HTTP requests
  • I replaced it with a simpler, direct implementation that handles the MCP protocol manually
  • Removing unused requires keeps the code cleaner

@keithschacht
Copy link
Author

@parruda I'm am using headless-browser-tool in a new project. Thanks for creating this ruby implementation. I want to do some experimental extension and it'll be much nicer to work in ruby rather than using playwright.

However, during my development I want to use the MCP in HTTP mode and I found it didn't work. Claude and I collaborated to introduce this fix. Is it worth merging into main? Let me know. I tried to keep the scope of it limited just to address the issue I was running into.

This is the core fix - tools without parameters must return an empty object schema
instead of null to satisfy Claude Code's validation requirements
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