mcp_server.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  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. result = {
  19. "atlas_id": entity.atlas_id,
  20. "canonical_label": entity.canonical_label,
  21. "canonical_description": entity.canonical_description,
  22. "entity_type": entity.entity_type,
  23. "needs_curation": entity.needs_curation,
  24. "aliases": [alias.label for alias in entity.aliases],
  25. "identifiers": [
  26. {
  27. "value": identifier.value,
  28. "source": identifier.source,
  29. "identifier_type": identifier.identifier_type,
  30. }
  31. for identifier in entity.identifiers
  32. ],
  33. "provenance": [
  34. {
  35. "source": provenance.source,
  36. "retrieval_method": provenance.retrieval_method,
  37. "confidence": provenance.confidence,
  38. "retrieved_at": provenance.retrieved_at,
  39. }
  40. for provenance in entity.provenance
  41. ],
  42. "g_trends_payload": {k: v for k, v in entity.raw_payload.items() if k != "wikidata"},
  43. "wikidata_payload": (
  44. entity.raw_payload.get("wikidata")
  45. if entity.raw_payload.get("wikidata") is not None
  46. else {"status": "missing"}
  47. ),
  48. }
  49. if debug:
  50. raw_claims, derived_claims = build_claim_sets(entity)
  51. turtle = entity_to_turtle(entity)
  52. result["raw_claims"] = raw_claims
  53. result["derived_claims"] = derived_claims
  54. result["turtle"] = turtle
  55. if debug_path:
  56. path = Path(debug_path)
  57. path.parent.mkdir(parents=True, exist_ok=True)
  58. path.write_text(turtle, encoding="utf-8")
  59. result["turtle_path"] = str(path)
  60. return result
  61. @mcp.tool(name="enrich_entity", description="Enrich a canonical Atlas entity.")
  62. async def enrich_entity_tool(subject: str, depth: int = 1, context: str | None = None):
  63. entity = await resolve_entity(subject, context)
  64. result = enrich_entity(entity, depth=depth)
  65. return {
  66. "seed": {
  67. "atlas_id": result.seed_entity.atlas_id,
  68. "canonical_label": result.seed_entity.canonical_label,
  69. },
  70. "related_entities": [
  71. {
  72. "atlas_id": item.atlas_id,
  73. "canonical_label": item.canonical_label,
  74. "entity_type": item.entity_type,
  75. }
  76. for item in result.related_entities
  77. ],
  78. "query_context": result.query_context,
  79. "depth": result.depth,
  80. }