Coverage for /home/admin/Documents/AI/applications/lexigram-dev/lexigram/experimental/ai/lexigram-ai-mcp/src/lexigram/ai/mcp/config.py: 100%
97 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 07:19 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 07:19 +0800
1"""MCP server configuration for the Lexigram framework."""
3from __future__ import annotations
5from dataclasses import dataclass, field
6from typing import ClassVar, cast
8from lexigram.ai.mcp.constants import ENV_NESTED_DELIMITER, ENV_PREFIX
9from lexigram.config.base import BaseConfig
10from lexigram.validation import ConfigDict, Field
13@dataclass
14class FilesystemConnectorConfig:
15 """Configuration for the built-in FilesystemConnector."""
17 root_dir: str = ""
18 """Sandboxed root directory. Must be set to a non-empty path to enable."""
20 read_only: bool = False
21 """When True, write_file and other mutating tools are disabled."""
24@dataclass
25class GitHubConnectorConfig:
26 """Configuration for the built-in GitHubConnector."""
28 token: str = ""
29 """GitHub personal access token or fine-grained token."""
31 api_url: str = "https://api.github.com"
32 """Override for GitHub Enterprise installations."""
35@dataclass
36class WebFetchConnectorConfig:
37 """Configuration for the built-in WebFetchConnector."""
39 enabled: bool = False
40 """When True, the web-fetch tool is active (disabled by default)."""
42 max_content_bytes: int = 512 * 1024
43 """Maximum response body size to fetch (default 512 KB)."""
45 user_agent: str = "lexigram-mcp/1.0"
46 """HTTP User-Agent header to send."""
49@dataclass
50class WebSearchConnectorConfig:
51 """Configuration for the built-in WebSearchConnector."""
53 provider: str = "brave"
54 """Search provider name: 'brave', 'serpapi', or 'google'."""
56 api_key: str = ""
57 """API key for the configured search provider."""
59 max_results: int = 10
60 """Maximum number of results to return."""
63@dataclass
64class SlackConnectorConfig:
65 """Configuration for the built-in SlackConnector."""
67 bot_token: str = ""
68 """Slack bot OAuth token (xoxb-...)."""
70 max_messages: int = 100
71 """Maximum messages to return per channel history request."""
74@dataclass
75class GoogleDriveConnectorConfig:
76 """Configuration for the built-in GoogleDriveConnector."""
78 service_account_json: str = ""
79 """Path to the Google service-account credentials JSON file."""
81 impersonated_email: str = ""
82 """Email to impersonate via domain-wide delegation (optional)."""
85@dataclass
86class SQLConnectorConfig:
87 """Configuration for the built-in SQLConnector."""
89 dsn: str = ""
90 """Database connection string (e.g. postgresql://user:pass@host/db)."""
92 allowed_tables: list[str] = field(default_factory=list)
93 """Explicit allowlist of table names that the connector may query."""
95 read_only: bool = True
96 """When True, only SELECT statements are permitted (default True)."""
99@dataclass
100class ConnectorsConfig:
101 """Top-level connector configuration block inside ``MCPConfig``."""
103 filesystem: FilesystemConnectorConfig = field(
104 default_factory=FilesystemConnectorConfig
105 )
106 github: GitHubConnectorConfig = field(default_factory=GitHubConnectorConfig)
107 web_fetch: WebFetchConnectorConfig = field(default_factory=WebFetchConnectorConfig)
108 web_search: WebSearchConnectorConfig = field(
109 default_factory=WebSearchConnectorConfig
110 )
111 slack: SlackConnectorConfig = field(default_factory=SlackConnectorConfig)
112 google_drive: GoogleDriveConnectorConfig = field(
113 default_factory=GoogleDriveConnectorConfig
114 )
115 sql: SQLConnectorConfig = field(default_factory=SQLConnectorConfig)
118@dataclass(init=False)
119class MCPConfig(BaseConfig):
120 """Configuration for the MCP server.
122 Attributes:
123 host: Host to bind to (for HTTP transport).
124 port: Port to bind to (for HTTP transport).
125 path: URL path for MCP endpoint (default /mcp).
126 enable_sse: Enable Server-Sent Events for streaming responses.
127 stdio_mode: Use stdio transport instead of HTTP.
128 server_name: Name of the MCP server.
129 server_version: Version of the MCP server.
130 cors_origins: CORS allowed origins (for HTTP transport).
131 """
133 config_section: ClassVar[str] = "ai_mcp"
135 model_config: ClassVar[ConfigDict] = cast(
136 "ConfigDict",
137 {
138 "env_prefix": ENV_PREFIX,
139 "env_nested_delimiter": ENV_NESTED_DELIMITER,
140 "extra": "ignore",
141 },
142 )
144 enabled: bool = Field(default=True, description="Enable the MCP server subsystem")
146 host: str = Field(default="0.0.0.0") # noqa: S104 — config default, operator overridable
147 """Host to bind to (for HTTP transport)."""
149 port: int = Field(default=8080, ge=1, le=65535)
150 """Port to bind to (for HTTP transport)."""
152 path: str = Field(default="/mcp")
153 """URL path for MCP endpoint."""
155 enable_sse: bool = Field(default=True)
156 """Enable Server-Sent Events for streaming responses."""
158 stdio_mode: bool = Field(default=False)
159 """Use stdio transport instead of HTTP."""
161 server_name: str = Field(default="lexigram-mcp")
162 """Name of the MCP server."""
164 server_version: str = Field(default="1.0.0")
165 """Version of the MCP server."""
167 cors_origins: list[str] = field(default_factory=list)
168 """CORS allowed origins (for HTTP transport)."""
170 max_request_size: int = Field(default=1024 * 1024, ge=1024)
171 """Maximum request size in bytes."""
173 request_timeout: float = Field(default=30.0, ge=1.0)
174 """Request timeout in seconds."""
176 allow_unauthenticated: bool = Field(default=False)
177 """Permit non-authorizer request dispatch.
179 ``False`` (default) fails closed: after ``initialize``, requests for
180 non-handshake methods are rejected with ``-32000`` unless an
181 authorizer is bound or this flag is ``True``. ``True`` is an explicit
182 opt-out restoring the open posture for local/development use.
183 """
185 # Client-side configuration
186 client_url: str | None = Field(default=None)
187 """URL of an external MCP server to connect to as a client.
189 When set, :class:`~lexigram.ai.mcp.client.MCPClient` is registered in the
190 container using :class:`~lexigram.ai.mcp.client.SSEClientTransport`.
191 For stdio-based clients, construct :class:`~lexigram.ai.mcp.client.MCPClient`
192 directly via the container or code.
193 """
195 client_stdio_command: list[str] = field(default_factory=list)
196 """Command and args to spawn a local MCP server as a subprocess client.
198 When non-empty, :class:`~lexigram.ai.mcp.client.MCPClient` is registered
199 using :class:`~lexigram.ai.mcp.client.StdioClientTransport`.
200 Takes precedence over ``client_url`` when both are set.
201 """
203 connectors: ConnectorsConfig = field(default_factory=ConnectorsConfig)
204 """Optional built-in connector configuration.
206 Each connector is enabled by supplying a non-empty key value (e.g. a
207 ``root_dir`` for the filesystem connector or a ``token`` for GitHub).
208 """
211__all__ = ["MCPConfig"]