mirror of
https://github.com/semantica-agi/semantica.git
synced 2026-08-29 04:26:20 +00:00
Adds a fully self-contained `mcp/` package that exposes Semantica as a
Model Context Protocol server over stdio (JSON-RPC 2.0).
17 tools across 5 domains:
- Extraction: extract_entities, extract_relations, extract_all
- Decision intelligence: record_decision, query_decisions, find_precedents,
get_causal_chain, analyze_decision_impact
- Knowledge graph: add_entity, add_relationship, search_graph,
get_graph_summary, get_graph_analytics
- Reasoning: run_reasoning, abductive_reasoning
- Export & provenance: export_graph (JSON/CSV/GraphML/Parquet/RDF), get_provenance
4 resources: semantica://graph/summary, semantica://decisions/list,
semantica://schema/info, semantica://ontology/schema
Package layout:
mcp/__init__.py + __main__.py — entry points (python -m mcp)
mcp/server.py — SemanticaMCPServer + stdio event loop
mcp/session.py — lazy ContextGraph singleton
mcp/schemas.py — JSON Schema for all 17 tool inputs
mcp/tools/{extraction,decisions,graph,reasoning,export}.py
mcp/resources/registry.py — URI → handler map
mcp/README.md — per-tool setup (Claude Code, Cursor, Windsurf,
Cline, Continue, VS Code, Amazon Q)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
168 lines
5.7 KiB
Python
168 lines
5.7 KiB
Python
"""
|
|
Extraction tools — NER, relation extraction, event detection, triplets.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from typing import Any
|
|
|
|
from mcp.schemas import EXTRACT_ALL, EXTRACT_ENTITIES, EXTRACT_RELATIONS
|
|
|
|
log = logging.getLogger("semantica.mcp.tools.extraction")
|
|
|
|
|
|
def _clear_cache() -> None:
|
|
try:
|
|
from semantica.semantic_extract.cache import _result_cache
|
|
_result_cache.clear()
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
def handle_extract_entities(args: dict) -> dict:
|
|
"""Extract named entities from text using Semantica NER."""
|
|
text = args.get("text", "").strip()
|
|
if not text:
|
|
return {"error": "text is required", "entities": []}
|
|
_clear_cache()
|
|
try:
|
|
from semantica.semantic_extract import NamedEntityRecognizer
|
|
entities = NamedEntityRecognizer().extract(text) or []
|
|
return {
|
|
"entities": [
|
|
{
|
|
"label": getattr(e, "label", str(e)),
|
|
"type": getattr(e, "type", None),
|
|
"start": getattr(e, "start", None),
|
|
"end": getattr(e, "end", None),
|
|
"confidence": getattr(e, "confidence", None),
|
|
}
|
|
for e in entities
|
|
],
|
|
"count": len(entities),
|
|
}
|
|
except Exception as exc:
|
|
log.exception("extract_entities failed")
|
|
return {"error": str(exc), "entities": []}
|
|
|
|
|
|
def handle_extract_relations(args: dict) -> dict:
|
|
"""Extract relations and triplets from text."""
|
|
text = args.get("text", "").strip()
|
|
if not text:
|
|
return {"error": "text is required", "relations": [], "triplets": []}
|
|
_clear_cache()
|
|
try:
|
|
from semantica.semantic_extract import RelationExtractor, TripletExtractor
|
|
relations = RelationExtractor().extract(text) or []
|
|
triplets = TripletExtractor().extract(text) or []
|
|
return {
|
|
"relations": [
|
|
{
|
|
"source": getattr(r, "source", None),
|
|
"type": getattr(r, "type", None),
|
|
"target": getattr(r, "target", None),
|
|
"confidence": getattr(r, "confidence", None),
|
|
}
|
|
for r in relations
|
|
],
|
|
"triplets": [
|
|
{
|
|
"subject": getattr(t, "subject", None),
|
|
"predicate": getattr(t, "predicate", None),
|
|
"object": getattr(t, "object", None),
|
|
}
|
|
for t in triplets
|
|
],
|
|
"relation_count": len(relations),
|
|
"triplet_count": len(triplets),
|
|
}
|
|
except Exception as exc:
|
|
log.exception("extract_relations failed")
|
|
return {"error": str(exc), "relations": [], "triplets": []}
|
|
|
|
|
|
def handle_extract_all(args: dict) -> dict:
|
|
"""Run the full extraction pipeline: NER + relations + events + triplets."""
|
|
text = args.get("text", "").strip()
|
|
if not text:
|
|
return {"error": "text is required"}
|
|
include_events = args.get("include_events", True)
|
|
include_triplets = args.get("include_triplets", True)
|
|
_clear_cache()
|
|
result: dict[str, Any] = {}
|
|
try:
|
|
from semantica.semantic_extract import (
|
|
CoreferenceResolver,
|
|
EventDetector,
|
|
NamedEntityRecognizer,
|
|
RelationExtractor,
|
|
TripletExtractor,
|
|
)
|
|
|
|
entities = NamedEntityRecognizer().extract(text) or []
|
|
result["entities"] = [
|
|
{"label": getattr(e, "label", str(e)), "type": getattr(e, "type", None)}
|
|
for e in entities
|
|
]
|
|
|
|
resolved = CoreferenceResolver().resolve(text)
|
|
relations = RelationExtractor().extract(resolved) or []
|
|
result["relations"] = [
|
|
{"source": getattr(r, "source", None),
|
|
"type": getattr(r, "type", None),
|
|
"target": getattr(r, "target", None)}
|
|
for r in relations
|
|
]
|
|
|
|
if include_events:
|
|
events = EventDetector().extract(text) or []
|
|
result["events"] = [
|
|
{"type": getattr(ev, "type", None),
|
|
"trigger": getattr(ev, "trigger", str(ev))}
|
|
for ev in events
|
|
]
|
|
|
|
if include_triplets:
|
|
triplets = TripletExtractor().extract(resolved) or []
|
|
result["triplets"] = [
|
|
{"subject": getattr(t, "subject", None),
|
|
"predicate": getattr(t, "predicate", None),
|
|
"object": getattr(t, "object", None)}
|
|
for t in triplets
|
|
]
|
|
|
|
result["summary"] = {
|
|
"entities": len(result.get("entities", [])),
|
|
"relations": len(result.get("relations", [])),
|
|
"events": len(result.get("events", [])),
|
|
"triplets": len(result.get("triplets", [])),
|
|
}
|
|
return result
|
|
except Exception as exc:
|
|
log.exception("extract_all failed")
|
|
return {"error": str(exc)}
|
|
|
|
|
|
EXTRACTION_TOOLS = [
|
|
{
|
|
"name": "extract_entities",
|
|
"description": "Extract named entities (people, places, organisations, concepts) from text.",
|
|
"inputSchema": EXTRACT_ENTITIES,
|
|
"_handler": handle_extract_entities,
|
|
},
|
|
{
|
|
"name": "extract_relations",
|
|
"description": "Extract relations and (subject, predicate, object) triplets from text.",
|
|
"inputSchema": EXTRACT_RELATIONS,
|
|
"_handler": handle_extract_relations,
|
|
},
|
|
{
|
|
"name": "extract_all",
|
|
"description": "Run the full Semantica extraction pipeline: NER, coreference resolution, relation extraction, event detection, and triplet generation.",
|
|
"inputSchema": EXTRACT_ALL,
|
|
"_handler": handle_extract_all,
|
|
},
|
|
]
|