MCPcopy Create free account
hub / github.com/github/gh-aw / argumentValidationMiddleware

Function argumentValidationMiddleware

pkg/cli/mcp_argument_validation.go:41–94  ·  view source on GitHub ↗

argumentValidationMiddleware returns a mcp.Middleware that intercepts tool-call results containing "unexpected additional properties" validation errors and replaces them with a helpful message that names the unknown parameter, suggests a close match, and points to the tool's --help output. toolPara

(toolParams map[string]toolParamEntry)

Source from the content-addressed store, hash-verified

39// toolParams maps tool names to their list of valid JSON parameter names. It is
40// provided by the caller as a hardcoded registry (see mcpToolParams).
41func argumentValidationMiddleware(toolParams map[string]toolParamEntry) mcp.Middleware {
42 return func(next mcp.MethodHandler) mcp.MethodHandler {
43 return func(ctx context.Context, method string, req mcp.Request) (mcp.Result, error) {
44 result, err := next(ctx, method, req)
45 if err != nil || method != "tools/call" {
46 return result, err
47 }
48
49 // Check whether the result is a tool error containing a schema
50 // "additional properties" validation message.
51 toolResult, ok := result.(*mcp.CallToolResult)
52 if !ok || !toolResult.IsError {
53 return result, err
54 }
55
56 // Extract the error text from the first TextContent element.
57 if len(toolResult.Content) == 0 {
58 return result, err
59 }
60 textContent, ok := toolResult.Content[0].(*mcp.TextContent)
61 if !ok {
62 return result, err
63 }
64 errMsg := textContent.Text
65
66 if !strings.Contains(errMsg, "unexpected additional properties") {
67 return result, err
68 }
69
70 // Parse the unknown parameter names from the error text.
71 unknownParams := extractUnknownParams(errMsg)
72 if len(unknownParams) == 0 {
73 return result, err
74 }
75
76 // Determine the tool name from the request so we can look up valid params.
77 toolName := extractMCPToolName(req)
78 validParams, ok := toolParams[toolName]
79 if !ok {
80 return nil, newMCPError(jsonrpc.CodeMethodNotFound, fmt.Sprintf("unknown MCP tool: %q", toolName), nil)
81 }
82
83 mcpArgValidationLog.Printf("Intercepted unknown param error: tool=%s, unknown_params=%v", toolName, unknownParams)
84
85 // Build a helpful replacement message.
86 helpMsg := buildHelpfulParamError(toolName, unknownParams, validParams)
87
88 // Return a modified tool result with the helpful message, preserving IsError.
89 replaced := *toolResult
90 replaced.Content = []mcp.Content{&mcp.TextContent{Text: helpMsg}}
91 return &replaced, nil
92 }
93 }
94}
95
96// extractMCPToolName retrieves the tool name from a MCP Request by casting the
97// request params to *mcp.CallToolParamsRaw. Returns an empty string if the cast

Calls 5

extractUnknownParamsFunction · 0.85
extractMCPToolNameFunction · 0.85
newMCPErrorFunction · 0.85
buildHelpfulParamErrorFunction · 0.85
PrintfMethod · 0.45