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.
 
 
 
 
 
 

168 lines
7.8 KiB

"""
Test script for the RiksdagenTools MCP server (HTTP transport).
This script connects to the MCP server via Streamable HTTP and tests your main tools.
Ensure the MCP server is running and that the environment variable MCP_SERVER_TOKEN is set.
Also adjust MCP_SERVER_URL if needed.
"""
import os
import asyncio
from typing import Any, Dict, List, Optional, Sequence
from mcp.client.streamable_http import streamablehttp_client
from mcp.client.session import ClientSession # adjusted import per SDK version
TOKEN: str = os.environ.get("MCP_SERVER_TOKEN", "2q89rwpfaiukdjshp298n3qw")
SERVER_URL: str = os.environ.get("MCP_SERVER_URL", "https://api.rixdagen.se/mcp") # use the public HTTPS endpoint by default so tests target the nginx proxy
async def run_tests() -> None:
"""
Attempt to connect to SERVER_URL and run the tool tests. On SSL certificate
verification failures, optionally retry against the backend IP if
MCP_FALLBACK_TO_IP=1 is set (or a custom MCP_FALLBACK_URL is provided).
"""
async def run_with_url(url: str) -> None:
print(f"Connecting to server URL: {url}")
async with streamablehttp_client(
url=url,
headers={ "Authorization": f"Bearer {TOKEN}" }
) as (read_stream, write_stream, get_session_id):
async with ClientSession(read_stream, write_stream) as session:
# initialize the session (if needed)
init_result = await session.initialize()
print("Initialized session:", init_result)
print("\nListing available tools...")
tools_info = await session.list_tools()
print("Tools:", [ tool.name for tool in tools_info.tools ])
# Test aql_query
print("\n== Testing aql_query ==")
result1 = await session.call_tool(
"aql_query",
arguments={
"token": TOKEN,
"query": "FOR doc IN talks LIMIT 2 RETURN { _id: doc._id, talare: doc.talare }"
}
)
print("aql_query result:", result1)
# Test search_documents
print("\n== Testing search_documents ==")
result2 = await session.call_tool(
"search_documents",
arguments={
"token": TOKEN,
"aql_query": "FOR doc IN talks LIMIT 2 RETURN { _id: doc._id, talare: doc.talare }"
}
)
print("search_documents result:", result2)
# Test vector_search_talks
print("\n== Testing vector_search_talks ==")
result3 = await session.call_tool(
"vector_search_talks",
arguments={
"token": TOKEN,
"query": "klimatförändringar",
"limit": 2
}
)
print("vector_search_talks result:", result3)
# Test fetch_documents
print("\n== Testing fetch_documents ==")
# try to pull out IDs from result3 if available
doc_ids: List[str]
maybe = result3
if hasattr(maybe, "output") and isinstance(maybe.output, list) and maybe.output:
doc_ids = [ maybe.output[0].get("_id", "") ]
else:
doc_ids = ["talks/1"]
result4 = await session.call_tool(
"fetch_documents",
arguments={
"token": TOKEN,
"document_ids": doc_ids
}
)
print("fetch_documents result:", result4)
# Test arango_search
print("\n== Testing arango_search ==")
result5 = await session.call_tool(
"arango_search",
arguments={
"token": TOKEN,
"query": "klimat",
"limit": 2
}
)
print("arango_search result:", result5)
# try primary URL first
try:
await run_with_url(SERVER_URL)
except Exception as e: # capture failures from streamablehttp_client / httpx
err_str = str(e).lower()
ssl_fail = "certificate_verify_failed" in err_str or "hostname mismatch" in err_str or "certificate verify failed" in err_str
gateway_fail = "502" in err_str or "bad gateway" in err_str or "502 bad gateway" in err_str
if gateway_fail:
print("Received 502 Bad Gateway from the proxy when connecting to the server URL.")
# If user explicitly set fallback env var, retry against backend IP or custom fallback
fallback_flag = os.environ.get("MCP_FALLBACK_TO_IP", "0").lower() in ("1", "true", "yes")
if fallback_flag:
fallback_url = os.environ.get("MCP_FALLBACK_URL", "http://127.0.0.1:8010/mcp")
print(f"Retrying with fallback URL (MCP_FALLBACK_URL or default backend): {fallback_url}")
await run_with_url(fallback_url)
return
print("")
print("Possible causes:")
print("- The proxy (nginx) couldn't reach the backend (backend down, wrong proxy_pass or path).")
print("- Proxy buffering or HTTP version issues interfering with streaming transport.")
print("")
print("Options:")
print("- Bypass the proxy and target the backend directly:")
print(" export MCP_SERVER_URL='http://127.0.0.1:8010/mcp'")
print("- Or enable automatic fallback to the backend (insecure) for testing:")
print(" export MCP_FALLBACK_TO_IP=1")
print(" # optionally override the fallback target")
print(" export MCP_FALLBACK_URL='http://127.0.0.1:8010/mcp'")
print("- Check the proxy's error log (e.g. /var/log/nginx/error.log) for upstream errors.")
print("")
# re-raise so caller still sees the error if they don't follow guidance
raise
if ssl_fail:
print("SSL certificate verification failed while connecting to the server URL.")
# If user explicitly set fallback env var, retry against backend IP or custom fallback
fallback_flag = os.environ.get("MCP_FALLBACK_TO_IP", "0").lower() in ("1", "true", "yes")
if fallback_flag:
fallback_url = os.environ.get("MCP_FALLBACK_URL", "http://192.168.1.10:8010/mcp")
print(f"Retrying with fallback URL (MCP_FALLBACK_URL or default backend IP): {fallback_url}")
await run_with_url(fallback_url)
return
# Otherwise give actionable guidance
print("")
print("Possible causes:")
print("- The TLS certificate served for api.rixdagen.se does not match that hostname on this machine.")
print("")
print("Options:")
print("- Set MCP_SERVER_URL to the backend HTTP address to bypass TLS: e.g.")
print(" export MCP_SERVER_URL='http://192.168.1.10:8010/mcp'")
print("- Or enable automatic fallback to the backend IP for testing (insecure):")
print(" export MCP_FALLBACK_TO_IP=1")
print(" # optionally override the fallback target")
print(" export MCP_FALLBACK_URL='http://192.168.1.10:8010/mcp'")
print("")
# re-raise so caller still sees the error if they don't follow guidance
raise
# Not an SSL or gateway failure: re-raise
raise
def main() -> None:
asyncio.run(run_tests())
if __name__ == "__main__":
main()