@hasna/mcps 0.0.14 → 0.0.15
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/bin/index.js +534 -99
- package/bin/mcp.js +352 -58
- package/dist/index.d.ts +2 -0
- package/dist/index.js +244 -7
- package/dist/lib/doctor.d.ts +4 -1
- package/dist/lib/install.d.ts +5 -1
- package/dist/lib/local-command-consent.d.ts +38 -0
- package/dist/lib/proxy.d.ts +6 -2
- package/dist/lib/remote.d.ts +4 -1
- package/dist/mcp/index.js +352 -58
- package/dist/types.d.ts +5 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -25242,6 +25242,185 @@ class StreamableHTTPClientTransport {
|
|
|
25242
25242
|
// src/lib/proxy.ts
|
|
25243
25243
|
init_config2();
|
|
25244
25244
|
init_db();
|
|
25245
|
+
|
|
25246
|
+
// src/lib/local-command-consent.ts
|
|
25247
|
+
class LocalCommandConsentError extends Error {
|
|
25248
|
+
review;
|
|
25249
|
+
constructor(message, review) {
|
|
25250
|
+
super(message);
|
|
25251
|
+
this.name = "LocalCommandConsentError";
|
|
25252
|
+
this.review = review;
|
|
25253
|
+
}
|
|
25254
|
+
}
|
|
25255
|
+
var SHELL_COMMANDS = new Set(["bash", "sh", "zsh", "fish", "cmd", "cmd.exe", "powershell", "powershell.exe", "pwsh"]);
|
|
25256
|
+
var DESTRUCTIVE_COMMANDS = new Set([
|
|
25257
|
+
"rm",
|
|
25258
|
+
"dd",
|
|
25259
|
+
"mkfs",
|
|
25260
|
+
"shutdown",
|
|
25261
|
+
"reboot",
|
|
25262
|
+
"poweroff",
|
|
25263
|
+
"halt",
|
|
25264
|
+
"killall",
|
|
25265
|
+
"pkill"
|
|
25266
|
+
]);
|
|
25267
|
+
var SHELL_EVAL_FLAGS = new Set(["-c", "/c", "-Command", "-command", "-EncodedCommand", "-encodedcommand"]);
|
|
25268
|
+
var SECRET_FLAG_PATTERN = /(?:^|[-_])(api[-_]?key|token|secret|password|passwd|credential|auth|private[-_]?key)(?:$|[-_])/i;
|
|
25269
|
+
var SECRET_KEY_PATTERN = /(?:^|[_-])(api[_-]?key|token|secret|password|passwd|credential|auth|private[_-]?key)(?:$|[_-])/i;
|
|
25270
|
+
var SECRET_VALUE_PATTERN = /^(sk_(?:live|test)_[A-Za-z0-9_]+|ghp_[A-Za-z0-9_]+|github_pat_[A-Za-z0-9_]+|xox[baprs]-[A-Za-z0-9-]+|AIza[A-Za-z0-9_-]{20,}|eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+)$/;
|
|
25271
|
+
var SHELL_META_PATTERN = /[;&|`<>]|\$\(/;
|
|
25272
|
+
function commandBase(command) {
|
|
25273
|
+
return command.trim().split(/[\\/]/).pop()?.toLowerCase() || command.trim().toLowerCase();
|
|
25274
|
+
}
|
|
25275
|
+
function normalizeArgs(args) {
|
|
25276
|
+
return (args ?? []).map((arg) => String(arg));
|
|
25277
|
+
}
|
|
25278
|
+
function isSecretKey(key) {
|
|
25279
|
+
return SECRET_KEY_PATTERN.test(key) || SECRET_FLAG_PATTERN.test(key);
|
|
25280
|
+
}
|
|
25281
|
+
function isSecretValue(value) {
|
|
25282
|
+
return SECRET_VALUE_PATTERN.test(value.trim());
|
|
25283
|
+
}
|
|
25284
|
+
function isSecretAssignment(arg) {
|
|
25285
|
+
const eqIdx = arg.indexOf("=");
|
|
25286
|
+
if (eqIdx <= 0)
|
|
25287
|
+
return false;
|
|
25288
|
+
const key = arg.slice(0, eqIdx);
|
|
25289
|
+
const value = arg.slice(eqIdx + 1);
|
|
25290
|
+
return isSecretKey(key) || isSecretValue(value);
|
|
25291
|
+
}
|
|
25292
|
+
function isSecretArg(args, index) {
|
|
25293
|
+
const arg = args[index] ?? "";
|
|
25294
|
+
const previous = args[index - 1] ?? "";
|
|
25295
|
+
return isSecretAssignment(arg) || isSecretValue(arg) || SECRET_FLAG_PATTERN.test(previous);
|
|
25296
|
+
}
|
|
25297
|
+
function quoteArg(value) {
|
|
25298
|
+
return JSON.stringify(value);
|
|
25299
|
+
}
|
|
25300
|
+
function displayCommand(command, args) {
|
|
25301
|
+
return [quoteArg(command), ...args.map((arg, index) => quoteArg(isSecretArg(args, index) ? "<redacted>" : arg))].join(" ");
|
|
25302
|
+
}
|
|
25303
|
+
function pushRisk(risks, risk) {
|
|
25304
|
+
if (risks.some((existing) => existing.code === risk.code && existing.evidence === risk.evidence))
|
|
25305
|
+
return;
|
|
25306
|
+
risks.push(risk);
|
|
25307
|
+
}
|
|
25308
|
+
function inspectRisks(command, args, env) {
|
|
25309
|
+
const risks = [];
|
|
25310
|
+
const base = commandBase(command);
|
|
25311
|
+
const joined = [command, ...args].join(" ");
|
|
25312
|
+
if (SHELL_COMMANDS.has(base)) {
|
|
25313
|
+
pushRisk(risks, {
|
|
25314
|
+
code: "shell_interpreter",
|
|
25315
|
+
severity: "warning",
|
|
25316
|
+
message: "Command launches a shell interpreter.",
|
|
25317
|
+
evidence: base
|
|
25318
|
+
});
|
|
25319
|
+
if (args.some((arg) => SHELL_EVAL_FLAGS.has(arg))) {
|
|
25320
|
+
pushRisk(risks, {
|
|
25321
|
+
code: "shell_eval",
|
|
25322
|
+
severity: "danger",
|
|
25323
|
+
message: "Shell command evaluates an inline script.",
|
|
25324
|
+
evidence: base
|
|
25325
|
+
});
|
|
25326
|
+
}
|
|
25327
|
+
}
|
|
25328
|
+
if (base === "sudo") {
|
|
25329
|
+
pushRisk(risks, {
|
|
25330
|
+
code: "privilege_escalation",
|
|
25331
|
+
severity: "danger",
|
|
25332
|
+
message: "Command requests elevated privileges.",
|
|
25333
|
+
evidence: base
|
|
25334
|
+
});
|
|
25335
|
+
}
|
|
25336
|
+
if (DESTRUCTIVE_COMMANDS.has(base) || /\brm\s+-[^\s]*[rf][^\s]*\b/.test(joined) || /--no-preserve-root\b/.test(joined)) {
|
|
25337
|
+
pushRisk(risks, {
|
|
25338
|
+
code: "destructive_command",
|
|
25339
|
+
severity: "danger",
|
|
25340
|
+
message: "Command includes a destructive system operation.",
|
|
25341
|
+
evidence: base
|
|
25342
|
+
});
|
|
25343
|
+
}
|
|
25344
|
+
if (/\b(curl|wget)\b[\s\S]*\|[\s\S]*\b(sh|bash|zsh|fish)\b/.test(joined)) {
|
|
25345
|
+
pushRisk(risks, {
|
|
25346
|
+
code: "download_pipe_shell",
|
|
25347
|
+
severity: "danger",
|
|
25348
|
+
message: "Command downloads remote content and pipes it to a shell."
|
|
25349
|
+
});
|
|
25350
|
+
}
|
|
25351
|
+
if ([command, ...args].some((part) => SHELL_META_PATTERN.test(part))) {
|
|
25352
|
+
pushRisk(risks, {
|
|
25353
|
+
code: "shell_metacharacters",
|
|
25354
|
+
severity: "warning",
|
|
25355
|
+
message: "Command or arguments contain shell metacharacters."
|
|
25356
|
+
});
|
|
25357
|
+
}
|
|
25358
|
+
if (args.some((arg, index) => isSecretArg(args, index))) {
|
|
25359
|
+
pushRisk(risks, {
|
|
25360
|
+
code: "inline_secret",
|
|
25361
|
+
severity: "danger",
|
|
25362
|
+
message: "Command arguments appear to contain inline secret material."
|
|
25363
|
+
});
|
|
25364
|
+
}
|
|
25365
|
+
const secretEnvKeys = Object.keys(env).filter(isSecretKey).sort();
|
|
25366
|
+
if (secretEnvKeys.length > 0) {
|
|
25367
|
+
pushRisk(risks, {
|
|
25368
|
+
code: "secret_env",
|
|
25369
|
+
severity: "warning",
|
|
25370
|
+
message: "Environment contains secret-like keys; values are redacted from consent output.",
|
|
25371
|
+
evidence: secretEnvKeys.join(", ")
|
|
25372
|
+
});
|
|
25373
|
+
}
|
|
25374
|
+
return risks;
|
|
25375
|
+
}
|
|
25376
|
+
function inspectLocalCommand(input) {
|
|
25377
|
+
const args = normalizeArgs(input.args);
|
|
25378
|
+
const env = input.env ?? {};
|
|
25379
|
+
const transport = input.transport ?? "stdio";
|
|
25380
|
+
const risks = inspectRisks(input.command, args, env);
|
|
25381
|
+
return {
|
|
25382
|
+
requiresConsent: transport === "stdio",
|
|
25383
|
+
operation: input.operation ?? "launch",
|
|
25384
|
+
command: input.command,
|
|
25385
|
+
args,
|
|
25386
|
+
displayCommand: displayCommand(input.command, args),
|
|
25387
|
+
envKeys: Object.keys(env).sort(),
|
|
25388
|
+
risks,
|
|
25389
|
+
hasDangerousRisk: risks.some((risk) => risk.severity === "danger")
|
|
25390
|
+
};
|
|
25391
|
+
}
|
|
25392
|
+
function formatLocalCommandReview(review) {
|
|
25393
|
+
const lines = [
|
|
25394
|
+
`Command: ${review.displayCommand}`,
|
|
25395
|
+
review.envKeys.length > 0 ? `Env keys: ${review.envKeys.join(", ")}` : "Env keys: <none>"
|
|
25396
|
+
];
|
|
25397
|
+
if (review.risks.length > 0) {
|
|
25398
|
+
lines.push("Risks:");
|
|
25399
|
+
for (const risk of review.risks) {
|
|
25400
|
+
lines.push(`- ${risk.severity}: ${risk.code} - ${risk.message}${risk.evidence ? ` (${risk.evidence})` : ""}`);
|
|
25401
|
+
}
|
|
25402
|
+
} else {
|
|
25403
|
+
lines.push("Risks: none detected");
|
|
25404
|
+
}
|
|
25405
|
+
return lines.join(`
|
|
25406
|
+
`);
|
|
25407
|
+
}
|
|
25408
|
+
function assertLocalCommandConsent(input, consent = {}) {
|
|
25409
|
+
const review = inspectLocalCommand(input);
|
|
25410
|
+
if (!review.requiresConsent)
|
|
25411
|
+
return review;
|
|
25412
|
+
if (consent.approved !== true) {
|
|
25413
|
+
throw new LocalCommandConsentError(`local stdio command approval is required before ${review.operation}.
|
|
25414
|
+
${formatLocalCommandReview(review)}`, review);
|
|
25415
|
+
}
|
|
25416
|
+
if (review.hasDangerousRisk && consent.allowRisky !== true) {
|
|
25417
|
+
throw new LocalCommandConsentError(`risky command approval is required before ${review.operation}.
|
|
25418
|
+
${formatLocalCommandReview(review)}`, review);
|
|
25419
|
+
}
|
|
25420
|
+
return review;
|
|
25421
|
+
}
|
|
25422
|
+
|
|
25423
|
+
// src/lib/proxy.ts
|
|
25245
25424
|
var connections = new Map;
|
|
25246
25425
|
var inflightConnections = new Map;
|
|
25247
25426
|
function buildEnv(extra) {
|
|
@@ -25267,7 +25446,7 @@ function requireUrl(entry) {
|
|
|
25267
25446
|
throw new Error(`Server "${entry.id}" has an invalid URL: ${entry.url}`);
|
|
25268
25447
|
}
|
|
25269
25448
|
}
|
|
25270
|
-
async function connectToServer(entry) {
|
|
25449
|
+
async function connectToServer(entry, options = {}) {
|
|
25271
25450
|
if (connections.has(entry.id)) {
|
|
25272
25451
|
return connections.get(entry.id);
|
|
25273
25452
|
}
|
|
@@ -25283,6 +25462,13 @@ async function connectToServer(entry) {
|
|
|
25283
25462
|
if (!entry.command?.trim()) {
|
|
25284
25463
|
throw new Error(`Server "${entry.id}" is missing a command`);
|
|
25285
25464
|
}
|
|
25465
|
+
assertLocalCommandConsent({
|
|
25466
|
+
command: entry.command,
|
|
25467
|
+
args: entry.args,
|
|
25468
|
+
env: entry.env,
|
|
25469
|
+
transport: entry.transport,
|
|
25470
|
+
operation: "launch"
|
|
25471
|
+
}, options.localCommandConsent);
|
|
25286
25472
|
transport = new StdioClientTransport({
|
|
25287
25473
|
command: entry.command,
|
|
25288
25474
|
args: entry.args,
|
|
@@ -25418,13 +25604,28 @@ async function refreshTools(id) {
|
|
|
25418
25604
|
}
|
|
25419
25605
|
|
|
25420
25606
|
// src/lib/doctor.ts
|
|
25421
|
-
async function diagnoseServer(server) {
|
|
25607
|
+
async function diagnoseServer(server, options = {}) {
|
|
25422
25608
|
const checks3 = [];
|
|
25609
|
+
let hasLocalConsent = true;
|
|
25423
25610
|
if (server.transport === "stdio") {
|
|
25611
|
+
try {
|
|
25612
|
+
assertLocalCommandConsent({
|
|
25613
|
+
command: server.command,
|
|
25614
|
+
args: server.args,
|
|
25615
|
+
env: server.env,
|
|
25616
|
+
transport: server.transport,
|
|
25617
|
+
operation: "diagnose"
|
|
25618
|
+
}, options.localCommandConsent);
|
|
25619
|
+
} catch (err) {
|
|
25620
|
+
hasLocalConsent = false;
|
|
25621
|
+
checks3.push({ name: "local command consent", pass: false, message: err.message });
|
|
25622
|
+
}
|
|
25424
25623
|
try {
|
|
25425
25624
|
const path = execFileSync("which", [server.command], { stdio: "pipe" }).toString().trim();
|
|
25426
25625
|
let version2 = "";
|
|
25427
25626
|
try {
|
|
25627
|
+
if (!hasLocalConsent)
|
|
25628
|
+
throw new Error("local stdio command approval is required before version probing");
|
|
25428
25629
|
version2 = execFileSync(server.command, ["--version"], { stdio: "pipe" }).toString().trim().split(`
|
|
25429
25630
|
`)[0];
|
|
25430
25631
|
} catch {}
|
|
@@ -25455,10 +25656,10 @@ async function diagnoseServer(server) {
|
|
|
25455
25656
|
checks3.push({ name: "URL reachable", pass: false, message: `unreachable: ${err.message}` });
|
|
25456
25657
|
}
|
|
25457
25658
|
}
|
|
25458
|
-
if (server.enabled) {
|
|
25659
|
+
if (server.enabled && hasLocalConsent) {
|
|
25459
25660
|
try {
|
|
25460
25661
|
await Promise.race([
|
|
25461
|
-
connectToServer(server),
|
|
25662
|
+
connectToServer(server, { localCommandConsent: options.localCommandConsent }),
|
|
25462
25663
|
new Promise((_, reject) => setTimeout(() => reject(new Error("timeout after 10s")), 1e4))
|
|
25463
25664
|
]);
|
|
25464
25665
|
await disconnectServer(server.id);
|
|
@@ -25466,8 +25667,10 @@ async function diagnoseServer(server) {
|
|
|
25466
25667
|
} catch (err) {
|
|
25467
25668
|
checks3.push({ name: "connect & list tools", pass: false, message: err.message });
|
|
25468
25669
|
}
|
|
25469
|
-
} else {
|
|
25670
|
+
} else if (!server.enabled) {
|
|
25470
25671
|
checks3.push({ name: "connect & list tools", pass: true, message: "skipped (server disabled)" });
|
|
25672
|
+
} else {
|
|
25673
|
+
checks3.push({ name: "connect & list tools", pass: false, message: "skipped until local stdio command is approved" });
|
|
25471
25674
|
}
|
|
25472
25675
|
return {
|
|
25473
25676
|
server,
|
|
@@ -25507,7 +25710,7 @@ async function getRegistryServer(id) {
|
|
|
25507
25710
|
const all = entries.map(parseRegistryEntry);
|
|
25508
25711
|
return all.find((s) => s.id === id) || null;
|
|
25509
25712
|
}
|
|
25510
|
-
async function installFromRegistry(id) {
|
|
25713
|
+
async function installFromRegistry(id, options = {}) {
|
|
25511
25714
|
const server = await getRegistryServer(id);
|
|
25512
25715
|
if (!server) {
|
|
25513
25716
|
throw new Error(`Server "${id}" not found in registry`);
|
|
@@ -25527,6 +25730,13 @@ async function installFromRegistry(id) {
|
|
|
25527
25730
|
transport = pkg.transport.type;
|
|
25528
25731
|
}
|
|
25529
25732
|
}
|
|
25733
|
+
assertLocalCommandConsent({
|
|
25734
|
+
command,
|
|
25735
|
+
args,
|
|
25736
|
+
transport,
|
|
25737
|
+
env: {},
|
|
25738
|
+
operation: "register"
|
|
25739
|
+
}, options.localCommandConsent);
|
|
25530
25740
|
return addServer({
|
|
25531
25741
|
name: server.name,
|
|
25532
25742
|
description: server.description,
|
|
@@ -25763,11 +25973,19 @@ function installProviderProfile(id, options = {}) {
|
|
|
25763
25973
|
if (!command) {
|
|
25764
25974
|
throw new Error(`Provider profile "${id}" does not define an install fallback command`);
|
|
25765
25975
|
}
|
|
25976
|
+
assertLocalCommandConsent({
|
|
25977
|
+
command,
|
|
25978
|
+
args,
|
|
25979
|
+
env: fallback?.env ?? {},
|
|
25980
|
+
transport: useFallback ? "stdio" : profile.transport,
|
|
25981
|
+
operation: "register"
|
|
25982
|
+
}, options.localCommandConsent);
|
|
25766
25983
|
return addServer({
|
|
25767
25984
|
name: options.name ?? profile.displayName,
|
|
25768
25985
|
description: profile.description ?? undefined,
|
|
25769
25986
|
command,
|
|
25770
25987
|
args,
|
|
25988
|
+
env: fallback?.env,
|
|
25771
25989
|
transport: useFallback ? "stdio" : profile.transport,
|
|
25772
25990
|
url: useFallback ? fallback?.url : profile.endpoint ?? undefined,
|
|
25773
25991
|
source: "provider-profile"
|
|
@@ -25856,7 +26074,22 @@ function installToGemini(entry) {
|
|
|
25856
26074
|
return { agent: "gemini", success: false, error: err.message };
|
|
25857
26075
|
}
|
|
25858
26076
|
}
|
|
25859
|
-
function installToAgents(entry, targets = ["claude", "codex", "gemini"]) {
|
|
26077
|
+
function installToAgents(entry, targets = ["claude", "codex", "gemini"], options = {}) {
|
|
26078
|
+
try {
|
|
26079
|
+
assertLocalCommandConsent({
|
|
26080
|
+
command: entry.command,
|
|
26081
|
+
args: entry.args,
|
|
26082
|
+
env: entry.env,
|
|
26083
|
+
transport: entry.transport,
|
|
26084
|
+
operation: "install"
|
|
26085
|
+
}, options.localCommandConsent);
|
|
26086
|
+
} catch (err) {
|
|
26087
|
+
return targets.map((target) => ({
|
|
26088
|
+
agent: target,
|
|
26089
|
+
success: false,
|
|
26090
|
+
error: err.message
|
|
26091
|
+
}));
|
|
26092
|
+
}
|
|
25860
26093
|
return targets.map((target) => {
|
|
25861
26094
|
if (target === "claude")
|
|
25862
26095
|
return installToClaude(entry);
|
|
@@ -26819,6 +27052,7 @@ export {
|
|
|
26819
27052
|
installToAgents,
|
|
26820
27053
|
installProviderProfile,
|
|
26821
27054
|
installFromRegistry,
|
|
27055
|
+
inspectLocalCommand,
|
|
26822
27056
|
getToolCounts,
|
|
26823
27057
|
getSource,
|
|
26824
27058
|
getServer,
|
|
@@ -26827,6 +27061,7 @@ export {
|
|
|
26827
27061
|
getMachine,
|
|
26828
27062
|
getDb,
|
|
26829
27063
|
getCachedTools,
|
|
27064
|
+
formatLocalCommandReview,
|
|
26830
27065
|
findServers,
|
|
26831
27066
|
enableSource,
|
|
26832
27067
|
enableServer,
|
|
@@ -26841,9 +27076,11 @@ export {
|
|
|
26841
27076
|
closeDb,
|
|
26842
27077
|
cloneServer,
|
|
26843
27078
|
callTool,
|
|
27079
|
+
assertLocalCommandConsent,
|
|
26844
27080
|
addSource,
|
|
26845
27081
|
addServer,
|
|
26846
27082
|
addMachine,
|
|
27083
|
+
LocalCommandConsentError,
|
|
26847
27084
|
DEFAULT_PROVIDER_PROFILE_SEEDS,
|
|
26848
27085
|
DEFAULT_MACHINE_SEEDS
|
|
26849
27086
|
};
|
package/dist/lib/doctor.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { McpServerEntry } from "../types.js";
|
|
2
|
+
import { type LocalCommandConsent } from "./local-command-consent.js";
|
|
2
3
|
export interface DoctorCheck {
|
|
3
4
|
name: string;
|
|
4
5
|
pass: boolean;
|
|
@@ -11,4 +12,6 @@ export interface DoctorReport {
|
|
|
11
12
|
checks: DoctorCheck[];
|
|
12
13
|
healthy: boolean;
|
|
13
14
|
}
|
|
14
|
-
export declare function diagnoseServer(server: McpServerEntry
|
|
15
|
+
export declare function diagnoseServer(server: McpServerEntry, options?: {
|
|
16
|
+
localCommandConsent?: LocalCommandConsent;
|
|
17
|
+
}): Promise<DoctorReport>;
|
package/dist/lib/install.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import type { McpServerEntry } from "../types.js";
|
|
2
|
+
import { type LocalCommandConsent } from "./local-command-consent.js";
|
|
2
3
|
export type AgentTarget = "claude" | "codex" | "gemini";
|
|
3
4
|
export interface InstallResult {
|
|
4
5
|
agent: AgentTarget;
|
|
5
6
|
success: boolean;
|
|
6
7
|
error?: string;
|
|
7
8
|
}
|
|
8
|
-
export
|
|
9
|
+
export interface InstallToAgentsOptions {
|
|
10
|
+
localCommandConsent?: LocalCommandConsent;
|
|
11
|
+
}
|
|
12
|
+
export declare function installToAgents(entry: McpServerEntry, targets?: AgentTarget[], options?: InstallToAgentsOptions): InstallResult[];
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { McpServerEntry } from "../types.js";
|
|
2
|
+
export type LocalCommandOperation = "register" | "install" | "launch" | "diagnose";
|
|
3
|
+
export type LocalCommandRiskSeverity = "warning" | "danger";
|
|
4
|
+
export interface LocalCommandInput {
|
|
5
|
+
command: string;
|
|
6
|
+
args?: string[];
|
|
7
|
+
env?: Record<string, string>;
|
|
8
|
+
transport?: McpServerEntry["transport"];
|
|
9
|
+
operation?: LocalCommandOperation;
|
|
10
|
+
}
|
|
11
|
+
export interface LocalCommandConsent {
|
|
12
|
+
approved?: boolean;
|
|
13
|
+
allowRisky?: boolean;
|
|
14
|
+
source?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface LocalCommandRisk {
|
|
17
|
+
code: string;
|
|
18
|
+
severity: LocalCommandRiskSeverity;
|
|
19
|
+
message: string;
|
|
20
|
+
evidence?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface LocalCommandReview {
|
|
23
|
+
requiresConsent: boolean;
|
|
24
|
+
operation: LocalCommandOperation;
|
|
25
|
+
command: string;
|
|
26
|
+
args: string[];
|
|
27
|
+
displayCommand: string;
|
|
28
|
+
envKeys: string[];
|
|
29
|
+
risks: LocalCommandRisk[];
|
|
30
|
+
hasDangerousRisk: boolean;
|
|
31
|
+
}
|
|
32
|
+
export declare class LocalCommandConsentError extends Error {
|
|
33
|
+
readonly review: LocalCommandReview;
|
|
34
|
+
constructor(message: string, review: LocalCommandReview);
|
|
35
|
+
}
|
|
36
|
+
export declare function inspectLocalCommand(input: LocalCommandInput): LocalCommandReview;
|
|
37
|
+
export declare function formatLocalCommandReview(review: LocalCommandReview): string;
|
|
38
|
+
export declare function assertLocalCommandConsent(input: LocalCommandInput, consent?: LocalCommandConsent): LocalCommandReview;
|
package/dist/lib/proxy.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import { type LocalCommandConsent } from "./local-command-consent.js";
|
|
1
2
|
import type { McpServerEntry, McpTool, ConnectedServer } from "../types.js";
|
|
2
|
-
export
|
|
3
|
+
export interface ConnectOptions {
|
|
4
|
+
localCommandConsent?: LocalCommandConsent;
|
|
5
|
+
}
|
|
6
|
+
export declare function connectToServer(entry: McpServerEntry, options?: ConnectOptions): Promise<ConnectedServer>;
|
|
3
7
|
export declare function disconnectServer(id: string): Promise<void>;
|
|
4
8
|
export declare function disconnectAll(): Promise<void>;
|
|
5
9
|
export declare function listAllTools(): McpTool[];
|
|
@@ -10,4 +14,4 @@ export declare function callTool(prefixedName: string, args: Record<string, unkn
|
|
|
10
14
|
}>;
|
|
11
15
|
}>;
|
|
12
16
|
export declare function refreshTools(id: string): Promise<McpTool[]>;
|
|
13
|
-
export declare function connectAllEnabled(): Promise<ConnectedServer[]>;
|
|
17
|
+
export declare function connectAllEnabled(options?: ConnectOptions): Promise<ConnectedServer[]>;
|
package/dist/lib/remote.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { type LocalCommandConsent } from "./local-command-consent.js";
|
|
1
2
|
import type { RegistryServer, McpServerEntry } from "../types.js";
|
|
2
3
|
export declare function searchRegistry(query: string): Promise<RegistryServer[]>;
|
|
3
4
|
export declare function getRegistryServer(id: string): Promise<RegistryServer | null>;
|
|
4
|
-
export declare function installFromRegistry(id: string
|
|
5
|
+
export declare function installFromRegistry(id: string, options?: {
|
|
6
|
+
localCommandConsent?: LocalCommandConsent;
|
|
7
|
+
}): Promise<McpServerEntry>;
|