Skip to content

Commit 793dce5

Browse files
Peterclaude
andcommitted
fix: add boolean field validator for force parameter in StartPreIngestionRequest
- Added field_validator with mode='before' to handle string-to-boolean conversion - Accepts 'true', '1', 'yes', 'on' as truthy values (case-insensitive) - Follows validate_include_unchanged pattern for consistency - Fixes MCP client compatibility issue where boolean values sent as strings - Updated all living memory documentation files with solution details 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 6736050 commit 793dce5

File tree

8 files changed

+101
-12
lines changed

8 files changed

+101
-12
lines changed

Architecture.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2915,6 +2915,7 @@ graph TB
29152915
VERSION_VAL[validate_version_string()<br/>SemVer + latest support]
29162916
PATH_VAL[validate_rust_path()<br/>Module path validation]
29172917
INT_BOUNDS[coerce_to_int_with_bounds()<br/>Type coercion + constraints]
2918+
BOOL_VAL[Boolean field validation pattern<br/>field_validator(mode='before')<br/>Truthy strings: 'true', '1', 'yes', 'on']
29182919
OPT_PATH[validate_optional_path()<br/>None-safe path validation]
29192920
end
29202921
@@ -2939,6 +2940,7 @@ graph TB
29392940
VERSION_VAL --> FIELD_VAL
29402941
PATH_VAL --> FIELD_VAL
29412942
INT_BOUNDS --> FIELD_VAL
2943+
BOOL_VAL --> FIELD_VAL
29422944
OPT_PATH --> FIELD_VAL
29432945
29442946
FIELD_VAL --> SEARCH_REQ
@@ -3089,6 +3091,13 @@ The `validation.py` module provides centralized validation utilities with perfor
30893091
- Applies path validation only when path is not None
30903092
- Used for optional module path parameters
30913093

3094+
**Boolean Field Validation Pattern (@field_validator(mode='before'))**
3095+
- Standardized pattern for all boolean parameters in MCP request models
3096+
- Accepts boolean types directly and converts string representations to boolean
3097+
- Truthy string values: `'true'`, `'1'`, `'yes'`, `'on'` (case-insensitive)
3098+
- Follows `validate_include_unchanged` implementation for consistency
3099+
- Required for MCP client compatibility when clients send boolean parameters as strings
3100+
30923101
#### Performance Optimizations
30933102

30943103
```python
@@ -3143,6 +3152,42 @@ def coerce_deprecated_to_bool(cls, v):
31433152
return bool(v)
31443153
```
31453154

3155+
### Boolean Field Validation Pattern
3156+
3157+
**Standard Implementation Pattern**
3158+
3159+
All boolean fields in MCP request models require `field_validator(mode='before')` to handle string inputs from MCP clients. The system implements a standardized boolean validation pattern that ensures consistent handling across all boolean parameters:
3160+
3161+
```python
3162+
@field_validator("include_unchanged", mode="before")
3163+
@classmethod
3164+
def validate_include_unchanged(cls, v: Any) -> bool:
3165+
"""Validate and coerce include_unchanged to boolean."""
3166+
if isinstance(v, bool):
3167+
return v
3168+
if isinstance(v, str):
3169+
return v.lower() in ("true", "1", "yes", "on")
3170+
return bool(v)
3171+
```
3172+
3173+
**Truthy String Values**
3174+
- `'true'` - Standard boolean string representation
3175+
- `'1'` - Numeric boolean representation
3176+
- `'yes'` - Human-readable affirmative
3177+
- `'on'` - Toggle-style representation
3178+
3179+
**Key Design Principles**
3180+
- **MCP Client Compatibility**: Handles string inputs from MCP clients that may serialize booleans as strings
3181+
- **Case Insensitive**: Uses `.lower()` for consistent string comparison
3182+
- **Fallback Behavior**: Uses Python's `bool()` for non-string, non-boolean inputs
3183+
- **Consistency**: Follows the same pattern as `validate_include_unchanged` implementation for uniform behavior
3184+
3185+
**Architecture Integration**
3186+
- **mode='before'**: Validates and coerces input before Pydantic's built-in type validation
3187+
- **Type Safety**: Ensures boolean type consistency after validation
3188+
- **Schema Compatibility**: Works with `anyOf` patterns in MCP manifest for dual boolean/string acceptance
3189+
- **Error Handling**: Invalid string values result in `False` through `bool(v)` fallback (for permissive validation) or explicit ValueError (for strict validation)
3190+
31463191
### MCP Manifest Schema Patterns
31473192

31483193
The MCP manifest schema uses consistent `anyOf` patterns for flexible parameter acceptance across all type-flexible parameters. This architectural decision ensures uniform handling of MCP client serialization variations:

ResearchFindings.json

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,15 @@
407407
"double_validation": "FastMCP + client side",
408408
"anyof_schema": "MANDATORY pattern for flexibility"
409409
},
410+
"boolean_validation": {
411+
"requirement": "field_validator with mode='before' REQUIRED for MCP boolean parameter compatibility",
412+
"performance_pattern": "Use fast path with isinstance(v, bool) check first for performance",
413+
"accepted_strings": "Standard truthy strings: 'true', '1', 'yes', 'on' (case-insensitive)",
414+
"mcp_manifest_status": "MCP manifest anyOf patterns correctly configured, issue was only in Pydantic validation layer",
415+
"decorator_order": "field_validator must precede @classmethod decorator",
416+
"mode_purpose": "mode='before' processes raw input before Pydantic's type conversion",
417+
"default_behavior": "Return False as default for invalid/None inputs maintains consistency"
418+
},
410419
"error_handling": {
411420
"field_validators": {
412421
"decorator": "@field_validator(mode='before')",
@@ -1038,7 +1047,8 @@
10381047
"p2: Always check for None before string operations - use (value or '').lower() pattern",
10391048
"p2: Test MCP validation with actual clients, not just unit tests",
10401049
"p2: Implement defensive programming patterns for NoneType handling",
1041-
"p2: Use field validators with mode='before' for MCP client compatibility"
1050+
"p2: Use field validators with mode='before' for MCP client compatibility",
1051+
"p2: Use isinstance(v, bool) fast path in Pydantic boolean validators for MCP parameter compatibility"
10421052
],
10431053
"performance": [
10441054
"#{sqlite_vec_query} with sqlite-vec",
@@ -1097,7 +1107,10 @@
10971107
"Implement any(condition for x in items if x is not None) for safe iterations",
10981108
"Test Pydantic validators with actual MCP client data, not synthetic tests",
10991109
"Use Union[str, int, bool] parameters for MCP client type flexibility",
1100-
"Include parameter path and expected formats in validation error messages"
1110+
"Include parameter path and expected formats in validation error messages",
1111+
"Use isinstance(v, bool) fast path followed by string validation in Pydantic boolean validators",
1112+
"Accept standard truthy strings ('true', '1', 'yes', 'on') case-insensitively for MCP compatibility",
1113+
"Return False as default for invalid/None inputs in boolean validators for consistency"
11011114
],
11021115
"production": [
11031116
"Distributed rate limiting with Redis for multi-worker",

Tasks.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1477,15 +1477,20 @@
14771477
"id": "bugfix-preingestion-validation",
14781478
"title": "Fix Pre-ingestion Parameter Validation",
14791479
"description": "Debug and fix parameter validation errors in StartPreIngestionRequest that prevent pre-ingestion initialization",
1480-
"status": "pending",
1480+
"status": "completed",
14811481
"priority": "critical",
1482-
"progress": 0,
1482+
"progress": 100,
14831483
"dependencies": [],
14841484
"effort": "small",
14851485
"impact": "high",
14861486
"estimatedHours": 4,
14871487
"relatedTasks": [],
1488-
"roadblocks": []
1488+
"roadblocks": [],
1489+
"completionDetails": {
1490+
"completedAt": "2025-08-11",
1491+
"implementation": "Added field_validator for force parameter with mode='before' to handle string-to-boolean conversion",
1492+
"notes": "Added field_validator for force parameter with mode='before' to handle string-to-boolean conversion"
1493+
}
14891494
},
14901495
{
14911496
"id": "bugfix-stdlib-item-retrieval",

UsefulInformation.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"projectName": "docsrs-mcp",
3-
"lastUpdated": "2025-08-11",
3+
"lastUpdated": "2025-01-11",
44
"purpose": "Track errors, solutions, and lessons learned during development",
55
"categories": {
66
"errorSolutions": {
@@ -220,6 +220,17 @@
220220
"codeExample": "ERROR_TEMPLATES = {\n 'invalid_type': '{field} must be {expected_type}. Got: {value}. Examples: {examples}',\n 'out_of_range': '{field} must be {constraint}. Got: {value}. Examples: {examples}'\n}",
221221
"prevention": "Define error message templates at module level for consistency and reusability"
222222
},
223+
{
224+
"error": "StartPreIngestionRequest force parameter validation fails when MCP clients send boolean as string",
225+
"rootCause": "Missing field_validator for force parameter - only concurrency and count had validators",
226+
"solution": "Added @field_validator('force', mode='before') following validate_include_unchanged pattern",
227+
"context": "MCP clients often send boolean values as strings ('true'/'false') which need conversion",
228+
"implementation": "Check isinstance(bool) first for fast path, then convert strings 'true', '1', 'yes', 'on' to True",
229+
"pattern": "All boolean fields in MCP request models require field_validator with mode='before'",
230+
"dateEncountered": "2025-01-11",
231+
"relatedFiles": ["src/docsrs_mcp/models.py"],
232+
"codeExample": "@field_validator('force', mode='before')\n@classmethod\ndef validate_force(cls, v: Any) -> bool:\n if isinstance(v, bool):\n return v\n if isinstance(v, str):\n return v.lower() in ('true', '1', 'yes', 'on')\n return False"
233+
},
223234
{
224235
"error": "MCP parameter string-to-type conversion compatibility issues",
225236
"solution": "All numeric and boolean parameters must support string-to-type conversion for MCP clients using coercion functions with mode='before' validators. Handle None values first, then check existing type, then attempt string conversion with try/catch",

src/docsrs_mcp/README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,25 @@ A high-performance MCP server for querying Rust crate documentation with memory-
66

77
This module provides a Model Context Protocol (MCP) server that enables efficient ingestion and querying of Rust crate documentation. The server features memory-optimized streaming processing, adaptive batch sizing, and comprehensive memory monitoring to handle large-scale documentation processing.
88

9+
## Recent Updates
10+
11+
- **Parameter Validation Enhancement**: Fixed force parameter validation in start_pre_ingestion tool to accept string boolean values
12+
- **Field Validator Implementation**: All MCP tool boolean parameters now use standardized field validators for string conversion
13+
- **Enhanced MCP Client Compatibility**: Improved support for diverse MCP client implementations with flexible parameter handling
14+
915
## MCP Compatibility
1016

1117
This server provides enhanced MCP (Model Context Protocol) compatibility with flexible parameter type handling:
1218

1319
### Boolean Parameter Support
1420
- **Flexible Type Input**: Boolean parameters (`has_examples`, `deprecated`) accept both native boolean values and string representations
21+
- **Field Validator Implementation**: All boolean parameters use Pydantic field validators for robust string-to-boolean conversion
1522
- **Automatic Type Conversion**: String values are automatically converted to booleans using the following mappings:
16-
- `"true"`, `"1"`, `"yes"``true`
17-
- `"false"`, `"0"`, `"no"``false`
23+
- `"true"`, `"1"`, `"yes"`, `"on"``true`
24+
- `"false"`, `"0"`, `"no"`, `"off"``false`
1825
- **Client Compatibility**: MCP clients can send boolean values in their preferred format without worrying about type mismatches
1926
- **Backward Compatibility**: Maintains full compatibility with existing MCP clients that send native boolean values
27+
- **Standard Pattern**: This field validator pattern ensures compatibility with various MCP client implementations
2028

2129
### Parameter Flexibility
2230
- **Numeric Parameters**: Parameters like `k` and `min_doc_length` support both integer and string input with automatic conversion

src/docsrs_mcp/batch_processor.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ class MemoryRecycleRequired(Exception):
1818
"""Raised when process recycling is needed due to memory pressure."""
1919

2020

21-
2221
class BatchProcessor:
2322
"""
2423
Core batch processing abstraction with memory-aware sizing and cleanup.

src/docsrs_mcp/models.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,6 +1143,16 @@ class StartPreIngestionRequest(BaseModel):
11431143
description="Number of crates to pre-ingest (10-500, default: 100)",
11441144
)
11451145

1146+
@field_validator("force", mode="before")
1147+
@classmethod
1148+
def validate_force(cls, v: Any) -> bool:
1149+
"""Validate and coerce force parameter to boolean."""
1150+
if isinstance(v, bool):
1151+
return v
1152+
if isinstance(v, str):
1153+
return v.lower() in ("true", "1", "yes", "on")
1154+
return False # default
1155+
11461156
@field_validator("concurrency", mode="before")
11471157
@classmethod
11481158
def coerce_concurrency_to_int(cls, v):

src/docsrs_mcp/validation.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -621,9 +621,7 @@ def count_tokens(text: str, encoding: str = "cl100k_base") -> int:
621621
return len(text) // 4
622622

623623

624-
def validate_tutorial_tokens(
625-
value: str | None, max_tokens: int = 200
626-
) -> str | None:
624+
def validate_tutorial_tokens(value: str | None, max_tokens: int = 200) -> str | None:
627625
"""
628626
Validate that tutorial text doesn't exceed token limit.
629627

0 commit comments

Comments
 (0)