@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.cjs
CHANGED
|
@@ -1361,9 +1361,13 @@ var init_tools = __esm({
|
|
|
1361
1361
|
get encryptionKey() {
|
|
1362
1362
|
return derivePurposeKey(this.masterKey, "identity-encryption");
|
|
1363
1363
|
}
|
|
1364
|
-
/** Load identities from storage on startup
|
|
1364
|
+
/** Load identities from storage on startup.
|
|
1365
|
+
* Returns { total: number of encrypted files found, loaded: number successfully decrypted }.
|
|
1366
|
+
* A mismatch (total > 0, loaded === 0) indicates a wrong master key / missing passphrase.
|
|
1367
|
+
*/
|
|
1365
1368
|
async load() {
|
|
1366
1369
|
const entries = await this.storage.list("_identities");
|
|
1370
|
+
let failed = 0;
|
|
1367
1371
|
for (const entry of entries) {
|
|
1368
1372
|
const raw = await this.storage.read("_identities", entry.key);
|
|
1369
1373
|
if (!raw) continue;
|
|
@@ -1376,8 +1380,10 @@ var init_tools = __esm({
|
|
|
1376
1380
|
this.primaryIdentityId = identity.identity_id;
|
|
1377
1381
|
}
|
|
1378
1382
|
} catch {
|
|
1383
|
+
failed++;
|
|
1379
1384
|
}
|
|
1380
1385
|
}
|
|
1386
|
+
return { total: entries.length, loaded: this.identities.size, failed };
|
|
1381
1387
|
}
|
|
1382
1388
|
/** Save an identity to storage */
|
|
1383
1389
|
async save(identity) {
|
|
@@ -4924,7 +4930,7 @@ async function startStandaloneDashboard(options = {}) {
|
|
|
4924
4930
|
// Default to auto-open in standalone mode
|
|
4925
4931
|
});
|
|
4926
4932
|
const identityManager = new IdentityManager(storage, masterKey);
|
|
4927
|
-
await identityManager.load();
|
|
4933
|
+
const loadResult = await identityManager.load();
|
|
4928
4934
|
const shrOpts = { config, identityManager, masterKey };
|
|
4929
4935
|
const handshakeResults = /* @__PURE__ */ new Map();
|
|
4930
4936
|
dashboard.setDependencies({
|
|
@@ -4940,9 +4946,31 @@ async function startStandaloneDashboard(options = {}) {
|
|
|
4940
4946
|
await dashboard.start();
|
|
4941
4947
|
console.error(`Sanctuary Dashboard v${SANCTUARY_VERSION} (standalone mode)`);
|
|
4942
4948
|
console.error(`Storage: ${config.storage_path}`);
|
|
4943
|
-
|
|
4944
|
-
console.error(`Identities loaded: ${identityCount}`);
|
|
4949
|
+
console.error(`Identities loaded: ${loadResult.loaded}`);
|
|
4945
4950
|
console.error(`Listening: http://${dashboardHost}:${dashboardPort}`);
|
|
4951
|
+
if (loadResult.total > 0 && loadResult.loaded === 0) {
|
|
4952
|
+
console.error(
|
|
4953
|
+
`
|
|
4954
|
+
\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
|
|
4955
|
+
\u2551 \u26A0 WARNING: Encrypted identities found but NONE loaded \u2551
|
|
4956
|
+
\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
|
|
4957
|
+
\u2551 ${loadResult.total} encrypted identity file(s) found on disk \u2551
|
|
4958
|
+
\u2551 0 could be decrypted with the current master key \u2551
|
|
4959
|
+
\u2551 \u2551
|
|
4960
|
+
\u2551 This usually means SANCTUARY_PASSPHRASE is missing or \u2551
|
|
4961
|
+
\u2551 incorrect. The dashboard will show empty panels. \u2551
|
|
4962
|
+
\u2551 \u2551
|
|
4963
|
+
\u2551 To fix: restart with the correct SANCTUARY_PASSPHRASE: \u2551
|
|
4964
|
+
\u2551 SANCTUARY_PASSPHRASE=<your-passphrase> npx \\ \u2551
|
|
4965
|
+
\u2551 @sanctuary-framework/mcp-server dashboard \u2551
|
|
4966
|
+
\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
|
|
4967
|
+
`
|
|
4968
|
+
);
|
|
4969
|
+
} else if (loadResult.failed > 0) {
|
|
4970
|
+
console.error(
|
|
4971
|
+
`Warning: ${loadResult.failed} of ${loadResult.total} identity files could not be decrypted (possibly corrupted).`
|
|
4972
|
+
);
|
|
4973
|
+
}
|
|
4946
4974
|
const saveBaseline = () => {
|
|
4947
4975
|
baseline.save().catch(() => {
|
|
4948
4976
|
});
|
|
@@ -11374,11 +11402,57 @@ var TOOL_API_SCOPED = {
|
|
|
11374
11402
|
],
|
|
11375
11403
|
default_action: "redact"
|
|
11376
11404
|
};
|
|
11405
|
+
var REMOTE_INFERENCE_SANITIZE = {
|
|
11406
|
+
id: "remote-inference-sanitize",
|
|
11407
|
+
name: "Remote Inference Sanitization",
|
|
11408
|
+
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.",
|
|
11409
|
+
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.",
|
|
11410
|
+
rules: [
|
|
11411
|
+
{
|
|
11412
|
+
provider: "inference",
|
|
11413
|
+
allow: [
|
|
11414
|
+
"task",
|
|
11415
|
+
"task_description",
|
|
11416
|
+
"current_query",
|
|
11417
|
+
"query",
|
|
11418
|
+
"prompt",
|
|
11419
|
+
"question",
|
|
11420
|
+
"instruction",
|
|
11421
|
+
"output_format",
|
|
11422
|
+
"format",
|
|
11423
|
+
"language",
|
|
11424
|
+
"code_context",
|
|
11425
|
+
// Stripped code snippets for coding tasks
|
|
11426
|
+
"error_message"
|
|
11427
|
+
// For debugging help
|
|
11428
|
+
],
|
|
11429
|
+
redact: [
|
|
11430
|
+
...ALWAYS_REDACT_SECRETS,
|
|
11431
|
+
...PII_PATTERNS,
|
|
11432
|
+
...INTERNAL_STATE_PATTERNS,
|
|
11433
|
+
...HISTORY_PATTERNS,
|
|
11434
|
+
"tool_results",
|
|
11435
|
+
"previous_results",
|
|
11436
|
+
// Additional redactions for remote inference
|
|
11437
|
+
"model_data",
|
|
11438
|
+
"agent_state",
|
|
11439
|
+
"runtime_config",
|
|
11440
|
+
"capabilities",
|
|
11441
|
+
"tool_list"
|
|
11442
|
+
],
|
|
11443
|
+
// Deny patterns — these must NEVER reach the remote model, not even redacted
|
|
11444
|
+
hash: [],
|
|
11445
|
+
summarize: []
|
|
11446
|
+
}
|
|
11447
|
+
],
|
|
11448
|
+
default_action: "deny"
|
|
11449
|
+
};
|
|
11377
11450
|
var TEMPLATES = {
|
|
11378
11451
|
"inference-minimal": INFERENCE_MINIMAL,
|
|
11379
11452
|
"inference-standard": INFERENCE_STANDARD,
|
|
11380
11453
|
"logging-strict": LOGGING_STRICT,
|
|
11381
|
-
"tool-api-scoped": TOOL_API_SCOPED
|
|
11454
|
+
"tool-api-scoped": TOOL_API_SCOPED,
|
|
11455
|
+
"remote-inference-sanitize": REMOTE_INFERENCE_SANITIZE
|
|
11382
11456
|
};
|
|
11383
11457
|
function listTemplateIds() {
|
|
11384
11458
|
return Object.keys(TEMPLATES);
|
|
@@ -12973,7 +13047,29 @@ async function createSanctuaryServer(options) {
|
|
|
12973
13047
|
keyProtection,
|
|
12974
13048
|
auditLog
|
|
12975
13049
|
);
|
|
12976
|
-
await identityManager.load();
|
|
13050
|
+
const loadResult = await identityManager.load();
|
|
13051
|
+
if (loadResult.total > 0 && loadResult.loaded === 0) {
|
|
13052
|
+
console.error(
|
|
13053
|
+
`
|
|
13054
|
+
\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
|
|
13055
|
+
\u2551 \u26A0 WARNING: Encrypted identities found but NONE loaded \u2551
|
|
13056
|
+
\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
|
|
13057
|
+
\u2551 ${loadResult.total} encrypted identity file(s) found on disk \u2551
|
|
13058
|
+
\u2551 0 could be decrypted with the current master key \u2551
|
|
13059
|
+
\u2551 \u2551
|
|
13060
|
+
\u2551 This usually means SANCTUARY_PASSPHRASE is missing or \u2551
|
|
13061
|
+
\u2551 incorrect. The server will start but with NO identity data. \u2551
|
|
13062
|
+
\u2551 \u2551
|
|
13063
|
+
\u2551 To fix: set SANCTUARY_PASSPHRASE to the passphrase used \u2551
|
|
13064
|
+
\u2551 when this Sanctuary instance was first configured. \u2551
|
|
13065
|
+
\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
|
|
13066
|
+
`
|
|
13067
|
+
);
|
|
13068
|
+
} else if (loadResult.failed > 0) {
|
|
13069
|
+
console.error(
|
|
13070
|
+
`Warning: ${loadResult.failed} of ${loadResult.total} identity files could not be decrypted (possibly corrupted).`
|
|
13071
|
+
);
|
|
13072
|
+
}
|
|
12977
13073
|
const l2Tools = [
|
|
12978
13074
|
{
|
|
12979
13075
|
name: "sanctuary/exec_attest",
|