@safekb/mcp 0.14.1 → 0.14.2
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.
- package/dist/safekb-mcp.js +10 -4
- package/package.json +1 -1
package/dist/safekb-mcp.js
CHANGED
|
@@ -2581,7 +2581,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
2581
2581
|
// package.json
|
|
2582
2582
|
var package_default = {
|
|
2583
2583
|
name: "@safekb/mcp",
|
|
2584
|
-
version: "0.14.
|
|
2584
|
+
version: "0.14.2",
|
|
2585
2585
|
description: "SafeKB local MCP client: proxies the hosted SafeKB tools and adds zero-knowledge sealed documents.",
|
|
2586
2586
|
license: "SEE LICENSE IN LICENSE",
|
|
2587
2587
|
author: "Mustafa Öztürk",
|
|
@@ -36169,6 +36169,7 @@ var credentialId = objectId2("Id of the sealed credential.");
|
|
|
36169
36169
|
var expectedVersion = exports_external.number().int().min(1).describe("The version you last read for this credential. The write fails if it changed since.");
|
|
36170
36170
|
var CLEARABLE = "An empty string clears the field.";
|
|
36171
36171
|
var SECRET_ARGUMENT_NOTE = "Secret values passed here are part of the conversation transcript and reach the model provider; the server never sees them.";
|
|
36172
|
+
var TYPED_NOTE = "For a secret you must not see (one the user has not given you, e.g. a card number, PIN or bank password), pass typed_at_sidecar with the field names instead of the value: the user types it at the sidecar while the call waits. Then use it with secret_exec, never by revealing it.";
|
|
36172
36173
|
var visibleFields = {
|
|
36173
36174
|
username: exports_external.string().describe(`Visible to the server. ${CLEARABLE}`).optional(),
|
|
36174
36175
|
url: exports_external.string().describe(`Visible to the server. ${CLEARABLE}`).optional(),
|
|
@@ -36189,7 +36190,7 @@ var sealedFields = {
|
|
|
36189
36190
|
function credentialTools(credentials, migration, names, entry) {
|
|
36190
36191
|
const atSidecar = (fields2) => fields2 === undefined ? undefined : { fields: fields2, entry };
|
|
36191
36192
|
return [
|
|
36192
|
-
defineTool("reveal_sealed_credential", `Decrypt one sealed field of a sealed credential on this machine. The server only sees that the ciphertext was fetched. Find credentials and their visible fields with the standard credential tools (search_credentials, get_credential). Refused unless its llm_visibility is visible. ${EXPOSURE_NOTE}`, {
|
|
36193
|
+
defineTool("reveal_sealed_credential", `Decrypt one sealed field of a sealed credential on this machine. The server only sees that the ciphertext was fetched. Find credentials and their visible fields with the standard credential tools (search_credentials, get_credential). Refused unless its llm_visibility is visible. To use a secret (log in, call an API, type it on a device), use secret_exec instead: it never shows the value. ${EXPOSURE_NOTE}`, {
|
|
36193
36194
|
credential_id: credentialId,
|
|
36194
36195
|
field: exports_external.string().min(1).describe("password, totp, sealed_notes, or custom:{key}.")
|
|
36195
36196
|
}, (args) => credentials.reveal(args.credential_id, args.field)),
|
|
@@ -36199,7 +36200,7 @@ function credentialTools(credentials, migration, names, entry) {
|
|
|
36199
36200
|
llm_visibility: exports_external.enum(["use_only", "human_only"]).describe("human_only is the more restrictive."),
|
|
36200
36201
|
field: exports_external.string().min(1).describe("One sealed field: password, totp, sealed_notes or custom:{key}. Omit for the whole credential; a field without its own value follows the credential.").optional()
|
|
36201
36202
|
}, (args) => credentials.setLlmVisibility(args.credential_id, args.llm_visibility, args.field)),
|
|
36202
|
-
defineTool("insert_sealed_credential", `Create a sealed credential in a seal root. It is kept in the space of that root. Whether an LLM may reveal its secrets follows the default the user chose for the tenant; only the user
|
|
36203
|
+
defineTool("insert_sealed_credential", `Create a sealed credential in a seal root. ${TYPED_NOTE} It is kept in the space of that root. Whether an LLM may reveal its secrets follows the default the user chose for the tenant (it may be visible): tighten a field the user wants hidden with set_sealed_credential_llm_visibility (use_only); only the user loosens it, in the SafeKB app. password, totp, sealed_notes and the values of sealed custom fields are encrypted on this machine; title, username, url, tags, notes, visible custom fields and the key name of every custom field (sealed ones too) stay readable by the server so search and duplicate detection work. ${SECRET_ARGUMENT_NOTE}`, {
|
|
36203
36204
|
root_id: rootRef("The seal root that will own it."),
|
|
36204
36205
|
title: exports_external.string().min(1).describe("Visible to the server."),
|
|
36205
36206
|
folder_id: exports_external.string().min(1).describe("Group it belongs to.").optional(),
|
|
@@ -36210,7 +36211,7 @@ function credentialTools(credentials, migration, names, entry) {
|
|
|
36210
36211
|
root_id: await names.resolve(args.root_id),
|
|
36211
36212
|
typed_at_sidecar: atSidecar(args.typed_at_sidecar)
|
|
36212
36213
|
})),
|
|
36213
|
-
defineTool("update_sealed_credential", `Change a sealed credential with its seal root's signature. Pass only the fields to change; the save also attests the visible fields as they are now. If visible fields were changed without the key since the last sealed save, the call fails and names them until accept_visible_changes is true. ${SECRET_ARGUMENT_NOTE}`, {
|
|
36214
|
+
defineTool("update_sealed_credential", `Change a sealed credential with its seal root's signature. Pass only the fields to change; the save also attests the visible fields as they are now. If visible fields were changed without the key since the last sealed save, the call fails and names them until accept_visible_changes is true. ${TYPED_NOTE} ${SECRET_ARGUMENT_NOTE}`, {
|
|
36214
36215
|
credential_id: credentialId,
|
|
36215
36216
|
expected_version: expectedVersion,
|
|
36216
36217
|
accept_visible_changes: exports_external.boolean().describe("Attest visible fields that were changed without the key, after reviewing them.").optional(),
|
|
@@ -36421,6 +36422,11 @@ The keys of this machine, and backups, are handled by tools that never take or r
|
|
|
36421
36422
|
|
|
36422
36423
|
## Sealed credentials
|
|
36423
36424
|
|
|
36425
|
+
Secrets in short:
|
|
36426
|
+
1. Store a secret you must not see: insert_sealed_credential with only the visible fields and typed_at_sidecar: ["password"] (or custom:{key}, totp, sealed_notes). The user types it at the sidecar (safekb-mcp --sidecar, started from a folder outside the knowledge-base repo) while the call waits. Never ask for it in the conversation.
|
|
36427
|
+
2. Keep it hidden: set_sealed_credential_llm_visibility(field, "use_only"); the account default may let LLMs reveal it.
|
|
36428
|
+
3. Use it: secret_exec with a handle {{secret://<credential_id>/<field>}} in env, stdin or files; your own program does the rest (HTTP, browser, adb, ssh, ...).
|
|
36429
|
+
|
|
36424
36430
|
A credential with \`sealed: true\` belongs to a seal root. Its title, username, url, tags, notes and visible custom fields are readable by the server: find it with the standard credential tools. Its password, TOTP seed, sealed_notes and sealed custom fields open only here: reveal_sealed_credential, get_sealed_totp, insert_sealed_credential, update_sealed_credential.
|
|
36425
36431
|
|
|
36426
36432
|
- A secret the user has not given you yet (a card number, a PIN, a new password): never ask for it in the conversation. Call insert_sealed_credential or update_sealed_credential with typed_at_sidecar naming the fields; the user types them at the sidecar (safekb-mcp --sidecar) while the call waits. Or they enter it in the SafeKB web app.
|
package/package.json
CHANGED