WithMCPParse creates a middleware that parses MCP JSON-RPC requests early in the request lifecycle and stores the parsed information in the request context. This enables: - Registry filtering via ForMCPRequest (only register needed tools/resources/prompts) - Avoiding duplicate JSON parsing in downst
()
| 35 | // The middleware reads the request body, parses it, restores the body for downstream |
| 36 | // handlers, and stores the parsed MCPMethodInfo in the request context. |
| 37 | func WithMCPParse() func(http.Handler) http.Handler { |
| 38 | return func(next http.Handler) http.Handler { |
| 39 | fn := func(w http.ResponseWriter, r *http.Request) { |
| 40 | ctx := r.Context() |
| 41 | |
| 42 | // Skip health check endpoints |
| 43 | if r.URL.Path == "/_ping" { |
| 44 | next.ServeHTTP(w, r) |
| 45 | return |
| 46 | } |
| 47 | |
| 48 | // Only parse POST requests (MCP uses JSON-RPC over POST) |
| 49 | if r.Method != http.MethodPost { |
| 50 | next.ServeHTTP(w, r) |
| 51 | return |
| 52 | } |
| 53 | |
| 54 | // Read the request body |
| 55 | body, err := io.ReadAll(r.Body) |
| 56 | if err != nil { |
| 57 | // Log but continue - don't block requests on parse errors |
| 58 | next.ServeHTTP(w, r) |
| 59 | return |
| 60 | } |
| 61 | |
| 62 | // Restore the body for downstream handlers |
| 63 | r.Body = io.NopCloser(bytes.NewReader(body)) |
| 64 | |
| 65 | // Skip empty bodies |
| 66 | if len(body) == 0 { |
| 67 | next.ServeHTTP(w, r) |
| 68 | return |
| 69 | } |
| 70 | |
| 71 | // Parse the JSON-RPC request |
| 72 | var mcpReq mcpJSONRPCRequest |
| 73 | err = json.Unmarshal(body, &mcpReq) |
| 74 | if err != nil { |
| 75 | // Log but continue - could be a non-MCP request or malformed JSON |
| 76 | next.ServeHTTP(w, r) |
| 77 | return |
| 78 | } |
| 79 | |
| 80 | // Skip if not a valid JSON-RPC 2.0 request |
| 81 | if mcpReq.JSONRPC != "2.0" || mcpReq.Method == "" { |
| 82 | next.ServeHTTP(w, r) |
| 83 | return |
| 84 | } |
| 85 | |
| 86 | // Build the MCPMethodInfo |
| 87 | methodInfo := &ghcontext.MCPMethodInfo{ |
| 88 | Method: mcpReq.Method, |
| 89 | } |
| 90 | |
| 91 | // Extract item name based on method type |
| 92 | |
| 93 | switch mcpReq.Method { |
| 94 | case "tools/call": |