You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
3.1 KiB
114 lines
3.1 KiB
""" |
|
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() |