Request Normalizer
Overview
Section titled “Overview”The Request Normalizer is a data-driven engine that sits between the MCP transport layer and tool handlers. It automatically corrects parameter mismatches that occur when AI clients (Claude Desktop, Claude Code) send parameters with wrong names, wrong types, or unexpected formats.
Introduced in v4.0.2 to address recurring patterns documented in Bug #22.
How It Works
Section titled “How It Works”- MCP request arrives with tool name and arguments
- Normalizer looks up applicable rules (tool-specific + wildcard)
- Each matching rule is applied in order
- Corrected arguments are passed to the tool handler
- Applied normalizations are recorded in the audit log
All normalization happens transparently — the tool handler receives clean arguments without knowing corrections were made.
Rule Types
Section titled “Rule Types”The normalizer supports 6 rule types:
| Type | Description | Example |
|---|---|---|
param_alias | Rename a top-level parameter | old_str → old_text |
param_default | Set a default value if parameter is missing | Missing id → auto-generated |
type_coerce | Convert a string value to the correct type | "true" → true (bool) |
json_accept_both | Accept a parameter as raw JSON or string | [{...}] or "[{...}]" both work |
nested_alias | Rename a field inside a JSON payload | Step type → action |
nested_default | Set default for missing field inside JSON array items | Step missing id → step-0, step-1, etc. |
Built-in Rules (14)
Section titled “Built-in Rules (14)”Parameter Aliases
Section titled “Parameter Aliases”| Rule ID | Tool | From | To |
|---|---|---|---|
edit-old_str | edit_file | old_str | old_text |
edit-new_str | edit_file | new_str | new_text |
Claude Desktop sometimes sends old_str/new_str instead of the expected old_text/new_text.
Boolean Coercions
Section titled “Boolean Coercions”| Rule ID | Tools | Parameter |
|---|---|---|
force-bool-coerce | All (*) | force |
dry_run-bool-coerce | All (*) | dry_run |
count_only-bool-coerce | search_files | count_only |
permanent-bool-coerce | delete_file | permanent |
whole_word-bool-coerce | edit_file, search_files | whole_word |
case_sensitive-bool-coerce | search_files, edit_file | case_sensitive |
include_content-bool-coerce | search_files | include_content |
include_context-bool-coerce | search_files | include_context |
recursive-bool-coerce | list_directory, search_files | recursive |
MCP transport delivers all values as strings. These rules convert "true"/"false"/"1"/"0" to native boolean values.
JSON Payload
Section titled “JSON Payload”| Rule ID | Tool | Description |
|---|---|---|
multi_edit-edits-coerce | multi_edit | Accept edits_json as raw JSON array or string |
pipeline-type-alias | batch_operations | Rename type → action inside pipeline steps |
pipeline-auto-id | batch_operations | Auto-generate step-0, step-1, etc. for steps missing id |
Custom Rules
Section titled “Custom Rules”Add custom rules via --normalizer-rules rules.json:
[ { "id": "my-custom-alias", "tools": ["read_file"], "type": "param_alias", "from": "filename", "to": "path" }, { "id": "my-default-encoding", "tools": ["read_file"], "type": "param_default", "from": "encoding", "value": "utf-8" }]External rules are merged after built-in rules. Both sets apply to every request.
Rule Schema
Section titled “Rule Schema”{ "id": "string (required, unique)", "tools": ["tool_name", ...], "type": "param_alias | param_default | type_coerce | json_accept_both | nested_alias | nested_default", "from": "source parameter name", "to": "target parameter name (alias types)", "coerce_to": "bool | int | float (type_coerce only)", "in_payload": "JSON payload param name (nested_* types)", "array_path": "array path: '[]' or 'steps[]' (nested_* types)", "value": "default value, supports '{{index}}' template (param_default, nested_default)"}Use "tools": ["*"] to apply a rule to all tools.
Statistics
Section titled “Statistics”When --log-dir is set, the normalizer writes normalizer_stats.json with:
{ "total_processed": 5000, "total_normalized": 1200, "last_updated": "2026-03-16T10:30:00Z", "by_tool": { "edit_file": { "processed": 800, "normalized": 350 }, "search_files": { "processed": 1200, "normalized": 400 } }, "by_rule": { "force-bool-coerce": { "rule_id": "force-bool-coerce", "type": "type_coerce", "hits": 500, "tools": ["edit_file", "delete_file"] }, "edit-old_str": { "rule_id": "edit-old_str", "type": "param_alias", "hits": 200, "tools": ["edit_file"] } }, "recent_normalizations": [ { "ts": "2026-03-16T10:29:55Z", "tool": "edit_file", "applied": [ { "rule_id": "edit-old_str", "type": "param_alias", "param": "old_str", "from": "old_str", "to": "old_text" } ] } ]}These statistics are also visible in the Dashboard Normalizer page.
Audit Integration
Section titled “Audit Integration”When a normalization is applied, it appears in the audit log entry:
{ "ts": "2026-03-16T10:29:55Z", "tool": "edit_file", "status": "ok", "duration_ms": 12, "norms": [ { "rule_id": "edit-old_str", "type": "param_alias", "param": "old_str", "from": "old_str", "to": "old_text" }, { "rule_id": "force-bool-coerce", "type": "type_coerce", "param": "force", "from": "\"true\"", "to": "true" } ]}This allows tracking which rules fire and how often, useful for identifying patterns in client behavior.
Configuration
Section titled “Configuration”{ "mcpServers": { "filesystem-ultra": { "command": "C:\\path\\to\\filesystem-ultra-v4.exe", "args": [ "--normalizer-rules", "C:\\config\\normalizer-rules.json", "--log-dir", "C:\\Logs\\MCP", "C:\\project" ] } }}| Flag | Description |
|---|---|
--normalizer-rules | Path to external rules JSON file (optional) |
--log-dir | Enables normalizer stats persistence (optional) |
The normalizer is always active with its 14 built-in rules. No flag is needed to enable it.
See Also
Section titled “See Also”- Bug #22: Parameter Normalization — The patterns that led to the normalizer
- Dashboard & Monitoring — Normalizer stats in the web UI
- Configuration — CLI flags reference
Last updated: March 2026 Version: 4.1.0