Skip to content

Update_webgui_settings — port parameter type mismatch prevents changing WebGUI port #7

@tvlc

Description

@tvlc

Bug: update_webgui_settingsport 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions