vaultzero 0.1.4__tar.gz → 0.1.6__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.
- {vaultzero-0.1.4 → vaultzero-0.1.6}/PKG-INFO +1 -1
- {vaultzero-0.1.4 → vaultzero-0.1.6}/pyproject.toml +1 -1
- {vaultzero-0.1.4 → vaultzero-0.1.6}/vaultzero/client/mcp_server.py +44 -42
- {vaultzero-0.1.4 → vaultzero-0.1.6}/.gitignore +0 -0
- {vaultzero-0.1.4 → vaultzero-0.1.6}/LICENSE +0 -0
- {vaultzero-0.1.4 → vaultzero-0.1.6}/README.md +0 -0
- {vaultzero-0.1.4 → vaultzero-0.1.6}/tests/__init__.py +0 -0
- {vaultzero-0.1.4 → vaultzero-0.1.6}/tests/unit/__init__.py +0 -0
- {vaultzero-0.1.4 → vaultzero-0.1.6}/tests/unit/golden_vectors.json +0 -0
- {vaultzero-0.1.4 → vaultzero-0.1.6}/tests/unit/test_crypto.py +0 -0
- {vaultzero-0.1.4 → vaultzero-0.1.6}/tests/unit/test_sdk_and_mcp.py +0 -0
- {vaultzero-0.1.4 → vaultzero-0.1.6}/vaultzero/__init__.py +0 -0
- {vaultzero-0.1.4 → vaultzero-0.1.6}/vaultzero/client/__init__.py +0 -0
- {vaultzero-0.1.4 → vaultzero-0.1.6}/vaultzero/client/_net.py +0 -0
- {vaultzero-0.1.4 → vaultzero-0.1.6}/vaultzero/client/crypto.py +0 -0
- {vaultzero-0.1.4 → vaultzero-0.1.6}/vaultzero/client/embeddings.py +0 -0
- {vaultzero-0.1.4 → vaultzero-0.1.6}/vaultzero/client/sdk.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: vaultzero
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.6
|
|
4
4
|
Summary: MCP server for a privacy-first agent memory vault: memories are encrypted on the client before they reach the server.
|
|
5
5
|
Project-URL: Homepage, https://vaultzero.cc
|
|
6
6
|
Project-URL: Documentation, https://github.com/xo0ps/VaultZero-Client#readme
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "vaultzero"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.6"
|
|
8
8
|
# This string is what MCP directories show next to the listing, so it names the thing a
|
|
9
9
|
# prospective user is looking for (an MCP server) before the architecture behind it.
|
|
10
10
|
description = "MCP server for a privacy-first agent memory vault: memories are encrypted on the client before they reach the server."
|
|
@@ -65,8 +65,41 @@ def create_mcp_server(
|
|
|
65
65
|
default_retention = choices[0]
|
|
66
66
|
mcp = FastMCP(name)
|
|
67
67
|
|
|
68
|
+
# The permitted scopes and retention choices are known here, so they go in the
|
|
69
|
+
# description literally. Saying "the scopes this server was configured with" and
|
|
70
|
+
# pointing at a list that does not exist left the agent to guess and learn from an
|
|
71
|
+
# error; naming them costs a few tokens and removes a round trip.
|
|
72
|
+
scope_list = ", ".join(sorted(permitted))
|
|
73
|
+
retention_list = ", ".join(choices)
|
|
74
|
+
|
|
68
75
|
@mcp.tool(
|
|
69
76
|
title="Remember a fact",
|
|
77
|
+
description=(
|
|
78
|
+
"Store one durable fact in encrypted long-term memory, readable later by "
|
|
79
|
+
"recall_context.\n\n"
|
|
80
|
+
"Use this when the user states something worth keeping across sessions: a "
|
|
81
|
+
"preference, a decision, an identifier, a recurring constraint. Do NOT use it "
|
|
82
|
+
"for conversation that only matters in this session, for secrets or "
|
|
83
|
+
"credentials, or to restate something already stored — storing the same fact "
|
|
84
|
+
"twice creates two memories that both surface on recall.\n\n"
|
|
85
|
+
"The write is only reversible by a client holding the same key store, so the "
|
|
86
|
+
"fact cannot be read back from another machine or a hosted instance. A stored "
|
|
87
|
+
"fact can be deleted before it expires, but only by that same holder.\n\n"
|
|
88
|
+
"Args:\n"
|
|
89
|
+
" fact_text: The fact to persist, as a self-contained sentence that still "
|
|
90
|
+
"makes sense alone: \"prefers oat milk in coffee\", not \"that one\". "
|
|
91
|
+
"Shorter text embeds more precisely and recalls better.\n"
|
|
92
|
+
f" scope: One of: {scope_list}. A partition label deciding who and what can "
|
|
93
|
+
"read the fact back, so recall must ask for the same one. Any other label "
|
|
94
|
+
"stores nothing and returns an error.\n"
|
|
95
|
+
f" retention: One of: {retention_list} (default {default_retention}). How "
|
|
96
|
+
"long the fact stays retrievable before the server expires and purges it. "
|
|
97
|
+
"Expiry is irreversible.\n\n"
|
|
98
|
+
"Returns the new memory id, or \"error: ...\" with nothing stored when the "
|
|
99
|
+
"scope or retention is rejected. An unusable credential, an unreachable API "
|
|
100
|
+
"or a rejected envelope all follow the same rule: an error and no partial "
|
|
101
|
+
"write."
|
|
102
|
+
),
|
|
70
103
|
annotations=ToolAnnotations(
|
|
71
104
|
title="Remember a fact",
|
|
72
105
|
# Writes durable state that survives this session. Not read-only, and two
|
|
@@ -78,37 +111,11 @@ def create_mcp_server(
|
|
|
78
111
|
),
|
|
79
112
|
)
|
|
80
113
|
async def remember_fact(fact_text: str, scope: str, retention: str = default_retention) -> str:
|
|
81
|
-
"""Store one durable fact in encrypted long-term memory,
|
|
82
|
-
recall_context
|
|
83
|
-
|
|
84
|
-
Use this when the user states something worth keeping across sessions: a
|
|
85
|
-
preference, a decision, an identifier, a recurring constraint. Do NOT use it for
|
|
86
|
-
conversation that only matters in this session, for secrets or credentials, or to
|
|
87
|
-
restate something already stored — storing the same fact twice creates two
|
|
88
|
-
memories that both surface on recall.
|
|
114
|
+
"""Store one durable fact in encrypted long-term memory, readable later by
|
|
115
|
+
recall_context.
|
|
89
116
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
different machine or a hosted instance.
|
|
93
|
-
|
|
94
|
-
Args:
|
|
95
|
-
fact_text: The fact to persist, as a self-contained sentence. Write it so it
|
|
96
|
-
still makes sense with no surrounding conversation, e.g. "prefers oat
|
|
97
|
-
milk in coffee" rather than "that one". Shorter text embeds more
|
|
98
|
-
precisely and recalls better.
|
|
99
|
-
scope: A partition label, chosen from the scopes this server was configured
|
|
100
|
-
with (see below). It restricts who and what can read the fact back, and
|
|
101
|
-
recall must ask for the same scope. If the label is not permitted, nothing
|
|
102
|
-
is stored and an error naming the allowed values is returned.
|
|
103
|
-
retention: One of the retention_choices configured for this server. Sets how
|
|
104
|
-
long the fact stays retrievable before it expires and is purged; expiry is
|
|
105
|
-
enforced by the server and cannot be undone. The default is the first
|
|
106
|
-
choice.
|
|
107
|
-
|
|
108
|
-
Returns the new memory id on success, or "error: ..." and stores nothing when the
|
|
109
|
-
scope or retention is not permitted. Failure modes: an unusable credential, an
|
|
110
|
-
unreachable API, or a rejected envelope all return an error with nothing stored —
|
|
111
|
-
there is no partial write.
|
|
117
|
+
The wire description is passed to @mcp.tool above, where the permitted scopes and
|
|
118
|
+
retention choices are interpolated. This docstring is the developer-facing summary.
|
|
112
119
|
"""
|
|
113
120
|
if scope not in permitted:
|
|
114
121
|
return f"error: scope is not permitted (allowed: {', '.join(sorted(permitted))})"
|
|
@@ -139,21 +146,16 @@ def create_mcp_server(
|
|
|
139
146
|
)
|
|
140
147
|
async def recall_context(query: str, scopes: list[str], limit: int = 5) -> str:
|
|
141
148
|
"""Retrieve facts previously written by remember_fact, ranked by similarity to
|
|
142
|
-
the query
|
|
149
|
+
the query and decrypted for this call.
|
|
143
150
|
|
|
144
151
|
Use this before answering a question that may depend on something the user told
|
|
145
152
|
you earlier — preferences, past decisions, standing constraints. Do NOT use it to
|
|
146
153
|
browse or audit everything stored: it ranks by relevance to one query and returns
|
|
147
154
|
at most `limit` items, so it is a lookup, not a listing.
|
|
148
155
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
Requires the key store that wrote the memories. If a matching key is not present,
|
|
153
|
-
the call returns "decryption key not found in the trusted key store" — that is
|
|
154
|
-
expected on a different machine, a hosted instance, or a fresh process without
|
|
155
|
-
VZ_KEY_STORE_PATH, and the memories are unreadable there by design rather than by
|
|
156
|
-
failure.
|
|
156
|
+
An empty result is a successful answer, not an error. Without the key store that
|
|
157
|
+
wrote the memories this returns "decryption key not found" — expected on another
|
|
158
|
+
machine or a hosted instance.
|
|
157
159
|
|
|
158
160
|
Args:
|
|
159
161
|
query: Natural-language description of what you are looking for. It is matched
|
|
@@ -191,9 +193,9 @@ def create_mcp_server(
|
|
|
191
193
|
lines.append("</memory>")
|
|
192
194
|
return "\n".join(lines)
|
|
193
195
|
|
|
194
|
-
#
|
|
195
|
-
#
|
|
196
|
-
|
|
196
|
+
# recall_context's description comes from its docstring, which FastMCP ships verbatim,
|
|
197
|
+
# indentation and all. Dedent it. remember_fact is not touched: its description was
|
|
198
|
+
# passed explicitly above, with the scope and retention values interpolated.
|
|
197
199
|
mcp._tool_manager.get_tool("recall_context").description = _doc(recall_context)
|
|
198
200
|
|
|
199
201
|
return mcp
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|