Skip to content

Commit 5b20b1b

Browse files
authored
[log] Add debug logging to MCP types schema normalization (#606)
## Summary Enhanced `internal/mcp/types.go` with debug logging to improve troubleshooting of MCP tool schema normalization. ## Changes Made Added debug logger declaration and 7 strategic logging calls to the `NormalizeInputSchema` function: 1. **Function entry logging** - Logs when schema normalization starts for a tool 2. **Nil schema detection** - Logs when a backend provides no input schema 3. **Type field analysis** - Logs schema structure (presence of type field) 4. **Missing type handling** - Logs when schema lacks type field and properties status 5. **Type normalization** - Logs when object type is added to schema 6. **Non-object type handling** - Logs when schema has non-object or invalid type 7. **Properties validation** - Logs object schema structure (properties and additionalProperties) 8. **Properties normalization** - Logs when empty properties are added 9. **Valid schema confirmation** - Logs when no normalization is needed ## Benefits - Easier debugging of schema validation issues from backend MCP servers - Visibility into which normalizations are applied and why - Better understanding of tool registration flow - No side effects in log arguments (all values already computed) ## Testing - Added logger following project convention: `var log = logger.New("mcp:types")` - All logging statements use parameters already available in scope - No expensive computations in log arguments - Preserved existing file logger warnings for operational visibility ## Quality Checklist - ✅ Exactly 1 file modified (focused, single-file PR) - ✅ No test files modified - ✅ Logger naming follows `pkg:filename` convention (`mcp:types`) - ✅ Logger arguments don't compute anything or cause side effects - ✅ Logging messages are meaningful and helpful for debugging - ✅ No duplicate logging with existing logs - ✅ Import statements properly ordered - ✅ Preserved all existing file logger calls for operational logging ## Example Debug Output With `DEBUG=mcp:*`, developers will see: ``````` mcp:types Normalizing input schema for tool: github-search mcp:types Tool github-search schema analysis: hasType=true mcp:types Tool github-search object type schema: hasProperties=true, hasAdditionalProperties=false mcp:types Tool github-search schema is valid, no normalization needed `````` Or when normalization is needed: `````` mcp:types Normalizing input schema for tool: legacy-tool mcp:types Tool legacy-tool has nil schema, applying default empty object schema ``````` > AI generated by [Go Logger Enhancement](https://github.com/github/gh-aw-mcpg/actions/runs/21629700132) <!-- gh-aw-workflow-id: go-logger -->
2 parents 0241ffe + 850811e commit 5b20b1b

1 file changed

Lines changed: 16 additions & 0 deletions

File tree

internal/mcp/types.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"github.com/github/gh-aw-mcpg/internal/logger"
77
)
88

9+
var log = logger.New("mcp:types")
10+
911
// Request represents a JSON-RPC 2.0 request
1012
type Request struct {
1113
JSONRPC string `json:"jsonrpc"`
@@ -59,9 +61,12 @@ type ContentItem struct {
5961
// but is missing the required "properties" field, we add an empty properties
6062
// object to make it valid per JSON Schema standards.
6163
func NormalizeInputSchema(schema map[string]interface{}, toolName string) map[string]interface{} {
64+
log.Printf("Normalizing input schema for tool: %s", toolName)
65+
6266
// If backend didn't provide a schema, use a default empty object schema
6367
// This allows the tool to be registered and clients will see it accepts any parameters
6468
if schema == nil {
69+
log.Printf("Tool %s has nil schema, applying default empty object schema", toolName)
6570
logger.LogWarn("backend", "Tool schema normalized: %s - backend provided no inputSchema, using default empty object schema", toolName)
6671
return map[string]interface{}{
6772
"type": "object",
@@ -72,10 +77,13 @@ func NormalizeInputSchema(schema map[string]interface{}, toolName string) map[st
7277
// Check if this is an object type schema
7378
typeVal, hasType := schema["type"]
7479

80+
log.Printf("Tool %s schema analysis: hasType=%v", toolName, hasType)
81+
7582
// If schema has no type but has properties, it's implicitly an object type
7683
// The MCP SDK requires "type": "object" to be present, so add it
7784
if !hasType {
7885
_, hasProperties := schema["properties"]
86+
log.Printf("Tool %s has no type field, hasProperties=%v", toolName, hasProperties)
7987
if hasProperties {
8088
logger.LogWarn("backend", "Tool schema normalized: %s - added 'type': 'object' to schema with properties", toolName)
8189
// Create a copy of the schema to avoid modifying the original
@@ -84,9 +92,11 @@ func NormalizeInputSchema(schema map[string]interface{}, toolName string) map[st
8492
normalized[k] = v
8593
}
8694
normalized["type"] = "object"
95+
log.Printf("Tool %s schema normalized: added object type", toolName)
8796
return normalized
8897
}
8998
// Schema without type and without properties - assume it's an empty object schema
99+
log.Printf("Tool %s has no type and no properties, using empty object schema", toolName)
90100
logger.LogWarn("backend", "Tool schema normalized: %s - schema missing type, assuming empty object schema", toolName)
91101
return map[string]interface{}{
92102
"type": "object",
@@ -96,13 +106,17 @@ func NormalizeInputSchema(schema map[string]interface{}, toolName string) map[st
96106

97107
typeStr, isString := typeVal.(string)
98108
if !isString || typeStr != "object" {
109+
log.Printf("Tool %s has non-object type or invalid type value, returning schema as-is", toolName)
99110
return schema
100111
}
101112

102113
// Check if properties field exists
103114
_, hasProperties := schema["properties"]
104115
_, hasAdditionalProperties := schema["additionalProperties"]
105116

117+
log.Printf("Tool %s object type schema: hasProperties=%v, hasAdditionalProperties=%v",
118+
toolName, hasProperties, hasAdditionalProperties)
119+
106120
// If it's an object type but missing both properties and additionalProperties,
107121
// add an empty properties object to make it valid
108122
if !hasProperties && !hasAdditionalProperties {
@@ -115,8 +129,10 @@ func NormalizeInputSchema(schema map[string]interface{}, toolName string) map[st
115129
}
116130
normalized["properties"] = map[string]interface{}{}
117131

132+
log.Printf("Tool %s schema normalized: added empty properties field", toolName)
118133
return normalized
119134
}
120135

136+
log.Printf("Tool %s schema is valid, no normalization needed", toolName)
121137
return schema
122138
}

0 commit comments

Comments
 (0)