sibyl-memory-mcp 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sibyl_memory_mcp-0.1.0/PKG-INFO +102 -0
- sibyl_memory_mcp-0.1.0/README.md +78 -0
- sibyl_memory_mcp-0.1.0/pyproject.toml +39 -0
- sibyl_memory_mcp-0.1.0/setup.cfg +4 -0
- sibyl_memory_mcp-0.1.0/src/sibyl_memory_mcp/__init__.py +28 -0
- sibyl_memory_mcp-0.1.0/src/sibyl_memory_mcp/__main__.py +10 -0
- sibyl_memory_mcp-0.1.0/src/sibyl_memory_mcp/server.py +252 -0
- sibyl_memory_mcp-0.1.0/src/sibyl_memory_mcp.egg-info/PKG-INFO +102 -0
- sibyl_memory_mcp-0.1.0/src/sibyl_memory_mcp.egg-info/SOURCES.txt +11 -0
- sibyl_memory_mcp-0.1.0/src/sibyl_memory_mcp.egg-info/dependency_links.txt +1 -0
- sibyl_memory_mcp-0.1.0/src/sibyl_memory_mcp.egg-info/entry_points.txt +2 -0
- sibyl_memory_mcp-0.1.0/src/sibyl_memory_mcp.egg-info/requires.txt +3 -0
- sibyl_memory_mcp-0.1.0/src/sibyl_memory_mcp.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sibyl-memory-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server for Sibyl Memory Plugin — wraps the local SQLite + FTS5 memory engine and exposes it to MCP-compatible agents (Claude Code, Codex, Cursor, Continue, anything that speaks MCP).
|
|
5
|
+
Author-email: "SIBYL, Sibyl Labs LLC" <sibyl@sibyllabs.org>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://sibyllabs.org/memory
|
|
8
|
+
Project-URL: Documentation, https://docs.sibyllabs.org/memory/integrations
|
|
9
|
+
Project-URL: Repository, https://github.com/sibyllabs/sibyl-memory-plugin
|
|
10
|
+
Keywords: mcp,model-context-protocol,memory,agent,claude,claude-code,codex,sibyl
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
Requires-Dist: mcp>=1.0.0
|
|
22
|
+
Requires-Dist: sibyl-memory-client>=0.3.2
|
|
23
|
+
Requires-Dist: sibyl-memory-hermes>=0.2.2
|
|
24
|
+
|
|
25
|
+
# sibyl-memory-mcp
|
|
26
|
+
|
|
27
|
+
MCP server for [Sibyl Memory Plugin](https://sibyllabs.org/memory). Exposes the local SQLite + FTS5 memory engine to any MCP-compatible agent: **Claude Code, Codex CLI, Cursor, Continue**, anything that speaks Model Context Protocol.
|
|
28
|
+
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install sibyl-memory-mcp
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
You also need an activated Sibyl Memory account. If you haven't already:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
sibyl init
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
This creates `~/.sibyl-memory/credentials.json` (server-issued, HMAC-signed) and a local SQLite database at `~/.sibyl-memory/memory.db`. The MCP server reads both automatically.
|
|
42
|
+
|
|
43
|
+
## Add to Claude Code
|
|
44
|
+
|
|
45
|
+
Edit `~/.claude/settings.json` (global) or `.mcp.json` (project-local):
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"mcpServers": {
|
|
50
|
+
"sibyl-memory": {
|
|
51
|
+
"command": "sibyl-memory-mcp"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Restart Claude Code. The 8 memory tools (prefixed `memory_*`) become available immediately.
|
|
58
|
+
|
|
59
|
+
## Add to Codex CLI
|
|
60
|
+
|
|
61
|
+
Edit `~/.codex/config.toml`:
|
|
62
|
+
|
|
63
|
+
```toml
|
|
64
|
+
[[mcp_servers]]
|
|
65
|
+
name = "sibyl-memory"
|
|
66
|
+
command = "sibyl-memory-mcp"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Restart Codex.
|
|
70
|
+
|
|
71
|
+
## Tools exposed
|
|
72
|
+
|
|
73
|
+
| Tool | What it does |
|
|
74
|
+
|------|--------------|
|
|
75
|
+
| `memory_remember` | Store an entity by (category, name) |
|
|
76
|
+
| `memory_recall` | Read an entity by exact key |
|
|
77
|
+
| `memory_search` | FTS5 search across all entities |
|
|
78
|
+
| `memory_list` | List entities in a category |
|
|
79
|
+
| `memory_forget` | Archive an entity (recoverable) |
|
|
80
|
+
| `memory_set_state` | Write a HOT-tier state doc |
|
|
81
|
+
| `memory_get_state` | Read a HOT-tier state doc |
|
|
82
|
+
| `memory_record_event` | Append a COLD-tier journal event |
|
|
83
|
+
|
|
84
|
+
Full docs at [docs.sibyllabs.org/memory/integrations](https://docs.sibyllabs.org/memory/integrations).
|
|
85
|
+
|
|
86
|
+
## Environment overrides
|
|
87
|
+
|
|
88
|
+
| Var | Default | What it overrides |
|
|
89
|
+
|-----|---------|--------------------|
|
|
90
|
+
| `SIBYL_MEMORY_DB` | `~/.sibyl-memory/memory.db` | Local SQLite path |
|
|
91
|
+
| `SIBYL_CREDENTIALS` | `~/.sibyl-memory/credentials.json` | Credentials file path |
|
|
92
|
+
|
|
93
|
+
## Tier behavior
|
|
94
|
+
|
|
95
|
+
- **Free tier**: 8 tools work. Hard-capped at 2 MB of local storage. Writes that would push past the cap return `CAP_EXCEEDED` with an `upgrade_url`. Self-learning and memory-check-up tools are not exposed on free tier.
|
|
96
|
+
- **Paid tiers** (Sync / Stake / Lifetime / Enterprise): cap removed. All tools enabled.
|
|
97
|
+
|
|
98
|
+
The cap-gate runs against the **server-authoritative** tier (verified via HMAC-signed credentials) — the MCP server can't bypass it by editing the local file.
|
|
99
|
+
|
|
100
|
+
## License
|
|
101
|
+
|
|
102
|
+
MIT — same as the rest of the `sibyl-memory-*` family.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# sibyl-memory-mcp
|
|
2
|
+
|
|
3
|
+
MCP server for [Sibyl Memory Plugin](https://sibyllabs.org/memory). Exposes the local SQLite + FTS5 memory engine to any MCP-compatible agent: **Claude Code, Codex CLI, Cursor, Continue**, anything that speaks Model Context Protocol.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install sibyl-memory-mcp
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
You also need an activated Sibyl Memory account. If you haven't already:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
sibyl init
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
This creates `~/.sibyl-memory/credentials.json` (server-issued, HMAC-signed) and a local SQLite database at `~/.sibyl-memory/memory.db`. The MCP server reads both automatically.
|
|
18
|
+
|
|
19
|
+
## Add to Claude Code
|
|
20
|
+
|
|
21
|
+
Edit `~/.claude/settings.json` (global) or `.mcp.json` (project-local):
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"mcpServers": {
|
|
26
|
+
"sibyl-memory": {
|
|
27
|
+
"command": "sibyl-memory-mcp"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Restart Claude Code. The 8 memory tools (prefixed `memory_*`) become available immediately.
|
|
34
|
+
|
|
35
|
+
## Add to Codex CLI
|
|
36
|
+
|
|
37
|
+
Edit `~/.codex/config.toml`:
|
|
38
|
+
|
|
39
|
+
```toml
|
|
40
|
+
[[mcp_servers]]
|
|
41
|
+
name = "sibyl-memory"
|
|
42
|
+
command = "sibyl-memory-mcp"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Restart Codex.
|
|
46
|
+
|
|
47
|
+
## Tools exposed
|
|
48
|
+
|
|
49
|
+
| Tool | What it does |
|
|
50
|
+
|------|--------------|
|
|
51
|
+
| `memory_remember` | Store an entity by (category, name) |
|
|
52
|
+
| `memory_recall` | Read an entity by exact key |
|
|
53
|
+
| `memory_search` | FTS5 search across all entities |
|
|
54
|
+
| `memory_list` | List entities in a category |
|
|
55
|
+
| `memory_forget` | Archive an entity (recoverable) |
|
|
56
|
+
| `memory_set_state` | Write a HOT-tier state doc |
|
|
57
|
+
| `memory_get_state` | Read a HOT-tier state doc |
|
|
58
|
+
| `memory_record_event` | Append a COLD-tier journal event |
|
|
59
|
+
|
|
60
|
+
Full docs at [docs.sibyllabs.org/memory/integrations](https://docs.sibyllabs.org/memory/integrations).
|
|
61
|
+
|
|
62
|
+
## Environment overrides
|
|
63
|
+
|
|
64
|
+
| Var | Default | What it overrides |
|
|
65
|
+
|-----|---------|--------------------|
|
|
66
|
+
| `SIBYL_MEMORY_DB` | `~/.sibyl-memory/memory.db` | Local SQLite path |
|
|
67
|
+
| `SIBYL_CREDENTIALS` | `~/.sibyl-memory/credentials.json` | Credentials file path |
|
|
68
|
+
|
|
69
|
+
## Tier behavior
|
|
70
|
+
|
|
71
|
+
- **Free tier**: 8 tools work. Hard-capped at 2 MB of local storage. Writes that would push past the cap return `CAP_EXCEEDED` with an `upgrade_url`. Self-learning and memory-check-up tools are not exposed on free tier.
|
|
72
|
+
- **Paid tiers** (Sync / Stake / Lifetime / Enterprise): cap removed. All tools enabled.
|
|
73
|
+
|
|
74
|
+
The cap-gate runs against the **server-authoritative** tier (verified via HMAC-signed credentials) — the MCP server can't bypass it by editing the local file.
|
|
75
|
+
|
|
76
|
+
## License
|
|
77
|
+
|
|
78
|
+
MIT — same as the rest of the `sibyl-memory-*` family.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=64", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "sibyl-memory-mcp"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "MCP server for Sibyl Memory Plugin — wraps the local SQLite + FTS5 memory engine and exposes it to MCP-compatible agents (Claude Code, Codex, Cursor, Continue, anything that speaks MCP)."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "SIBYL, Sibyl Labs LLC", email = "sibyl@sibyllabs.org" }]
|
|
13
|
+
keywords = ["mcp", "model-context-protocol", "memory", "agent", "claude", "claude-code", "codex", "sibyl"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
17
|
+
"Programming Language :: Python :: 3.10",
|
|
18
|
+
"Programming Language :: Python :: 3.11",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Operating System :: OS Independent",
|
|
22
|
+
"Topic :: Software Development :: Libraries",
|
|
23
|
+
]
|
|
24
|
+
dependencies = [
|
|
25
|
+
"mcp>=1.0.0",
|
|
26
|
+
"sibyl-memory-client>=0.3.2",
|
|
27
|
+
"sibyl-memory-hermes>=0.2.2",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.scripts]
|
|
31
|
+
sibyl-memory-mcp = "sibyl_memory_mcp.__main__:main"
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Homepage = "https://sibyllabs.org/memory"
|
|
35
|
+
Documentation = "https://docs.sibyllabs.org/memory/integrations"
|
|
36
|
+
Repository = "https://github.com/sibyllabs/sibyl-memory-plugin"
|
|
37
|
+
|
|
38
|
+
[tool.setuptools.packages.find]
|
|
39
|
+
where = ["src"]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""sibyl-memory-mcp — MCP server for Sibyl Memory Plugin.
|
|
2
|
+
|
|
3
|
+
Wraps the local SQLite + FTS5 memory engine (sibyl-memory-client) and
|
|
4
|
+
exposes it to any MCP-compatible agent: Claude Code, Codex CLI, Cursor,
|
|
5
|
+
Continue, etc.
|
|
6
|
+
|
|
7
|
+
Usage (Claude Code):
|
|
8
|
+
Add to ~/.claude/settings.json or project .mcp.json:
|
|
9
|
+
{
|
|
10
|
+
"mcpServers": {
|
|
11
|
+
"sibyl-memory": { "command": "sibyl-memory-mcp" }
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
Usage (Codex CLI):
|
|
16
|
+
Add to ~/.codex/config.toml:
|
|
17
|
+
[[mcp_servers]]
|
|
18
|
+
name = "sibyl-memory"
|
|
19
|
+
command = "sibyl-memory-mcp"
|
|
20
|
+
|
|
21
|
+
Both expect `sibyl init` to have been run first so credentials.json and
|
|
22
|
+
memory.db exist at ~/.sibyl-memory/.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from .server import build_server, run_stdio
|
|
26
|
+
|
|
27
|
+
__version__ = "0.1.0"
|
|
28
|
+
__all__ = ["build_server", "run_stdio", "__version__"]
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
"""MCP server exposing Sibyl Memory Plugin tools.
|
|
2
|
+
|
|
3
|
+
8 tools:
|
|
4
|
+
- memory_remember store an entity
|
|
5
|
+
- memory_recall read an entity by category+name
|
|
6
|
+
- memory_search FTS5 search across all entities
|
|
7
|
+
- memory_list list entities in a category
|
|
8
|
+
- memory_forget delete an entity (archived, not destroyed)
|
|
9
|
+
- memory_set_state write a HOT-tier state document
|
|
10
|
+
- memory_get_state read a HOT-tier state document
|
|
11
|
+
- memory_record_event append a COLD-tier journal event
|
|
12
|
+
|
|
13
|
+
All operations run against the local SQLite at ~/.sibyl-memory/memory.db.
|
|
14
|
+
The cap gate (free-tier 2 MB hard cap, paid-tier uncapped) is enforced
|
|
15
|
+
automatically by the underlying sibyl-memory-client SDK — the MCP server
|
|
16
|
+
just surfaces the typed errors back to the caller.
|
|
17
|
+
"""
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import json
|
|
21
|
+
import os
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
from typing import Any
|
|
24
|
+
|
|
25
|
+
from mcp.server.fastmcp import FastMCP
|
|
26
|
+
from sibyl_memory_client import MemoryClient
|
|
27
|
+
from sibyl_memory_client.exceptions import (
|
|
28
|
+
CapExceededError,
|
|
29
|
+
NotFoundError,
|
|
30
|
+
TierGateError,
|
|
31
|
+
TierVerificationError,
|
|
32
|
+
ValidationError,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
# Default install location matches the rest of the plugin ecosystem.
|
|
36
|
+
DEFAULT_DB_PATH = Path(os.environ.get(
|
|
37
|
+
"SIBYL_MEMORY_DB",
|
|
38
|
+
Path.home() / ".sibyl-memory" / "memory.db",
|
|
39
|
+
))
|
|
40
|
+
DEFAULT_CRED_PATH = Path(os.environ.get(
|
|
41
|
+
"SIBYL_CREDENTIALS",
|
|
42
|
+
Path.home() / ".sibyl-memory" / "credentials.json",
|
|
43
|
+
))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _load_credentials() -> dict[str, Any]:
|
|
47
|
+
"""Read credentials.json if present. Missing file = pre-activation, free tier."""
|
|
48
|
+
if not DEFAULT_CRED_PATH.exists():
|
|
49
|
+
return {}
|
|
50
|
+
try:
|
|
51
|
+
return json.loads(DEFAULT_CRED_PATH.read_text())
|
|
52
|
+
except (OSError, json.JSONDecodeError):
|
|
53
|
+
return {}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _open_client() -> MemoryClient:
|
|
57
|
+
"""Open a MemoryClient bound to the local DB + credentials.
|
|
58
|
+
|
|
59
|
+
Re-opens on every tool call so the server picks up tier changes from
|
|
60
|
+
`sibyl upgrade` without a restart. SQLite open is sub-millisecond.
|
|
61
|
+
"""
|
|
62
|
+
creds = _load_credentials()
|
|
63
|
+
DEFAULT_DB_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
64
|
+
return MemoryClient.local(
|
|
65
|
+
str(DEFAULT_DB_PATH),
|
|
66
|
+
tenant_id=creds.get("tenant_id"),
|
|
67
|
+
account_id=creds.get("account_id"),
|
|
68
|
+
session_token=creds.get("session_token"),
|
|
69
|
+
tier=creds.get("tier", "free"),
|
|
70
|
+
credentials_claim={
|
|
71
|
+
"account_id": creds.get("account_id"),
|
|
72
|
+
"tenant_id": creds.get("tenant_id"),
|
|
73
|
+
"tier": creds.get("tier"),
|
|
74
|
+
"email": creds.get("email"),
|
|
75
|
+
"wallet": creds.get("wallet"),
|
|
76
|
+
"issued_at": creds.get("issued_at"),
|
|
77
|
+
"schema_version": creds.get("schema_version", 1),
|
|
78
|
+
} if creds.get("signature") else None,
|
|
79
|
+
credentials_signature=creds.get("signature"),
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _err(e: Exception) -> dict[str, Any]:
|
|
84
|
+
"""Map SDK exception → structured error payload the agent can reason about."""
|
|
85
|
+
cls = type(e).__name__
|
|
86
|
+
payload = {"error": cls, "message": str(e)}
|
|
87
|
+
if isinstance(e, CapExceededError):
|
|
88
|
+
payload["code"] = "CAP_EXCEEDED"
|
|
89
|
+
payload["recovery"] = "Run `sibyl upgrade` to lift the 2 MB free-tier cap."
|
|
90
|
+
payload["upgrade_url"] = getattr(e, "upgrade_url", "https://sibyllabs.org/plugin/upgrade")
|
|
91
|
+
elif isinstance(e, TierGateError):
|
|
92
|
+
payload["code"] = "TIER_GATED"
|
|
93
|
+
payload["recovery"] = "This feature requires a paid tier. Run `sibyl upgrade`."
|
|
94
|
+
elif isinstance(e, TierVerificationError):
|
|
95
|
+
payload["code"] = "TIER_VERIFICATION_FAILED"
|
|
96
|
+
payload["recovery"] = "The server couldn't verify your tier. Check connectivity and try again."
|
|
97
|
+
elif isinstance(e, NotFoundError):
|
|
98
|
+
payload["code"] = "NOT_FOUND"
|
|
99
|
+
elif isinstance(e, ValidationError):
|
|
100
|
+
payload["code"] = "VALIDATION_ERROR"
|
|
101
|
+
return payload
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def build_server() -> FastMCP:
|
|
105
|
+
"""Build and return the MCP server. Tool names are prefixed with `memory_`."""
|
|
106
|
+
mcp = FastMCP("sibyl-memory")
|
|
107
|
+
|
|
108
|
+
@mcp.tool()
|
|
109
|
+
def memory_remember(category: str, name: str, body: dict[str, Any]) -> dict[str, Any]:
|
|
110
|
+
"""Store an entity in long-term memory.
|
|
111
|
+
|
|
112
|
+
Use for facts, project state, person profiles, anything the agent
|
|
113
|
+
should remember across sessions. Idempotent on (category, name) —
|
|
114
|
+
a second call with the same key updates the entry.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
category: Logical grouping (e.g. "people", "projects", "facts").
|
|
118
|
+
name: Unique-within-category identifier (e.g. "alice", "acme-deal").
|
|
119
|
+
body: Arbitrary JSON-serializable object. Become the entity body.
|
|
120
|
+
"""
|
|
121
|
+
try:
|
|
122
|
+
client = _open_client()
|
|
123
|
+
client.set_entity(category, name, body)
|
|
124
|
+
return {"ok": True, "category": category, "name": name}
|
|
125
|
+
except Exception as e:
|
|
126
|
+
return _err(e)
|
|
127
|
+
|
|
128
|
+
@mcp.tool()
|
|
129
|
+
def memory_recall(category: str, name: str) -> dict[str, Any]:
|
|
130
|
+
"""Read an entity by exact (category, name) lookup.
|
|
131
|
+
|
|
132
|
+
Returns the entity dict {name, category, body, created_at,
|
|
133
|
+
updated_at} or a NOT_FOUND error. Sub-millisecond against the
|
|
134
|
+
local SQLite.
|
|
135
|
+
"""
|
|
136
|
+
try:
|
|
137
|
+
client = _open_client()
|
|
138
|
+
return {"ok": True, "entity": client.get_entity(category, name)}
|
|
139
|
+
except Exception as e:
|
|
140
|
+
return _err(e)
|
|
141
|
+
|
|
142
|
+
@mcp.tool()
|
|
143
|
+
def memory_search(query: str, limit: int = 10) -> dict[str, Any]:
|
|
144
|
+
"""Full-text search across all entity bodies + names.
|
|
145
|
+
|
|
146
|
+
Uses SQLite FTS5. Returns up to `limit` matching entities ranked
|
|
147
|
+
by relevance. Best path when you know roughly what you're looking
|
|
148
|
+
for but not the exact (category, name) key.
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
query: Search terms. Supports FTS5 operators (AND, OR, NEAR/N).
|
|
152
|
+
limit: Maximum results to return (default 10, max 50).
|
|
153
|
+
"""
|
|
154
|
+
try:
|
|
155
|
+
client = _open_client()
|
|
156
|
+
results = client.search_entities(query, limit=min(max(limit, 1), 50))
|
|
157
|
+
return {"ok": True, "query": query, "count": len(results), "results": results}
|
|
158
|
+
except Exception as e:
|
|
159
|
+
return _err(e)
|
|
160
|
+
|
|
161
|
+
@mcp.tool()
|
|
162
|
+
def memory_list(category: str, limit: int = 50) -> dict[str, Any]:
|
|
163
|
+
"""List entities in a category, most-recently-updated first.
|
|
164
|
+
|
|
165
|
+
Useful for "show me everything I've stored about X" queries.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
category: Which category to enumerate.
|
|
169
|
+
limit: Max entities to return (default 50).
|
|
170
|
+
"""
|
|
171
|
+
try:
|
|
172
|
+
client = _open_client()
|
|
173
|
+
results = client.list_entities(category, limit=min(max(limit, 1), 200))
|
|
174
|
+
return {"ok": True, "category": category, "count": len(results), "results": results}
|
|
175
|
+
except Exception as e:
|
|
176
|
+
return _err(e)
|
|
177
|
+
|
|
178
|
+
@mcp.tool()
|
|
179
|
+
def memory_forget(category: str, name: str, reason: str | None = None) -> dict[str, Any]:
|
|
180
|
+
"""Archive an entity (not destroyed — moved to archived_entities).
|
|
181
|
+
|
|
182
|
+
The body is preserved in the archive table for forensic recovery
|
|
183
|
+
but no longer appears in recall/list/search. Pass a `reason` to
|
|
184
|
+
record why; useful in audit reviews.
|
|
185
|
+
"""
|
|
186
|
+
try:
|
|
187
|
+
client = _open_client()
|
|
188
|
+
client.archive_entity(category, name, reason=reason)
|
|
189
|
+
return {"ok": True, "archived": {"category": category, "name": name}}
|
|
190
|
+
except Exception as e:
|
|
191
|
+
return _err(e)
|
|
192
|
+
|
|
193
|
+
@mcp.tool()
|
|
194
|
+
def memory_set_state(key: str, body: dict[str, Any] | list[Any]) -> dict[str, Any]:
|
|
195
|
+
"""Write a HOT-tier state document.
|
|
196
|
+
|
|
197
|
+
Use for ephemeral working state the agent updates frequently —
|
|
198
|
+
current focus, in-flight task list, working draft. Faster than
|
|
199
|
+
entity writes; one row per key, overwritten on each set.
|
|
200
|
+
"""
|
|
201
|
+
try:
|
|
202
|
+
client = _open_client()
|
|
203
|
+
client.set_state(key, body)
|
|
204
|
+
return {"ok": True, "key": key}
|
|
205
|
+
except Exception as e:
|
|
206
|
+
return _err(e)
|
|
207
|
+
|
|
208
|
+
@mcp.tool()
|
|
209
|
+
def memory_get_state(key: str) -> dict[str, Any]:
|
|
210
|
+
"""Read a HOT-tier state document by key."""
|
|
211
|
+
try:
|
|
212
|
+
client = _open_client()
|
|
213
|
+
doc = client.get_state(key)
|
|
214
|
+
if doc is None:
|
|
215
|
+
return {"ok": False, "code": "NOT_FOUND", "key": key}
|
|
216
|
+
return {"ok": True, "key": key, "body": doc}
|
|
217
|
+
except Exception as e:
|
|
218
|
+
return _err(e)
|
|
219
|
+
|
|
220
|
+
@mcp.tool()
|
|
221
|
+
def memory_record_event(
|
|
222
|
+
kind: str,
|
|
223
|
+
body: dict[str, Any],
|
|
224
|
+
category: str | None = None,
|
|
225
|
+
name: str | None = None,
|
|
226
|
+
) -> dict[str, Any]:
|
|
227
|
+
"""Append a COLD-tier journal event.
|
|
228
|
+
|
|
229
|
+
Use for things that happened — actions taken, decisions made,
|
|
230
|
+
observations recorded. Append-only; never overwrites. Best paired
|
|
231
|
+
with entities (the entity is the noun, the journal is the verb).
|
|
232
|
+
|
|
233
|
+
Args:
|
|
234
|
+
kind: Event class (e.g. "decision", "observation", "action").
|
|
235
|
+
body: JSON-serializable event payload.
|
|
236
|
+
category: Optional entity category this event is about.
|
|
237
|
+
name: Optional entity name this event is about.
|
|
238
|
+
"""
|
|
239
|
+
try:
|
|
240
|
+
client = _open_client()
|
|
241
|
+
event_id = client.write_event(kind, body, category=category, name=name)
|
|
242
|
+
return {"ok": True, "event_id": event_id, "kind": kind}
|
|
243
|
+
except Exception as e:
|
|
244
|
+
return _err(e)
|
|
245
|
+
|
|
246
|
+
return mcp
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def run_stdio() -> None:
|
|
250
|
+
"""Run the server on stdio transport (what Claude Code / Codex / Cursor expect)."""
|
|
251
|
+
mcp = build_server()
|
|
252
|
+
mcp.run()
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sibyl-memory-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server for Sibyl Memory Plugin — wraps the local SQLite + FTS5 memory engine and exposes it to MCP-compatible agents (Claude Code, Codex, Cursor, Continue, anything that speaks MCP).
|
|
5
|
+
Author-email: "SIBYL, Sibyl Labs LLC" <sibyl@sibyllabs.org>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://sibyllabs.org/memory
|
|
8
|
+
Project-URL: Documentation, https://docs.sibyllabs.org/memory/integrations
|
|
9
|
+
Project-URL: Repository, https://github.com/sibyllabs/sibyl-memory-plugin
|
|
10
|
+
Keywords: mcp,model-context-protocol,memory,agent,claude,claude-code,codex,sibyl
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
Requires-Dist: mcp>=1.0.0
|
|
22
|
+
Requires-Dist: sibyl-memory-client>=0.3.2
|
|
23
|
+
Requires-Dist: sibyl-memory-hermes>=0.2.2
|
|
24
|
+
|
|
25
|
+
# sibyl-memory-mcp
|
|
26
|
+
|
|
27
|
+
MCP server for [Sibyl Memory Plugin](https://sibyllabs.org/memory). Exposes the local SQLite + FTS5 memory engine to any MCP-compatible agent: **Claude Code, Codex CLI, Cursor, Continue**, anything that speaks Model Context Protocol.
|
|
28
|
+
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install sibyl-memory-mcp
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
You also need an activated Sibyl Memory account. If you haven't already:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
sibyl init
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
This creates `~/.sibyl-memory/credentials.json` (server-issued, HMAC-signed) and a local SQLite database at `~/.sibyl-memory/memory.db`. The MCP server reads both automatically.
|
|
42
|
+
|
|
43
|
+
## Add to Claude Code
|
|
44
|
+
|
|
45
|
+
Edit `~/.claude/settings.json` (global) or `.mcp.json` (project-local):
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"mcpServers": {
|
|
50
|
+
"sibyl-memory": {
|
|
51
|
+
"command": "sibyl-memory-mcp"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Restart Claude Code. The 8 memory tools (prefixed `memory_*`) become available immediately.
|
|
58
|
+
|
|
59
|
+
## Add to Codex CLI
|
|
60
|
+
|
|
61
|
+
Edit `~/.codex/config.toml`:
|
|
62
|
+
|
|
63
|
+
```toml
|
|
64
|
+
[[mcp_servers]]
|
|
65
|
+
name = "sibyl-memory"
|
|
66
|
+
command = "sibyl-memory-mcp"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Restart Codex.
|
|
70
|
+
|
|
71
|
+
## Tools exposed
|
|
72
|
+
|
|
73
|
+
| Tool | What it does |
|
|
74
|
+
|------|--------------|
|
|
75
|
+
| `memory_remember` | Store an entity by (category, name) |
|
|
76
|
+
| `memory_recall` | Read an entity by exact key |
|
|
77
|
+
| `memory_search` | FTS5 search across all entities |
|
|
78
|
+
| `memory_list` | List entities in a category |
|
|
79
|
+
| `memory_forget` | Archive an entity (recoverable) |
|
|
80
|
+
| `memory_set_state` | Write a HOT-tier state doc |
|
|
81
|
+
| `memory_get_state` | Read a HOT-tier state doc |
|
|
82
|
+
| `memory_record_event` | Append a COLD-tier journal event |
|
|
83
|
+
|
|
84
|
+
Full docs at [docs.sibyllabs.org/memory/integrations](https://docs.sibyllabs.org/memory/integrations).
|
|
85
|
+
|
|
86
|
+
## Environment overrides
|
|
87
|
+
|
|
88
|
+
| Var | Default | What it overrides |
|
|
89
|
+
|-----|---------|--------------------|
|
|
90
|
+
| `SIBYL_MEMORY_DB` | `~/.sibyl-memory/memory.db` | Local SQLite path |
|
|
91
|
+
| `SIBYL_CREDENTIALS` | `~/.sibyl-memory/credentials.json` | Credentials file path |
|
|
92
|
+
|
|
93
|
+
## Tier behavior
|
|
94
|
+
|
|
95
|
+
- **Free tier**: 8 tools work. Hard-capped at 2 MB of local storage. Writes that would push past the cap return `CAP_EXCEEDED` with an `upgrade_url`. Self-learning and memory-check-up tools are not exposed on free tier.
|
|
96
|
+
- **Paid tiers** (Sync / Stake / Lifetime / Enterprise): cap removed. All tools enabled.
|
|
97
|
+
|
|
98
|
+
The cap-gate runs against the **server-authoritative** tier (verified via HMAC-signed credentials) — the MCP server can't bypass it by editing the local file.
|
|
99
|
+
|
|
100
|
+
## License
|
|
101
|
+
|
|
102
|
+
MIT — same as the rest of the `sibyl-memory-*` family.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/sibyl_memory_mcp/__init__.py
|
|
4
|
+
src/sibyl_memory_mcp/__main__.py
|
|
5
|
+
src/sibyl_memory_mcp/server.py
|
|
6
|
+
src/sibyl_memory_mcp.egg-info/PKG-INFO
|
|
7
|
+
src/sibyl_memory_mcp.egg-info/SOURCES.txt
|
|
8
|
+
src/sibyl_memory_mcp.egg-info/dependency_links.txt
|
|
9
|
+
src/sibyl_memory_mcp.egg-info/entry_points.txt
|
|
10
|
+
src/sibyl_memory_mcp.egg-info/requires.txt
|
|
11
|
+
src/sibyl_memory_mcp.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
sibyl_memory_mcp
|