Source code for novelai_image_mcp.settings

"""Environment-driven configuration for the NovelAI Image MCP server.

Two ``pydantic-settings`` models expose the runtime configuration surface:
``NovelAISettings`` (credentials + generation defaults, ``NOVELAI_*`` env
vars) and ``MCPServerSettings`` (transport, ``MCP_*`` env vars).

``NovelAISettings`` structurally satisfies ``nai.NovelAIConfigLike`` so the
client factory consumes it directly.
"""

from __future__ import annotations

from typing import Literal

from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict


[docs] class NovelAISettings(BaseSettings): """NovelAI credentials, endpoints, and generation defaults. All fields are read from ``NOVELAI_*`` environment variables (and an optional ``.env`` file in the working directory). Exactly one auth method is required at runtime: either ``token`` (preferred) or the ``username``+``password`` pair. """ model_config = SettingsConfigDict( env_prefix="NOVELAI_", env_file=".env", env_file_encoding="utf-8", extra="ignore", case_sensitive=False, ) # ── Credentials ── token: str | None = None username: str | None = None password: str | None = None # ── Endpoints ── image_base_url: str = "https://image.novelai.net" account_base_url: str = "https://api.novelai.net" timeout: float = Field(default=120.0, gt=0) # ── Generation defaults (overridable per tool call) ── default_model: str = "nai-diffusion-4-5-full" default_width: int = Field(default=832, ge=64, le=49_152) default_height: int = Field(default=1216, ge=64, le=49_152) default_steps: int = Field(default=28, ge=1, le=50) default_scale: float = Field(default=5.0, gt=0, le=20) default_sampler: str = "k_euler_ancestral" # ── Client ── vibe_cache_entries: int = Field(default=64, ge=1, le=1024) # ── Output ── output_dir: str = "outputs"
[docs] def has_credentials(self) -> bool: """True when either a token or a complete username/password pair is set.""" return bool(self.token) or bool(self.username and self.password)
[docs] class MCPServerSettings(BaseSettings): """MCP server transport selection (``MCP_*`` env vars).""" model_config = SettingsConfigDict( env_prefix="MCP_", env_file=".env", env_file_encoding="utf-8", extra="ignore", case_sensitive=False, ) transport: Literal["stdio", "streamable-http"] = "stdio" host: str = "127.0.0.1" port: int = Field(default=8000, ge=1, le=65_535) path: str = "/mcp"
[docs] def get_novelai_settings() -> NovelAISettings: """Load NovelAI settings from environment / .env.""" return NovelAISettings()
[docs] def get_mcp_settings() -> MCPServerSettings: """Load MCP server settings from environment / .env.""" return MCPServerSettings()
__all__ = [ "MCPServerSettings", "NovelAISettings", "get_mcp_settings", "get_novelai_settings", ]