[UPDATE PRIMITIVE] Normalize camelCase params to kebab-case with actionable error messages for CLI tools#224
Conversation
…ept camelCase aliases Add parameter normalization layer (buildEnhancedToolSchema) that: - Silently normalizes camelCase/snake_case keys to kebab-case equivalents (e.g. sourceRoot → source-root) - Rejects truly unknown properties with the property name in the error and a "did you mean?" suggestion when a close match exists - Applies to all 16+ CLI tools that use kebab-case parameter names Closes #208 (Area 2) Agent-Logs-Url: https://github.com/advanced-security/codeql-development-mcp-server/sessions/5ed1c1a7-10c5-4e53-8454-128d1d6e46ae Co-authored-by: data-douser <70299490+data-douser@users.noreply.github.com>
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Snapshot WarningsEnsure that dependencies are being submitted on PR branches and consider enabling retry-on-snapshot-warnings. See the documentation for more information and troubleshooting advice. Scanned FilesNone |
…ration and resolve_queries parameter name (#225) * fix: use registerTool() instead of deprecated tool() to fix ZodEffects schema rejection by MCP SDK The MCP SDK's tool() method argument parsing rejects ZodEffects schemas (from buildEnhancedToolSchema) as 'unrecognized objects' because its isZodRawShapeCompat() check returns false for Zod schema instances. registerTool() passes inputSchema directly to getZodSchemaObject(), which correctly recognises any Zod schema instance, avoiding the error: 'Tool codeql_bqrs_decode expected a Zod schema or ToolAnnotations, but received an unrecognized object' Agent-Logs-Url: https://github.com/advanced-security/codeql-development-mcp-server/sessions/ba14c9e0-173d-49fd-820b-b77bfdd973b0 Co-authored-by: data-douser <70299490+data-douser@users.noreply.github.com> * fix: use correct parameter name 'directory' instead of 'path' for codeql_resolve_queries integration test The codeql_resolve_queries tool schema defines 'directory' as the parameter for specifying the directory to search for queries, but the integration test runner was sending 'path' which was rejected as an unknown property by the parameter normalization layer. Agent-Logs-Url: https://github.com/advanced-security/codeql-development-mcp-server/sessions/ba14c9e0-173d-49fd-820b-b77bfdd973b0 Co-authored-by: data-douser <70299490+data-douser@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: data-douser <70299490+data-douser@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR improves MCP CLI tool usability by wrapping all CLI tool input schemas with a normalization/validation layer, so callers can use camelCase/snake_case variants of kebab-case parameters and receive more actionable validation errors.
Changes:
- Added
buildEnhancedToolSchema()and related helpers to normalize parameter keys and improve unknown-key errors. - Switched
registerCLIToolfromserver.tool()toserver.registerTool()so pre-builtZodEffectsschemas can be used. - Updated and added unit tests to cover schema wrapping and tool registration behavior.
Show a summary per file
| File | Description |
|---|---|
| server/src/lib/cli-tool-registry.ts | Wrapes CLI tool input schemas with the enhanced normalization schema and registers CLI tools via registerTool(). |
| server/src/lib/param-normalization.ts | Introduces case conversion, suggestion logic, and the enhanced Zod schema wrapper used by CLI tools. |
| server/test/src/lib/cli-tool-registry.test.ts | Updates CLI tool registry tests for registerTool() and the new wrapped schema type. |
| server/test/src/lib/param-normalization.test.ts | Adds unit tests for key normalization and schema behavior. |
| server/test/src/tools/codeql-tools.test.ts | Updates registration assertions to account for both tool() and registerTool() usage. |
| server/dist/codeql-development-mcp-server.js | Rebuilt bundle reflecting the new normalization module and registration changes. |
| client/src/lib/integration-test-runner.js | Adjusts codeql_resolve_queries test param name (directory), unrelated to server-side schema normalization. |
Copilot's findings
Comments suppressed due to low confidence (1)
server/src/lib/param-normalization.ts:96
- The collision checks use the
inoperator (suggestion in data/suggestion in normalized), which also considers properties on the prototype chain. This can mis-detect keys liketoString/constructoras already present and prevent expected normalization. UsingObject.hasOwn(data, suggestion)/Object.hasOwn(normalized, suggestion)(or creatingnormalizedwithObject.create(null)) avoids prototype-chain surprises and reduces prototype-pollution footguns.
// Try to find a kebab-case equivalent
const suggestion = suggestPropertyName(key, knownKeys);
if (suggestion && !(suggestion in data) && !(suggestion in normalized)) {
// Silently normalize to the canonical kebab-case key
normalized[suggestion] = value;
} else if (suggestion && (suggestion in data || suggestion in normalized)) {
// Both forms provided — prefer the canonical (kebab-case) key,
// silently ignore the alias
} else {
- Files reviewed: 6/8 changed files
- Comments generated: 2
…hints The hint is now stored at determination time rather than re-computed in the error loop (where it was always undefined). When both kebab-case and camelCase forms are provided (e.g. source-root + sourceRoot), the duplicate is now rejected with a "did you mean?" suggestion instead of being silently ignored. Agent-Logs-Url: https://github.com/advanced-security/codeql-development-mcp-server/sessions/02a09bd4-39e4-4e83-968e-8562405a9f4c Co-authored-by: data-douser <70299490+data-douser@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR improves usability of CLI-registered MCP tools by normalizing common JSON key styles (camelCase/snake_case) to the kebab-case parameter names used by CodeQL CLI flags, and by emitting more actionable “unknown property” validation errors.
Changes:
- Added
buildEnhancedToolSchema()(plus helpers) to normalize key variants and produce “did you mean?” messages. - Updated
registerCLIToolto wrap tool schemas with the enhanced schema and to register CLI tools viaserver.registerTool(). - Added/updated unit tests to cover normalization behavior and updated tool-registration tests accordingly.
Show a summary per file
| File | Description |
|---|---|
| server/src/lib/param-normalization.ts | Implements key normalization + unknown-property reporting via a Zod transform wrapper. |
| server/src/lib/cli-tool-registry.ts | Wraps CLI tool schemas with buildEnhancedToolSchema and switches CLI tool registration to registerTool(). |
| server/test/src/lib/param-normalization.test.ts | Adds coverage for normalization, unknown keys, duplicates, and type validation. |
| server/test/src/lib/cli-tool-registry.test.ts | Updates mocks/expectations for registerTool() and the wrapped schema. |
| server/test/src/tools/codeql-tools.test.ts | Updates tool registration test to account for both tool() and registerTool() usage. |
| server/dist/codeql-development-mcp-server.js | Rebuilt bundle reflecting the new normalization + registration behavior. |
| client/src/lib/integration-test-runner.js | Adjusts integration test runner params for codeql_resolve_queries (uses directory). |
Copilot's findings
- Files reviewed: 6/8 changed files
- Comments generated: 4
There was a problem hiding this comment.
Pull request overview
This PR improves usability of CLI-registered MCP tools by normalizing common parameter key variants (camelCase/snake_case) to the canonical tool schema keys (typically kebab-case) and emitting more actionable unknown-property errors, applied centrally via registerCLITool.
Changes:
- Added
buildEnhancedToolSchema()+ related helpers to normalize parameter keys and provide “did you mean?” error messages. - Updated
registerCLIToolto wrap schemas with the enhanced normalization layer and register CLI tools viaserver.registerTool(...). - Updated/added unit tests to validate normalization behavior and updated tool registration expectations.
Show a summary per file
| File | Description |
|---|---|
| server/src/lib/param-normalization.ts | Adds normalization + suggestion logic and a schema wrapper that rejects unknown keys with clearer messages. |
| server/src/lib/cli-tool-registry.ts | Applies enhanced schema wrapping for all CLI tools and switches CLI tool registration to registerTool. |
| server/test/src/lib/param-normalization.test.ts | Adds unit tests covering conversions, suggestions, normalization, duplicates, and unknown properties. |
| server/test/src/lib/cli-tool-registry.test.ts | Updates mocks/assertions to reflect registerTool registration and enhanced schema behavior. |
| server/test/src/tools/codeql-tools.test.ts | Updates tool registration test to account for both tool() and registerTool() usage. |
| server/dist/codeql-development-mcp-server.js | Rebuilt bundle reflecting the new normalization module and registerTool usage. |
| client/src/lib/integration-test-runner.js | Adjusts integration test runner params for codeql_resolve_queries to use directory. |
Copilot's findings
- Files reviewed: 6/8 changed files
- Comments generated: 1
📝 Update Information
Primitive Details
registerCLITool— affectscodeql_database_createand 15+ other CLI tools with kebab-case params✅ ALLOWED FILES:
server/src/**/*.ts)server/src/lib/*.ts)server/test/**/*.ts)🚫 FORBIDDEN FILES: None included.
🛑 MANDATORY PR VALIDATION CHECKLIST
registerCLIToolUpdate Metadata
🎯 Changes Description
Current Behavior
CLI tools reject camelCase keys (e.g.
sourceRoot) with a generic error from JSON Schema validation:No property name is mentioned. LLMs default to camelCase, causing frequent first-invocation failures.
Updated Behavior
The schema layer now normalizes variant key formats before validation:
sourceRoot→source-root✅ silently acceptedsource_root→source-root✅ silently acceptedfooBar→unknown property 'fooBar'with "did you mean?" when a close match existsMotivation
LLM agents commonly emit camelCase JSON keys. 16+ CLI tools use kebab-case parameter names (mirroring
codeqlCLI flags), making this the most frequent tool invocation failure.🔄 Before vs. After Comparison
Functionality Changes
API Changes
No schema changes to individual tools. The enhancement is applied centrally in
registerCLITool.Output Format Changes
🧪 Testing & Validation
Test Coverage Updates
Validation Scenarios
sourceRoot), snake_case (source_root) normalize to kebab-casesource-rootandsourceRootprovided, kebab-case winsTest Results
📋 Implementation Details
Files Modified
server/src/lib/param-normalization.ts—camelToKebabCase,kebabToCamelCase,suggestPropertyName,buildEnhancedToolSchemaserver/src/lib/cli-tool-registry.ts— import + usebuildEnhancedToolSchemainregisterCLIToolserver/test/src/lib/param-normalization.test.ts— 31 testsserver/test/src/lib/cli-tool-registry.test.ts— 2 assertions updated forZodEffectstypeserver/dist/— rebuiltCode Changes Summary
z.object().passthrough().transform()Dependencies
zodAPI (passthrough,transform,ZodIssueCode.custom)🔍 Quality Improvements
Bug Fixes (if applicable)
additionalProperties: falsefrom defaultz.object()— no key normalizationpassthrough+transformlayer normalizes variants, rejects unknowns with namesregisterCLIToolCode Quality Enhancements
param-normalization.tsmodule with clear JSDocsuggestPropertyNameusable beyond CLI tools🔗 References
Related Issues/PRs
database_createuses kebab-case params with unhelpful rejection message)🚀 Compatibility & Migration
Backward Compatibility
API Evolution
👥 Review Guidelines
For Reviewers
Testing Instructions
📊 Impact Assessment
Server Impact
AI Assistant Impact