mcp-server-evolutiondb 1.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.
- mcp_server_evolutiondb-1.1.0/PKG-INFO +229 -0
- mcp_server_evolutiondb-1.1.0/README.md +200 -0
- mcp_server_evolutiondb-1.1.0/mcp_server_evolutiondb.egg-info/PKG-INFO +229 -0
- mcp_server_evolutiondb-1.1.0/mcp_server_evolutiondb.egg-info/SOURCES.txt +12 -0
- mcp_server_evolutiondb-1.1.0/mcp_server_evolutiondb.egg-info/dependency_links.txt +1 -0
- mcp_server_evolutiondb-1.1.0/mcp_server_evolutiondb.egg-info/entry_points.txt +3 -0
- mcp_server_evolutiondb-1.1.0/mcp_server_evolutiondb.egg-info/requires.txt +1 -0
- mcp_server_evolutiondb-1.1.0/mcp_server_evolutiondb.egg-info/top_level.txt +1 -0
- mcp_server_evolutiondb-1.1.0/mcp_server_evosql/__init__.py +2 -0
- mcp_server_evolutiondb-1.1.0/mcp_server_evosql/__main__.py +5 -0
- mcp_server_evolutiondb-1.1.0/mcp_server_evosql/server.py +430 -0
- mcp_server_evolutiondb-1.1.0/pyproject.toml +57 -0
- mcp_server_evolutiondb-1.1.0/setup.cfg +4 -0
- mcp_server_evolutiondb-1.1.0/tests/test_mcp.py +204 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mcp-server-evolutiondb
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: MCP (Model Context Protocol) server backed by EvolutionDB — gives Claude Desktop / Claude Code persistent long-term memory.
|
|
5
|
+
Author-email: alptekin topal <topal.alptekin@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/alptekin/evolutiondb
|
|
8
|
+
Project-URL: Documentation, https://alptekin.github.io/evolutiondb/
|
|
9
|
+
Project-URL: Repository, https://github.com/alptekin/evolutiondb
|
|
10
|
+
Project-URL: Issues, https://github.com/alptekin/evolutiondb/issues
|
|
11
|
+
Project-URL: Source, https://github.com/alptekin/evolutiondb/tree/main/client/mcp-server-evosql
|
|
12
|
+
Keywords: mcp,model-context-protocol,evolutiondb,claude,claude-desktop,claude-code,long-term-memory,agent-memory
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Database
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
|
+
Requires-Python: >=3.9
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
Requires-Dist: psycopg[binary]>=3.1
|
|
29
|
+
|
|
30
|
+
# mcp-server-evolutiondb
|
|
31
|
+
|
|
32
|
+
<!-- mcp-name: io.github.alptekin/evolutiondb-memory -->
|
|
33
|
+
|
|
34
|
+
A [Model Context Protocol](https://modelcontextprotocol.io) server
|
|
35
|
+
that gives Claude Desktop / Claude Code persistent **long-term
|
|
36
|
+
memory** backed by EvolutionDB. Anything Claude decides to remember
|
|
37
|
+
during a conversation is written to a real database; in any future
|
|
38
|
+
session — same window or weeks later — Claude can search it back
|
|
39
|
+
without you having to repaste context.
|
|
40
|
+
|
|
41
|
+
## Install
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pipx install mcp-server-evolutiondb
|
|
45
|
+
# or: pip install --user mcp-server-evolutiondb
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The package installs the `mcp-server-evolutiondb` console entry-point
|
|
49
|
+
(also aliased as `mcp-server-evosql`). It speaks the PostgreSQL wire
|
|
50
|
+
protocol over `psycopg`, so installation is **pure-Python** — no C
|
|
51
|
+
toolchain, no `libevosql-memory.so` to build. EvolutionDB still has
|
|
52
|
+
to be running somewhere reachable; `docker compose up -d` in the
|
|
53
|
+
[main repo](https://github.com/alptekin/evolutiondb) is the easiest
|
|
54
|
+
way.
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
┌──────────────────┐ ┌─────────────────────┐ ┌────────────────┐
|
|
58
|
+
│ Claude Desktop │ stdio │ mcp-server-evosql │ TCP │ EvolutionDB │
|
|
59
|
+
│ (or Claude │ ◀──────▶│ (this package) │ ◀──────▶│ (port 9967) │
|
|
60
|
+
│ Code) │ JSON- │ │ │ │
|
|
61
|
+
│ │ RPC │ save_memory │ │ MEMORY STORE │
|
|
62
|
+
│ │ 2.0 │ search_memory │ │ ENTITY STORE │
|
|
63
|
+
│ │ │ recent_memories │ │ │
|
|
64
|
+
│ │ │ forget │ │ │
|
|
65
|
+
│ │ │ list_tags │ │ │
|
|
66
|
+
└──────────────────┘ └─────────────────────┘ └────────────────┘
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Why
|
|
70
|
+
|
|
71
|
+
The default Claude experience is **stateless** — every new chat starts
|
|
72
|
+
from scratch, so you waste tokens re-explaining who you are, what
|
|
73
|
+
project you're on, what your preferences are. Plug this server in
|
|
74
|
+
and the model:
|
|
75
|
+
|
|
76
|
+
- saves preferences / decisions / facts during natural conversation,
|
|
77
|
+
- searches them back the next time you ask something related,
|
|
78
|
+
- forgets entries on demand,
|
|
79
|
+
- never sees the user_id that pins the namespace (we override it
|
|
80
|
+
server-side, so the model can't accidentally fragment the
|
|
81
|
+
namespace by inventing IDs across sessions).
|
|
82
|
+
|
|
83
|
+
Token math: 100 chats × 3,000 tokens of pre-loaded context (~$0.90
|
|
84
|
+
on Sonnet) → 100 chats × ~250 tokens of just-relevant facts pulled
|
|
85
|
+
on demand (~$0.26). Roughly **3.5× cheaper inputs** without losing
|
|
86
|
+
context fidelity.
|
|
87
|
+
|
|
88
|
+
## What's exposed to Claude
|
|
89
|
+
|
|
90
|
+
Five tools, all under one `evolutiondb-memory` MCP server:
|
|
91
|
+
|
|
92
|
+
| Tool | Purpose |
|
|
93
|
+
|---------------------|--------------------------------------------------|
|
|
94
|
+
| `save_memory` | Persist a fact + optional tags |
|
|
95
|
+
| `search_memory` | Substring + tag search (use before answering) |
|
|
96
|
+
| `recent_memories` | Last N saved facts (most-recent-first) |
|
|
97
|
+
| `forget` | Delete by key |
|
|
98
|
+
| `list_tags` | All distinct tags in use, with counts |
|
|
99
|
+
|
|
100
|
+
Each call's `user_id` is overridden server-side from the
|
|
101
|
+
`MCP_USER_ID` env var — stops the model from drifting the namespace
|
|
102
|
+
across "user" / "default_user" / your name etc.
|
|
103
|
+
|
|
104
|
+
## Install + run
|
|
105
|
+
|
|
106
|
+
**1. Bring up EvolutionDB**
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
cd /path/to/evolutiondb
|
|
110
|
+
docker compose up -d
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**2. Build the SDK once**
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
make -C client/libevosql-memory
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**3. Configure Claude Desktop**
|
|
120
|
+
|
|
121
|
+
Open the config file:
|
|
122
|
+
|
|
123
|
+
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
124
|
+
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
125
|
+
|
|
126
|
+
Drop in the entry from
|
|
127
|
+
[`examples/claude_desktop_config.json`](examples/claude_desktop_config.json),
|
|
128
|
+
substituting the absolute paths for your machine. Quit + restart
|
|
129
|
+
Claude Desktop.
|
|
130
|
+
|
|
131
|
+
You'll see a small 🔌 / hammer icon in the bottom-right of the
|
|
132
|
+
chat composer once `evolutiondb-memory` is connected.
|
|
133
|
+
|
|
134
|
+
**4. Talk normally**
|
|
135
|
+
|
|
136
|
+
Say "remember that I take my espresso single-shot, no sugar"; Claude
|
|
137
|
+
will run `save_memory(...)`. Days later open a new chat, ask "what
|
|
138
|
+
do I drink?" — Claude runs `search_memory(...)` and recalls.
|
|
139
|
+
|
|
140
|
+
## Same setup for Claude Code
|
|
141
|
+
|
|
142
|
+
If you use Claude Code (the CLI), drop the same `mcpServers` entry
|
|
143
|
+
into `~/.claude/mcp.json`:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
mkdir -p ~/.claude
|
|
147
|
+
cp client/mcp-server-evosql/examples/claude_desktop_config.json ~/.claude/mcp.json
|
|
148
|
+
# edit the absolute paths
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Claude Code picks it up automatically on the next `claude` invocation.
|
|
152
|
+
|
|
153
|
+
## Configuration
|
|
154
|
+
|
|
155
|
+
| Env var | Default | Purpose |
|
|
156
|
+
|-----------------------|--------------------|---------|
|
|
157
|
+
| `EVOSQL_HOST` | `127.0.0.1` | DB host |
|
|
158
|
+
| `EVOSQL_PORT` | `9967` | EVO port |
|
|
159
|
+
| `EVOSQL_USER` | `admin` | DB user |
|
|
160
|
+
| `EVOSQL_PASSWORD` | `admin` | DB password |
|
|
161
|
+
| `MCP_USER_ID` | `default_user` | Sticky namespace for every tool call |
|
|
162
|
+
| `MCP_STORE_PREFIX` | `mcp` | Catalog object prefix |
|
|
163
|
+
| `EVOSQL_PYTHON_SDK` | (auto-discovered) | Override path to the Python ctypes binding |
|
|
164
|
+
| `EVOSQL_MEMORY_LIB` | (auto-discovered) | Override path to libevosql-memory.dylib/so |
|
|
165
|
+
|
|
166
|
+
## Tests
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
cd client/mcp-server-evosql
|
|
170
|
+
python3 tests/test_mcp.py
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Eight cases — initialize handshake, tools/list discovery, save+search
|
|
174
|
+
round-trip, tag-filtered search, recent ordering, forget, list_tags
|
|
175
|
+
aggregation, and the "user_id can't be hijacked from the LLM side"
|
|
176
|
+
isolation case. Each test spawns the server as a real subprocess and
|
|
177
|
+
talks JSON-RPC, so framing bugs that an in-process unit test would
|
|
178
|
+
hide get caught.
|
|
179
|
+
|
|
180
|
+
## Inspect the database directly
|
|
181
|
+
|
|
182
|
+
While Claude is using the server, open another terminal and:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
docker compose exec evosql evosql-cli -W admin
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Then:
|
|
189
|
+
|
|
190
|
+
```sql
|
|
191
|
+
SELECT mem_namespace, mem_key, mem_value FROM __mem_mcp_mem;
|
|
192
|
+
ENTITY RANK FROM mcp_ents;
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Everything Claude has decided to remember is right there as
|
|
196
|
+
queryable rows — no opaque blob storage.
|
|
197
|
+
|
|
198
|
+
## Wire format
|
|
199
|
+
|
|
200
|
+
Newline-delimited JSON-RPC 2.0 over stdio (no Content-Length
|
|
201
|
+
headers — that's the LSP variant; MCP uses plain `\n`-delimited).
|
|
202
|
+
The server speaks protocol version `2024-11-05`.
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
{"jsonrpc":"2.0","id":1,"method":"initialize",
|
|
206
|
+
"params":{"protocolVersion":"2024-11-05","capabilities":{}}}
|
|
207
|
+
|
|
208
|
+
{"jsonrpc":"2.0","id":2,"method":"tools/list"}
|
|
209
|
+
|
|
210
|
+
{"jsonrpc":"2.0","id":3,"method":"tools/call",
|
|
211
|
+
"params":{"name":"save_memory",
|
|
212
|
+
"arguments":{"fact":"loves jazz","tags":["preference"]}}}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Errors come back as `{"jsonrpc":"2.0","id":N,"error":{"code":..,"message":..}}`
|
|
216
|
+
or as a `tools/call` result with `isError: true`.
|
|
217
|
+
|
|
218
|
+
## Known limitations
|
|
219
|
+
|
|
220
|
+
- **Single-process EvolutionDB connection.** The server holds one
|
|
221
|
+
Connection — the SDK contract is one-per-thread, and MCP stdio is
|
|
222
|
+
inherently single-threaded so this is fine.
|
|
223
|
+
- **No streaming responses.** Tool results return as single JSON
|
|
224
|
+
blobs. Larger memories (>100 facts) take ~50 ms to serialise; the
|
|
225
|
+
protocol can stream but Claude's tool-use UI doesn't render
|
|
226
|
+
partial responses anyway.
|
|
227
|
+
- **Authentication via env-vars only.** If you expose the server to
|
|
228
|
+
another machine (which you shouldn't — it's stdio), set
|
|
229
|
+
`EVOSQL_PASSWORD` accordingly. The server doesn't rotate secrets.
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# mcp-server-evolutiondb
|
|
2
|
+
|
|
3
|
+
<!-- mcp-name: io.github.alptekin/evolutiondb-memory -->
|
|
4
|
+
|
|
5
|
+
A [Model Context Protocol](https://modelcontextprotocol.io) server
|
|
6
|
+
that gives Claude Desktop / Claude Code persistent **long-term
|
|
7
|
+
memory** backed by EvolutionDB. Anything Claude decides to remember
|
|
8
|
+
during a conversation is written to a real database; in any future
|
|
9
|
+
session — same window or weeks later — Claude can search it back
|
|
10
|
+
without you having to repaste context.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pipx install mcp-server-evolutiondb
|
|
16
|
+
# or: pip install --user mcp-server-evolutiondb
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The package installs the `mcp-server-evolutiondb` console entry-point
|
|
20
|
+
(also aliased as `mcp-server-evosql`). It speaks the PostgreSQL wire
|
|
21
|
+
protocol over `psycopg`, so installation is **pure-Python** — no C
|
|
22
|
+
toolchain, no `libevosql-memory.so` to build. EvolutionDB still has
|
|
23
|
+
to be running somewhere reachable; `docker compose up -d` in the
|
|
24
|
+
[main repo](https://github.com/alptekin/evolutiondb) is the easiest
|
|
25
|
+
way.
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
┌──────────────────┐ ┌─────────────────────┐ ┌────────────────┐
|
|
29
|
+
│ Claude Desktop │ stdio │ mcp-server-evosql │ TCP │ EvolutionDB │
|
|
30
|
+
│ (or Claude │ ◀──────▶│ (this package) │ ◀──────▶│ (port 9967) │
|
|
31
|
+
│ Code) │ JSON- │ │ │ │
|
|
32
|
+
│ │ RPC │ save_memory │ │ MEMORY STORE │
|
|
33
|
+
│ │ 2.0 │ search_memory │ │ ENTITY STORE │
|
|
34
|
+
│ │ │ recent_memories │ │ │
|
|
35
|
+
│ │ │ forget │ │ │
|
|
36
|
+
│ │ │ list_tags │ │ │
|
|
37
|
+
└──────────────────┘ └─────────────────────┘ └────────────────┘
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Why
|
|
41
|
+
|
|
42
|
+
The default Claude experience is **stateless** — every new chat starts
|
|
43
|
+
from scratch, so you waste tokens re-explaining who you are, what
|
|
44
|
+
project you're on, what your preferences are. Plug this server in
|
|
45
|
+
and the model:
|
|
46
|
+
|
|
47
|
+
- saves preferences / decisions / facts during natural conversation,
|
|
48
|
+
- searches them back the next time you ask something related,
|
|
49
|
+
- forgets entries on demand,
|
|
50
|
+
- never sees the user_id that pins the namespace (we override it
|
|
51
|
+
server-side, so the model can't accidentally fragment the
|
|
52
|
+
namespace by inventing IDs across sessions).
|
|
53
|
+
|
|
54
|
+
Token math: 100 chats × 3,000 tokens of pre-loaded context (~$0.90
|
|
55
|
+
on Sonnet) → 100 chats × ~250 tokens of just-relevant facts pulled
|
|
56
|
+
on demand (~$0.26). Roughly **3.5× cheaper inputs** without losing
|
|
57
|
+
context fidelity.
|
|
58
|
+
|
|
59
|
+
## What's exposed to Claude
|
|
60
|
+
|
|
61
|
+
Five tools, all under one `evolutiondb-memory` MCP server:
|
|
62
|
+
|
|
63
|
+
| Tool | Purpose |
|
|
64
|
+
|---------------------|--------------------------------------------------|
|
|
65
|
+
| `save_memory` | Persist a fact + optional tags |
|
|
66
|
+
| `search_memory` | Substring + tag search (use before answering) |
|
|
67
|
+
| `recent_memories` | Last N saved facts (most-recent-first) |
|
|
68
|
+
| `forget` | Delete by key |
|
|
69
|
+
| `list_tags` | All distinct tags in use, with counts |
|
|
70
|
+
|
|
71
|
+
Each call's `user_id` is overridden server-side from the
|
|
72
|
+
`MCP_USER_ID` env var — stops the model from drifting the namespace
|
|
73
|
+
across "user" / "default_user" / your name etc.
|
|
74
|
+
|
|
75
|
+
## Install + run
|
|
76
|
+
|
|
77
|
+
**1. Bring up EvolutionDB**
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
cd /path/to/evolutiondb
|
|
81
|
+
docker compose up -d
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**2. Build the SDK once**
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
make -C client/libevosql-memory
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**3. Configure Claude Desktop**
|
|
91
|
+
|
|
92
|
+
Open the config file:
|
|
93
|
+
|
|
94
|
+
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
95
|
+
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
96
|
+
|
|
97
|
+
Drop in the entry from
|
|
98
|
+
[`examples/claude_desktop_config.json`](examples/claude_desktop_config.json),
|
|
99
|
+
substituting the absolute paths for your machine. Quit + restart
|
|
100
|
+
Claude Desktop.
|
|
101
|
+
|
|
102
|
+
You'll see a small 🔌 / hammer icon in the bottom-right of the
|
|
103
|
+
chat composer once `evolutiondb-memory` is connected.
|
|
104
|
+
|
|
105
|
+
**4. Talk normally**
|
|
106
|
+
|
|
107
|
+
Say "remember that I take my espresso single-shot, no sugar"; Claude
|
|
108
|
+
will run `save_memory(...)`. Days later open a new chat, ask "what
|
|
109
|
+
do I drink?" — Claude runs `search_memory(...)` and recalls.
|
|
110
|
+
|
|
111
|
+
## Same setup for Claude Code
|
|
112
|
+
|
|
113
|
+
If you use Claude Code (the CLI), drop the same `mcpServers` entry
|
|
114
|
+
into `~/.claude/mcp.json`:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
mkdir -p ~/.claude
|
|
118
|
+
cp client/mcp-server-evosql/examples/claude_desktop_config.json ~/.claude/mcp.json
|
|
119
|
+
# edit the absolute paths
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Claude Code picks it up automatically on the next `claude` invocation.
|
|
123
|
+
|
|
124
|
+
## Configuration
|
|
125
|
+
|
|
126
|
+
| Env var | Default | Purpose |
|
|
127
|
+
|-----------------------|--------------------|---------|
|
|
128
|
+
| `EVOSQL_HOST` | `127.0.0.1` | DB host |
|
|
129
|
+
| `EVOSQL_PORT` | `9967` | EVO port |
|
|
130
|
+
| `EVOSQL_USER` | `admin` | DB user |
|
|
131
|
+
| `EVOSQL_PASSWORD` | `admin` | DB password |
|
|
132
|
+
| `MCP_USER_ID` | `default_user` | Sticky namespace for every tool call |
|
|
133
|
+
| `MCP_STORE_PREFIX` | `mcp` | Catalog object prefix |
|
|
134
|
+
| `EVOSQL_PYTHON_SDK` | (auto-discovered) | Override path to the Python ctypes binding |
|
|
135
|
+
| `EVOSQL_MEMORY_LIB` | (auto-discovered) | Override path to libevosql-memory.dylib/so |
|
|
136
|
+
|
|
137
|
+
## Tests
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
cd client/mcp-server-evosql
|
|
141
|
+
python3 tests/test_mcp.py
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Eight cases — initialize handshake, tools/list discovery, save+search
|
|
145
|
+
round-trip, tag-filtered search, recent ordering, forget, list_tags
|
|
146
|
+
aggregation, and the "user_id can't be hijacked from the LLM side"
|
|
147
|
+
isolation case. Each test spawns the server as a real subprocess and
|
|
148
|
+
talks JSON-RPC, so framing bugs that an in-process unit test would
|
|
149
|
+
hide get caught.
|
|
150
|
+
|
|
151
|
+
## Inspect the database directly
|
|
152
|
+
|
|
153
|
+
While Claude is using the server, open another terminal and:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
docker compose exec evosql evosql-cli -W admin
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Then:
|
|
160
|
+
|
|
161
|
+
```sql
|
|
162
|
+
SELECT mem_namespace, mem_key, mem_value FROM __mem_mcp_mem;
|
|
163
|
+
ENTITY RANK FROM mcp_ents;
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Everything Claude has decided to remember is right there as
|
|
167
|
+
queryable rows — no opaque blob storage.
|
|
168
|
+
|
|
169
|
+
## Wire format
|
|
170
|
+
|
|
171
|
+
Newline-delimited JSON-RPC 2.0 over stdio (no Content-Length
|
|
172
|
+
headers — that's the LSP variant; MCP uses plain `\n`-delimited).
|
|
173
|
+
The server speaks protocol version `2024-11-05`.
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
{"jsonrpc":"2.0","id":1,"method":"initialize",
|
|
177
|
+
"params":{"protocolVersion":"2024-11-05","capabilities":{}}}
|
|
178
|
+
|
|
179
|
+
{"jsonrpc":"2.0","id":2,"method":"tools/list"}
|
|
180
|
+
|
|
181
|
+
{"jsonrpc":"2.0","id":3,"method":"tools/call",
|
|
182
|
+
"params":{"name":"save_memory",
|
|
183
|
+
"arguments":{"fact":"loves jazz","tags":["preference"]}}}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Errors come back as `{"jsonrpc":"2.0","id":N,"error":{"code":..,"message":..}}`
|
|
187
|
+
or as a `tools/call` result with `isError: true`.
|
|
188
|
+
|
|
189
|
+
## Known limitations
|
|
190
|
+
|
|
191
|
+
- **Single-process EvolutionDB connection.** The server holds one
|
|
192
|
+
Connection — the SDK contract is one-per-thread, and MCP stdio is
|
|
193
|
+
inherently single-threaded so this is fine.
|
|
194
|
+
- **No streaming responses.** Tool results return as single JSON
|
|
195
|
+
blobs. Larger memories (>100 facts) take ~50 ms to serialise; the
|
|
196
|
+
protocol can stream but Claude's tool-use UI doesn't render
|
|
197
|
+
partial responses anyway.
|
|
198
|
+
- **Authentication via env-vars only.** If you expose the server to
|
|
199
|
+
another machine (which you shouldn't — it's stdio), set
|
|
200
|
+
`EVOSQL_PASSWORD` accordingly. The server doesn't rotate secrets.
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mcp-server-evolutiondb
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: MCP (Model Context Protocol) server backed by EvolutionDB — gives Claude Desktop / Claude Code persistent long-term memory.
|
|
5
|
+
Author-email: alptekin topal <topal.alptekin@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/alptekin/evolutiondb
|
|
8
|
+
Project-URL: Documentation, https://alptekin.github.io/evolutiondb/
|
|
9
|
+
Project-URL: Repository, https://github.com/alptekin/evolutiondb
|
|
10
|
+
Project-URL: Issues, https://github.com/alptekin/evolutiondb/issues
|
|
11
|
+
Project-URL: Source, https://github.com/alptekin/evolutiondb/tree/main/client/mcp-server-evosql
|
|
12
|
+
Keywords: mcp,model-context-protocol,evolutiondb,claude,claude-desktop,claude-code,long-term-memory,agent-memory
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Database
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
|
+
Requires-Python: >=3.9
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
Requires-Dist: psycopg[binary]>=3.1
|
|
29
|
+
|
|
30
|
+
# mcp-server-evolutiondb
|
|
31
|
+
|
|
32
|
+
<!-- mcp-name: io.github.alptekin/evolutiondb-memory -->
|
|
33
|
+
|
|
34
|
+
A [Model Context Protocol](https://modelcontextprotocol.io) server
|
|
35
|
+
that gives Claude Desktop / Claude Code persistent **long-term
|
|
36
|
+
memory** backed by EvolutionDB. Anything Claude decides to remember
|
|
37
|
+
during a conversation is written to a real database; in any future
|
|
38
|
+
session — same window or weeks later — Claude can search it back
|
|
39
|
+
without you having to repaste context.
|
|
40
|
+
|
|
41
|
+
## Install
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pipx install mcp-server-evolutiondb
|
|
45
|
+
# or: pip install --user mcp-server-evolutiondb
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The package installs the `mcp-server-evolutiondb` console entry-point
|
|
49
|
+
(also aliased as `mcp-server-evosql`). It speaks the PostgreSQL wire
|
|
50
|
+
protocol over `psycopg`, so installation is **pure-Python** — no C
|
|
51
|
+
toolchain, no `libevosql-memory.so` to build. EvolutionDB still has
|
|
52
|
+
to be running somewhere reachable; `docker compose up -d` in the
|
|
53
|
+
[main repo](https://github.com/alptekin/evolutiondb) is the easiest
|
|
54
|
+
way.
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
┌──────────────────┐ ┌─────────────────────┐ ┌────────────────┐
|
|
58
|
+
│ Claude Desktop │ stdio │ mcp-server-evosql │ TCP │ EvolutionDB │
|
|
59
|
+
│ (or Claude │ ◀──────▶│ (this package) │ ◀──────▶│ (port 9967) │
|
|
60
|
+
│ Code) │ JSON- │ │ │ │
|
|
61
|
+
│ │ RPC │ save_memory │ │ MEMORY STORE │
|
|
62
|
+
│ │ 2.0 │ search_memory │ │ ENTITY STORE │
|
|
63
|
+
│ │ │ recent_memories │ │ │
|
|
64
|
+
│ │ │ forget │ │ │
|
|
65
|
+
│ │ │ list_tags │ │ │
|
|
66
|
+
└──────────────────┘ └─────────────────────┘ └────────────────┘
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Why
|
|
70
|
+
|
|
71
|
+
The default Claude experience is **stateless** — every new chat starts
|
|
72
|
+
from scratch, so you waste tokens re-explaining who you are, what
|
|
73
|
+
project you're on, what your preferences are. Plug this server in
|
|
74
|
+
and the model:
|
|
75
|
+
|
|
76
|
+
- saves preferences / decisions / facts during natural conversation,
|
|
77
|
+
- searches them back the next time you ask something related,
|
|
78
|
+
- forgets entries on demand,
|
|
79
|
+
- never sees the user_id that pins the namespace (we override it
|
|
80
|
+
server-side, so the model can't accidentally fragment the
|
|
81
|
+
namespace by inventing IDs across sessions).
|
|
82
|
+
|
|
83
|
+
Token math: 100 chats × 3,000 tokens of pre-loaded context (~$0.90
|
|
84
|
+
on Sonnet) → 100 chats × ~250 tokens of just-relevant facts pulled
|
|
85
|
+
on demand (~$0.26). Roughly **3.5× cheaper inputs** without losing
|
|
86
|
+
context fidelity.
|
|
87
|
+
|
|
88
|
+
## What's exposed to Claude
|
|
89
|
+
|
|
90
|
+
Five tools, all under one `evolutiondb-memory` MCP server:
|
|
91
|
+
|
|
92
|
+
| Tool | Purpose |
|
|
93
|
+
|---------------------|--------------------------------------------------|
|
|
94
|
+
| `save_memory` | Persist a fact + optional tags |
|
|
95
|
+
| `search_memory` | Substring + tag search (use before answering) |
|
|
96
|
+
| `recent_memories` | Last N saved facts (most-recent-first) |
|
|
97
|
+
| `forget` | Delete by key |
|
|
98
|
+
| `list_tags` | All distinct tags in use, with counts |
|
|
99
|
+
|
|
100
|
+
Each call's `user_id` is overridden server-side from the
|
|
101
|
+
`MCP_USER_ID` env var — stops the model from drifting the namespace
|
|
102
|
+
across "user" / "default_user" / your name etc.
|
|
103
|
+
|
|
104
|
+
## Install + run
|
|
105
|
+
|
|
106
|
+
**1. Bring up EvolutionDB**
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
cd /path/to/evolutiondb
|
|
110
|
+
docker compose up -d
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**2. Build the SDK once**
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
make -C client/libevosql-memory
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**3. Configure Claude Desktop**
|
|
120
|
+
|
|
121
|
+
Open the config file:
|
|
122
|
+
|
|
123
|
+
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
124
|
+
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
125
|
+
|
|
126
|
+
Drop in the entry from
|
|
127
|
+
[`examples/claude_desktop_config.json`](examples/claude_desktop_config.json),
|
|
128
|
+
substituting the absolute paths for your machine. Quit + restart
|
|
129
|
+
Claude Desktop.
|
|
130
|
+
|
|
131
|
+
You'll see a small 🔌 / hammer icon in the bottom-right of the
|
|
132
|
+
chat composer once `evolutiondb-memory` is connected.
|
|
133
|
+
|
|
134
|
+
**4. Talk normally**
|
|
135
|
+
|
|
136
|
+
Say "remember that I take my espresso single-shot, no sugar"; Claude
|
|
137
|
+
will run `save_memory(...)`. Days later open a new chat, ask "what
|
|
138
|
+
do I drink?" — Claude runs `search_memory(...)` and recalls.
|
|
139
|
+
|
|
140
|
+
## Same setup for Claude Code
|
|
141
|
+
|
|
142
|
+
If you use Claude Code (the CLI), drop the same `mcpServers` entry
|
|
143
|
+
into `~/.claude/mcp.json`:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
mkdir -p ~/.claude
|
|
147
|
+
cp client/mcp-server-evosql/examples/claude_desktop_config.json ~/.claude/mcp.json
|
|
148
|
+
# edit the absolute paths
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Claude Code picks it up automatically on the next `claude` invocation.
|
|
152
|
+
|
|
153
|
+
## Configuration
|
|
154
|
+
|
|
155
|
+
| Env var | Default | Purpose |
|
|
156
|
+
|-----------------------|--------------------|---------|
|
|
157
|
+
| `EVOSQL_HOST` | `127.0.0.1` | DB host |
|
|
158
|
+
| `EVOSQL_PORT` | `9967` | EVO port |
|
|
159
|
+
| `EVOSQL_USER` | `admin` | DB user |
|
|
160
|
+
| `EVOSQL_PASSWORD` | `admin` | DB password |
|
|
161
|
+
| `MCP_USER_ID` | `default_user` | Sticky namespace for every tool call |
|
|
162
|
+
| `MCP_STORE_PREFIX` | `mcp` | Catalog object prefix |
|
|
163
|
+
| `EVOSQL_PYTHON_SDK` | (auto-discovered) | Override path to the Python ctypes binding |
|
|
164
|
+
| `EVOSQL_MEMORY_LIB` | (auto-discovered) | Override path to libevosql-memory.dylib/so |
|
|
165
|
+
|
|
166
|
+
## Tests
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
cd client/mcp-server-evosql
|
|
170
|
+
python3 tests/test_mcp.py
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Eight cases — initialize handshake, tools/list discovery, save+search
|
|
174
|
+
round-trip, tag-filtered search, recent ordering, forget, list_tags
|
|
175
|
+
aggregation, and the "user_id can't be hijacked from the LLM side"
|
|
176
|
+
isolation case. Each test spawns the server as a real subprocess and
|
|
177
|
+
talks JSON-RPC, so framing bugs that an in-process unit test would
|
|
178
|
+
hide get caught.
|
|
179
|
+
|
|
180
|
+
## Inspect the database directly
|
|
181
|
+
|
|
182
|
+
While Claude is using the server, open another terminal and:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
docker compose exec evosql evosql-cli -W admin
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Then:
|
|
189
|
+
|
|
190
|
+
```sql
|
|
191
|
+
SELECT mem_namespace, mem_key, mem_value FROM __mem_mcp_mem;
|
|
192
|
+
ENTITY RANK FROM mcp_ents;
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Everything Claude has decided to remember is right there as
|
|
196
|
+
queryable rows — no opaque blob storage.
|
|
197
|
+
|
|
198
|
+
## Wire format
|
|
199
|
+
|
|
200
|
+
Newline-delimited JSON-RPC 2.0 over stdio (no Content-Length
|
|
201
|
+
headers — that's the LSP variant; MCP uses plain `\n`-delimited).
|
|
202
|
+
The server speaks protocol version `2024-11-05`.
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
{"jsonrpc":"2.0","id":1,"method":"initialize",
|
|
206
|
+
"params":{"protocolVersion":"2024-11-05","capabilities":{}}}
|
|
207
|
+
|
|
208
|
+
{"jsonrpc":"2.0","id":2,"method":"tools/list"}
|
|
209
|
+
|
|
210
|
+
{"jsonrpc":"2.0","id":3,"method":"tools/call",
|
|
211
|
+
"params":{"name":"save_memory",
|
|
212
|
+
"arguments":{"fact":"loves jazz","tags":["preference"]}}}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Errors come back as `{"jsonrpc":"2.0","id":N,"error":{"code":..,"message":..}}`
|
|
216
|
+
or as a `tools/call` result with `isError: true`.
|
|
217
|
+
|
|
218
|
+
## Known limitations
|
|
219
|
+
|
|
220
|
+
- **Single-process EvolutionDB connection.** The server holds one
|
|
221
|
+
Connection — the SDK contract is one-per-thread, and MCP stdio is
|
|
222
|
+
inherently single-threaded so this is fine.
|
|
223
|
+
- **No streaming responses.** Tool results return as single JSON
|
|
224
|
+
blobs. Larger memories (>100 facts) take ~50 ms to serialise; the
|
|
225
|
+
protocol can stream but Claude's tool-use UI doesn't render
|
|
226
|
+
partial responses anyway.
|
|
227
|
+
- **Authentication via env-vars only.** If you expose the server to
|
|
228
|
+
another machine (which you shouldn't — it's stdio), set
|
|
229
|
+
`EVOSQL_PASSWORD` accordingly. The server doesn't rotate secrets.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
mcp_server_evolutiondb.egg-info/PKG-INFO
|
|
4
|
+
mcp_server_evolutiondb.egg-info/SOURCES.txt
|
|
5
|
+
mcp_server_evolutiondb.egg-info/dependency_links.txt
|
|
6
|
+
mcp_server_evolutiondb.egg-info/entry_points.txt
|
|
7
|
+
mcp_server_evolutiondb.egg-info/requires.txt
|
|
8
|
+
mcp_server_evolutiondb.egg-info/top_level.txt
|
|
9
|
+
mcp_server_evosql/__init__.py
|
|
10
|
+
mcp_server_evosql/__main__.py
|
|
11
|
+
mcp_server_evosql/server.py
|
|
12
|
+
tests/test_mcp.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
psycopg[binary]>=3.1
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
mcp_server_evosql
|