mirror of
https://github.com/semantica-agi/semantica.git
synced 2026-08-29 04:26:20 +00:00
feat(plugins): add MCP server + 4 new plugin bundles (Windsurf, Cline, Continue, VS Code)
MCP Server (semantica/mcp_server.py): - Full stdio-based MCP server compatible with Claude Desktop, Windsurf, Cline, Continue, VS Code, Roo Code, and any MCP-aware tool - 12 tools: extract_entities, extract_relations, record_decision, query_decisions, find_precedents, get_causal_chain, add_entity, add_relationship, run_reasoning, get_graph_analytics, export_graph, get_graph_summary - 3 resources: semantica://graph/summary, semantica://decisions/list, semantica://schema/info - Lazy graph session with optional SEMANTICA_KG_PATH env var - JSON-RPC 2.0 over stdin/stdout; run with: python -m semantica.mcp_server New plugin bundles (each: plugin.json + marketplace.json + README.md): - plugins/.windsurf-plugin/ — Windsurf MCP config + 17 skills + 3 agents - plugins/.cline-plugin/ — Cline MCP config + 17 skills + 3 agents - plugins/.continue-plugin/ — Continue MCP config + 17 skills + 3 agents - plugins/.vscode-plugin/ — VS Code MCP config + 17 skills + 3 agents Updated plugins/.claude-plugin/README.md: - Platform support table expanded to 9 tools - Full MCP server section: per-tool config snippets for Claude Desktop, Windsurf, Cline, Continue, VS Code; tool/resource reference tables; environment variables Updated README.md: - Hero line updated to mention MCP server - Visual grid: Windsurf/VS Code/Cline/Continue → 'MCP server + plugin'; Claude Desktop → 'MCP server' - Plugin Bundles section: expanded table listing all 7 bundles with dirs - New MCP Server section with quick-start snippet and tool/resource list - Detailed integrations table: corrected connection types and config paths Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
f2eb3e1608
commit
ab93ec3e8f
@@ -55,7 +55,7 @@ pip install semantica
|
|||||||
|
|
||||||
## 🔌 Works With Every AI Tool
|
## 🔌 Works With Every AI Tool
|
||||||
|
|
||||||
Semantica ships **native plugin bundles** for Claude Code, Cursor, and Codex — and connects to any other tool via its **REST API** (FastAPI server, port 8000) or as an **MCP data source** you can pull from.
|
Semantica ships **native plugin bundles** for Claude Code, Cursor, and Codex, an **MCP server** (`python -m semantica.mcp_server`) for Windsurf, Cline, Continue, VS Code, and Claude Desktop, and a **REST API** (FastAPI, port 8000) for any other tool.
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -77,17 +77,17 @@ Semantica ships **native plugin bundles** for Claude Code, Cursor, and Codex —
|
|||||||
<td align="center" width="12.5%">
|
<td align="center" width="12.5%">
|
||||||
<a href="https://windsurf.com"><img src="https://exafunction.github.io/public/brand/windsurf-black-symbol.svg" alt="Windsurf" width="48" height="48" /></a><br/>
|
<a href="https://windsurf.com"><img src="https://exafunction.github.io/public/brand/windsurf-black-symbol.svg" alt="Windsurf" width="48" height="48" /></a><br/>
|
||||||
<strong>Windsurf</strong><br/>
|
<strong>Windsurf</strong><br/>
|
||||||
<sub>REST API</sub>
|
<sub>MCP server + plugin</sub>
|
||||||
</td>
|
</td>
|
||||||
<td align="center" width="12.5%">
|
<td align="center" width="12.5%">
|
||||||
<a href="https://claude.ai/download"><img src="https://github.com/anthropics.png?size=120" alt="Claude Desktop" width="48" height="48" /></a><br/>
|
<a href="https://claude.ai/download"><img src="https://github.com/anthropics.png?size=120" alt="Claude Desktop" width="48" height="48" /></a><br/>
|
||||||
<strong>Claude Desktop</strong><br/>
|
<strong>Claude Desktop</strong><br/>
|
||||||
<sub>REST API</sub>
|
<sub>MCP server</sub>
|
||||||
</td>
|
</td>
|
||||||
<td align="center" width="12.5%">
|
<td align="center" width="12.5%">
|
||||||
<a href="https://github.com/microsoft/vscode"><img src="https://github.com/microsoft.png?size=120" alt="VS Code" width="48" height="48" /></a><br/>
|
<a href="https://github.com/microsoft/vscode"><img src="https://github.com/microsoft.png?size=120" alt="VS Code" width="48" height="48" /></a><br/>
|
||||||
<strong>VS Code</strong><br/>
|
<strong>VS Code</strong><br/>
|
||||||
<sub>REST API</sub>
|
<sub>MCP server + plugin</sub>
|
||||||
</td>
|
</td>
|
||||||
<td align="center" width="12.5%">
|
<td align="center" width="12.5%">
|
||||||
<a href="https://github.com/features/copilot"><img src="https://github.com/github.png?size=120" alt="GitHub Copilot" width="48" height="48" /></a><br/>
|
<a href="https://github.com/features/copilot"><img src="https://github.com/github.png?size=120" alt="GitHub Copilot" width="48" height="48" /></a><br/>
|
||||||
@@ -97,7 +97,7 @@ Semantica ships **native plugin bundles** for Claude Code, Cursor, and Codex —
|
|||||||
<td align="center" width="12.5%">
|
<td align="center" width="12.5%">
|
||||||
<a href="https://github.com/cline/cline"><img src="https://github.com/cline.png?size=120" alt="Cline" width="48" height="48" /></a><br/>
|
<a href="https://github.com/cline/cline"><img src="https://github.com/cline.png?size=120" alt="Cline" width="48" height="48" /></a><br/>
|
||||||
<strong>Cline</strong><br/>
|
<strong>Cline</strong><br/>
|
||||||
<sub>REST API</sub>
|
<sub>MCP server + plugin</sub>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -109,7 +109,7 @@ Semantica ships **native plugin bundles** for Claude Code, Cursor, and Codex —
|
|||||||
<td align="center" width="12.5%">
|
<td align="center" width="12.5%">
|
||||||
<a href="https://github.com/continuedev/continue"><img src="https://github.com/continuedev.png?size=120" alt="Continue" width="48" height="48" /></a><br/>
|
<a href="https://github.com/continuedev/continue"><img src="https://github.com/continuedev.png?size=120" alt="Continue" width="48" height="48" /></a><br/>
|
||||||
<strong>Continue</strong><br/>
|
<strong>Continue</strong><br/>
|
||||||
<sub>REST API</sub>
|
<sub>MCP server + plugin</sub>
|
||||||
</td>
|
</td>
|
||||||
<td align="center" width="12.5%">
|
<td align="center" width="12.5%">
|
||||||
<a href="https://github.com/block/goose"><img src="https://github.com/block.png?size=120" alt="Goose" width="48" height="48" /></a><br/>
|
<a href="https://github.com/block/goose"><img src="https://github.com/block.png?size=120" alt="Goose" width="48" height="48" /></a><br/>
|
||||||
@@ -146,7 +146,17 @@ Semantica ships **native plugin bundles** for Claude Code, Cursor, and Codex —
|
|||||||
|
|
||||||
### Plugin Bundles (Claude Code · Cursor · Codex)
|
### Plugin Bundles (Claude Code · Cursor · Codex)
|
||||||
|
|
||||||
Native plugin bundles live under [`plugins/`](plugins/) — install once, works across all three tools.
|
Native plugin bundles live under [`plugins/`](plugins/). Each directory contains a `plugin.json`, `marketplace.json`, and `README.md`.
|
||||||
|
|
||||||
|
| Bundle | Directory | Tools |
|
||||||
|
|---|---|---|
|
||||||
|
| Claude Code | [`plugins/.claude-plugin/`](plugins/.claude-plugin/) | 17 skills · 3 agents · hooks |
|
||||||
|
| Cursor | [`plugins/.cursor-plugin/`](plugins/.cursor-plugin/) | 17 skills · 3 agents · hooks |
|
||||||
|
| Codex CLI | [`plugins/.codex-plugin/`](plugins/.codex-plugin/) | 17 skills · 3 agents |
|
||||||
|
| Windsurf | [`plugins/.windsurf-plugin/`](plugins/.windsurf-plugin/) | 17 skills · 3 agents · MCP config |
|
||||||
|
| Cline | [`plugins/.cline-plugin/`](plugins/.cline-plugin/) | 17 skills · 3 agents · MCP config |
|
||||||
|
| Continue | [`plugins/.continue-plugin/`](plugins/.continue-plugin/) | 17 skills · 3 agents · MCP config |
|
||||||
|
| VS Code | [`plugins/.vscode-plugin/`](plugins/.vscode-plugin/) | 17 skills · 3 agents · MCP config |
|
||||||
|
|
||||||
**17 domain skills:**
|
**17 domain skills:**
|
||||||
|
|
||||||
@@ -182,9 +192,36 @@ Native plugin bundles live under [`plugins/`](plugins/) — install once, works
|
|||||||
|
|
||||||
→ [`plugins/.claude-plugin/README.md`](plugins/.claude-plugin/README.md)
|
→ [`plugins/.claude-plugin/README.md`](plugins/.claude-plugin/README.md)
|
||||||
|
|
||||||
|
### MCP Server (expose Semantica to any MCP-aware tool)
|
||||||
|
|
||||||
|
Semantica ships a full **MCP server** (`semantica/mcp_server.py`) — run it once and any MCP-compatible tool connects automatically:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -m semantica.mcp_server
|
||||||
|
```
|
||||||
|
|
||||||
|
Add to your tool's config (Claude Desktop, Windsurf, Cline, Continue, VS Code, Roo Code):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"semantica": {
|
||||||
|
"command": "python",
|
||||||
|
"args": ["-m", "semantica.mcp_server"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**12 tools exposed:** `extract_entities`, `extract_relations`, `record_decision`, `query_decisions`, `find_precedents`, `get_causal_chain`, `add_entity`, `add_relationship`, `run_reasoning`, `get_graph_analytics`, `export_graph`, `get_graph_summary`
|
||||||
|
|
||||||
|
**3 resources:** `semantica://graph/summary`, `semantica://decisions/list`, `semantica://schema/info`
|
||||||
|
|
||||||
|
See [`plugins/.claude-plugin/README.md`](plugins/.claude-plugin/README.md) for per-tool config snippets.
|
||||||
|
|
||||||
### MCP Client (Ingest from MCP Servers)
|
### MCP Client (Ingest from MCP Servers)
|
||||||
|
|
||||||
Semantica includes an **MCP client** (`semantica/ingest/mcp_client.py`) that lets you pull data from any Python/FastMCP server into a knowledge graph:
|
Semantica also includes an **MCP client** (`semantica/ingest/mcp_client.py`) that lets you pull data from any Python/FastMCP server into a knowledge graph:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from semantica.ingest import MCPClient
|
from semantica.ingest import MCPClient
|
||||||
@@ -825,13 +862,13 @@ Start the Semantica server (`python -m semantica.server`, port 8000) and point a
|
|||||||
| [Claude Code](https://claude.com/product/claude-code) | **Native plugin** | `plugins/.claude-plugin/` — 17 skills, 3 agents, `hooks.json` |
|
| [Claude Code](https://claude.com/product/claude-code) | **Native plugin** | `plugins/.claude-plugin/` — 17 skills, 3 agents, `hooks.json` |
|
||||||
| [Cursor](https://cursor.com) | **Native plugin** | `plugins/.cursor-plugin/` — same 17 skills + 3 agents |
|
| [Cursor](https://cursor.com) | **Native plugin** | `plugins/.cursor-plugin/` — same 17 skills + 3 agents |
|
||||||
| [Codex CLI](https://github.com/openai/codex) | **Native plugin** | `plugins/.codex-plugin/` — same 17 skills + 3 agents |
|
| [Codex CLI](https://github.com/openai/codex) | **Native plugin** | `plugins/.codex-plugin/` — same 17 skills + 3 agents |
|
||||||
| [Windsurf](https://windsurf.com) | REST API | Point at `http://localhost:8000/api` |
|
| [Windsurf](https://windsurf.com) | **MCP server** + plugin | `plugins/.windsurf-plugin/` · add `python -m semantica.mcp_server` to `~/.codeium/windsurf/mcp_config.json` |
|
||||||
| [Claude Desktop](https://claude.ai/download) | REST API | Point at `http://localhost:8000/api` |
|
| [Claude Desktop](https://claude.ai/download) | **MCP server** | Add `python -m semantica.mcp_server` to `claude_desktop_config.json` |
|
||||||
| [VS Code](https://github.com/microsoft/vscode) | REST API | Use any REST client extension |
|
| [VS Code](https://github.com/microsoft/vscode) | **MCP server** + plugin | `plugins/.vscode-plugin/` · add to `settings.json` under `mcp.servers` |
|
||||||
| [GitHub Copilot](https://github.com/features/copilot) | REST API | Use via Copilot Chat custom tools |
|
| [GitHub Copilot](https://github.com/features/copilot) | REST API | Use via Copilot Chat custom tools |
|
||||||
| [Cline](https://github.com/cline/cline) | REST API | Add as a custom tool endpoint |
|
| [Cline](https://github.com/cline/cline) | **MCP server** + plugin | `plugins/.cline-plugin/` · add server in Cline MCP settings panel |
|
||||||
| [Roo Code](https://github.com/RooCodeInc/Roo-Code) | REST API | Add as a custom tool endpoint |
|
| [Roo Code](https://github.com/RooCodeInc/Roo-Code) | **MCP server** | Add `python -m semantica.mcp_server` in Roo Code MCP settings |
|
||||||
| [Continue](https://github.com/continuedev/continue) | REST API | Add to `~/.continue/config.json` as context provider |
|
| [Continue](https://github.com/continuedev/continue) | **MCP server** + plugin | `plugins/.continue-plugin/` · add to `~/.continue/config.json` under `mcpServers` |
|
||||||
| [Goose](https://github.com/block/goose) | REST API | Add to Goose toolset config |
|
| [Goose](https://github.com/block/goose) | REST API | Add to Goose toolset config |
|
||||||
| [Kilo Code](https://github.com/Kilo-Org/kilocode) | REST API | Add as custom REST tool |
|
| [Kilo Code](https://github.com/Kilo-Org/kilocode) | REST API | Add as custom REST tool |
|
||||||
| [Aider](https://github.com/Aider-AI/aider) | REST API | Pass context from the API into prompts |
|
| [Aider](https://github.com/Aider-AI/aider) | REST API | Pass context from the API into prompts |
|
||||||
|
|||||||
@@ -2,13 +2,21 @@
|
|||||||
|
|
||||||
Semantica ships a shared plugin bundle under `plugins/` with skills, agents, and hooks for knowledge graphs, context graphs, decision intelligence, reasoning, explainability, provenance, ontology, and export workflows.
|
Semantica ships a shared plugin bundle under `plugins/` with skills, agents, and hooks for knowledge graphs, context graphs, decision intelligence, reasoning, explainability, provenance, ontology, and export workflows.
|
||||||
|
|
||||||
This README is for community users who want to install or reuse the plugin package across Claude, Cursor, and Codex.
|
This README covers installation across every supported platform.
|
||||||
|
|
||||||
## Supported Platforms
|
## Supported Platforms
|
||||||
|
|
||||||
- Claude Code
|
| Platform | Method | Config file |
|
||||||
- Cursor
|
|---|---|---|
|
||||||
- Codex
|
| Claude Code | Native plugin bundle | `plugins/.claude-plugin/plugin.json` |
|
||||||
|
| Cursor | Native plugin bundle | `plugins/.cursor-plugin/plugin.json` |
|
||||||
|
| Codex CLI | Native plugin bundle | `plugins/.codex-plugin/plugin.json` |
|
||||||
|
| Windsurf | MCP server + plugin bundle | `plugins/.windsurf-plugin/plugin.json` |
|
||||||
|
| Cline (VS Code) | MCP server + plugin bundle | `plugins/.cline-plugin/plugin.json` |
|
||||||
|
| Continue | MCP server | `plugins/.continue-plugin/plugin.json` |
|
||||||
|
| VS Code | MCP server | `plugins/.vscode-plugin/plugin.json` |
|
||||||
|
| Claude Desktop | MCP server | — (see MCP section below) |
|
||||||
|
| Any MCP client | MCP server | `python -m semantica.mcp_server` |
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
@@ -23,12 +31,16 @@ cd semantica
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
plugins/
|
plugins/
|
||||||
skills/
|
skills/ ← 17 domain skills
|
||||||
agents/
|
agents/ ← 3 specialized agents
|
||||||
hooks/
|
hooks/ ← hooks.json
|
||||||
.claude-plugin/
|
.claude-plugin/ ← Claude Code manifest
|
||||||
.cursor-plugin/
|
.cursor-plugin/ ← Cursor manifest
|
||||||
.codex-plugin/
|
.codex-plugin/ ← Codex CLI manifest
|
||||||
|
.windsurf-plugin/← Windsurf manifest + MCP config
|
||||||
|
.cline-plugin/ ← Cline manifest + MCP config
|
||||||
|
.continue-plugin/← Continue manifest + MCP config
|
||||||
|
.vscode-plugin/ ← VS Code manifest + MCP config
|
||||||
```
|
```
|
||||||
|
|
||||||
## Plugin Contents
|
## Plugin Contents
|
||||||
@@ -128,6 +140,114 @@ After installing on any platform, these are good smoke tests:
|
|||||||
4. `/semantica:explain decision <decision_id>`
|
4. `/semantica:explain decision <decision_id>`
|
||||||
5. `/semantica:validate graph`
|
5. `/semantica:validate graph`
|
||||||
|
|
||||||
|
## MCP Server (Windsurf · Cline · Continue · VS Code · Claude Desktop · Any tool)
|
||||||
|
|
||||||
|
Semantica includes a full MCP server (`semantica/mcp_server.py`) that exposes 12 tools and 3 resources over stdio — compatible with any MCP-aware tool.
|
||||||
|
|
||||||
|
### Start the server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -m semantica.mcp_server
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configure in your tool
|
||||||
|
|
||||||
|
**Claude Desktop** — `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"semantica": {
|
||||||
|
"command": "python",
|
||||||
|
"args": ["-m", "semantica.mcp_server"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Windsurf** — `~/.codeium/windsurf/mcp_config.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"semantica": {
|
||||||
|
"command": "python",
|
||||||
|
"args": ["-m", "semantica.mcp_server"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Cline** — Cline MCP settings panel → Add server:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"semantica": {
|
||||||
|
"command": "python",
|
||||||
|
"args": ["-m", "semantica.mcp_server"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Continue** — `~/.continue/config.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": [
|
||||||
|
{
|
||||||
|
"name": "semantica",
|
||||||
|
"command": "python",
|
||||||
|
"args": ["-m", "semantica.mcp_server"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**VS Code** — `settings.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcp.servers": {
|
||||||
|
"semantica": {
|
||||||
|
"command": "python",
|
||||||
|
"args": ["-m", "semantica.mcp_server"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Available MCP tools
|
||||||
|
|
||||||
|
| Tool | Description |
|
||||||
|
|---|---|
|
||||||
|
| `extract_entities` | Named entity recognition from text |
|
||||||
|
| `extract_relations` | Relation and triplet extraction from text |
|
||||||
|
| `record_decision` | Record a decision with full context and metadata |
|
||||||
|
| `query_decisions` | Query recorded decisions by natural language or category |
|
||||||
|
| `find_precedents` | Find past decisions similar to a scenario |
|
||||||
|
| `get_causal_chain` | Trace upstream/downstream causal chain from a decision |
|
||||||
|
| `add_entity` | Add a node/entity to the knowledge graph |
|
||||||
|
| `add_relationship` | Add a directed edge between two entities |
|
||||||
|
| `run_reasoning` | Run IF/THEN rules over facts to derive new facts |
|
||||||
|
| `get_graph_analytics` | PageRank centrality and community detection |
|
||||||
|
| `export_graph` | Export graph as Turtle, JSON-LD, N-Triples, or JSON |
|
||||||
|
| `get_graph_summary` | Node count, decision count, graph status |
|
||||||
|
|
||||||
|
### Available MCP resources
|
||||||
|
|
||||||
|
| URI | Description |
|
||||||
|
|---|---|
|
||||||
|
| `semantica://graph/summary` | High-level graph statistics |
|
||||||
|
| `semantica://decisions/list` | All recorded decisions |
|
||||||
|
| `semantica://schema/info` | Server info and capability list |
|
||||||
|
|
||||||
|
### Environment variables
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
|---|---|
|
||||||
|
| `SEMANTICA_KG_PATH` | Path to a persisted graph to load on start |
|
||||||
|
| `SEMANTICA_LOG_LEVEL` | Log level: DEBUG, INFO, WARNING (default: WARNING) |
|
||||||
|
|
||||||
## Community Notes
|
## Community Notes
|
||||||
|
|
||||||
- Keep plugin name/version/keywords updated in each manifest before publishing.
|
- Keep plugin name/version/keywords updated in each manifest before publishing.
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Semantica — Cline Plugin
|
||||||
|
|
||||||
|
Adds all 17 Semantica skills, 3 agents, and hook configuration to Cline (VS Code extension).
|
||||||
|
|
||||||
|
## MCP Server Setup (recommended)
|
||||||
|
|
||||||
|
In Cline settings, add a new MCP server:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"semantica": {
|
||||||
|
"command": "python",
|
||||||
|
"args": ["-m", "semantica.mcp_server"],
|
||||||
|
"env": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Cline will discover all 12 Semantica tools automatically on connection.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Python 3.8+
|
||||||
|
- `pip install semantica`
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "semantica-cline",
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "semantica",
|
||||||
|
"description": "Semantica plugin for Cline: knowledge graph skills, reasoning, extraction, and visualization.",
|
||||||
|
"source": "./",
|
||||||
|
"category": "Productivity",
|
||||||
|
"tags": [
|
||||||
|
"knowledge-graph",
|
||||||
|
"reasoning",
|
||||||
|
"semantica",
|
||||||
|
"cline"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "semantica-cline",
|
||||||
|
"displayName": "Semantica Cline Plugin",
|
||||||
|
"description": "Semantica plugin for Cline: knowledge graph skills, decision intelligence, reasoning, extraction, and visualization.",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"author": {
|
||||||
|
"name": "Semantica Contributors"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/Hawksight-AI/semantica",
|
||||||
|
"repository": "https://github.com/Hawksight-AI/semantica",
|
||||||
|
"license": "MIT",
|
||||||
|
"keywords": [
|
||||||
|
"semantica",
|
||||||
|
"knowledge graph",
|
||||||
|
"cline",
|
||||||
|
"context graphs",
|
||||||
|
"decision intelligence",
|
||||||
|
"explainability",
|
||||||
|
"causal analysis",
|
||||||
|
"provenance",
|
||||||
|
"ontology",
|
||||||
|
"graph analytics",
|
||||||
|
"semantic extraction",
|
||||||
|
"visualization",
|
||||||
|
"reasoning",
|
||||||
|
"mcp"
|
||||||
|
],
|
||||||
|
"skills": "../skills",
|
||||||
|
"agents": "../agents",
|
||||||
|
"hooks": "../hooks/hooks.json",
|
||||||
|
"mcp": {
|
||||||
|
"server": "python -m semantica.mcp_server",
|
||||||
|
"transport": "stdio"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# Semantica — Continue Plugin
|
||||||
|
|
||||||
|
Adds Semantica as an MCP server and context provider to [Continue.dev](https://continue.dev).
|
||||||
|
|
||||||
|
## MCP Server Setup
|
||||||
|
|
||||||
|
Add to `~/.continue/config.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": [
|
||||||
|
{
|
||||||
|
"name": "semantica",
|
||||||
|
"command": "python",
|
||||||
|
"args": ["-m", "semantica.mcp_server"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Continue will show all Semantica tools in the `@semantica` context provider dropdown.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Python 3.8+
|
||||||
|
- `pip install semantica`
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "semantica-continue",
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "semantica",
|
||||||
|
"description": "Semantica plugin for Continue.dev: knowledge graph context provider, reasoning, and extraction.",
|
||||||
|
"source": "./",
|
||||||
|
"category": "Productivity",
|
||||||
|
"tags": [
|
||||||
|
"knowledge-graph",
|
||||||
|
"reasoning",
|
||||||
|
"semantica",
|
||||||
|
"continue"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"name": "semantica-continue",
|
||||||
|
"displayName": "Semantica Continue Plugin",
|
||||||
|
"description": "Semantica plugin for Continue.dev: knowledge graph context provider, decision intelligence, reasoning, and semantic extraction.",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"author": {
|
||||||
|
"name": "Semantica Contributors"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/Hawksight-AI/semantica",
|
||||||
|
"repository": "https://github.com/Hawksight-AI/semantica",
|
||||||
|
"license": "MIT",
|
||||||
|
"keywords": [
|
||||||
|
"semantica",
|
||||||
|
"knowledge graph",
|
||||||
|
"continue",
|
||||||
|
"context provider",
|
||||||
|
"decision intelligence",
|
||||||
|
"explainability",
|
||||||
|
"causal analysis",
|
||||||
|
"provenance",
|
||||||
|
"ontology",
|
||||||
|
"semantic extraction",
|
||||||
|
"reasoning",
|
||||||
|
"mcp"
|
||||||
|
],
|
||||||
|
"skills": "../skills",
|
||||||
|
"agents": "../agents",
|
||||||
|
"hooks": "../hooks/hooks.json",
|
||||||
|
"mcp": {
|
||||||
|
"server": "python -m semantica.mcp_server",
|
||||||
|
"transport": "stdio"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# Semantica — VS Code Plugin
|
||||||
|
|
||||||
|
Adds Semantica as an MCP server to VS Code (via GitHub Copilot Chat or any MCP-aware extension).
|
||||||
|
|
||||||
|
## MCP Server Setup
|
||||||
|
|
||||||
|
Add to your VS Code `settings.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"github.copilot.chat.mcp.servers": {
|
||||||
|
"semantica": {
|
||||||
|
"command": "python",
|
||||||
|
"args": ["-m", "semantica.mcp_server"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Or if using the VS Code MCP extension directly:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcp.servers": {
|
||||||
|
"semantica": {
|
||||||
|
"command": "python",
|
||||||
|
"args": ["-m", "semantica.mcp_server"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Python 3.8+
|
||||||
|
- `pip install semantica`
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "semantica-vscode",
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "semantica",
|
||||||
|
"description": "Semantica plugin for VS Code: knowledge graph skills, reasoning, extraction, and visualization.",
|
||||||
|
"source": "./",
|
||||||
|
"category": "Productivity",
|
||||||
|
"tags": [
|
||||||
|
"knowledge-graph",
|
||||||
|
"reasoning",
|
||||||
|
"semantica",
|
||||||
|
"vscode"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "semantica-vscode",
|
||||||
|
"displayName": "Semantica VS Code Plugin",
|
||||||
|
"description": "Semantica plugin for VS Code: knowledge graph skills, decision intelligence, reasoning, extraction, and visualization via MCP server.",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"author": {
|
||||||
|
"name": "Semantica Contributors"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/Hawksight-AI/semantica",
|
||||||
|
"repository": "https://github.com/Hawksight-AI/semantica",
|
||||||
|
"license": "MIT",
|
||||||
|
"keywords": [
|
||||||
|
"semantica",
|
||||||
|
"knowledge graph",
|
||||||
|
"vscode",
|
||||||
|
"context graphs",
|
||||||
|
"decision intelligence",
|
||||||
|
"explainability",
|
||||||
|
"causal analysis",
|
||||||
|
"provenance",
|
||||||
|
"ontology",
|
||||||
|
"graph analytics",
|
||||||
|
"semantic extraction",
|
||||||
|
"visualization",
|
||||||
|
"reasoning",
|
||||||
|
"mcp"
|
||||||
|
],
|
||||||
|
"skills": "../skills",
|
||||||
|
"agents": "../agents",
|
||||||
|
"hooks": "../hooks/hooks.json",
|
||||||
|
"mcp": {
|
||||||
|
"server": "python -m semantica.mcp_server",
|
||||||
|
"transport": "stdio"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# Semantica — Windsurf Plugin
|
||||||
|
|
||||||
|
Adds all 17 Semantica skills, 3 agents, and hook configuration to Windsurf.
|
||||||
|
|
||||||
|
## MCP Server Setup (recommended)
|
||||||
|
|
||||||
|
Add to your Windsurf MCP config (`~/.codeium/windsurf/mcp_config.json`):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"semantica": {
|
||||||
|
"command": "python",
|
||||||
|
"args": ["-m", "semantica.mcp_server"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Windsurf will then have access to all 12 Semantica tools (extract, record_decision, query_decisions, find_precedents, get_causal_chain, add_entity, add_relationship, run_reasoning, get_graph_analytics, export_graph, and more) directly in the AI panel.
|
||||||
|
|
||||||
|
## Skills
|
||||||
|
|
||||||
|
All 17 skills under `plugins/skills/` are available as slash commands once the plugin is loaded.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Python 3.8+
|
||||||
|
- `pip install semantica`
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "semantica-windsurf",
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "semantica",
|
||||||
|
"description": "Semantica plugin for Windsurf: knowledge graph skills, reasoning, extraction, and visualization.",
|
||||||
|
"source": "./",
|
||||||
|
"category": "Productivity",
|
||||||
|
"tags": [
|
||||||
|
"knowledge-graph",
|
||||||
|
"reasoning",
|
||||||
|
"semantica",
|
||||||
|
"windsurf"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "semantica-windsurf",
|
||||||
|
"displayName": "Semantica Windsurf Plugin",
|
||||||
|
"description": "Semantica plugin for Windsurf: knowledge graph skills, decision intelligence, reasoning, extraction, and visualization.",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"author": {
|
||||||
|
"name": "Semantica Contributors"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/Hawksight-AI/semantica",
|
||||||
|
"repository": "https://github.com/Hawksight-AI/semantica",
|
||||||
|
"license": "MIT",
|
||||||
|
"keywords": [
|
||||||
|
"semantica",
|
||||||
|
"knowledge graph",
|
||||||
|
"windsurf",
|
||||||
|
"context graphs",
|
||||||
|
"decision intelligence",
|
||||||
|
"explainability",
|
||||||
|
"causal analysis",
|
||||||
|
"provenance",
|
||||||
|
"ontology",
|
||||||
|
"graph analytics",
|
||||||
|
"semantic extraction",
|
||||||
|
"visualization",
|
||||||
|
"reasoning",
|
||||||
|
"mcp"
|
||||||
|
],
|
||||||
|
"skills": "../skills",
|
||||||
|
"agents": "../agents",
|
||||||
|
"hooks": "../hooks/hooks.json",
|
||||||
|
"mcp": {
|
||||||
|
"server": "python -m semantica.mcp_server",
|
||||||
|
"transport": "stdio"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,606 @@
|
|||||||
|
"""
|
||||||
|
Semantica MCP Server
|
||||||
|
|
||||||
|
Exposes Semantica's knowledge graph, decision intelligence, semantic extraction,
|
||||||
|
reasoning, and analytics capabilities as an MCP (Model Context Protocol) server
|
||||||
|
over stdio — compatible with Claude Desktop, Windsurf, Cline, Continue, VS Code,
|
||||||
|
Roo Code, and any other MCP-aware tool.
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
Configure in your tool's MCP settings:
|
||||||
|
|
||||||
|
Claude Desktop / Windsurf / Cline / Continue / VS Code:
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"semantica": {
|
||||||
|
"command": "python",
|
||||||
|
"args": ["-m", "semantica.mcp_server"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Run directly:
|
||||||
|
python -m semantica.mcp_server
|
||||||
|
|
||||||
|
Environment variables:
|
||||||
|
SEMANTICA_KG_PATH — path to a persisted graph to load on start (optional)
|
||||||
|
SEMANTICA_LOG_LEVEL — log level: DEBUG, INFO, WARNING (default: WARNING)
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
# ── logging ────────────────────────────────────────────────────────────────
|
||||||
|
_log_level = getattr(logging, os.environ.get("SEMANTICA_LOG_LEVEL", "WARNING").upper(), logging.WARNING)
|
||||||
|
logging.basicConfig(stream=sys.stderr, level=_log_level,
|
||||||
|
format="%(asctime)s [semantica-mcp] %(levelname)s %(message)s")
|
||||||
|
log = logging.getLogger("semantica.mcp_server")
|
||||||
|
|
||||||
|
# ── lazy graph session ──────────────────────────────────────────────────────
|
||||||
|
_graph: Any = None
|
||||||
|
|
||||||
|
|
||||||
|
def _get_graph():
|
||||||
|
global _graph
|
||||||
|
if _graph is None:
|
||||||
|
from semantica.context import ContextGraph
|
||||||
|
_graph = ContextGraph(advanced_analytics=True)
|
||||||
|
kg_path = os.environ.get("SEMANTICA_KG_PATH")
|
||||||
|
if kg_path and os.path.exists(kg_path):
|
||||||
|
try:
|
||||||
|
_graph.load(kg_path)
|
||||||
|
log.info("Loaded graph from %s", kg_path)
|
||||||
|
except Exception as exc:
|
||||||
|
log.warning("Could not load graph from %s: %s", kg_path, exc)
|
||||||
|
return _graph
|
||||||
|
|
||||||
|
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
# Tool implementations
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
def _tool_extract_entities(args: dict) -> dict:
|
||||||
|
"""Extract named entities from text."""
|
||||||
|
text = args.get("text", "")
|
||||||
|
if not text:
|
||||||
|
return {"error": "text is required"}
|
||||||
|
from semantica.semantic_extract import NamedEntityRecognizer
|
||||||
|
from semantica.semantic_extract.cache import _result_cache
|
||||||
|
_result_cache.clear()
|
||||||
|
entities = NamedEntityRecognizer().extract(text)
|
||||||
|
return {
|
||||||
|
"entities": [
|
||||||
|
{"label": getattr(e, "label", str(e)),
|
||||||
|
"type": getattr(e, "type", None),
|
||||||
|
"start": getattr(e, "start", None),
|
||||||
|
"end": getattr(e, "end", None)}
|
||||||
|
for e in (entities or [])
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _tool_extract_relations(args: dict) -> dict:
|
||||||
|
"""Extract relations and triplets from text."""
|
||||||
|
text = args.get("text", "")
|
||||||
|
if not text:
|
||||||
|
return {"error": "text is required"}
|
||||||
|
from semantica.semantic_extract import RelationExtractor, TripletExtractor
|
||||||
|
from semantica.semantic_extract.cache import _result_cache
|
||||||
|
_result_cache.clear()
|
||||||
|
relations = RelationExtractor().extract(text)
|
||||||
|
triplets = TripletExtractor().extract(text)
|
||||||
|
return {
|
||||||
|
"relations": [
|
||||||
|
{"source": getattr(r, "source", None),
|
||||||
|
"type": getattr(r, "type", None),
|
||||||
|
"target": getattr(r, "target", None)}
|
||||||
|
for r in (relations or [])
|
||||||
|
],
|
||||||
|
"triplets": [
|
||||||
|
{"subject": getattr(t, "subject", None),
|
||||||
|
"predicate": getattr(t, "predicate", None),
|
||||||
|
"object": getattr(t, "object", None)}
|
||||||
|
for t in (triplets or [])
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _tool_record_decision(args: dict) -> dict:
|
||||||
|
"""Record a decision with full context into the graph."""
|
||||||
|
required = ["category", "scenario", "reasoning", "outcome", "confidence"]
|
||||||
|
for field in required:
|
||||||
|
if field not in args:
|
||||||
|
return {"error": f"missing required field: {field}"}
|
||||||
|
graph = _get_graph()
|
||||||
|
decision_id = graph.record_decision(
|
||||||
|
category=args["category"],
|
||||||
|
scenario=args["scenario"],
|
||||||
|
reasoning=args["reasoning"],
|
||||||
|
outcome=args["outcome"],
|
||||||
|
confidence=float(args["confidence"]),
|
||||||
|
entities=args.get("entities", []),
|
||||||
|
decision_maker=args.get("decision_maker", "mcp_client"),
|
||||||
|
valid_from=args.get("valid_from"),
|
||||||
|
valid_until=args.get("valid_until"),
|
||||||
|
)
|
||||||
|
return {"decision_id": decision_id, "status": "recorded"}
|
||||||
|
|
||||||
|
|
||||||
|
def _tool_query_decisions(args: dict) -> dict:
|
||||||
|
"""Query decisions by natural language or structured filters."""
|
||||||
|
query = args.get("query", "")
|
||||||
|
category = args.get("category")
|
||||||
|
limit = int(args.get("limit", 10))
|
||||||
|
graph = _get_graph()
|
||||||
|
try:
|
||||||
|
if query:
|
||||||
|
results = graph.find_similar_decisions(query, max_results=limit)
|
||||||
|
elif category:
|
||||||
|
nodes = graph.find_nodes(node_type="decision")
|
||||||
|
results = [n for n in nodes if n.get("category") == category][:limit]
|
||||||
|
else:
|
||||||
|
results = graph.find_nodes(node_type="decision")[:limit]
|
||||||
|
return {"decisions": results if isinstance(results, list) else list(results)}
|
||||||
|
except Exception as exc:
|
||||||
|
return {"error": str(exc), "decisions": []}
|
||||||
|
|
||||||
|
|
||||||
|
def _tool_find_precedents(args: dict) -> dict:
|
||||||
|
"""Find past decisions similar to a given scenario."""
|
||||||
|
scenario = args.get("scenario", "")
|
||||||
|
if not scenario:
|
||||||
|
return {"error": "scenario is required"}
|
||||||
|
max_results = int(args.get("max_results", 5))
|
||||||
|
graph = _get_graph()
|
||||||
|
try:
|
||||||
|
precedents = graph.find_similar_decisions(scenario, max_results=max_results)
|
||||||
|
return {"precedents": precedents if isinstance(precedents, list) else list(precedents)}
|
||||||
|
except Exception as exc:
|
||||||
|
return {"error": str(exc), "precedents": []}
|
||||||
|
|
||||||
|
|
||||||
|
def _tool_get_causal_chain(args: dict) -> dict:
|
||||||
|
"""Get the causal chain for a decision."""
|
||||||
|
decision_id = args.get("decision_id", "")
|
||||||
|
if not decision_id:
|
||||||
|
return {"error": "decision_id is required"}
|
||||||
|
direction = args.get("direction", "downstream")
|
||||||
|
max_depth = int(args.get("max_depth", 5))
|
||||||
|
graph = _get_graph()
|
||||||
|
try:
|
||||||
|
from semantica.context.causal_analyzer import CausalChainAnalyzer
|
||||||
|
analyzer = CausalChainAnalyzer(graph_store=graph)
|
||||||
|
chain = analyzer.get_causal_chain(decision_id, direction=direction, max_depth=max_depth)
|
||||||
|
return {"chain": chain if isinstance(chain, list) else list(chain)}
|
||||||
|
except Exception as exc:
|
||||||
|
return {"error": str(exc), "chain": []}
|
||||||
|
|
||||||
|
|
||||||
|
def _tool_add_entity(args: dict) -> dict:
|
||||||
|
"""Add a node/entity to the knowledge graph."""
|
||||||
|
node_id = args.get("id", "")
|
||||||
|
label = args.get("label", node_id)
|
||||||
|
node_type = args.get("type", "Entity")
|
||||||
|
if not node_id:
|
||||||
|
return {"error": "id is required"}
|
||||||
|
graph = _get_graph()
|
||||||
|
graph.add_node(node_id=node_id, label=label, node_type=node_type,
|
||||||
|
metadata=args.get("metadata", {}))
|
||||||
|
return {"status": "added", "id": node_id}
|
||||||
|
|
||||||
|
|
||||||
|
def _tool_add_relationship(args: dict) -> dict:
|
||||||
|
"""Add a relationship (edge) between two entities."""
|
||||||
|
source = args.get("source", "")
|
||||||
|
target = args.get("target", "")
|
||||||
|
rel_type = args.get("type", "RELATED_TO")
|
||||||
|
if not source or not target:
|
||||||
|
return {"error": "source and target are required"}
|
||||||
|
graph = _get_graph()
|
||||||
|
graph.add_edge(source_id=source, target_id=target, edge_type=rel_type,
|
||||||
|
metadata=args.get("metadata", {}))
|
||||||
|
return {"status": "added", "source": source, "target": target, "type": rel_type}
|
||||||
|
|
||||||
|
|
||||||
|
def _tool_run_reasoning(args: dict) -> dict:
|
||||||
|
"""Run forward-chaining reasoning rules over a set of facts."""
|
||||||
|
facts = args.get("facts", [])
|
||||||
|
rules = args.get("rules", [])
|
||||||
|
if not facts or not rules:
|
||||||
|
return {"error": "facts and rules are required"}
|
||||||
|
from semantica.reasoning import Reasoner
|
||||||
|
reasoner = Reasoner()
|
||||||
|
for rule in rules:
|
||||||
|
reasoner.add_rule(rule)
|
||||||
|
derived = reasoner.infer_facts(facts)
|
||||||
|
return {"derived_facts": derived if isinstance(derived, list) else list(derived)}
|
||||||
|
|
||||||
|
|
||||||
|
def _tool_get_graph_analytics(args: dict) -> dict:
|
||||||
|
"""Compute graph analytics: centrality, community detection, metrics."""
|
||||||
|
graph = _get_graph()
|
||||||
|
try:
|
||||||
|
from semantica.kg import CentralityCalculator, CommunityDetector
|
||||||
|
centrality = CentralityCalculator().calculate_pagerank(graph)
|
||||||
|
communities = CommunityDetector().detect_communities(graph)
|
||||||
|
node_count = len(list(graph.find_nodes()))
|
||||||
|
edge_count = getattr(graph, "edge_count", lambda: 0)()
|
||||||
|
return {
|
||||||
|
"node_count": node_count,
|
||||||
|
"edge_count": edge_count,
|
||||||
|
"top_nodes_by_pagerank": sorted(
|
||||||
|
centrality.items() if hasattr(centrality, "items") else [],
|
||||||
|
key=lambda x: x[1], reverse=True
|
||||||
|
)[:10],
|
||||||
|
"community_count": len(communities) if isinstance(communities, (list, dict)) else 0,
|
||||||
|
}
|
||||||
|
except Exception as exc:
|
||||||
|
return {"error": str(exc)}
|
||||||
|
|
||||||
|
|
||||||
|
def _tool_export_graph(args: dict) -> dict:
|
||||||
|
"""Export the current knowledge graph to a serialised format."""
|
||||||
|
fmt = args.get("format", "json-ld")
|
||||||
|
graph = _get_graph()
|
||||||
|
try:
|
||||||
|
from semantica.export import RDFExporter, JSONExporter
|
||||||
|
if fmt in ("turtle", "ttl", "nt", "xml", "json-ld"):
|
||||||
|
result = RDFExporter().export_to_rdf(graph, format=fmt)
|
||||||
|
else:
|
||||||
|
result = JSONExporter().export(graph)
|
||||||
|
return {"format": fmt, "data": result}
|
||||||
|
except Exception as exc:
|
||||||
|
return {"error": str(exc)}
|
||||||
|
|
||||||
|
|
||||||
|
def _tool_get_graph_summary(args: dict) -> dict:
|
||||||
|
"""Return a high-level summary of the current graph."""
|
||||||
|
graph = _get_graph()
|
||||||
|
try:
|
||||||
|
node_count = len(list(graph.find_nodes()))
|
||||||
|
decisions = graph.find_nodes(node_type="decision")
|
||||||
|
return {
|
||||||
|
"node_count": node_count,
|
||||||
|
"decision_count": len(list(decisions)),
|
||||||
|
"graph_ready": True,
|
||||||
|
}
|
||||||
|
except Exception as exc:
|
||||||
|
return {"error": str(exc), "graph_ready": False}
|
||||||
|
|
||||||
|
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
# MCP protocol tables
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
TOOLS = [
|
||||||
|
{
|
||||||
|
"name": "extract_entities",
|
||||||
|
"description": "Extract named entities (people, places, organisations, concepts) from text using Semantica NER.",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"text": {"type": "string", "description": "Input text to extract entities from"}
|
||||||
|
},
|
||||||
|
"required": ["text"],
|
||||||
|
},
|
||||||
|
"_handler": _tool_extract_entities,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "extract_relations",
|
||||||
|
"description": "Extract relations and (subject, predicate, object) triplets from text.",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"text": {"type": "string", "description": "Input text to extract relations from"}
|
||||||
|
},
|
||||||
|
"required": ["text"],
|
||||||
|
},
|
||||||
|
"_handler": _tool_extract_relations,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "record_decision",
|
||||||
|
"description": "Record a decision into the Semantica knowledge graph with full context, causal links, and metadata.",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"category": {"type": "string", "description": "Decision category, e.g. 'loan_approval'"},
|
||||||
|
"scenario": {"type": "string", "description": "Natural-language situation description"},
|
||||||
|
"reasoning": {"type": "string", "description": "Why this decision was made"},
|
||||||
|
"outcome": {"type": "string", "description": "Decision outcome, e.g. 'approved'"},
|
||||||
|
"confidence": {"type": "number", "description": "Confidence score 0–1"},
|
||||||
|
"decision_maker":{"type": "string", "description": "Who/what made the decision"},
|
||||||
|
"valid_from": {"type": "string", "description": "ISO date validity start (optional)"},
|
||||||
|
"valid_until": {"type": "string", "description": "ISO date validity end (optional)"},
|
||||||
|
},
|
||||||
|
"required": ["category", "scenario", "reasoning", "outcome", "confidence"],
|
||||||
|
},
|
||||||
|
"_handler": _tool_record_decision,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "query_decisions",
|
||||||
|
"description": "Query recorded decisions by natural language, category, or get all recent decisions.",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"query": {"type": "string", "description": "Natural language query (optional)"},
|
||||||
|
"category": {"type": "string", "description": "Filter by category (optional)"},
|
||||||
|
"limit": {"type": "integer", "description": "Max results (default 10)"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"_handler": _tool_query_decisions,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "find_precedents",
|
||||||
|
"description": "Find past decisions similar to a given scenario using hybrid similarity search.",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"scenario": {"type": "string", "description": "Scenario description to find precedents for"},
|
||||||
|
"max_results": {"type": "integer", "description": "Max results (default 5)"},
|
||||||
|
},
|
||||||
|
"required": ["scenario"],
|
||||||
|
},
|
||||||
|
"_handler": _tool_find_precedents,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "get_causal_chain",
|
||||||
|
"description": "Trace the causal chain upstream or downstream from a decision.",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"decision_id": {"type": "string", "description": "Decision ID to trace"},
|
||||||
|
"direction": {"type": "string", "enum": ["upstream", "downstream"], "description": "Trace direction"},
|
||||||
|
"max_depth": {"type": "integer", "description": "Max chain depth (default 5)"},
|
||||||
|
},
|
||||||
|
"required": ["decision_id"],
|
||||||
|
},
|
||||||
|
"_handler": _tool_get_causal_chain,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "add_entity",
|
||||||
|
"description": "Add a node/entity to the Semantica knowledge graph.",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {"type": "string", "description": "Unique node ID"},
|
||||||
|
"label": {"type": "string", "description": "Human-readable label"},
|
||||||
|
"type": {"type": "string", "description": "Node type, e.g. 'Person', 'Organisation'"},
|
||||||
|
"metadata": {"type": "object", "description": "Additional properties"},
|
||||||
|
},
|
||||||
|
"required": ["id"],
|
||||||
|
},
|
||||||
|
"_handler": _tool_add_entity,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "add_relationship",
|
||||||
|
"description": "Add a directed relationship (edge) between two entities in the knowledge graph.",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"source": {"type": "string", "description": "Source node ID"},
|
||||||
|
"target": {"type": "string", "description": "Target node ID"},
|
||||||
|
"type": {"type": "string", "description": "Relationship type, e.g. 'WORKS_AT'"},
|
||||||
|
"metadata": {"type": "object", "description": "Additional edge properties"},
|
||||||
|
},
|
||||||
|
"required": ["source", "target"],
|
||||||
|
},
|
||||||
|
"_handler": _tool_add_relationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "run_reasoning",
|
||||||
|
"description": "Run forward-chaining IF/THEN rules over a set of facts to derive new facts.",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"facts": {
|
||||||
|
"type": "array", "items": {"type": "string"},
|
||||||
|
"description": "List of fact strings, e.g. ['Person(John)', 'Employee(John)']",
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"type": "array", "items": {"type": "string"},
|
||||||
|
"description": "IF/THEN rule strings, e.g. ['IF Employee(?x) THEN WorkerBee(?x)']",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": ["facts", "rules"],
|
||||||
|
},
|
||||||
|
"_handler": _tool_run_reasoning,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "get_graph_analytics",
|
||||||
|
"description": "Compute PageRank centrality and community detection over the knowledge graph.",
|
||||||
|
"inputSchema": {"type": "object", "properties": {}},
|
||||||
|
"_handler": _tool_get_graph_analytics,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "export_graph",
|
||||||
|
"description": "Export the current knowledge graph. Formats: turtle, ttl, nt, xml, json-ld, json.",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"format": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["turtle", "ttl", "nt", "xml", "json-ld", "json"],
|
||||||
|
"description": "Export format (default: json-ld)",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"_handler": _tool_export_graph,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "get_graph_summary",
|
||||||
|
"description": "Return a high-level summary of the current knowledge graph: node count, decision count, status.",
|
||||||
|
"inputSchema": {"type": "object", "properties": {}},
|
||||||
|
"_handler": _tool_get_graph_summary,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
RESOURCES = [
|
||||||
|
{
|
||||||
|
"uri": "semantica://graph/summary",
|
||||||
|
"name": "Graph Summary",
|
||||||
|
"description": "High-level statistics about the current knowledge graph",
|
||||||
|
"mimeType": "application/json",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "semantica://decisions/list",
|
||||||
|
"name": "Decisions",
|
||||||
|
"description": "List of all recorded decisions in the graph",
|
||||||
|
"mimeType": "application/json",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "semantica://schema/info",
|
||||||
|
"name": "Schema Info",
|
||||||
|
"description": "Semantica server info and available capabilities",
|
||||||
|
"mimeType": "application/json",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def _read_resource(uri: str) -> dict:
|
||||||
|
if uri == "semantica://graph/summary":
|
||||||
|
return _tool_get_graph_summary({})
|
||||||
|
if uri == "semantica://decisions/list":
|
||||||
|
return _tool_query_decisions({"limit": 50})
|
||||||
|
if uri == "semantica://schema/info":
|
||||||
|
return {
|
||||||
|
"name": "Semantica",
|
||||||
|
"version": "0.4.0",
|
||||||
|
"tools": [t["name"] for t in TOOLS],
|
||||||
|
"resources": [r["uri"] for r in RESOURCES],
|
||||||
|
}
|
||||||
|
return {"error": f"Unknown resource URI: {uri}"}
|
||||||
|
|
||||||
|
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
# JSON-RPC / MCP protocol handler
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
SERVER_INFO = {
|
||||||
|
"name": "semantica",
|
||||||
|
"version": "0.4.0",
|
||||||
|
}
|
||||||
|
|
||||||
|
CAPABILITIES = {
|
||||||
|
"tools": {"listChanged": False},
|
||||||
|
"resources": {"listChanged": False, "subscribe": False},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _handle(req: dict) -> dict | None:
|
||||||
|
"""Dispatch a single JSON-RPC request; return None for notifications."""
|
||||||
|
method = req.get("method", "")
|
||||||
|
params = req.get("params") or {}
|
||||||
|
req_id = req.get("id")
|
||||||
|
|
||||||
|
def ok(result):
|
||||||
|
return {"jsonrpc": "2.0", "id": req_id, "result": result}
|
||||||
|
|
||||||
|
def err(code, message):
|
||||||
|
return {"jsonrpc": "2.0", "id": req_id, "error": {"code": code, "message": message}}
|
||||||
|
|
||||||
|
# Notifications (no id) — acknowledge silently
|
||||||
|
if req_id is None and method.startswith("notifications/"):
|
||||||
|
return None
|
||||||
|
|
||||||
|
if method == "initialize":
|
||||||
|
return ok({
|
||||||
|
"protocolVersion": "2024-11-05",
|
||||||
|
"capabilities": CAPABILITIES,
|
||||||
|
"serverInfo": SERVER_INFO,
|
||||||
|
})
|
||||||
|
|
||||||
|
if method == "notifications/initialized":
|
||||||
|
return None
|
||||||
|
|
||||||
|
if method == "ping":
|
||||||
|
return ok({})
|
||||||
|
|
||||||
|
if method == "tools/list":
|
||||||
|
tools_out = [
|
||||||
|
{"name": t["name"], "description": t["description"], "inputSchema": t["inputSchema"]}
|
||||||
|
for t in TOOLS
|
||||||
|
]
|
||||||
|
return ok({"tools": tools_out})
|
||||||
|
|
||||||
|
if method == "tools/call":
|
||||||
|
name = params.get("name", "")
|
||||||
|
arguments = params.get("arguments") or {}
|
||||||
|
handler = next((t["_handler"] for t in TOOLS if t["name"] == name), None)
|
||||||
|
if handler is None:
|
||||||
|
return err(-32601, f"Unknown tool: {name}")
|
||||||
|
try:
|
||||||
|
result = handler(arguments)
|
||||||
|
text = json.dumps(result, ensure_ascii=False, indent=2)
|
||||||
|
return ok({"content": [{"type": "text", "text": text}]})
|
||||||
|
except Exception as exc:
|
||||||
|
log.exception("Tool %s raised", name)
|
||||||
|
return err(-32603, str(exc))
|
||||||
|
|
||||||
|
if method == "resources/list":
|
||||||
|
return ok({"resources": RESOURCES})
|
||||||
|
|
||||||
|
if method == "resources/read":
|
||||||
|
uri = params.get("uri", "")
|
||||||
|
data = _read_resource(uri)
|
||||||
|
text = json.dumps(data, ensure_ascii=False, indent=2)
|
||||||
|
return ok({"contents": [{"uri": uri, "mimeType": "application/json", "text": text}]})
|
||||||
|
|
||||||
|
if method == "prompts/list":
|
||||||
|
return ok({"prompts": []})
|
||||||
|
|
||||||
|
return err(-32601, f"Method not found: {method}")
|
||||||
|
|
||||||
|
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
# stdio event loop
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
def _run_stdio():
|
||||||
|
log.info("Semantica MCP server starting on stdio")
|
||||||
|
# Use binary stdin/stdout for reliable newline handling on Windows
|
||||||
|
stdin = sys.stdin.buffer
|
||||||
|
stdout = sys.stdout.buffer
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
line = stdin.readline()
|
||||||
|
if not line:
|
||||||
|
break
|
||||||
|
line = line.strip()
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
req = json.loads(line)
|
||||||
|
except json.JSONDecodeError as exc:
|
||||||
|
resp = {"jsonrpc": "2.0", "id": None,
|
||||||
|
"error": {"code": -32700, "message": f"Parse error: {exc}"}}
|
||||||
|
stdout.write(json.dumps(resp).encode() + b"\n")
|
||||||
|
stdout.flush()
|
||||||
|
continue
|
||||||
|
|
||||||
|
resp = _handle(req)
|
||||||
|
if resp is not None:
|
||||||
|
stdout.write(json.dumps(resp, ensure_ascii=False).encode() + b"\n")
|
||||||
|
stdout.flush()
|
||||||
|
except EOFError:
|
||||||
|
break
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
break
|
||||||
|
except Exception as exc:
|
||||||
|
log.exception("Unhandled error in MCP loop: %s", exc)
|
||||||
|
|
||||||
|
log.info("Semantica MCP server stopped")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
_run_stdio()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user