Bug: update_webgui_settings — port parameter type mismatch prevents changing WebGUI port
Summary
The update_webgui_settings tool defines the port parameter as integer in the MCP tool schema (Pydantic model), but the pfSense REST API v2 endpoint PATCH /api/v2/system/webgui/settings requires port to be of type string. This makes it impossible to change the WebGUI port via MCP — the call is rejected either by local Pydantic validation (if a string is passed) or by the pfSense API (if an integer is passed).
Environment
- pfSense version: domonstrated on 25.11.1 with pfSense-pkg-RESTAPI v2.7.5
- API endpoint:
PATCH /api/v2/system/webgui/settings
- MCP server: pfsense MCP (Claude Desktop, macOS, Apple Silicon)
Steps to Reproduce
1. Call update_webgui_settings with port as integer (as the schema requires):
Tool call: pfsense pf1:update_webgui_settings
Parameters: { "port": 10443, "apply_immediately": true }
Result — pfSense API rejects with 400:
{
"code": 400,
"status": "bad request",
"response_id": "FIELD_INVALID_TYPE",
"message": "Field `port` must be of type `string`",
"data": []
}
2. Attempt to pass port as a string to work around the API requirement:
Tool call: pfsense pf1:update_webgui_settings
Parameters: { "port": "10443", "apply_immediately": true }
Result — local Pydantic validation rejects before the API call is even made:
1 validation error for call[update_webgui_settings]
port
Input should be a valid integer, unable to parse string as an integer
[type=int_parsing, input_value='"10443"', input_type=str]
For further information visit https://errors.pydantic.dev/2.12/v/int_parsing
Current MCP Tool Schema (from tool definition)
# port is typed as Optional[int] in the Pydantic model:
port: {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null}
Expected pfSense API v2 Behavior
The pfSense REST API v2 PATCH /api/v2/system/webgui/settings endpoint expects port as a string, not an integer. This is consistent with how pfSense stores the port in config.xml (as a text value) and how the GET endpoint returns it:
{
"success": true,
"settings": {
"protocol": "https",
"port": "443",
"sslcertref": "64e6641552fa1"
}
}
Note: the GET response returns "port": "443" — a string, not an integer.
Root Cause
The MCP server's Pydantic model for update_webgui_settings declares port as Optional[int], but it should be Optional[str] (or Optional[Union[int, str]] with an int-to-str coercion validator) to match the pfSense REST API v2 contract.
Suggested Fix
Keep accepting int for ergonomics but coerce to str before sending to the API:
from pydantic import field_validator
port: Optional[Union[int, str]] = None
@field_validator('port', mode='before')
@classmethod
def coerce_port_to_str(cls, v):
if v is not None:
return str(v)
return v
Then ensure the value is sent as a string in the API request body.
Impact
- Severity: Medium — prevents a common administrative operation (changing the WebGUI port) via MCP
- Workaround: Change the WebGUI port manually via pfSense GUI (System → Advanced → Admin Access → TCP Port)
Additional Context
The same type mismatch pattern may exist in other MCP tools where pfSense stores config values as strings but the MCP Pydantic model uses integer types. A systematic audit of parameter types against the pfSense REST API v2 OpenAPI spec (if available) or against actual API error responses would be valuable.
Bug:
update_webgui_settings—portparameter type mismatch prevents changing WebGUI portSummary
The
update_webgui_settingstool defines theportparameter asintegerin the MCP tool schema (Pydantic model), but the pfSense REST API v2 endpointPATCH /api/v2/system/webgui/settingsrequiresportto be of typestring. This makes it impossible to change the WebGUI port via MCP — the call is rejected either by local Pydantic validation (if a string is passed) or by the pfSense API (if an integer is passed).Environment
PATCH /api/v2/system/webgui/settingsSteps to Reproduce
1. Call
update_webgui_settingswithportas integer (as the schema requires):Result — pfSense API rejects with 400:
{ "code": 400, "status": "bad request", "response_id": "FIELD_INVALID_TYPE", "message": "Field `port` must be of type `string`", "data": [] }2. Attempt to pass
portas a string to work around the API requirement:Result — local Pydantic validation rejects before the API call is even made:
Current MCP Tool Schema (from tool definition)
Expected pfSense API v2 Behavior
The pfSense REST API v2
PATCH /api/v2/system/webgui/settingsendpoint expectsportas a string, not an integer. This is consistent with how pfSense stores the port inconfig.xml(as a text value) and how theGETendpoint returns it:{ "success": true, "settings": { "protocol": "https", "port": "443", "sslcertref": "64e6641552fa1" } }Note: the
GETresponse returns"port": "443"— a string, not an integer.Root Cause
The MCP server's Pydantic model for
update_webgui_settingsdeclaresportasOptional[int], but it should beOptional[str](orOptional[Union[int, str]]with anint-to-strcoercion validator) to match the pfSense REST API v2 contract.Suggested Fix
Keep accepting
intfor ergonomics but coerce tostrbefore sending to the API:Then ensure the value is sent as a string in the API request body.
Impact
Additional Context
The same type mismatch pattern may exist in other MCP tools where pfSense stores config values as strings but the MCP Pydantic model uses integer types. A systematic audit of parameter types against the pfSense REST API v2 OpenAPI spec (if available) or against actual API error responses would be valuable.