mcp_server.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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": entity.raw_payload.get("wikidata"),
  44. }
  45. if debug:
  46. raw_claims, derived_claims = build_claim_sets(entity)
  47. turtle = entity_to_turtle(entity)
  48. result["raw_claims"] = raw_claims
  49. result["derived_claims"] = derived_claims
  50. result["turtle"] = turtle
  51. if debug_path:
  52. path = Path(debug_path)
  53. path.parent.mkdir(parents=True, exist_ok=True)
  54. path.write_text(turtle, encoding="utf-8")
  55. result["turtle_path"] = str(path)
  56. return result
  57. @mcp.tool(name="enrich_entity", description="Enrich a canonical Atlas entity.")
  58. async def enrich_entity_tool(subject: str, depth: int = 1, context: str | None = None):
  59. entity = await resolve_entity(subject, context)
  60. result = enrich_entity(entity, depth=depth)
  61. return {
  62. "seed": {
  63. "atlas_id": result.seed_entity.atlas_id,
  64. "canonical_label": result.seed_entity.canonical_label,
  65. },
  66. "related_entities": [
  67. {
  68. "atlas_id": item.atlas_id,
  69. "canonical_label": item.canonical_label,
  70. "entity_type": item.entity_type,
  71. }
  72. for item in result.related_entities
  73. ],
  74. "query_context": result.query_context,
  75. "depth": result.depth,
  76. }