memoryintelligence-mcp 0.2.0__tar.gz → 0.2.1__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.
Files changed (24) hide show
  1. {memoryintelligence_mcp-0.2.0 → memoryintelligence_mcp-0.2.1}/CHANGELOG.md +23 -0
  2. memoryintelligence_mcp-0.2.1/PKG-INFO +237 -0
  3. memoryintelligence_mcp-0.2.1/README.md +198 -0
  4. {memoryintelligence_mcp-0.2.0 → memoryintelligence_mcp-0.2.1}/pyproject.toml +1 -1
  5. {memoryintelligence_mcp-0.2.0 → memoryintelligence_mcp-0.2.1}/src/mi_mcp/__init__.py +1 -1
  6. {memoryintelligence_mcp-0.2.0 → memoryintelligence_mcp-0.2.1}/src/mi_mcp/cli.py +53 -11
  7. {memoryintelligence_mcp-0.2.0 → memoryintelligence_mcp-0.2.1}/src/mi_mcp/umo_format.py +8 -5
  8. memoryintelligence_mcp-0.2.0/PKG-INFO +0 -407
  9. memoryintelligence_mcp-0.2.0/README.md +0 -368
  10. {memoryintelligence_mcp-0.2.0 → memoryintelligence_mcp-0.2.1}/.gitignore +0 -0
  11. {memoryintelligence_mcp-0.2.0 → memoryintelligence_mcp-0.2.1}/CONTRIBUTING.md +0 -0
  12. {memoryintelligence_mcp-0.2.0 → memoryintelligence_mcp-0.2.1}/LICENSE +0 -0
  13. {memoryintelligence_mcp-0.2.0 → memoryintelligence_mcp-0.2.1}/src/mi_mcp/__main__.py +0 -0
  14. {memoryintelligence_mcp-0.2.0 → memoryintelligence_mcp-0.2.1}/src/mi_mcp/client.py +0 -0
  15. {memoryintelligence_mcp-0.2.0 → memoryintelligence_mcp-0.2.1}/src/mi_mcp/config.py +0 -0
  16. {memoryintelligence_mcp-0.2.0 → memoryintelligence_mcp-0.2.1}/src/mi_mcp/embedder.py +0 -0
  17. {memoryintelligence_mcp-0.2.0 → memoryintelligence_mcp-0.2.1}/src/mi_mcp/indexer.py +0 -0
  18. {memoryintelligence_mcp-0.2.0 → memoryintelligence_mcp-0.2.1}/src/mi_mcp/keys.py +0 -0
  19. {memoryintelligence_mcp-0.2.0 → memoryintelligence_mcp-0.2.1}/src/mi_mcp/local_index.py +0 -0
  20. {memoryintelligence_mcp-0.2.0 → memoryintelligence_mcp-0.2.1}/src/mi_mcp/localreads.py +0 -0
  21. {memoryintelligence_mcp-0.2.0 → memoryintelligence_mcp-0.2.1}/src/mi_mcp/paths.py +0 -0
  22. {memoryintelligence_mcp-0.2.0 → memoryintelligence_mcp-0.2.1}/src/mi_mcp/scrub.py +0 -0
  23. {memoryintelligence_mcp-0.2.0 → memoryintelligence_mcp-0.2.1}/src/mi_mcp/server.py +0 -0
  24. {memoryintelligence_mcp-0.2.0 → memoryintelligence_mcp-0.2.1}/src/mi_mcp/vault.py +0 -0
@@ -3,6 +3,29 @@
3
3
  All notable changes to `memoryintelligence-mcp` are documented here.
4
4
  The format follows [Keep a Changelog](https://keepachangelog.com/); this project uses [Semantic Versioning](https://semver.org/).
5
5
 
6
+ ## [0.2.1] — 2026-07-05
7
+
8
+ ### Fixed — one shared vault with the MemorySpace Desktop (MI#653)
9
+ `0.2.0` noted that `mi-mcp` defaulted its local `.umo` vault to `~/MemoryIntelligence`
10
+ while the MemorySpace Desktop app reads `~/Somewhere` — two separate folders, so a
11
+ memory captured or backfilled through `mi-mcp` never showed up in the Desktop app, and
12
+ told you to point `MI_VAULT` there by hand. This release makes that automatic.
13
+
14
+ - **`mi-mcp wire` / `setup` now point the vault at `~/Somewhere`** — they write
15
+ `export MI_VAULT="$HOME/Somewhere"` into the launcher (`run-mi-mcp.sh`), so `mi-mcp`
16
+ and the Desktop resolve **one** vault out of the box. It's a default only: it's
17
+ guarded so an explicit `MI_VAULT` you set yourself (env or MCP config) still wins.
18
+ - **`paths.py`'s default is unchanged** (`~/MemoryIntelligence`) — existing installs are
19
+ never silently moved; the unification happens the next time you run `wire`.
20
+ - **`mi-mcp doctor` reports the effective vault** and whether it matches the Desktop's,
21
+ reading the value the launcher will actually use — so the check goes green once wired.
22
+
23
+ **To pick this up:** upgrade, then **re-run `mi-mcp wire`** (upgrading alone doesn't
24
+ rewrite the launcher), and restart Claude Desktop. `mi-mcp doctor` should show the vault
25
+ as `~/Somewhere`. Files already backfilled into `~/MemoryIntelligence` by `0.2.0` stay
26
+ where they are — move them into `~/Somewhere` (or re-run `backfill`) if you want them in
27
+ the app; `doctor` flags the mismatch.
28
+
6
29
  ## [0.2.0] — 2026-07-04
7
30
 
8
31
  ### Added — the local vault (Path A), previously built on `main` but never released
@@ -0,0 +1,237 @@
1
+ Metadata-Version: 2.4
2
+ Name: memoryintelligence-mcp
3
+ Version: 0.2.1
4
+ Summary: MCP server for MemoryIntelligence — give Claude a memory you own, set up in one command
5
+ Project-URL: Homepage, https://memoryintelligence.io
6
+ Project-URL: Repository, https://github.com/somewhere11/memoryintelligence-mcp
7
+ Project-URL: Issues, https://github.com/somewhere11/memoryintelligence-mcp/issues
8
+ Project-URL: Changelog, https://github.com/somewhere11/memoryintelligence-mcp/blob/main/CHANGELOG.md
9
+ Project-URL: Documentation, https://memoryintelligence.io/docs/api-reference
10
+ Author-email: Somewhere <connect@somewheremedia.com>
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: ai,claude,llm,mcp,memory,memory-intelligence,model-context-protocol
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: httpx<1.0,>=0.27.0
25
+ Requires-Dist: mcp[cli]<2.0,>=1.0.0
26
+ Requires-Dist: pydantic<3.0,>=2.5.0
27
+ Provides-Extra: dev
28
+ Requires-Dist: cryptography<46,>=42.0; extra == 'dev'
29
+ Requires-Dist: fastembed<1.0,>=0.3.0; extra == 'dev'
30
+ Requires-Dist: numpy<3,>=1.24; extra == 'dev'
31
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
32
+ Requires-Dist: pytest>=8.0; extra == 'dev'
33
+ Requires-Dist: ruff>=0.4.0; extra == 'dev'
34
+ Provides-Extra: local
35
+ Requires-Dist: cryptography<46,>=42.0; extra == 'local'
36
+ Requires-Dist: fastembed<1.0,>=0.3.0; extra == 'local'
37
+ Requires-Dist: numpy<3,>=1.24; extra == 'local'
38
+ Description-Content-Type: text/markdown
39
+
40
+ # MemoryIntelligence MCP Server
41
+
42
+ [![PyPI](https://img.shields.io/pypi/v/memoryintelligence-mcp.svg)](https://pypi.org/project/memoryintelligence-mcp/)
43
+ [![Python](https://img.shields.io/pypi/pyversions/memoryintelligence-mcp.svg)](https://pypi.org/project/memoryintelligence-mcp/)
44
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
45
+ [![MCP](https://img.shields.io/badge/MCP-server-blue.svg)](https://modelcontextprotocol.io)
46
+
47
+ > ## Stop paying AI to reread the same context.
48
+
49
+ Receipted memory for your AI, via MCP. What you tell your assistant becomes
50
+ **structured memory you own** — recalled by meaning, with **every answer cited to
51
+ its source**. Works with Claude Desktop, Claude Code, Cursor, VS Code, and any MCP client.
52
+
53
+ ## Start in 30 seconds
54
+
55
+ ```bash
56
+ pip install memoryintelligence-mcp # or: pipx / uvx / uv tool install
57
+ mi-mcp setup # paste your key once — wires everything
58
+ # restart your assistant, then just talk to it:
59
+ # "remember we picked Postgres for billing — we needed transactions"
60
+ # (new session) "what did we decide about the billing database?"
61
+ ```
62
+
63
+ `mi-mcp setup` stores your key **securely** (macOS Keychain, or a `chmod 600`
64
+ keyfile), wires your assistants, opts the current folder in for capture, and
65
+ verifies it — in one command. **Your API key is never written into a config file.**
66
+
67
+ **👉 [Get a free API key](https://memoryintelligence.io/portal)** ·
68
+ [Product](https://memoryintelligence.io) ·
69
+ [Issues](https://github.com/somewhere11/memoryintelligence-mcp/issues)
70
+
71
+ ## What you get
72
+
73
+ Three tools, ready the moment it's wired — a compatible host (Claude Desktop,
74
+ Claude Code, Cursor) **recalls and captures on its own**, no prompts to memorize:
75
+
76
+ | Tool | What it does | Try saying |
77
+ |------|-------------|-----------|
78
+ | `mi_capture` | Save a decision, fact, or preference | *"Remember we chose Postgres for billing — we needed transactions."* |
79
+ | `mi_ask` | Search your memory by meaning, with citations | *"What did we decide about the billing database?"* |
80
+ | `mi_list` | Browse recent memories | *"List what I've saved this week."* |
81
+
82
+ And four things that make it more than a notepad:
83
+
84
+ - **Receipted** — every recall cites the memory it came from. It cites, it doesn't guess.
85
+ - **Reusable** — capture once, recall by meaning across every session and every tool.
86
+ - **Owned** — memories are portable structured objects in *your* account, not locked in a model.
87
+ - **Private** — capture is opt-in per project; PII is redacted from what the agent sees.
88
+
89
+ > Set `MI_MCP_FULL=1` for the full surface (`mi_upload`, `mi_verify`, `mi_forget`,
90
+ > `mi_batch`, `mi_explain`, `mi_match`, `mi_account`). Tools outside the active
91
+ > surface are rejected at the call boundary, not just hidden.
92
+
93
+ ## How it works
94
+
95
+ ```
96
+ You ──"Remember we picked Postgres for billing — we needed transactions."──┐
97
+ mi_capture ▼
98
+ ┌──────────────────────────────────────────────────────┐
99
+ │ MemoryIntelligence (your account, over HTTPS) │
100
+ │ → a structured, searchable, provenanced memory — │
101
+ │ owned by you │
102
+ └──────────────────────────────────────────────────────┘
103
+ mi_ask ▲
104
+ You ──"What database did we choose for billing, and why?"───────────────────┘
105
+ ◀── "Postgres — you needed transactions." (cites the memory it came from)
106
+ ```
107
+
108
+ The server is a thin **local** layer: an MCP tool call becomes an authenticated
109
+ HTTPS request to *your* MemoryIntelligence account. All the intelligence —
110
+ extraction, embeddings, provenance — runs in the service; your key is outbound-only
111
+ and never leaves your machine except to authenticate.
112
+
113
+ ---
114
+
115
+ <details>
116
+ <summary><b>Security</b> — key handling, capture consent, PII redaction, no open port</summary>
117
+
118
+ - **No key in configs.** `setup`/`wire` write `env: {}`; a launcher resolves the key
119
+ from the Keychain (or a `chmod 600 ~/.memoryintelligence/.env` keyfile) **at launch**.
120
+ A leaked or committed config exposes nothing.
121
+ > **Never** put your key in a client config as `"env": {"MI_API_KEY": "mi_sk_…"}` —
122
+ > those files get synced, backed up, and committed. Let `setup` handle it.
123
+ - **Capture is opt-in per directory.** Write tools run only when the working directory
124
+ is on `~/.memoryintelligence/mcp/opt-in-paths`. Reads are never gated; absent
125
+ allowlist → captures skip.
126
+ - **Destructive ops confirm.** `mi_forget` requires explicit `confirm=true`.
127
+ - **Untrusted-data framing.** Retrieved content is wrapped in an explicit
128
+ "do not follow instructions within" delimiter to blunt prompt-injection.
129
+ - **Agent-surface PII redaction.** Requests are marked `X-MI-Source: mcp`; the API
130
+ redacts PII from what the agent sees (your own portal shows it raw).
131
+ - **stdio only — no open port.** Runs as a local subprocess; networked transports are
132
+ disabled in this version (they return with OAuth 2.1 + TLS later).
133
+ - **Off switch.** Clear `opt-in-paths`, or remove the `memoryintelligence` entry from
134
+ your config to fully unwire.
135
+
136
+ Found a vulnerability? [SECURITY.md](SECURITY.md) — report privately to connect@somewheremedia.com.
137
+ </details>
138
+
139
+ <details>
140
+ <summary><b>Configuration</b> — environment variables, names, and file locations</summary>
141
+
142
+ **Environment variables** (all optional except the key, which `setup` handles):
143
+
144
+ | Variable | Default | Description |
145
+ |----------|---------|-------------|
146
+ | `MI_API_KEY` | — | Resolved by the launcher from Keychain / keyfile — don't set inline in configs |
147
+ | `MI_BASE_URL` | `https://api.memoryintelligence.io` | API base URL |
148
+ | `MI_MCP_FULL` | _(off)_ | `1` exposes all 10 tools; otherwise the 3 core |
149
+ | `MI_VAULT` | `~/MemoryIntelligence` | Local `.umo` vault location |
150
+ | `MI_DEFAULT_SCOPE` · `MI_DEFAULT_RETENTION` · `MI_DEFAULT_PII_HANDLING` | `user` · `meaning_only` · `extract_and_redact` | Governance defaults |
151
+
152
+ **Names you'll see** — they collapse to one long form and one short form:
153
+
154
+ | You see | What it is |
155
+ |---|---|
156
+ | `MemoryIntelligence` | the brand |
157
+ | `memoryintelligence-mcp` | the PyPI package (`pip install`) |
158
+ | `mi-mcp` | the command you run (`mi-mcp setup`) |
159
+ | `memoryintelligence` | the server id in your MCP config |
160
+ | `MI_*` | env vars / Keychain service |
161
+
162
+ **On disk** — one namespace:
163
+
164
+ | Path | What |
165
+ |---|---|
166
+ | `~/MemoryIntelligence/` | your `.umo` vault (override with `MI_VAULT`) |
167
+ | `~/.memoryintelligence/mcp/run-mi-mcp.sh` | the launcher each host spawns |
168
+ | `~/.memoryintelligence/mcp/opt-in-paths` | per-directory capture allowlist |
169
+ | `~/.memoryintelligence/.env` | `chmod 600` keyfile (Keychain fallback) |
170
+ </details>
171
+
172
+ <details>
173
+ <summary><b>Manual & cross-platform setup</b> — do it by hand, or script it</summary>
174
+
175
+ `mi-mcp setup` is the recommended path everywhere. To do it manually, store the key
176
+ where your platform fits, then run `mi-mcp wire`:
177
+
178
+ ```bash
179
+ # macOS — Keychain:
180
+ read -s K; security add-generic-password -a "$USER" -s "MI_API_KEY" -w "$K" -U; unset K
181
+
182
+ # Linux / Windows — chmod 600 keyfile:
183
+ mkdir -p ~/.memoryintelligence
184
+ umask 077 && printf 'MI_API_KEY="%s"\n' "$YOUR_KEY" > ~/.memoryintelligence/.env
185
+
186
+ # then, on any OS:
187
+ mi-mcp wire
188
+ echo "$(pwd)" >> ~/.memoryintelligence/mcp/opt-in-paths # allow captures here
189
+ ```
190
+
191
+ The launcher resolves the key in order: **inherited env → macOS Keychain → keyfile**.
192
+ Never paste the key into an MCP client config.
193
+
194
+ **Repair / inspect without re-running setup:**
195
+ ```bash
196
+ mi-mcp doctor # checks binary, PATH, key, wiring, opt-in, vault path
197
+ mi-mcp status # wired surfaces + opt-in allowlist
198
+ mi-mcp wire --dry-run # preview wiring changes
199
+ ```
200
+ </details>
201
+
202
+ <details>
203
+ <summary><b>VS Code / GitHub Copilot</b></summary>
204
+
205
+ VS Code / Copilot read a different config than Claude: servers live under `"servers"`
206
+ (not `"mcpServers"`) and need `"type": "stdio"`. `mi-mcp wire --surfaces vscode` writes
207
+ it, or add per-workspace `.vscode/mcp.json`:
208
+
209
+ ```json
210
+ { "servers": { "memoryintelligence": { "type": "stdio", "command": "mi-mcp" } } }
211
+ ```
212
+
213
+ Then open Copilot Chat in **Agent** mode — the memory tools only appear there.
214
+ </details>
215
+
216
+ <details>
217
+ <summary><b>Development</b></summary>
218
+
219
+ ```bash
220
+ pip install -e ".[dev]" # from mcp-server/
221
+ PYTHONPATH=src python -m pytest
222
+ ruff check src/
223
+ ```
224
+ `src/mi_mcp/`: `__main__.py` (CLI + dispatch) · `cli.py` (setup/wire/doctor) ·
225
+ `config.py` (consent gate) · `client.py` (MI API) · `server.py` (tools + instructions).
226
+ Contributions welcome — [CONTRIBUTING.md](CONTRIBUTING.md).
227
+ </details>
228
+
229
+ ---
230
+
231
+ **Learn more:** [memoryintelligence.io](https://memoryintelligence.io) ·
232
+ [Get a key](https://memoryintelligence.io/portal) ·
233
+ [API reference](https://memoryintelligence.io/docs/api-reference) ·
234
+ [What is MCP](https://modelcontextprotocol.io) ·
235
+ [Changelog](CHANGELOG.md)
236
+
237
+ MIT © Somewhere. See [LICENSE](LICENSE).
@@ -0,0 +1,198 @@
1
+ # MemoryIntelligence MCP Server
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/memoryintelligence-mcp.svg)](https://pypi.org/project/memoryintelligence-mcp/)
4
+ [![Python](https://img.shields.io/pypi/pyversions/memoryintelligence-mcp.svg)](https://pypi.org/project/memoryintelligence-mcp/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
+ [![MCP](https://img.shields.io/badge/MCP-server-blue.svg)](https://modelcontextprotocol.io)
7
+
8
+ > ## Stop paying AI to reread the same context.
9
+
10
+ Receipted memory for your AI, via MCP. What you tell your assistant becomes
11
+ **structured memory you own** — recalled by meaning, with **every answer cited to
12
+ its source**. Works with Claude Desktop, Claude Code, Cursor, VS Code, and any MCP client.
13
+
14
+ ## Start in 30 seconds
15
+
16
+ ```bash
17
+ pip install memoryintelligence-mcp # or: pipx / uvx / uv tool install
18
+ mi-mcp setup # paste your key once — wires everything
19
+ # restart your assistant, then just talk to it:
20
+ # "remember we picked Postgres for billing — we needed transactions"
21
+ # (new session) "what did we decide about the billing database?"
22
+ ```
23
+
24
+ `mi-mcp setup` stores your key **securely** (macOS Keychain, or a `chmod 600`
25
+ keyfile), wires your assistants, opts the current folder in for capture, and
26
+ verifies it — in one command. **Your API key is never written into a config file.**
27
+
28
+ **👉 [Get a free API key](https://memoryintelligence.io/portal)** ·
29
+ [Product](https://memoryintelligence.io) ·
30
+ [Issues](https://github.com/somewhere11/memoryintelligence-mcp/issues)
31
+
32
+ ## What you get
33
+
34
+ Three tools, ready the moment it's wired — a compatible host (Claude Desktop,
35
+ Claude Code, Cursor) **recalls and captures on its own**, no prompts to memorize:
36
+
37
+ | Tool | What it does | Try saying |
38
+ |------|-------------|-----------|
39
+ | `mi_capture` | Save a decision, fact, or preference | *"Remember we chose Postgres for billing — we needed transactions."* |
40
+ | `mi_ask` | Search your memory by meaning, with citations | *"What did we decide about the billing database?"* |
41
+ | `mi_list` | Browse recent memories | *"List what I've saved this week."* |
42
+
43
+ And four things that make it more than a notepad:
44
+
45
+ - **Receipted** — every recall cites the memory it came from. It cites, it doesn't guess.
46
+ - **Reusable** — capture once, recall by meaning across every session and every tool.
47
+ - **Owned** — memories are portable structured objects in *your* account, not locked in a model.
48
+ - **Private** — capture is opt-in per project; PII is redacted from what the agent sees.
49
+
50
+ > Set `MI_MCP_FULL=1` for the full surface (`mi_upload`, `mi_verify`, `mi_forget`,
51
+ > `mi_batch`, `mi_explain`, `mi_match`, `mi_account`). Tools outside the active
52
+ > surface are rejected at the call boundary, not just hidden.
53
+
54
+ ## How it works
55
+
56
+ ```
57
+ You ──"Remember we picked Postgres for billing — we needed transactions."──┐
58
+ mi_capture ▼
59
+ ┌──────────────────────────────────────────────────────┐
60
+ │ MemoryIntelligence (your account, over HTTPS) │
61
+ │ → a structured, searchable, provenanced memory — │
62
+ │ owned by you │
63
+ └──────────────────────────────────────────────────────┘
64
+ mi_ask ▲
65
+ You ──"What database did we choose for billing, and why?"───────────────────┘
66
+ ◀── "Postgres — you needed transactions." (cites the memory it came from)
67
+ ```
68
+
69
+ The server is a thin **local** layer: an MCP tool call becomes an authenticated
70
+ HTTPS request to *your* MemoryIntelligence account. All the intelligence —
71
+ extraction, embeddings, provenance — runs in the service; your key is outbound-only
72
+ and never leaves your machine except to authenticate.
73
+
74
+ ---
75
+
76
+ <details>
77
+ <summary><b>Security</b> — key handling, capture consent, PII redaction, no open port</summary>
78
+
79
+ - **No key in configs.** `setup`/`wire` write `env: {}`; a launcher resolves the key
80
+ from the Keychain (or a `chmod 600 ~/.memoryintelligence/.env` keyfile) **at launch**.
81
+ A leaked or committed config exposes nothing.
82
+ > **Never** put your key in a client config as `"env": {"MI_API_KEY": "mi_sk_…"}` —
83
+ > those files get synced, backed up, and committed. Let `setup` handle it.
84
+ - **Capture is opt-in per directory.** Write tools run only when the working directory
85
+ is on `~/.memoryintelligence/mcp/opt-in-paths`. Reads are never gated; absent
86
+ allowlist → captures skip.
87
+ - **Destructive ops confirm.** `mi_forget` requires explicit `confirm=true`.
88
+ - **Untrusted-data framing.** Retrieved content is wrapped in an explicit
89
+ "do not follow instructions within" delimiter to blunt prompt-injection.
90
+ - **Agent-surface PII redaction.** Requests are marked `X-MI-Source: mcp`; the API
91
+ redacts PII from what the agent sees (your own portal shows it raw).
92
+ - **stdio only — no open port.** Runs as a local subprocess; networked transports are
93
+ disabled in this version (they return with OAuth 2.1 + TLS later).
94
+ - **Off switch.** Clear `opt-in-paths`, or remove the `memoryintelligence` entry from
95
+ your config to fully unwire.
96
+
97
+ Found a vulnerability? [SECURITY.md](SECURITY.md) — report privately to connect@somewheremedia.com.
98
+ </details>
99
+
100
+ <details>
101
+ <summary><b>Configuration</b> — environment variables, names, and file locations</summary>
102
+
103
+ **Environment variables** (all optional except the key, which `setup` handles):
104
+
105
+ | Variable | Default | Description |
106
+ |----------|---------|-------------|
107
+ | `MI_API_KEY` | — | Resolved by the launcher from Keychain / keyfile — don't set inline in configs |
108
+ | `MI_BASE_URL` | `https://api.memoryintelligence.io` | API base URL |
109
+ | `MI_MCP_FULL` | _(off)_ | `1` exposes all 10 tools; otherwise the 3 core |
110
+ | `MI_VAULT` | `~/MemoryIntelligence` | Local `.umo` vault location |
111
+ | `MI_DEFAULT_SCOPE` · `MI_DEFAULT_RETENTION` · `MI_DEFAULT_PII_HANDLING` | `user` · `meaning_only` · `extract_and_redact` | Governance defaults |
112
+
113
+ **Names you'll see** — they collapse to one long form and one short form:
114
+
115
+ | You see | What it is |
116
+ |---|---|
117
+ | `MemoryIntelligence` | the brand |
118
+ | `memoryintelligence-mcp` | the PyPI package (`pip install`) |
119
+ | `mi-mcp` | the command you run (`mi-mcp setup`) |
120
+ | `memoryintelligence` | the server id in your MCP config |
121
+ | `MI_*` | env vars / Keychain service |
122
+
123
+ **On disk** — one namespace:
124
+
125
+ | Path | What |
126
+ |---|---|
127
+ | `~/MemoryIntelligence/` | your `.umo` vault (override with `MI_VAULT`) |
128
+ | `~/.memoryintelligence/mcp/run-mi-mcp.sh` | the launcher each host spawns |
129
+ | `~/.memoryintelligence/mcp/opt-in-paths` | per-directory capture allowlist |
130
+ | `~/.memoryintelligence/.env` | `chmod 600` keyfile (Keychain fallback) |
131
+ </details>
132
+
133
+ <details>
134
+ <summary><b>Manual & cross-platform setup</b> — do it by hand, or script it</summary>
135
+
136
+ `mi-mcp setup` is the recommended path everywhere. To do it manually, store the key
137
+ where your platform fits, then run `mi-mcp wire`:
138
+
139
+ ```bash
140
+ # macOS — Keychain:
141
+ read -s K; security add-generic-password -a "$USER" -s "MI_API_KEY" -w "$K" -U; unset K
142
+
143
+ # Linux / Windows — chmod 600 keyfile:
144
+ mkdir -p ~/.memoryintelligence
145
+ umask 077 && printf 'MI_API_KEY="%s"\n' "$YOUR_KEY" > ~/.memoryintelligence/.env
146
+
147
+ # then, on any OS:
148
+ mi-mcp wire
149
+ echo "$(pwd)" >> ~/.memoryintelligence/mcp/opt-in-paths # allow captures here
150
+ ```
151
+
152
+ The launcher resolves the key in order: **inherited env → macOS Keychain → keyfile**.
153
+ Never paste the key into an MCP client config.
154
+
155
+ **Repair / inspect without re-running setup:**
156
+ ```bash
157
+ mi-mcp doctor # checks binary, PATH, key, wiring, opt-in, vault path
158
+ mi-mcp status # wired surfaces + opt-in allowlist
159
+ mi-mcp wire --dry-run # preview wiring changes
160
+ ```
161
+ </details>
162
+
163
+ <details>
164
+ <summary><b>VS Code / GitHub Copilot</b></summary>
165
+
166
+ VS Code / Copilot read a different config than Claude: servers live under `"servers"`
167
+ (not `"mcpServers"`) and need `"type": "stdio"`. `mi-mcp wire --surfaces vscode` writes
168
+ it, or add per-workspace `.vscode/mcp.json`:
169
+
170
+ ```json
171
+ { "servers": { "memoryintelligence": { "type": "stdio", "command": "mi-mcp" } } }
172
+ ```
173
+
174
+ Then open Copilot Chat in **Agent** mode — the memory tools only appear there.
175
+ </details>
176
+
177
+ <details>
178
+ <summary><b>Development</b></summary>
179
+
180
+ ```bash
181
+ pip install -e ".[dev]" # from mcp-server/
182
+ PYTHONPATH=src python -m pytest
183
+ ruff check src/
184
+ ```
185
+ `src/mi_mcp/`: `__main__.py` (CLI + dispatch) · `cli.py` (setup/wire/doctor) ·
186
+ `config.py` (consent gate) · `client.py` (MI API) · `server.py` (tools + instructions).
187
+ Contributions welcome — [CONTRIBUTING.md](CONTRIBUTING.md).
188
+ </details>
189
+
190
+ ---
191
+
192
+ **Learn more:** [memoryintelligence.io](https://memoryintelligence.io) ·
193
+ [Get a key](https://memoryintelligence.io/portal) ·
194
+ [API reference](https://memoryintelligence.io/docs/api-reference) ·
195
+ [What is MCP](https://modelcontextprotocol.io) ·
196
+ [Changelog](CHANGELOG.md)
197
+
198
+ MIT © Somewhere. See [LICENSE](LICENSE).
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "memoryintelligence-mcp"
7
- version = "0.2.0"
7
+ version = "0.2.1"
8
8
  description = "MCP server for MemoryIntelligence — give Claude a memory you own, set up in one command"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -1,3 +1,3 @@
1
1
  """MI MCP Server — MemoryIntelligence tools for Claude."""
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.2.1"
@@ -30,6 +30,7 @@ import argparse
30
30
  import getpass
31
31
  import json
32
32
  import os
33
+ import re
33
34
  import shutil
34
35
  import subprocess
35
36
  import sys
@@ -72,6 +73,16 @@ if [[ -z "${MI_API_KEY:-}" ]]; then
72
73
  fi
73
74
  export MI_API_KEY
74
75
 
76
+ # Point the local .umo vault at the MemorySpace Desktop vault (~/Somewhere) so
77
+ # both surfaces resolve ONE vault (#653). Without this, mi-mcp defaults to
78
+ # ~/MemoryIntelligence and backfilled memories never appear in the Desktop (and
79
+ # on a dev machine ~/MemoryIntelligence is the monorepo checkout itself). An
80
+ # explicit MI_VAULT (inherited env or a config `env` entry) still wins — we only
81
+ # fill the default.
82
+ if [[ -z "${MI_VAULT:-}" ]]; then
83
+ export MI_VAULT="$HOME/Somewhere"
84
+ fi
85
+
75
86
  # Resolve the mi-mcp binary. The path captured at `wire` time is tried first —
76
87
  # it's the most reliable under a host's minimal GUI PATH (e.g. Claude Desktop).
77
88
  # If a reinstall/upgrade moved it, fall back to PATH then the common install
@@ -128,6 +139,23 @@ def _wrapper_path(home: Path) -> Path:
128
139
  return paths.wrapper_path(home=home)
129
140
 
130
141
 
142
+ def _wrapper_vault(home: Path) -> Path | None:
143
+ """The ``MI_VAULT`` default baked into the rendered wrapper by ``wire``, if any.
144
+
145
+ The wrapper ``export MI_VAULT="$HOME/Somewhere"``s (behind a guard) so the
146
+ server resolves the same vault as the Desktop (#653). ``doctor`` reads it to
147
+ report the vault the *server* will actually use at launch — which isn't
148
+ necessarily set in the shell running ``doctor``. Returns ``None`` if the
149
+ wrapper is absent or sets no vault default."""
150
+ wrapper = _wrapper_path(home)
151
+ if not wrapper.exists():
152
+ return None
153
+ m = re.search(r'MI_VAULT="([^"]*)"', wrapper.read_text())
154
+ if not m:
155
+ return None
156
+ return Path(m.group(1).replace("$HOME", str(home))).expanduser()
157
+
158
+
131
159
  def _mi_mcp_bin() -> str:
132
160
  return shutil.which("mi-mcp") or str(Path(sys.executable).parent / "mi-mcp")
133
161
 
@@ -379,19 +407,33 @@ def cmd_doctor(argv: list[str]) -> int:
379
407
  f"{n} entries" if optin.exists() else "absent — all captures will skip",
380
408
  critical=False)
381
409
 
382
- # Vault path — surface where the local vault resolves and whether it matches the
383
- # MemorySpace Desktop vault (~/Somewhere). They differ by default (#653): mi-mcp
384
- # defaults to ~/MemoryIntelligence; the Desktop reads ~/Somewhere. If MI_VAULT
385
- # isn't unifying them, backfilled memories won't appear in the Desktop.
386
- from . import vault as _vault
387
- vpath = _vault.vault_path()
410
+ # Vault path — where the local .umo vault resolves, and whether it matches the
411
+ # MemorySpace Desktop vault (~/Somewhere). By default they differ (#653): mi-mcp
412
+ # defaults to ~/MemoryIntelligence, the Desktop reads ~/Somewhere. `mi-mcp wire`
413
+ # bakes `MI_VAULT="$HOME/Somewhere"` into the wrapper to unify them, so the
414
+ # EFFECTIVE vault is the one the wrapper exports when it spawns the server — not
415
+ # necessarily what's set in this doctor shell. Resolve in that order: a live
416
+ # MI_VAULT (an explicit override always wins) → the wrapper's baked-in default →
417
+ # the paths default.
388
418
  desktop_vault = home / "Somewhere"
389
- mi_vault_set = "MI_VAULT" in os.environ
419
+ live_vault = os.environ.get("MI_VAULT")
420
+ if live_vault:
421
+ vpath, vsrc = Path(live_vault).expanduser(), "MI_VAULT env"
422
+ elif (wired := _wrapper_vault(home)) is not None:
423
+ vpath, vsrc = wired, "wrapper (wired)"
424
+ else:
425
+ vpath, vsrc = paths.vault_dir(home=home), "default"
390
426
  matches = vpath.resolve() == desktop_vault.resolve()
391
- check("vault path", matches or mi_vault_set,
392
- str(vpath) if matches else
393
- f"{vpath} Desktop reads {desktop_vault}; set MI_VAULT={desktop_vault} so both share one vault (#653)",
394
- critical=False)
427
+ # Green when it resolves to the Desktop vault, or when the user set an explicit
428
+ # MI_VAULT of their own (their choice wins — we don't second-guess it). Only the
429
+ # unresolved default (mismatch, no explicit override) gets the #653 nag.
430
+ green = matches or bool(live_vault)
431
+ if green:
432
+ detail = f"{vpath} [{vsrc}]"
433
+ else:
434
+ detail = (f"{vpath} [{vsrc}] — Desktop reads {desktop_vault}; run `mi-mcp wire` "
435
+ f"(bakes MI_VAULT={desktop_vault}) so both share one vault (#653)")
436
+ check("vault path", green, detail, critical=False)
395
437
 
396
438
  for s, p in _surface_paths(home).items():
397
439
  servers = _load_json(p).get(_surface_key(s), {})
@@ -36,11 +36,14 @@ from dataclasses import dataclass
36
36
  MAGIC = b"UMO!" # 0x554D4F21
37
37
  FORMAT_VERSION = 0x0100 # canonical FEAT-0051 v1.0
38
38
 
39
- # Shared cross-surface conventions (the unified local home). The Rust desktop app
40
- # ("Somewhere") writes these same values, so files written by the MCP and by the
41
- # desktop are mutually readable in one vault. owner_did is a plaintext metadata
42
- # label only (NOT used in decryption that's the X25519 key), so a fixed value is
43
- # safe and keeps the home consistent.
39
+ # Shared cross-surface .umo conventions. The Rust desktop app ("Somewhere") writes
40
+ # these same values, so a file written by the MCP and one written by the desktop
41
+ # are mutually READABLE but only when both surfaces point at the SAME directory.
42
+ # By default they do NOT: mi-mcp resolves ~/MemoryIntelligence while the desktop
43
+ # reads ~/Somewhere (#653), so identical conventions in two dirs are two vaults,
44
+ # not one. `mi-mcp wire` bakes MI_VAULT=~/Somewhere into its launcher to unify them.
45
+ # owner_did is a plaintext metadata label only (NOT used in decryption — that's the
46
+ # X25519 key), so a fixed value is safe and keeps the conventions consistent.
44
47
  LOCAL_OWNER_DID = "did:mi:owner-local"
45
48
  FORMAT_VERSION_STR = "0x0100" # string form the desktop stores in public_metadata
46
49
  _HKDF_INFO = b"umo-cek-wrap-v1"