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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: vaultzero
3
- Version: 0.1.4
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.4"
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, so a later call to
82
- recall_context can retrieve it by meaning.
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
- Counterpart: recall_context (the read side). Every fact written here is only
91
- readable by a client holding the same key store; it cannot be read back from a
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, and decrypt them for this call.
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
- This is the read counterpart to remember_fact. Results are ranked nearest-first
150
- and may be empty; "no memories found" is a successful answer, not an error.
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
- # FastMCP ships __doc__ verbatim, indentation and all. Rewrite both descriptions with
195
- # the dedented form so the schema a client reads is clean and costs fewer tokens.
196
- mcp._tool_manager.get_tool("remember_fact").description = _doc(remember_fact)
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