{"record":{"id":"0e9e9fa2edefcab0","repo":"siyuan-note/siyuan","slug":"property-q-x-mcp-header-must-be-a-non-empty-stri","errorCode":null,"errorMessage":"property %q: x-mcp-header must be a non-empty string","messagePattern":"property %q: x-mcp-header must be a non-empty string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/mcp/tools/validation.go","lineNumber":241,"sourceCode":"\t\treturn nil\n\t}\n\tproperties, _ := root[\"properties\"].(map[string]any)\n\tseen := map[string]bool{}\n\tvar walk func(map[string]any, string) error\n\twalk = func(props map[string]any, prefix string) error {\n\t\tfor propertyName, rawProperty := range props {\n\t\t\tproperty, ok := rawProperty.(map[string]any)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath := propertyName\n\t\t\tif prefix != \"\" {\n\t\t\t\tpath = prefix + \".\" + propertyName\n\t\t\t}\n\t\t\tif rawHeader, exists := property[\"x-mcp-header\"]; exists {\n\t\t\t\theader, ok := rawHeader.(string)\n\t\t\t\tif !ok || header == \"\" {\n\t\t\t\t\treturn fmt.Errorf(`property %q: x-mcp-header must be a non-empty string`, path)\n\t\t\t\t}\n\t\t\t\tpropertyType, _ := property[\"type\"].(string)\n\t\t\t\tif propertyType != \"string\" && propertyType != \"integer\" && propertyType != \"boolean\" {\n\t\t\t\t\treturn fmt.Errorf(\n\t\t\t\t\t\t`property %q: x-mcp-header can only be applied to primitive types (integer, string, boolean), got %q`,\n\t\t\t\t\t\tpath, propertyType)\n\t\t\t\t}\n\t\t\t\tif !validHTTPFieldName(header) {\n\t\t\t\t\treturn fmt.Errorf(`property %q: x-mcp-header value %q is not a valid HTTP field name`, path, header)\n\t\t\t\t}\n\t\t\t\tnormalized := strings.ToLower(header)\n\t\t\t\tif seen[normalized] {\n\t\t\t\t\treturn fmt.Errorf(`property %q: duplicate x-mcp-header value %q`, path, header)\n\t\t\t\t}\n\t\t\t\tseen[normalized] = true\n\t\t\t}\n\t\t\tnested, _ := property[\"properties\"].(map[string]any)\n\t\t\tif err := walk(nested, path); err != nil {","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/mcp/tools/validation.go#L223-L259","documentation":"Thrown by validateParamHeaderAnnotations while walking input-schema properties: a property declares the x-mcp-header annotation but its value is not a string or is the empty string. The annotation marks a property whose value should be bound to an HTTP request header when the tool is backed by an HTTP request, so it must name a concrete header.","triggerScenarios":"Registering a tool whose input schema has a property like {\"x-mcp-header\": 123} or {\"x-mcp-header\": \"\"}. The walker checks every property under the top-level properties map, including nested objects.","commonSituations":"A typo sets x-mcp-header to a non-string (number/boolean/object); a templating step leaves an empty placeholder; copy-paste of an annotation block with the header name stripped.","solutions":["Set x-mcp-header to a non-empty header name string, e.g. \"X-Request-Id\".","Remove the x-mcp-header key entirely if the property is not meant to be bound to a header.","Lint the schema before registration: every x-mcp-header must be a non-empty string."],"exampleFix":"// before\n{\"name\": {\"type\": \"string\", \"x-mcp-header\": \"\"}}\n// after\n{\"name\": {\"type\": \"string\", \"x-mcp-header\": \"X-Custom-Header\"}}","handlingStrategy":"validation","validationCode":"if h, ok := prop[\"x-mcp-header\"].(string); !ok || h == \"\" {\n    return fmt.Errorf(\"property x-mcp-header must be a non-empty string\")\n}","typeGuard":"func isNonEmptyStringHeader(prop map[string]any) bool {\n    h, ok := prop[\"x-mcp-header\"].(string)\n    return ok && h != \"\"\n}","tryCatchPattern":null,"preventionTips":["Lint tool schemas for x-mcp-header type correctness before registration.","Generate header annotations from a single source of truth rather than hand-editing.","Drop the x-mcp-header key when a property is not header-bound."],"tags":["mcp","json-schema","http-header","annotation","validation"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}