feat(mcp): FastMCP server exposing read-only KB tools (stdio)
Implements F-14: thin FastMCP wrapper over existing codex domain modules.
Seven read-only tools: search, ask, wiki_read, wiki_list, discover_leads,
provenance_verify, synthesis_browse. All optional-feature tools degrade
gracefully to {"error": "feature not available"} instead of crashing.
Adds mcp[cli]>=1.0 dependency and codex-mcp console_script entry-point.
28 new tests across test_server, test_search, test_readonly, test_graceful,
test_http_auth — all green; 0 regressions in existing 172 tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -222,6 +222,93 @@ class Settings(BaseSettings):
|
||||
),
|
||||
)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# F-13 Synthesis / Lead-Engine
|
||||
# ------------------------------------------------------------------
|
||||
leads_dir: str = Field(
|
||||
default="leads/",
|
||||
description=(
|
||||
"Directory where synthesis leads are written. "
|
||||
"Grounded leads land in <leads_dir>/grounded/, conjectures in "
|
||||
"<leads_dir>/conjectures/. INVARIANT: conjectures NEVER touch wiki/."
|
||||
),
|
||||
)
|
||||
|
||||
synthesis_llm_model: str = Field(
|
||||
default="qwen2.5:7b",
|
||||
description=(
|
||||
"Ollama model name used for synthesis (connection / gap / improvement / "
|
||||
"conjecture). Defaults to the qwen-light profile on the Jetson."
|
||||
),
|
||||
)
|
||||
|
||||
synthesis_llm_url: str | None = Field(
|
||||
default=None,
|
||||
description=(
|
||||
"Ollama base URL for synthesis. When None, falls back to OLLAMA_BASE_URL."
|
||||
),
|
||||
)
|
||||
|
||||
synthesis_top_k: int = Field(
|
||||
default=20,
|
||||
gt=0,
|
||||
description=(
|
||||
"Number of top chunks retrieved per synthesis probe. Higher values "
|
||||
"improve recall at the cost of a larger LLM prompt."
|
||||
),
|
||||
)
|
||||
|
||||
synthesis_min_grounded_ratio: float = Field(
|
||||
default=0.5,
|
||||
ge=0.0,
|
||||
le=1.0,
|
||||
description=(
|
||||
"Minimum fraction of claims that must be grounded for a grounded lead "
|
||||
"(connection / gap / improvement) to be emitted. Leads below this "
|
||||
"threshold are dropped rather than written to leads/grounded/."
|
||||
),
|
||||
)
|
||||
|
||||
synthesis_gap_min_coverage: int = Field(
|
||||
default=2,
|
||||
gt=0,
|
||||
description=(
|
||||
"A topic is considered a 'gap' candidate when it is covered by fewer "
|
||||
"than this many distinct bibkeys in the retrieved top-K."
|
||||
),
|
||||
)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# F-14 MCP Server
|
||||
# ------------------------------------------------------------------
|
||||
mcp_transport: str = Field(
|
||||
default="stdio",
|
||||
description=(
|
||||
"Transport protocol for the MCP server. "
|
||||
"Allowed values: 'stdio' (default) or 'http'. "
|
||||
"HTTP transport requires MCP_AUTH_TOKEN to be set."
|
||||
),
|
||||
)
|
||||
|
||||
mcp_host: str = Field(
|
||||
default="127.0.0.1",
|
||||
description="Bind host for HTTP transport (ignored for stdio).",
|
||||
)
|
||||
|
||||
mcp_port: int = Field(
|
||||
default=8765,
|
||||
gt=0,
|
||||
description="Bind port for HTTP transport (ignored for stdio).",
|
||||
)
|
||||
|
||||
mcp_auth_token: str | None = Field(
|
||||
default=None,
|
||||
description=(
|
||||
"Bearer token required when mcp_transport='http'. "
|
||||
"If HTTP transport is requested but this is None, the server refuses to start."
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def get_settings() -> Settings:
|
||||
|
||||
Reference in New Issue
Block a user