mcp_server.py 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. """FastMCP transport for Atlas tools."""
  2. from __future__ import annotations
  3. from pathlib import Path
  4. from mcp.server.fastmcp import FastMCP
  5. from mcp.server.transport_security import TransportSecuritySettings
  6. from .atlas import enrich_entity, resolve_entity
  7. from .claims import build_claim_sets
  8. from .triple_export import entity_to_turtle
  9. mcp = FastMCP(
  10. "atlas",
  11. transport_security=TransportSecuritySettings(
  12. enable_dns_rebinding_protection=False
  13. ),
  14. )
  15. @mcp.tool(name="resolve_entity", description="Resolve a subject string to a canonical Atlas entity.")
  16. async def resolve_entity_tool(subject: str, context: str | None = None, debug: bool = False, debug_path: str | None = None):
  17. entity = await resolve_entity(subject, context)
  18. raw_claims, derived_claims = build_claim_sets(entity)
  19. result = {
  20. "atlas_id": entity.atlas_id,
  21. "canonical_label": entity.canonical_label,
  22. "canonical_description": entity.canonical_description,
  23. "entity_type": entity.entity_type,
  24. "needs_curation": entity.needs_curation,
  25. "aliases": [alias.label for alias in entity.aliases],
  26. "active_claims": raw_claims + derived_claims,
  27. "g_trends_payload": {k: v for k, v in entity.raw_payload.items() if k != "wikidata"},
  28. "wikidata_payload": (
  29. entity.raw_payload.get("wikidata")
  30. if entity.raw_payload.get("wikidata") is not None
  31. else {"wikidata_status": "missing"}
  32. ),
  33. }
  34. if debug:
  35. turtle = entity_to_turtle(entity)
  36. result["raw_claims"] = raw_claims
  37. result["derived_claims"] = derived_claims
  38. result["source_payloads"] = {
  39. "g_trends_payload": result["g_trends_payload"],
  40. "wikidata_payload": result["wikidata_payload"],
  41. }
  42. result["turtle"] = turtle
  43. if debug_path:
  44. path = Path(debug_path)
  45. path.parent.mkdir(parents=True, exist_ok=True)
  46. path.write_text(turtle, encoding="utf-8")
  47. result["turtle_path"] = str(path)
  48. return result
  49. @mcp.tool(name="enrich_entity", description="Enrich a canonical Atlas entity.")
  50. async def enrich_entity_tool(subject: str, depth: int = 1, context: str | None = None):
  51. entity = await resolve_entity(subject, context)
  52. result = enrich_entity(entity, depth=depth)
  53. return {
  54. "seed": {
  55. "atlas_id": result.seed_entity.atlas_id,
  56. "canonical_label": result.seed_entity.canonical_label,
  57. },
  58. "related_entities": [
  59. {
  60. "atlas_id": item.atlas_id,
  61. "canonical_label": item.canonical_label,
  62. "entity_type": item.entity_type,
  63. }
  64. for item in result.related_entities
  65. ],
  66. "query_context": result.query_context,
  67. "depth": result.depth,
  68. }