@sanctuary-framework/mcp-server 0.5.10 → 0.5.12
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/cli.cjs +102 -6
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +102 -6
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +174 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +124 -3
- package/dist/index.d.ts +124 -3
- package/dist/index.js +173 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1358,9 +1358,13 @@ var init_tools = __esm({
|
|
|
1358
1358
|
get encryptionKey() {
|
|
1359
1359
|
return derivePurposeKey(this.masterKey, "identity-encryption");
|
|
1360
1360
|
}
|
|
1361
|
-
/** Load identities from storage on startup
|
|
1361
|
+
/** Load identities from storage on startup.
|
|
1362
|
+
* Returns { total: number of encrypted files found, loaded: number successfully decrypted }.
|
|
1363
|
+
* A mismatch (total > 0, loaded === 0) indicates a wrong master key / missing passphrase.
|
|
1364
|
+
*/
|
|
1362
1365
|
async load() {
|
|
1363
1366
|
const entries = await this.storage.list("_identities");
|
|
1367
|
+
let failed = 0;
|
|
1364
1368
|
for (const entry of entries) {
|
|
1365
1369
|
const raw = await this.storage.read("_identities", entry.key);
|
|
1366
1370
|
if (!raw) continue;
|
|
@@ -1373,8 +1377,10 @@ var init_tools = __esm({
|
|
|
1373
1377
|
this.primaryIdentityId = identity.identity_id;
|
|
1374
1378
|
}
|
|
1375
1379
|
} catch {
|
|
1380
|
+
failed++;
|
|
1376
1381
|
}
|
|
1377
1382
|
}
|
|
1383
|
+
return { total: entries.length, loaded: this.identities.size, failed };
|
|
1378
1384
|
}
|
|
1379
1385
|
/** Save an identity to storage */
|
|
1380
1386
|
async save(identity) {
|
|
@@ -4921,7 +4927,7 @@ async function startStandaloneDashboard(options = {}) {
|
|
|
4921
4927
|
// Default to auto-open in standalone mode
|
|
4922
4928
|
});
|
|
4923
4929
|
const identityManager = new IdentityManager(storage, masterKey);
|
|
4924
|
-
await identityManager.load();
|
|
4930
|
+
const loadResult = await identityManager.load();
|
|
4925
4931
|
const shrOpts = { config, identityManager, masterKey };
|
|
4926
4932
|
const handshakeResults = /* @__PURE__ */ new Map();
|
|
4927
4933
|
dashboard.setDependencies({
|
|
@@ -4937,9 +4943,31 @@ async function startStandaloneDashboard(options = {}) {
|
|
|
4937
4943
|
await dashboard.start();
|
|
4938
4944
|
console.error(`Sanctuary Dashboard v${SANCTUARY_VERSION} (standalone mode)`);
|
|
4939
4945
|
console.error(`Storage: ${config.storage_path}`);
|
|
4940
|
-
|
|
4941
|
-
console.error(`Identities loaded: ${identityCount}`);
|
|
4946
|
+
console.error(`Identities loaded: ${loadResult.loaded}`);
|
|
4942
4947
|
console.error(`Listening: http://${dashboardHost}:${dashboardPort}`);
|
|
4948
|
+
if (loadResult.total > 0 && loadResult.loaded === 0) {
|
|
4949
|
+
console.error(
|
|
4950
|
+
`
|
|
4951
|
+
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
4952
|
+
\u2551 \u26A0 WARNING: Encrypted identities found but NONE loaded \u2551
|
|
4953
|
+
\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
|
|
4954
|
+
\u2551 ${loadResult.total} encrypted identity file(s) found on disk \u2551
|
|
4955
|
+
\u2551 0 could be decrypted with the current master key \u2551
|
|
4956
|
+
\u2551 \u2551
|
|
4957
|
+
\u2551 This usually means SANCTUARY_PASSPHRASE is missing or \u2551
|
|
4958
|
+
\u2551 incorrect. The dashboard will show empty panels. \u2551
|
|
4959
|
+
\u2551 \u2551
|
|
4960
|
+
\u2551 To fix: restart with the correct SANCTUARY_PASSPHRASE: \u2551
|
|
4961
|
+
\u2551 SANCTUARY_PASSPHRASE=<your-passphrase> npx \\ \u2551
|
|
4962
|
+
\u2551 @sanctuary-framework/mcp-server dashboard \u2551
|
|
4963
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
4964
|
+
`
|
|
4965
|
+
);
|
|
4966
|
+
} else if (loadResult.failed > 0) {
|
|
4967
|
+
console.error(
|
|
4968
|
+
`Warning: ${loadResult.failed} of ${loadResult.total} identity files could not be decrypted (possibly corrupted).`
|
|
4969
|
+
);
|
|
4970
|
+
}
|
|
4943
4971
|
const saveBaseline = () => {
|
|
4944
4972
|
baseline.save().catch(() => {
|
|
4945
4973
|
});
|
|
@@ -11371,11 +11399,57 @@ var TOOL_API_SCOPED = {
|
|
|
11371
11399
|
],
|
|
11372
11400
|
default_action: "redact"
|
|
11373
11401
|
};
|
|
11402
|
+
var REMOTE_INFERENCE_SANITIZE = {
|
|
11403
|
+
id: "remote-inference-sanitize",
|
|
11404
|
+
name: "Remote Inference Sanitization",
|
|
11405
|
+
description: "Maximum privacy for remote/cloud LLM calls. Strips all identity, financial, location, and personal data before passing queries to external models. Inspired by Vitalik Buterin's 2-of-2 sovereignty model.",
|
|
11406
|
+
use_when: "Your local agent needs to call a remote LLM for tasks beyond local model capability (complex coding, deep research) and you want to minimize data leakage to the remote provider. The remote model gets only the task, query, format requirements, and stripped code context.",
|
|
11407
|
+
rules: [
|
|
11408
|
+
{
|
|
11409
|
+
provider: "inference",
|
|
11410
|
+
allow: [
|
|
11411
|
+
"task",
|
|
11412
|
+
"task_description",
|
|
11413
|
+
"current_query",
|
|
11414
|
+
"query",
|
|
11415
|
+
"prompt",
|
|
11416
|
+
"question",
|
|
11417
|
+
"instruction",
|
|
11418
|
+
"output_format",
|
|
11419
|
+
"format",
|
|
11420
|
+
"language",
|
|
11421
|
+
"code_context",
|
|
11422
|
+
// Stripped code snippets for coding tasks
|
|
11423
|
+
"error_message"
|
|
11424
|
+
// For debugging help
|
|
11425
|
+
],
|
|
11426
|
+
redact: [
|
|
11427
|
+
...ALWAYS_REDACT_SECRETS,
|
|
11428
|
+
...PII_PATTERNS,
|
|
11429
|
+
...INTERNAL_STATE_PATTERNS,
|
|
11430
|
+
...HISTORY_PATTERNS,
|
|
11431
|
+
"tool_results",
|
|
11432
|
+
"previous_results",
|
|
11433
|
+
// Additional redactions for remote inference
|
|
11434
|
+
"model_data",
|
|
11435
|
+
"agent_state",
|
|
11436
|
+
"runtime_config",
|
|
11437
|
+
"capabilities",
|
|
11438
|
+
"tool_list"
|
|
11439
|
+
],
|
|
11440
|
+
// Deny patterns — these must NEVER reach the remote model, not even redacted
|
|
11441
|
+
hash: [],
|
|
11442
|
+
summarize: []
|
|
11443
|
+
}
|
|
11444
|
+
],
|
|
11445
|
+
default_action: "deny"
|
|
11446
|
+
};
|
|
11374
11447
|
var TEMPLATES = {
|
|
11375
11448
|
"inference-minimal": INFERENCE_MINIMAL,
|
|
11376
11449
|
"inference-standard": INFERENCE_STANDARD,
|
|
11377
11450
|
"logging-strict": LOGGING_STRICT,
|
|
11378
|
-
"tool-api-scoped": TOOL_API_SCOPED
|
|
11451
|
+
"tool-api-scoped": TOOL_API_SCOPED,
|
|
11452
|
+
"remote-inference-sanitize": REMOTE_INFERENCE_SANITIZE
|
|
11379
11453
|
};
|
|
11380
11454
|
function listTemplateIds() {
|
|
11381
11455
|
return Object.keys(TEMPLATES);
|
|
@@ -12970,7 +13044,29 @@ async function createSanctuaryServer(options) {
|
|
|
12970
13044
|
keyProtection,
|
|
12971
13045
|
auditLog
|
|
12972
13046
|
);
|
|
12973
|
-
await identityManager.load();
|
|
13047
|
+
const loadResult = await identityManager.load();
|
|
13048
|
+
if (loadResult.total > 0 && loadResult.loaded === 0) {
|
|
13049
|
+
console.error(
|
|
13050
|
+
`
|
|
13051
|
+
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
13052
|
+
\u2551 \u26A0 WARNING: Encrypted identities found but NONE loaded \u2551
|
|
13053
|
+
\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
|
|
13054
|
+
\u2551 ${loadResult.total} encrypted identity file(s) found on disk \u2551
|
|
13055
|
+
\u2551 0 could be decrypted with the current master key \u2551
|
|
13056
|
+
\u2551 \u2551
|
|
13057
|
+
\u2551 This usually means SANCTUARY_PASSPHRASE is missing or \u2551
|
|
13058
|
+
\u2551 incorrect. The server will start but with NO identity data. \u2551
|
|
13059
|
+
\u2551 \u2551
|
|
13060
|
+
\u2551 To fix: set SANCTUARY_PASSPHRASE to the passphrase used \u2551
|
|
13061
|
+
\u2551 when this Sanctuary instance was first configured. \u2551
|
|
13062
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
13063
|
+
`
|
|
13064
|
+
);
|
|
13065
|
+
} else if (loadResult.failed > 0) {
|
|
13066
|
+
console.error(
|
|
13067
|
+
`Warning: ${loadResult.failed} of ${loadResult.total} identity files could not be decrypted (possibly corrupted).`
|
|
13068
|
+
);
|
|
13069
|
+
}
|
|
12974
13070
|
const l2Tools = [
|
|
12975
13071
|
{
|
|
12976
13072
|
name: "sanctuary/exec_attest",
|