# Fix: Invalid Field Names in Tool Generation
## Problem
The MCP server was crashing when listing tools due to invalid Python parameter names in the form schema:
```
ValueError: 'is_process_legitimated_?' is not a valid parameter name
```
The error occurred because the form schema from the main server contained field names with special characters (like `?`, `-`, `.`, spaces, etc.) that are not valid Python identifiers.
## Root Cause
In `tool_function_factory.py`, the `extract_parameters_from_schema()` function was trying to create Python function parameters directly from field names without validation. When it encountered `'is_process_legitimated_?'`, Python's `inspect.Parameter()` raised a `ValueError` because `?` is not allowed in parameter names.
## Solution
**Modified `tool_function_factory.py` to skip fields with invalid names instead of trying to sanitize them.**
### Changes Made
#### 1. Added `is_valid_parameter_name()` function (lines 29-47)
```python
def is_valid_parameter_name(name: str) -> bool:
"""
Check if a name is a valid Python identifier.
Returns:
True if the name is a valid Python identifier, False otherwise
"""
return name.isidentifier()
```
This uses Python's built-in `str.isidentifier()` method to check if a string is a valid Python identifier.
#### 2. Updated `extract_parameters_from_schema()` function (lines 73-123)
**Before:**
```python
for param_name, prop_def in properties.items():
# Directly used param_name without validation
param_info = {
"name": param_name, # Could be invalid!
...
}
parameters.append(param_info)
```
**After:**
```python
for param_name, prop_def in properties.items():
# Skip fields with invalid Python identifier names
if not is_valid_parameter_name(param_name):
skipped_fields.append(param_name)
logger.debug(f"Skipping field '{param_name}' - not a valid Python identifier")
continue
param_info = {
"name": param_name, # Guaranteed to be valid
...
}
parameters.append(param_info)
if skipped_fields:
logger.info(f"Skipped {len(skipped_fields)} fields with invalid names: {skipped_fields}")
```
## Testing
Created `test_invalid_field_names.py` to verify the fix:
### Test Results
```
✅ is_valid_parameter_name() test PASSED
- Valid names: field_name, fieldName, field123, _private, __dunder__
- Invalid names: is_process_legitimated_?, user-name, field name, 123field, field.name
✅ extract_parameters_from_schema() test PASSED
- Correctly extracted 4 valid fields
- Correctly skipped 3 invalid fields: ['is_process_legitimated_?', 'user-name', 'field.with.dots']
```
## Impact
### Positive
- ✅ **Server no longer crashes** when encountering invalid field names
- ✅ **Tool generation succeeds** with valid fields only
- ✅ **Clear logging** shows which fields were skipped and why
- ✅ **No data loss** for valid fields
### Limitations
- ⚠️ **Fields with invalid names are not available** in the generated tools
- ⚠️ **Users cannot set these fields** through the MCP interface
### Example
If the form schema has these fields:
```json
{
"subject": {...},
"description": {...},
"is_process_legitimated_?": {...}, // Invalid
"priority": {...}
}
```
The generated tool will only have:
```python
async def create_request(
subject: str,
description: str,
priority: str
# is_process_legitimated_? is skipped
):
...
```
## Server Logs
When the server starts and processes a schema with invalid field names, you'll see:
```
2025-10-23 13:28:01,046 - tool_function_factory - INFO - Skipped 1 fields with invalid names: ['is_process_legitimated_?']
```
## Recommendation
**For the main server team:** Consider renaming fields with special characters to use only valid Python identifiers:
- `is_process_legitimated_?` → `is_process_legitimated`
- `user-name` → `user_name`
- `field.name` → `field_name`
This will ensure all fields are available through the MCP interface.
## Files Modified
- `tool_function_factory.py` - Added validation and skipping logic
## Files Created
- `test_invalid_field_names.py` - Test suite for invalid field name handling
- `FIX_INVALID_FIELD_NAMES.md` - This documentation