Fix MCP server to work with Claude Code#1
Conversation
- 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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
- 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
|
@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
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
inputSchemaobject, but tools without parameters were returningnull/mcpendpoint for JSON-RPC communicationChanges Made
1. Fixed Input Schema Issue
{ type: 'object', properties: {}, required: [] }for tools without parametersnullinputSchema2. Implemented Direct MCP Protocol Handler
/mcpendpoint that handles:initialize- Returns server capabilities and protocol versiontools/list- Returns all 47 tools with proper schemastools/call- Executes tools with proper session contextnotifications/initialized- Acknowledges client initialization3. Fixed Tool Naming
4. Updated Session Middleware
Testing
Added
test_mcp_connection.rbscript to verify:Result
Claude Code now successfully:
This enables Claude Code users to automate web interactions through natural language commands.