""" RiksdagenTools MCP server (HTTP only, compatible with current FastMCP version) """ from __future__ import annotations import asyncio import logging import os import inspect from typing import Any, Dict, List, Optional, Sequence from fastmcp import FastMCP from mcp_server.auth import validate_token from mcp_server import tools HOST = os.getenv("MCP_HOST", "127.0.0.1") PORT = int(os.getenv("MCP_PORT", "8010")) PATH = os.getenv("MCP_PATH", "/mcp") LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO").upper() logging.basicConfig( level=LOG_LEVEL, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s", datefmt="%Y-%m-%d %H:%M:%S", ) log = logging.getLogger("mcp_server") app = FastMCP("RiksdagenTools") # --- tools unchanged --- @app.tool() async def search_documents(token: str, aql_query: str) -> Dict[str, Any]: validate_token(token) return await asyncio.to_thread(tools.search_documents, aql_query) @app.tool() async def aql_query(token: str, query: str) -> List[Dict[str, Any]]: validate_token(token) return await asyncio.to_thread(tools.run_aql_query, query) @app.tool() async def vector_search_talks(token: str, query: str, limit: int = 8) -> List[Dict[str, Any]]: validate_token(token) return await asyncio.to_thread(tools.vector_search, query, limit) @app.tool() async def fetch_documents( token: str, document_ids: Sequence[str], fields: Optional[Sequence[str]] = None ) -> List[Dict[str, Any]]: validate_token(token) return await asyncio.to_thread( tools.fetch_documents, list(document_ids), list(fields) if fields else None ) @app.tool() async def arango_search( token: str, query: str, limit: int = 20, parties: Optional[Sequence[str]] = None, people: Optional[Sequence[str]] = None, from_year: Optional[int] = None, to_year: Optional[int] = None, return_snippets: bool = False, focus_ids: Optional[Sequence[str]] = None, speaker_ids: Optional[Sequence[str]] = None, ) -> Dict[str, Any]: validate_token(token) return await asyncio.to_thread( tools.arango_search, query, limit, parties, people, from_year, to_year, return_snippets, focus_ids, speaker_ids, ) @app.tool() async def ping() -> str: """ Lightweight test tool for connectivity checks. Returns: A short confirmation string ("ok"). This tool is intentionally unauthenticated so it can be used to validate the transport/proxy (e.g. nginx -> backend) without presenting credentials. """ return "ok" # --- Entrypoint --- def run() -> None: log.info( "Starting RiksdagenTools MCP server (HTTP) on http://%s:%d%s", HOST, PORT, PATH, ) try: # Pass host, port, and path directly to run() method app.run( transport="streamable-http", host=HOST, port=PORT, path=PATH, ) except Exception: log.exception("Unexpected error while running the MCP server.") raise if __name__ == "__main__": run()