feat: deploy jarca ledger network mcp service

- add Docker deployment for independent jarca-ledger container
- enable FastMCP streamable-http runtime configuration
- document dcy-013, REQ-019, and BAT-015 verification evidence
- update structure/runtime baselines and deployment runbook
This commit is contained in:
Jarca
2026-07-07 23:04:42 +09:00
parent a7b18c435d
commit 2ccfc9c064
19 changed files with 829 additions and 16 deletions
+69 -2
View File
@@ -1,13 +1,80 @@
from __future__ import annotations
import os
from dataclasses import dataclass
from pathlib import Path
from typing import Literal
from dotenv import load_dotenv
from mcp.server.fastmcp import FastMCP
from . import tool_contracts as contracts
load_dotenv(Path(__file__).resolve().parents[3] / ".env")
mcp = FastMCP("jarca-ledger-mcp")
McpTransport = Literal["stdio", "sse", "streamable-http"]
_ALLOWED_TRANSPORTS: set[str] = {"stdio", "sse", "streamable-http"}
@dataclass(frozen=True)
class McpRuntimeConfig:
transport: McpTransport = "stdio"
host: str = "127.0.0.1"
port: int = 8000
streamable_http_path: str = "/mcp"
sse_path: str = "/sse"
message_path: str = "/messages/"
stateless_http: bool = False
def _env_bool(name: str, default: bool = False) -> bool:
raw = os.getenv(name)
if raw is None or raw == "":
return default
return raw.strip().lower() in {"1", "true", "yes", "on"}
def _env_int(name: str, default: int) -> int:
raw = os.getenv(name)
if raw is None or raw == "":
return default
try:
return int(raw)
except ValueError as exc:
raise ValueError(f"{name} must be an integer, got {raw!r}") from exc
def _env_path(name: str, default: str) -> str:
raw = os.getenv(name, default).strip() or default
return raw if raw.startswith("/") else f"/{raw}"
def get_mcp_runtime_config() -> McpRuntimeConfig:
transport = os.getenv("JARCA_MCP_TRANSPORT", "stdio").strip() or "stdio"
if transport not in _ALLOWED_TRANSPORTS:
allowed = ", ".join(sorted(_ALLOWED_TRANSPORTS))
raise ValueError(f"JARCA_MCP_TRANSPORT must be one of: {allowed}; got {transport!r}")
return McpRuntimeConfig(
transport=transport, # type: ignore[arg-type]
host=os.getenv("JARCA_MCP_HOST", "127.0.0.1").strip() or "127.0.0.1",
port=_env_int("JARCA_MCP_PORT", 8000),
streamable_http_path=_env_path("JARCA_MCP_STREAMABLE_HTTP_PATH", "/mcp"),
sse_path=_env_path("JARCA_MCP_SSE_PATH", "/sse"),
message_path=_env_path("JARCA_MCP_MESSAGE_PATH", "/messages/"),
stateless_http=_env_bool("JARCA_MCP_STATELESS_HTTP", False),
)
_runtime_config = get_mcp_runtime_config()
mcp = FastMCP(
"jarca-ledger-mcp",
host=_runtime_config.host,
port=_runtime_config.port,
streamable_http_path=_runtime_config.streamable_http_path,
sse_path=_runtime_config.sse_path,
message_path=_runtime_config.message_path,
stateless_http=_runtime_config.stateless_http,
)
@mcp.tool()
def ledger_health_check() -> dict:
@@ -290,7 +357,7 @@ def delete_ledger_category(category: str, subcategory: str = "", hard_delete: bo
return contracts.delete_ledger_category(category, subcategory, hard_delete, force)
def main() -> None:
mcp.run()
mcp.run(transport=_runtime_config.transport)
if __name__ == "__main__":
main()