Settings in the MCP server config is a frozen dataclass:
https://github.com/OpenSemanticLab/osw-python/blob/feat/mcp-server/src/osw/mcp/config.py#L45
Every other configuration-shaped object in osw is pydantic: OswBaseModel and all the *Param classes. Consequences of the outlier:
max_results and max_chars are parsed by a hand-written _int_env helper with its own ValueError to RuntimeError translation, which pydantic does for free.
- Nothing validates
domain (a bare domain vs a full URL is a real distinction here, see _derive_domain), sparql_endpoint, or state_dir.
- The type annotations are enforced by nothing at runtime, and
src/osw/mcp is excluded from ty (pyproject.toml), so they are not enforced statically either.
Suggested fix: convert to a pydantic model, ideally BaseSettings-style with env aliases, replacing _first_env and _int_env. Natural point to do it is right after the config module moves to the shared service package in the MCP/CLI refactor, so it is one change instead of two.
Depends on: #133.
Settingsin the MCP server config is a frozendataclass:https://github.com/OpenSemanticLab/osw-python/blob/feat/mcp-server/src/osw/mcp/config.py#L45
Every other configuration-shaped object in osw is pydantic:
OswBaseModeland all the*Paramclasses. Consequences of the outlier:max_resultsandmax_charsare parsed by a hand-written_int_envhelper with its ownValueErrortoRuntimeErrortranslation, which pydantic does for free.domain(a bare domain vs a full URL is a real distinction here, see_derive_domain),sparql_endpoint, orstate_dir.src/osw/mcpis excluded fromty(pyproject.toml), so they are not enforced statically either.Suggested fix: convert to a pydantic model, ideally
BaseSettings-style with env aliases, replacing_first_envand_int_env. Natural point to do it is right after the config module moves to the shared service package in the MCP/CLI refactor, so it is one change instead of two.Depends on: #133.