sealnet-mcp 0.2.1 → 0.2.3
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 +72 -124
- package/dist/cli.js +72 -124
- package/dist/index.cjs +72 -124
- package/dist/index.d.cts +3 -4
- package/dist/index.d.ts +3 -4
- package/dist/index.js +72 -124
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -2914,7 +2914,6 @@ var upload_default = {
|
|
|
2914
2914
|
HEDGE_MIN_INFLIGHT_MS: 3e3,
|
|
2915
2915
|
HEDGE_LAG_FACTOR: 3,
|
|
2916
2916
|
HEDGE_POLL_MS: 1e3,
|
|
2917
|
-
HEDGE_MAX_CONCURRENT: 1,
|
|
2918
2917
|
LIVENESS_SILENCE_MS: 3e4,
|
|
2919
2918
|
RETRY_BACKOFF_MS: [1e3, 3e3, 7e3, 15e3, 3e4],
|
|
2920
2919
|
RETRY_JITTER_RATIO: 0.2,
|
|
@@ -4209,7 +4208,6 @@ var DEFAULT_TRANSPORT_POLICY = {
|
|
|
4209
4208
|
hedgeMinInflightMs: upload_default.upload.HEDGE_MIN_INFLIGHT_MS,
|
|
4210
4209
|
hedgeLagFactor: upload_default.upload.HEDGE_LAG_FACTOR,
|
|
4211
4210
|
hedgePollMs: upload_default.upload.HEDGE_POLL_MS,
|
|
4212
|
-
hedgeMaxConcurrent: upload_default.upload.HEDGE_MAX_CONCURRENT,
|
|
4213
4211
|
livenessSilenceMs: upload_default.upload.LIVENESS_SILENCE_MS,
|
|
4214
4212
|
verifyPollBackoffMs: upload_default.upload.VERIFY_POLL_BACKOFF_MS,
|
|
4215
4213
|
verifyFallbackWaitMs: upload_default.upload.VERIFY_FALLBACK_WAIT_MS,
|
|
@@ -4531,7 +4529,6 @@ async function multipartUploadStream(options) {
|
|
|
4531
4529
|
let lastRoundRate = null;
|
|
4532
4530
|
let roomWaiters = [];
|
|
4533
4531
|
const fullPartPace = [];
|
|
4534
|
-
let hedgesInFlight = 0;
|
|
4535
4532
|
const partsInFlight = /* @__PURE__ */ new Set();
|
|
4536
4533
|
let lastSocketActivityAt = performance.now();
|
|
4537
4534
|
let socketActivityObservable = false;
|
|
@@ -4576,10 +4573,10 @@ async function multipartUploadStream(options) {
|
|
|
4576
4573
|
roundBytes = 0;
|
|
4577
4574
|
roundDeliveries = 0;
|
|
4578
4575
|
}
|
|
4579
|
-
function hedgeDue(item, lastLaunchAt
|
|
4576
|
+
function hedgeDue(item, lastLaunchAt) {
|
|
4580
4577
|
const inFlightMs = performance.now() - lastLaunchAt;
|
|
4581
4578
|
if (inFlightMs < policy.hedgeMinInflightMs) return false;
|
|
4582
|
-
const flowsNow = runningParts.size
|
|
4579
|
+
const flowsNow = runningParts.size;
|
|
4583
4580
|
const peers = fullPartPace.filter((p) => p.flows >= flowsNow).map((p) => p.rate);
|
|
4584
4581
|
if (peers.length === 0) return false;
|
|
4585
4582
|
peers.sort((a, b) => a - b);
|
|
@@ -4701,135 +4698,80 @@ async function multipartUploadStream(options) {
|
|
|
4701
4698
|
}
|
|
4702
4699
|
async function hedgedPut(item, presignedUrl) {
|
|
4703
4700
|
const t0 = performance.now();
|
|
4704
|
-
let controllers = [];
|
|
4705
|
-
const detachFns = [];
|
|
4706
4701
|
let hedgeTicker = null;
|
|
4707
4702
|
let hedgeCount = 0;
|
|
4708
|
-
let liveHedges = 0;
|
|
4709
|
-
let currentHedge = null;
|
|
4710
4703
|
let lastLaunchAt = t0;
|
|
4711
|
-
let
|
|
4712
|
-
|
|
4713
|
-
let reconnect = () => {
|
|
4714
|
-
};
|
|
4715
|
-
const launchCopy = async (isHedge) => {
|
|
4716
|
-
const ctl = new AbortController();
|
|
4717
|
-
controllers.push(ctl);
|
|
4718
|
-
if (isHedge) currentHedge = ctl;
|
|
4719
|
-
unsentByCopy.set(ctl, true);
|
|
4720
|
-
lastSocketActivityAt = performance.now();
|
|
4721
|
-
if (runSignal) {
|
|
4722
|
-
if (runSignal.aborted) {
|
|
4723
|
-
ctl.abort();
|
|
4724
|
-
} else {
|
|
4725
|
-
const onAbort = () => ctl.abort();
|
|
4726
|
-
runSignal.addEventListener("abort", onAbort, { once: true });
|
|
4727
|
-
detachFns.push(() => runSignal.removeEventListener("abort", onAbort));
|
|
4728
|
-
}
|
|
4729
|
-
}
|
|
4730
|
-
try {
|
|
4731
|
-
const outcome = await transportPut(
|
|
4732
|
-
item.ciphertext,
|
|
4733
|
-
item.contentMd5,
|
|
4734
|
-
item.partNumber,
|
|
4735
|
-
presignedUrl,
|
|
4736
|
-
ctl.signal,
|
|
4737
|
-
{
|
|
4738
|
-
onSocketActivity: (loaded, total) => {
|
|
4739
|
-
lastSocketActivityAt = performance.now();
|
|
4740
|
-
unsentByCopy.set(ctl, loaded < total);
|
|
4741
|
-
},
|
|
4742
|
-
onDeadline: () => reconnect("copy deadline")
|
|
4743
|
-
}
|
|
4744
|
-
);
|
|
4745
|
-
return validatePutOutcome(item.partNumber, outcome);
|
|
4746
|
-
} finally {
|
|
4747
|
-
unsentByCopy.delete(ctl);
|
|
4748
|
-
}
|
|
4704
|
+
let current = null;
|
|
4705
|
+
let replace = () => {
|
|
4749
4706
|
};
|
|
4750
4707
|
const inFlight = {
|
|
4751
|
-
reconnect: (why) =>
|
|
4752
|
-
hasUnsentBytes: () =>
|
|
4708
|
+
reconnect: (why) => replace(why, false),
|
|
4709
|
+
hasUnsentBytes: () => current?.unsent ?? false
|
|
4753
4710
|
};
|
|
4754
4711
|
partsInFlight.add(inFlight);
|
|
4755
4712
|
try {
|
|
4756
4713
|
const etag = await new Promise((resolve5, reject) => {
|
|
4757
|
-
let pending = 0;
|
|
4758
4714
|
let settled = false;
|
|
4759
|
-
const
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4715
|
+
const settle = (outcome) => {
|
|
4716
|
+
if (settled) return;
|
|
4717
|
+
settled = true;
|
|
4718
|
+
outcome();
|
|
4719
|
+
};
|
|
4720
|
+
const launch = () => {
|
|
4721
|
+
const ctl = new AbortController();
|
|
4722
|
+
const onUploadEnd = () => ctl.abort();
|
|
4723
|
+
if (runSignal?.aborted) ctl.abort();
|
|
4724
|
+
else runSignal?.addEventListener("abort", onUploadEnd, { once: true });
|
|
4725
|
+
const copy = { ctl, unsent: true, ended: Promise.resolve() };
|
|
4726
|
+
current = copy;
|
|
4727
|
+
lastLaunchAt = performance.now();
|
|
4728
|
+
lastSocketActivityAt = lastLaunchAt;
|
|
4729
|
+
copy.ended = transportPut(item.ciphertext, item.contentMd5, item.partNumber, presignedUrl, ctl.signal, {
|
|
4730
|
+
onSocketActivity: (loaded, total) => {
|
|
4731
|
+
lastSocketActivityAt = performance.now();
|
|
4732
|
+
copy.unsent = loaded < total;
|
|
4733
|
+
},
|
|
4734
|
+
onDeadline: () => replace("copy deadline", false)
|
|
4735
|
+
}).then(
|
|
4736
|
+
(outcome) => {
|
|
4737
|
+
if (current !== copy) return;
|
|
4738
|
+
try {
|
|
4739
|
+
const confirmed = validatePutOutcome(item.partNumber, outcome);
|
|
4740
|
+
settle(() => resolve5(confirmed));
|
|
4741
|
+
} catch (err2) {
|
|
4742
|
+
settle(() => reject(err2));
|
|
4786
4743
|
}
|
|
4787
|
-
|
|
4788
|
-
|
|
4744
|
+
},
|
|
4745
|
+
(err2) => {
|
|
4746
|
+
if (current === copy) settle(() => reject(toUploadError(err2, `Failed to upload part ${item.partNumber}`)));
|
|
4789
4747
|
}
|
|
4748
|
+
).finally(() => {
|
|
4749
|
+
copy.unsent = false;
|
|
4750
|
+
runSignal?.removeEventListener("abort", onUploadEnd);
|
|
4790
4751
|
});
|
|
4791
4752
|
};
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4753
|
+
replace = (why, spendsTicket) => {
|
|
4754
|
+
const old = current;
|
|
4755
|
+
if (settled || old === null || signal?.aborted) return;
|
|
4756
|
+
current = null;
|
|
4757
|
+
hedgeCount = spendsTicket ? hedgeCount + 1 : 0;
|
|
4758
|
+
log3.debug(`${spendsTicket ? "replace" : "reconnect"} part=${item.partNumber} (${why})`);
|
|
4759
|
+
old.ctl.abort();
|
|
4760
|
+
void old.ended.then(() => {
|
|
4761
|
+
if (settled) return;
|
|
4762
|
+
if (runSignal?.aborted) {
|
|
4763
|
+
settle(() => reject(new UploadError("Upload aborted", "ABORTED", void 0, item.partNumber)));
|
|
4764
|
+
} else {
|
|
4765
|
+
launch();
|
|
4766
|
+
}
|
|
4767
|
+
});
|
|
4806
4768
|
};
|
|
4807
|
-
|
|
4769
|
+
launch();
|
|
4808
4770
|
hedgeTicker = setInterval(() => {
|
|
4809
|
-
if (settled || signal?.aborted)
|
|
4810
|
-
if (hedgeTicker !== null) {
|
|
4811
|
-
clearInterval(hedgeTicker);
|
|
4812
|
-
hedgeTicker = null;
|
|
4813
|
-
}
|
|
4814
|
-
return;
|
|
4815
|
-
}
|
|
4771
|
+
if (settled || signal?.aborted || current === null) return;
|
|
4816
4772
|
if (hedgeCount >= HEDGE_MAX_PER_PART) return;
|
|
4817
|
-
if (!hedgeDue(item, lastLaunchAt
|
|
4818
|
-
|
|
4819
|
-
if (currentHedge !== null) {
|
|
4820
|
-
currentHedge.abort();
|
|
4821
|
-
currentHedge = null;
|
|
4822
|
-
}
|
|
4823
|
-
return;
|
|
4824
|
-
}
|
|
4825
|
-
hedgeCount++;
|
|
4826
|
-
liveHedges++;
|
|
4827
|
-
hedgesInFlight++;
|
|
4828
|
-
lastLaunchAt = performance.now();
|
|
4829
|
-
log3.debug(
|
|
4830
|
-
`hedge launched part=${item.partNumber} copy=${hedgeCount + 1} after ${Math.round(performance.now() - t0)}ms`
|
|
4831
|
-
);
|
|
4832
|
-
run("hedge");
|
|
4773
|
+
if (!hedgeDue(item, lastLaunchAt)) return;
|
|
4774
|
+
replace(`slower than its peers after ${Math.round(performance.now() - t0)}ms`, true);
|
|
4833
4775
|
}, policy.hedgePollMs);
|
|
4834
4776
|
});
|
|
4835
4777
|
const tPut = performance.now();
|
|
@@ -4840,17 +4782,15 @@ async function multipartUploadStream(options) {
|
|
|
4840
4782
|
clock.delivered();
|
|
4841
4783
|
lastSocketActivityAt = tPut;
|
|
4842
4784
|
log3.debug(
|
|
4843
|
-
`part=${item.partNumber}/${totalParts} put=${Math.round(tPut - t0)}ms size=${item.ciphertext.length}${hedgeCount > 0 ? `
|
|
4785
|
+
`part=${item.partNumber}/${totalParts} put=${Math.round(tPut - t0)}ms size=${item.ciphertext.length}${hedgeCount > 0 ? ` replaced\xD7${hedgeCount}` : ""}`
|
|
4844
4786
|
);
|
|
4845
4787
|
report("uploading");
|
|
4846
4788
|
} finally {
|
|
4847
4789
|
partsInFlight.delete(inFlight);
|
|
4848
|
-
|
|
4790
|
+
replace = () => {
|
|
4849
4791
|
};
|
|
4850
4792
|
if (hedgeTicker !== null) clearInterval(hedgeTicker);
|
|
4851
|
-
|
|
4852
|
-
for (const ctl of controllers) ctl.abort();
|
|
4853
|
-
for (const detach of detachFns) detach();
|
|
4793
|
+
current?.ctl.abort();
|
|
4854
4794
|
}
|
|
4855
4795
|
}
|
|
4856
4796
|
const controlFetch = (url, init3, timeoutMs) => policyFetch(url, init3, timeoutMs, runSignal);
|
|
@@ -4955,6 +4895,10 @@ async function multipartUploadStream(options) {
|
|
|
4955
4895
|
item.round = round;
|
|
4956
4896
|
item.flowsAtStart = runningParts.size;
|
|
4957
4897
|
let url = presignedUrlCache.get(item.partNumber);
|
|
4898
|
+
if (!url && presignPrefetchInFlight) {
|
|
4899
|
+
await presignPrefetchInFlight;
|
|
4900
|
+
url = presignedUrlCache.get(item.partNumber);
|
|
4901
|
+
}
|
|
4958
4902
|
presignedUrlCache.delete(item.partNumber);
|
|
4959
4903
|
schedulePresignPrefetch(item.partNumber + 1);
|
|
4960
4904
|
await retrying(
|
|
@@ -11398,6 +11342,10 @@ var seal_mcp_v1_default = {
|
|
|
11398
11342
|
server_info: "name `sealnet-mcp` (the npm package and its binary); version = `package.json::version`, injected at build time (tsup `define`), never a source literal. The state directory, the keychain service and the handoff directory keep the name `seal-mcp`: they are where existing state lives.",
|
|
11399
11343
|
progress: "When a `tools/call` carries `_meta.progressToken`, `seal_share` and `seal_open mode=file` send `notifications/progress` with `progress` = ciphertext bytes done (upload: confirmed by storage) and `total` = ciphertext bytes in all; at most one per second, `progress` strictly increasing, the last one at `progress = total`."
|
|
11400
11344
|
},
|
|
11345
|
+
server_instructions: {
|
|
11346
|
+
text: "SEAL moves files and secrets between people and agents without their content entering this conversation. When someone wants a file, folder or secret sent to them, to another machine or to another agent, call seal_share with its path and do not open, print or Read it first. When you need an API key, password, file or folder from the user, or they offer or ask how to give you one, call seal_request right away instead of explaining other ways or asking them to paste or upload it. Open a SEAL link someone gave you with seal_open (mode=file for secrets and large files).",
|
|
11347
|
+
note: "The `instructions` of the `initialize` result (SPEC-AGENTS \xA78.1). Hosts that defer MCP tools behind a tool search (Claude Code) show the model only tool names until it searches, but put these instructions into the system prompt: this is the one text a model reads before it decides to look for a tool, or reads the file it was asked to send."
|
|
11348
|
+
},
|
|
11401
11349
|
tools: {
|
|
11402
11350
|
seal_share: {
|
|
11403
11351
|
title: "Share a file via SEAL",
|
|
@@ -13989,7 +13937,7 @@ function proFileGetOutputToWire(out) {
|
|
|
13989
13937
|
}
|
|
13990
13938
|
|
|
13991
13939
|
// src/server.ts
|
|
13992
|
-
var SERVER_VERSION = "0.2.
|
|
13940
|
+
var SERVER_VERSION = "0.2.3";
|
|
13993
13941
|
var toolMeta = (name) => {
|
|
13994
13942
|
const { title, description, annotations } = seal_mcp_v1_default.tools[name];
|
|
13995
13943
|
return { title, description, annotations };
|
|
@@ -14057,7 +14005,7 @@ async function createServer(options) {
|
|
|
14057
14005
|
};
|
|
14058
14006
|
const mcp = new import_mcp.McpServer(
|
|
14059
14007
|
{ name: "sealnet-mcp", version: SERVER_VERSION },
|
|
14060
|
-
{ capabilities: { tools: {} } }
|
|
14008
|
+
{ capabilities: { tools: {} }, instructions: seal_mcp_v1_default.server_instructions.text }
|
|
14061
14009
|
);
|
|
14062
14010
|
const disableClipboard = process.env.SEAL_MCP_DISABLE_CLIPBOARD === "1";
|
|
14063
14011
|
mcp.registerTool(
|
package/dist/cli.js
CHANGED
|
@@ -2886,7 +2886,6 @@ var upload_default = {
|
|
|
2886
2886
|
HEDGE_MIN_INFLIGHT_MS: 3e3,
|
|
2887
2887
|
HEDGE_LAG_FACTOR: 3,
|
|
2888
2888
|
HEDGE_POLL_MS: 1e3,
|
|
2889
|
-
HEDGE_MAX_CONCURRENT: 1,
|
|
2890
2889
|
LIVENESS_SILENCE_MS: 3e4,
|
|
2891
2890
|
RETRY_BACKOFF_MS: [1e3, 3e3, 7e3, 15e3, 3e4],
|
|
2892
2891
|
RETRY_JITTER_RATIO: 0.2,
|
|
@@ -4181,7 +4180,6 @@ var DEFAULT_TRANSPORT_POLICY = {
|
|
|
4181
4180
|
hedgeMinInflightMs: upload_default.upload.HEDGE_MIN_INFLIGHT_MS,
|
|
4182
4181
|
hedgeLagFactor: upload_default.upload.HEDGE_LAG_FACTOR,
|
|
4183
4182
|
hedgePollMs: upload_default.upload.HEDGE_POLL_MS,
|
|
4184
|
-
hedgeMaxConcurrent: upload_default.upload.HEDGE_MAX_CONCURRENT,
|
|
4185
4183
|
livenessSilenceMs: upload_default.upload.LIVENESS_SILENCE_MS,
|
|
4186
4184
|
verifyPollBackoffMs: upload_default.upload.VERIFY_POLL_BACKOFF_MS,
|
|
4187
4185
|
verifyFallbackWaitMs: upload_default.upload.VERIFY_FALLBACK_WAIT_MS,
|
|
@@ -4503,7 +4501,6 @@ async function multipartUploadStream(options) {
|
|
|
4503
4501
|
let lastRoundRate = null;
|
|
4504
4502
|
let roomWaiters = [];
|
|
4505
4503
|
const fullPartPace = [];
|
|
4506
|
-
let hedgesInFlight = 0;
|
|
4507
4504
|
const partsInFlight = /* @__PURE__ */ new Set();
|
|
4508
4505
|
let lastSocketActivityAt = performance.now();
|
|
4509
4506
|
let socketActivityObservable = false;
|
|
@@ -4548,10 +4545,10 @@ async function multipartUploadStream(options) {
|
|
|
4548
4545
|
roundBytes = 0;
|
|
4549
4546
|
roundDeliveries = 0;
|
|
4550
4547
|
}
|
|
4551
|
-
function hedgeDue(item, lastLaunchAt
|
|
4548
|
+
function hedgeDue(item, lastLaunchAt) {
|
|
4552
4549
|
const inFlightMs = performance.now() - lastLaunchAt;
|
|
4553
4550
|
if (inFlightMs < policy.hedgeMinInflightMs) return false;
|
|
4554
|
-
const flowsNow = runningParts.size
|
|
4551
|
+
const flowsNow = runningParts.size;
|
|
4555
4552
|
const peers = fullPartPace.filter((p) => p.flows >= flowsNow).map((p) => p.rate);
|
|
4556
4553
|
if (peers.length === 0) return false;
|
|
4557
4554
|
peers.sort((a, b) => a - b);
|
|
@@ -4673,135 +4670,80 @@ async function multipartUploadStream(options) {
|
|
|
4673
4670
|
}
|
|
4674
4671
|
async function hedgedPut(item, presignedUrl) {
|
|
4675
4672
|
const t0 = performance.now();
|
|
4676
|
-
let controllers = [];
|
|
4677
|
-
const detachFns = [];
|
|
4678
4673
|
let hedgeTicker = null;
|
|
4679
4674
|
let hedgeCount = 0;
|
|
4680
|
-
let liveHedges = 0;
|
|
4681
|
-
let currentHedge = null;
|
|
4682
4675
|
let lastLaunchAt = t0;
|
|
4683
|
-
let
|
|
4684
|
-
|
|
4685
|
-
let reconnect = () => {
|
|
4686
|
-
};
|
|
4687
|
-
const launchCopy = async (isHedge) => {
|
|
4688
|
-
const ctl = new AbortController();
|
|
4689
|
-
controllers.push(ctl);
|
|
4690
|
-
if (isHedge) currentHedge = ctl;
|
|
4691
|
-
unsentByCopy.set(ctl, true);
|
|
4692
|
-
lastSocketActivityAt = performance.now();
|
|
4693
|
-
if (runSignal) {
|
|
4694
|
-
if (runSignal.aborted) {
|
|
4695
|
-
ctl.abort();
|
|
4696
|
-
} else {
|
|
4697
|
-
const onAbort = () => ctl.abort();
|
|
4698
|
-
runSignal.addEventListener("abort", onAbort, { once: true });
|
|
4699
|
-
detachFns.push(() => runSignal.removeEventListener("abort", onAbort));
|
|
4700
|
-
}
|
|
4701
|
-
}
|
|
4702
|
-
try {
|
|
4703
|
-
const outcome = await transportPut(
|
|
4704
|
-
item.ciphertext,
|
|
4705
|
-
item.contentMd5,
|
|
4706
|
-
item.partNumber,
|
|
4707
|
-
presignedUrl,
|
|
4708
|
-
ctl.signal,
|
|
4709
|
-
{
|
|
4710
|
-
onSocketActivity: (loaded, total) => {
|
|
4711
|
-
lastSocketActivityAt = performance.now();
|
|
4712
|
-
unsentByCopy.set(ctl, loaded < total);
|
|
4713
|
-
},
|
|
4714
|
-
onDeadline: () => reconnect("copy deadline")
|
|
4715
|
-
}
|
|
4716
|
-
);
|
|
4717
|
-
return validatePutOutcome(item.partNumber, outcome);
|
|
4718
|
-
} finally {
|
|
4719
|
-
unsentByCopy.delete(ctl);
|
|
4720
|
-
}
|
|
4676
|
+
let current = null;
|
|
4677
|
+
let replace = () => {
|
|
4721
4678
|
};
|
|
4722
4679
|
const inFlight = {
|
|
4723
|
-
reconnect: (why) =>
|
|
4724
|
-
hasUnsentBytes: () =>
|
|
4680
|
+
reconnect: (why) => replace(why, false),
|
|
4681
|
+
hasUnsentBytes: () => current?.unsent ?? false
|
|
4725
4682
|
};
|
|
4726
4683
|
partsInFlight.add(inFlight);
|
|
4727
4684
|
try {
|
|
4728
4685
|
const etag = await new Promise((resolve5, reject) => {
|
|
4729
|
-
let pending = 0;
|
|
4730
4686
|
let settled = false;
|
|
4731
|
-
const
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4687
|
+
const settle = (outcome) => {
|
|
4688
|
+
if (settled) return;
|
|
4689
|
+
settled = true;
|
|
4690
|
+
outcome();
|
|
4691
|
+
};
|
|
4692
|
+
const launch = () => {
|
|
4693
|
+
const ctl = new AbortController();
|
|
4694
|
+
const onUploadEnd = () => ctl.abort();
|
|
4695
|
+
if (runSignal?.aborted) ctl.abort();
|
|
4696
|
+
else runSignal?.addEventListener("abort", onUploadEnd, { once: true });
|
|
4697
|
+
const copy = { ctl, unsent: true, ended: Promise.resolve() };
|
|
4698
|
+
current = copy;
|
|
4699
|
+
lastLaunchAt = performance.now();
|
|
4700
|
+
lastSocketActivityAt = lastLaunchAt;
|
|
4701
|
+
copy.ended = transportPut(item.ciphertext, item.contentMd5, item.partNumber, presignedUrl, ctl.signal, {
|
|
4702
|
+
onSocketActivity: (loaded, total) => {
|
|
4703
|
+
lastSocketActivityAt = performance.now();
|
|
4704
|
+
copy.unsent = loaded < total;
|
|
4705
|
+
},
|
|
4706
|
+
onDeadline: () => replace("copy deadline", false)
|
|
4707
|
+
}).then(
|
|
4708
|
+
(outcome) => {
|
|
4709
|
+
if (current !== copy) return;
|
|
4710
|
+
try {
|
|
4711
|
+
const confirmed = validatePutOutcome(item.partNumber, outcome);
|
|
4712
|
+
settle(() => resolve5(confirmed));
|
|
4713
|
+
} catch (err2) {
|
|
4714
|
+
settle(() => reject(err2));
|
|
4758
4715
|
}
|
|
4759
|
-
|
|
4760
|
-
|
|
4716
|
+
},
|
|
4717
|
+
(err2) => {
|
|
4718
|
+
if (current === copy) settle(() => reject(toUploadError(err2, `Failed to upload part ${item.partNumber}`)));
|
|
4761
4719
|
}
|
|
4720
|
+
).finally(() => {
|
|
4721
|
+
copy.unsent = false;
|
|
4722
|
+
runSignal?.removeEventListener("abort", onUploadEnd);
|
|
4762
4723
|
});
|
|
4763
4724
|
};
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4725
|
+
replace = (why, spendsTicket) => {
|
|
4726
|
+
const old = current;
|
|
4727
|
+
if (settled || old === null || signal?.aborted) return;
|
|
4728
|
+
current = null;
|
|
4729
|
+
hedgeCount = spendsTicket ? hedgeCount + 1 : 0;
|
|
4730
|
+
log3.debug(`${spendsTicket ? "replace" : "reconnect"} part=${item.partNumber} (${why})`);
|
|
4731
|
+
old.ctl.abort();
|
|
4732
|
+
void old.ended.then(() => {
|
|
4733
|
+
if (settled) return;
|
|
4734
|
+
if (runSignal?.aborted) {
|
|
4735
|
+
settle(() => reject(new UploadError("Upload aborted", "ABORTED", void 0, item.partNumber)));
|
|
4736
|
+
} else {
|
|
4737
|
+
launch();
|
|
4738
|
+
}
|
|
4739
|
+
});
|
|
4778
4740
|
};
|
|
4779
|
-
|
|
4741
|
+
launch();
|
|
4780
4742
|
hedgeTicker = setInterval(() => {
|
|
4781
|
-
if (settled || signal?.aborted)
|
|
4782
|
-
if (hedgeTicker !== null) {
|
|
4783
|
-
clearInterval(hedgeTicker);
|
|
4784
|
-
hedgeTicker = null;
|
|
4785
|
-
}
|
|
4786
|
-
return;
|
|
4787
|
-
}
|
|
4743
|
+
if (settled || signal?.aborted || current === null) return;
|
|
4788
4744
|
if (hedgeCount >= HEDGE_MAX_PER_PART) return;
|
|
4789
|
-
if (!hedgeDue(item, lastLaunchAt
|
|
4790
|
-
|
|
4791
|
-
if (currentHedge !== null) {
|
|
4792
|
-
currentHedge.abort();
|
|
4793
|
-
currentHedge = null;
|
|
4794
|
-
}
|
|
4795
|
-
return;
|
|
4796
|
-
}
|
|
4797
|
-
hedgeCount++;
|
|
4798
|
-
liveHedges++;
|
|
4799
|
-
hedgesInFlight++;
|
|
4800
|
-
lastLaunchAt = performance.now();
|
|
4801
|
-
log3.debug(
|
|
4802
|
-
`hedge launched part=${item.partNumber} copy=${hedgeCount + 1} after ${Math.round(performance.now() - t0)}ms`
|
|
4803
|
-
);
|
|
4804
|
-
run("hedge");
|
|
4745
|
+
if (!hedgeDue(item, lastLaunchAt)) return;
|
|
4746
|
+
replace(`slower than its peers after ${Math.round(performance.now() - t0)}ms`, true);
|
|
4805
4747
|
}, policy.hedgePollMs);
|
|
4806
4748
|
});
|
|
4807
4749
|
const tPut = performance.now();
|
|
@@ -4812,17 +4754,15 @@ async function multipartUploadStream(options) {
|
|
|
4812
4754
|
clock.delivered();
|
|
4813
4755
|
lastSocketActivityAt = tPut;
|
|
4814
4756
|
log3.debug(
|
|
4815
|
-
`part=${item.partNumber}/${totalParts} put=${Math.round(tPut - t0)}ms size=${item.ciphertext.length}${hedgeCount > 0 ? `
|
|
4757
|
+
`part=${item.partNumber}/${totalParts} put=${Math.round(tPut - t0)}ms size=${item.ciphertext.length}${hedgeCount > 0 ? ` replaced\xD7${hedgeCount}` : ""}`
|
|
4816
4758
|
);
|
|
4817
4759
|
report("uploading");
|
|
4818
4760
|
} finally {
|
|
4819
4761
|
partsInFlight.delete(inFlight);
|
|
4820
|
-
|
|
4762
|
+
replace = () => {
|
|
4821
4763
|
};
|
|
4822
4764
|
if (hedgeTicker !== null) clearInterval(hedgeTicker);
|
|
4823
|
-
|
|
4824
|
-
for (const ctl of controllers) ctl.abort();
|
|
4825
|
-
for (const detach of detachFns) detach();
|
|
4765
|
+
current?.ctl.abort();
|
|
4826
4766
|
}
|
|
4827
4767
|
}
|
|
4828
4768
|
const controlFetch = (url, init3, timeoutMs) => policyFetch(url, init3, timeoutMs, runSignal);
|
|
@@ -4927,6 +4867,10 @@ async function multipartUploadStream(options) {
|
|
|
4927
4867
|
item.round = round;
|
|
4928
4868
|
item.flowsAtStart = runningParts.size;
|
|
4929
4869
|
let url = presignedUrlCache.get(item.partNumber);
|
|
4870
|
+
if (!url && presignPrefetchInFlight) {
|
|
4871
|
+
await presignPrefetchInFlight;
|
|
4872
|
+
url = presignedUrlCache.get(item.partNumber);
|
|
4873
|
+
}
|
|
4930
4874
|
presignedUrlCache.delete(item.partNumber);
|
|
4931
4875
|
schedulePresignPrefetch(item.partNumber + 1);
|
|
4932
4876
|
await retrying(
|
|
@@ -11370,6 +11314,10 @@ var seal_mcp_v1_default = {
|
|
|
11370
11314
|
server_info: "name `sealnet-mcp` (the npm package and its binary); version = `package.json::version`, injected at build time (tsup `define`), never a source literal. The state directory, the keychain service and the handoff directory keep the name `seal-mcp`: they are where existing state lives.",
|
|
11371
11315
|
progress: "When a `tools/call` carries `_meta.progressToken`, `seal_share` and `seal_open mode=file` send `notifications/progress` with `progress` = ciphertext bytes done (upload: confirmed by storage) and `total` = ciphertext bytes in all; at most one per second, `progress` strictly increasing, the last one at `progress = total`."
|
|
11372
11316
|
},
|
|
11317
|
+
server_instructions: {
|
|
11318
|
+
text: "SEAL moves files and secrets between people and agents without their content entering this conversation. When someone wants a file, folder or secret sent to them, to another machine or to another agent, call seal_share with its path and do not open, print or Read it first. When you need an API key, password, file or folder from the user, or they offer or ask how to give you one, call seal_request right away instead of explaining other ways or asking them to paste or upload it. Open a SEAL link someone gave you with seal_open (mode=file for secrets and large files).",
|
|
11319
|
+
note: "The `instructions` of the `initialize` result (SPEC-AGENTS \xA78.1). Hosts that defer MCP tools behind a tool search (Claude Code) show the model only tool names until it searches, but put these instructions into the system prompt: this is the one text a model reads before it decides to look for a tool, or reads the file it was asked to send."
|
|
11320
|
+
},
|
|
11373
11321
|
tools: {
|
|
11374
11322
|
seal_share: {
|
|
11375
11323
|
title: "Share a file via SEAL",
|
|
@@ -13961,7 +13909,7 @@ function proFileGetOutputToWire(out) {
|
|
|
13961
13909
|
}
|
|
13962
13910
|
|
|
13963
13911
|
// src/server.ts
|
|
13964
|
-
var SERVER_VERSION = "0.2.
|
|
13912
|
+
var SERVER_VERSION = "0.2.3";
|
|
13965
13913
|
var toolMeta = (name) => {
|
|
13966
13914
|
const { title, description, annotations } = seal_mcp_v1_default.tools[name];
|
|
13967
13915
|
return { title, description, annotations };
|
|
@@ -14029,7 +13977,7 @@ async function createServer(options) {
|
|
|
14029
13977
|
};
|
|
14030
13978
|
const mcp = new McpServer(
|
|
14031
13979
|
{ name: "sealnet-mcp", version: SERVER_VERSION },
|
|
14032
|
-
{ capabilities: { tools: {} } }
|
|
13980
|
+
{ capabilities: { tools: {} }, instructions: seal_mcp_v1_default.server_instructions.text }
|
|
14033
13981
|
);
|
|
14034
13982
|
const disableClipboard = process.env.SEAL_MCP_DISABLE_CLIPBOARD === "1";
|
|
14035
13983
|
mcp.registerTool(
|
package/dist/index.cjs
CHANGED
|
@@ -4137,6 +4137,10 @@ var seal_mcp_v1_default = {
|
|
|
4137
4137
|
server_info: "name `sealnet-mcp` (the npm package and its binary); version = `package.json::version`, injected at build time (tsup `define`), never a source literal. The state directory, the keychain service and the handoff directory keep the name `seal-mcp`: they are where existing state lives.",
|
|
4138
4138
|
progress: "When a `tools/call` carries `_meta.progressToken`, `seal_share` and `seal_open mode=file` send `notifications/progress` with `progress` = ciphertext bytes done (upload: confirmed by storage) and `total` = ciphertext bytes in all; at most one per second, `progress` strictly increasing, the last one at `progress = total`."
|
|
4139
4139
|
},
|
|
4140
|
+
server_instructions: {
|
|
4141
|
+
text: "SEAL moves files and secrets between people and agents without their content entering this conversation. When someone wants a file, folder or secret sent to them, to another machine or to another agent, call seal_share with its path and do not open, print or Read it first. When you need an API key, password, file or folder from the user, or they offer or ask how to give you one, call seal_request right away instead of explaining other ways or asking them to paste or upload it. Open a SEAL link someone gave you with seal_open (mode=file for secrets and large files).",
|
|
4142
|
+
note: "The `instructions` of the `initialize` result (SPEC-AGENTS \xA78.1). Hosts that defer MCP tools behind a tool search (Claude Code) show the model only tool names until it searches, but put these instructions into the system prompt: this is the one text a model reads before it decides to look for a tool, or reads the file it was asked to send."
|
|
4143
|
+
},
|
|
4140
4144
|
tools: {
|
|
4141
4145
|
seal_share: {
|
|
4142
4146
|
title: "Share a file via SEAL",
|
|
@@ -7579,7 +7583,6 @@ var upload_default = {
|
|
|
7579
7583
|
HEDGE_MIN_INFLIGHT_MS: 3e3,
|
|
7580
7584
|
HEDGE_LAG_FACTOR: 3,
|
|
7581
7585
|
HEDGE_POLL_MS: 1e3,
|
|
7582
|
-
HEDGE_MAX_CONCURRENT: 1,
|
|
7583
7586
|
LIVENESS_SILENCE_MS: 3e4,
|
|
7584
7587
|
RETRY_BACKOFF_MS: [1e3, 3e3, 7e3, 15e3, 3e4],
|
|
7585
7588
|
RETRY_JITTER_RATIO: 0.2,
|
|
@@ -8874,7 +8877,6 @@ var DEFAULT_TRANSPORT_POLICY = {
|
|
|
8874
8877
|
hedgeMinInflightMs: upload_default.upload.HEDGE_MIN_INFLIGHT_MS,
|
|
8875
8878
|
hedgeLagFactor: upload_default.upload.HEDGE_LAG_FACTOR,
|
|
8876
8879
|
hedgePollMs: upload_default.upload.HEDGE_POLL_MS,
|
|
8877
|
-
hedgeMaxConcurrent: upload_default.upload.HEDGE_MAX_CONCURRENT,
|
|
8878
8880
|
livenessSilenceMs: upload_default.upload.LIVENESS_SILENCE_MS,
|
|
8879
8881
|
verifyPollBackoffMs: upload_default.upload.VERIFY_POLL_BACKOFF_MS,
|
|
8880
8882
|
verifyFallbackWaitMs: upload_default.upload.VERIFY_FALLBACK_WAIT_MS,
|
|
@@ -9196,7 +9198,6 @@ async function multipartUploadStream(options) {
|
|
|
9196
9198
|
let lastRoundRate = null;
|
|
9197
9199
|
let roomWaiters = [];
|
|
9198
9200
|
const fullPartPace = [];
|
|
9199
|
-
let hedgesInFlight = 0;
|
|
9200
9201
|
const partsInFlight = /* @__PURE__ */ new Set();
|
|
9201
9202
|
let lastSocketActivityAt = performance.now();
|
|
9202
9203
|
let socketActivityObservable = false;
|
|
@@ -9241,10 +9242,10 @@ async function multipartUploadStream(options) {
|
|
|
9241
9242
|
roundBytes = 0;
|
|
9242
9243
|
roundDeliveries = 0;
|
|
9243
9244
|
}
|
|
9244
|
-
function hedgeDue(item, lastLaunchAt
|
|
9245
|
+
function hedgeDue(item, lastLaunchAt) {
|
|
9245
9246
|
const inFlightMs = performance.now() - lastLaunchAt;
|
|
9246
9247
|
if (inFlightMs < policy.hedgeMinInflightMs) return false;
|
|
9247
|
-
const flowsNow = runningParts.size
|
|
9248
|
+
const flowsNow = runningParts.size;
|
|
9248
9249
|
const peers = fullPartPace.filter((p) => p.flows >= flowsNow).map((p) => p.rate);
|
|
9249
9250
|
if (peers.length === 0) return false;
|
|
9250
9251
|
peers.sort((a, b) => a - b);
|
|
@@ -9366,135 +9367,80 @@ async function multipartUploadStream(options) {
|
|
|
9366
9367
|
}
|
|
9367
9368
|
async function hedgedPut(item, presignedUrl) {
|
|
9368
9369
|
const t0 = performance.now();
|
|
9369
|
-
let controllers = [];
|
|
9370
|
-
const detachFns = [];
|
|
9371
9370
|
let hedgeTicker = null;
|
|
9372
9371
|
let hedgeCount = 0;
|
|
9373
|
-
let liveHedges = 0;
|
|
9374
|
-
let currentHedge = null;
|
|
9375
9372
|
let lastLaunchAt = t0;
|
|
9376
|
-
let
|
|
9377
|
-
|
|
9378
|
-
let reconnect = () => {
|
|
9379
|
-
};
|
|
9380
|
-
const launchCopy = async (isHedge) => {
|
|
9381
|
-
const ctl = new AbortController();
|
|
9382
|
-
controllers.push(ctl);
|
|
9383
|
-
if (isHedge) currentHedge = ctl;
|
|
9384
|
-
unsentByCopy.set(ctl, true);
|
|
9385
|
-
lastSocketActivityAt = performance.now();
|
|
9386
|
-
if (runSignal) {
|
|
9387
|
-
if (runSignal.aborted) {
|
|
9388
|
-
ctl.abort();
|
|
9389
|
-
} else {
|
|
9390
|
-
const onAbort = () => ctl.abort();
|
|
9391
|
-
runSignal.addEventListener("abort", onAbort, { once: true });
|
|
9392
|
-
detachFns.push(() => runSignal.removeEventListener("abort", onAbort));
|
|
9393
|
-
}
|
|
9394
|
-
}
|
|
9395
|
-
try {
|
|
9396
|
-
const outcome = await transportPut(
|
|
9397
|
-
item.ciphertext,
|
|
9398
|
-
item.contentMd5,
|
|
9399
|
-
item.partNumber,
|
|
9400
|
-
presignedUrl,
|
|
9401
|
-
ctl.signal,
|
|
9402
|
-
{
|
|
9403
|
-
onSocketActivity: (loaded, total) => {
|
|
9404
|
-
lastSocketActivityAt = performance.now();
|
|
9405
|
-
unsentByCopy.set(ctl, loaded < total);
|
|
9406
|
-
},
|
|
9407
|
-
onDeadline: () => reconnect("copy deadline")
|
|
9408
|
-
}
|
|
9409
|
-
);
|
|
9410
|
-
return validatePutOutcome(item.partNumber, outcome);
|
|
9411
|
-
} finally {
|
|
9412
|
-
unsentByCopy.delete(ctl);
|
|
9413
|
-
}
|
|
9373
|
+
let current = null;
|
|
9374
|
+
let replace = () => {
|
|
9414
9375
|
};
|
|
9415
9376
|
const inFlight = {
|
|
9416
|
-
reconnect: (why) =>
|
|
9417
|
-
hasUnsentBytes: () =>
|
|
9377
|
+
reconnect: (why) => replace(why, false),
|
|
9378
|
+
hasUnsentBytes: () => current?.unsent ?? false
|
|
9418
9379
|
};
|
|
9419
9380
|
partsInFlight.add(inFlight);
|
|
9420
9381
|
try {
|
|
9421
9382
|
const etag = await new Promise((resolve5, reject) => {
|
|
9422
|
-
let pending = 0;
|
|
9423
9383
|
let settled = false;
|
|
9424
|
-
const
|
|
9425
|
-
|
|
9426
|
-
|
|
9427
|
-
|
|
9428
|
-
|
|
9429
|
-
|
|
9430
|
-
|
|
9431
|
-
|
|
9432
|
-
|
|
9433
|
-
|
|
9434
|
-
|
|
9435
|
-
|
|
9436
|
-
|
|
9437
|
-
|
|
9438
|
-
|
|
9439
|
-
|
|
9440
|
-
|
|
9441
|
-
|
|
9442
|
-
|
|
9443
|
-
|
|
9444
|
-
|
|
9445
|
-
|
|
9446
|
-
|
|
9447
|
-
|
|
9448
|
-
|
|
9449
|
-
|
|
9450
|
-
|
|
9384
|
+
const settle = (outcome) => {
|
|
9385
|
+
if (settled) return;
|
|
9386
|
+
settled = true;
|
|
9387
|
+
outcome();
|
|
9388
|
+
};
|
|
9389
|
+
const launch = () => {
|
|
9390
|
+
const ctl = new AbortController();
|
|
9391
|
+
const onUploadEnd = () => ctl.abort();
|
|
9392
|
+
if (runSignal?.aborted) ctl.abort();
|
|
9393
|
+
else runSignal?.addEventListener("abort", onUploadEnd, { once: true });
|
|
9394
|
+
const copy = { ctl, unsent: true, ended: Promise.resolve() };
|
|
9395
|
+
current = copy;
|
|
9396
|
+
lastLaunchAt = performance.now();
|
|
9397
|
+
lastSocketActivityAt = lastLaunchAt;
|
|
9398
|
+
copy.ended = transportPut(item.ciphertext, item.contentMd5, item.partNumber, presignedUrl, ctl.signal, {
|
|
9399
|
+
onSocketActivity: (loaded, total) => {
|
|
9400
|
+
lastSocketActivityAt = performance.now();
|
|
9401
|
+
copy.unsent = loaded < total;
|
|
9402
|
+
},
|
|
9403
|
+
onDeadline: () => replace("copy deadline", false)
|
|
9404
|
+
}).then(
|
|
9405
|
+
(outcome) => {
|
|
9406
|
+
if (current !== copy) return;
|
|
9407
|
+
try {
|
|
9408
|
+
const confirmed = validatePutOutcome(item.partNumber, outcome);
|
|
9409
|
+
settle(() => resolve5(confirmed));
|
|
9410
|
+
} catch (err2) {
|
|
9411
|
+
settle(() => reject(err2));
|
|
9451
9412
|
}
|
|
9452
|
-
|
|
9453
|
-
|
|
9413
|
+
},
|
|
9414
|
+
(err2) => {
|
|
9415
|
+
if (current === copy) settle(() => reject(toUploadError(err2, `Failed to upload part ${item.partNumber}`)));
|
|
9454
9416
|
}
|
|
9417
|
+
).finally(() => {
|
|
9418
|
+
copy.unsent = false;
|
|
9419
|
+
runSignal?.removeEventListener("abort", onUploadEnd);
|
|
9455
9420
|
});
|
|
9456
9421
|
};
|
|
9457
|
-
|
|
9458
|
-
|
|
9459
|
-
|
|
9460
|
-
|
|
9461
|
-
|
|
9462
|
-
|
|
9463
|
-
|
|
9464
|
-
|
|
9465
|
-
|
|
9466
|
-
|
|
9467
|
-
|
|
9468
|
-
|
|
9469
|
-
|
|
9470
|
-
|
|
9422
|
+
replace = (why, spendsTicket) => {
|
|
9423
|
+
const old = current;
|
|
9424
|
+
if (settled || old === null || signal?.aborted) return;
|
|
9425
|
+
current = null;
|
|
9426
|
+
hedgeCount = spendsTicket ? hedgeCount + 1 : 0;
|
|
9427
|
+
log3.debug(`${spendsTicket ? "replace" : "reconnect"} part=${item.partNumber} (${why})`);
|
|
9428
|
+
old.ctl.abort();
|
|
9429
|
+
void old.ended.then(() => {
|
|
9430
|
+
if (settled) return;
|
|
9431
|
+
if (runSignal?.aborted) {
|
|
9432
|
+
settle(() => reject(new UploadError("Upload aborted", "ABORTED", void 0, item.partNumber)));
|
|
9433
|
+
} else {
|
|
9434
|
+
launch();
|
|
9435
|
+
}
|
|
9436
|
+
});
|
|
9471
9437
|
};
|
|
9472
|
-
|
|
9438
|
+
launch();
|
|
9473
9439
|
hedgeTicker = setInterval(() => {
|
|
9474
|
-
if (settled || signal?.aborted)
|
|
9475
|
-
if (hedgeTicker !== null) {
|
|
9476
|
-
clearInterval(hedgeTicker);
|
|
9477
|
-
hedgeTicker = null;
|
|
9478
|
-
}
|
|
9479
|
-
return;
|
|
9480
|
-
}
|
|
9440
|
+
if (settled || signal?.aborted || current === null) return;
|
|
9481
9441
|
if (hedgeCount >= HEDGE_MAX_PER_PART) return;
|
|
9482
|
-
if (!hedgeDue(item, lastLaunchAt
|
|
9483
|
-
|
|
9484
|
-
if (currentHedge !== null) {
|
|
9485
|
-
currentHedge.abort();
|
|
9486
|
-
currentHedge = null;
|
|
9487
|
-
}
|
|
9488
|
-
return;
|
|
9489
|
-
}
|
|
9490
|
-
hedgeCount++;
|
|
9491
|
-
liveHedges++;
|
|
9492
|
-
hedgesInFlight++;
|
|
9493
|
-
lastLaunchAt = performance.now();
|
|
9494
|
-
log3.debug(
|
|
9495
|
-
`hedge launched part=${item.partNumber} copy=${hedgeCount + 1} after ${Math.round(performance.now() - t0)}ms`
|
|
9496
|
-
);
|
|
9497
|
-
run("hedge");
|
|
9442
|
+
if (!hedgeDue(item, lastLaunchAt)) return;
|
|
9443
|
+
replace(`slower than its peers after ${Math.round(performance.now() - t0)}ms`, true);
|
|
9498
9444
|
}, policy.hedgePollMs);
|
|
9499
9445
|
});
|
|
9500
9446
|
const tPut = performance.now();
|
|
@@ -9505,17 +9451,15 @@ async function multipartUploadStream(options) {
|
|
|
9505
9451
|
clock.delivered();
|
|
9506
9452
|
lastSocketActivityAt = tPut;
|
|
9507
9453
|
log3.debug(
|
|
9508
|
-
`part=${item.partNumber}/${totalParts} put=${Math.round(tPut - t0)}ms size=${item.ciphertext.length}${hedgeCount > 0 ? `
|
|
9454
|
+
`part=${item.partNumber}/${totalParts} put=${Math.round(tPut - t0)}ms size=${item.ciphertext.length}${hedgeCount > 0 ? ` replaced\xD7${hedgeCount}` : ""}`
|
|
9509
9455
|
);
|
|
9510
9456
|
report("uploading");
|
|
9511
9457
|
} finally {
|
|
9512
9458
|
partsInFlight.delete(inFlight);
|
|
9513
|
-
|
|
9459
|
+
replace = () => {
|
|
9514
9460
|
};
|
|
9515
9461
|
if (hedgeTicker !== null) clearInterval(hedgeTicker);
|
|
9516
|
-
|
|
9517
|
-
for (const ctl of controllers) ctl.abort();
|
|
9518
|
-
for (const detach of detachFns) detach();
|
|
9462
|
+
current?.ctl.abort();
|
|
9519
9463
|
}
|
|
9520
9464
|
}
|
|
9521
9465
|
const controlFetch = (url, init3, timeoutMs) => policyFetch(url, init3, timeoutMs, runSignal);
|
|
@@ -9620,6 +9564,10 @@ async function multipartUploadStream(options) {
|
|
|
9620
9564
|
item.round = round;
|
|
9621
9565
|
item.flowsAtStart = runningParts.size;
|
|
9622
9566
|
let url = presignedUrlCache.get(item.partNumber);
|
|
9567
|
+
if (!url && presignPrefetchInFlight) {
|
|
9568
|
+
await presignPrefetchInFlight;
|
|
9569
|
+
url = presignedUrlCache.get(item.partNumber);
|
|
9570
|
+
}
|
|
9623
9571
|
presignedUrlCache.delete(item.partNumber);
|
|
9624
9572
|
schedulePresignPrefetch(item.partNumber + 1);
|
|
9625
9573
|
await retrying(
|
|
@@ -13844,7 +13792,7 @@ function proFileGetOutputToWire(out) {
|
|
|
13844
13792
|
}
|
|
13845
13793
|
|
|
13846
13794
|
// src/server.ts
|
|
13847
|
-
var SERVER_VERSION = "0.2.
|
|
13795
|
+
var SERVER_VERSION = "0.2.3";
|
|
13848
13796
|
var toolMeta = (name) => {
|
|
13849
13797
|
const { title, description, annotations } = seal_mcp_v1_default.tools[name];
|
|
13850
13798
|
return { title, description, annotations };
|
|
@@ -13912,7 +13860,7 @@ async function createServer(options) {
|
|
|
13912
13860
|
};
|
|
13913
13861
|
const mcp = new import_mcp.McpServer(
|
|
13914
13862
|
{ name: "sealnet-mcp", version: SERVER_VERSION },
|
|
13915
|
-
{ capabilities: { tools: {} } }
|
|
13863
|
+
{ capabilities: { tools: {} }, instructions: seal_mcp_v1_default.server_instructions.text }
|
|
13916
13864
|
);
|
|
13917
13865
|
const disableClipboard = process.env.SEAL_MCP_DISABLE_CLIPBOARD === "1";
|
|
13918
13866
|
mcp.registerTool(
|
package/dist/index.d.cts
CHANGED
|
@@ -218,7 +218,8 @@ interface TransportPolicy {
|
|
|
218
218
|
/**
|
|
219
219
|
* Parallel part PUTs: where the pool starts, and how wide it may get.
|
|
220
220
|
* Storage speaks HTTP/1.1 only, so every PUT is a connection of its own and
|
|
221
|
-
* a browser gives a host six: `poolMax`
|
|
221
|
+
* a browser gives a host six: `poolMax` must fit. A replacement takes the
|
|
222
|
+
* connection of the copy it replaces, never a second one (F-263).
|
|
222
223
|
*/
|
|
223
224
|
poolStart: number;
|
|
224
225
|
poolMax: number;
|
|
@@ -234,13 +235,11 @@ interface TransportPolicy {
|
|
|
234
235
|
poolShrinkRatio: number;
|
|
235
236
|
/** Encrypted parts that may wait for a slot (bounds memory). */
|
|
236
237
|
partQueueLimit: number;
|
|
237
|
-
/** Never
|
|
238
|
+
/** Never replace a copy before it has been in flight this long. */
|
|
238
239
|
hedgeMinInflightMs: number;
|
|
239
240
|
/** A part is an outlier when it is this many times slower than its peers' median. */
|
|
240
241
|
hedgeLagFactor: number;
|
|
241
242
|
hedgePollMs: number;
|
|
242
|
-
/** Duplicate copies in flight across the whole upload, at most. */
|
|
243
|
-
hedgeMaxConcurrent: number;
|
|
244
243
|
/**
|
|
245
244
|
* No part delivered and no socket of ANY copy taking bytes for this long,
|
|
246
245
|
* while some copy still has bytes to send ⇒ the connections are dead: every
|
package/dist/index.d.ts
CHANGED
|
@@ -218,7 +218,8 @@ interface TransportPolicy {
|
|
|
218
218
|
/**
|
|
219
219
|
* Parallel part PUTs: where the pool starts, and how wide it may get.
|
|
220
220
|
* Storage speaks HTTP/1.1 only, so every PUT is a connection of its own and
|
|
221
|
-
* a browser gives a host six: `poolMax`
|
|
221
|
+
* a browser gives a host six: `poolMax` must fit. A replacement takes the
|
|
222
|
+
* connection of the copy it replaces, never a second one (F-263).
|
|
222
223
|
*/
|
|
223
224
|
poolStart: number;
|
|
224
225
|
poolMax: number;
|
|
@@ -234,13 +235,11 @@ interface TransportPolicy {
|
|
|
234
235
|
poolShrinkRatio: number;
|
|
235
236
|
/** Encrypted parts that may wait for a slot (bounds memory). */
|
|
236
237
|
partQueueLimit: number;
|
|
237
|
-
/** Never
|
|
238
|
+
/** Never replace a copy before it has been in flight this long. */
|
|
238
239
|
hedgeMinInflightMs: number;
|
|
239
240
|
/** A part is an outlier when it is this many times slower than its peers' median. */
|
|
240
241
|
hedgeLagFactor: number;
|
|
241
242
|
hedgePollMs: number;
|
|
242
|
-
/** Duplicate copies in flight across the whole upload, at most. */
|
|
243
|
-
hedgeMaxConcurrent: number;
|
|
244
243
|
/**
|
|
245
244
|
* No part delivered and no socket of ANY copy taking bytes for this long,
|
|
246
245
|
* while some copy still has bytes to send ⇒ the connections are dead: every
|
package/dist/index.js
CHANGED
|
@@ -4065,6 +4065,10 @@ var seal_mcp_v1_default = {
|
|
|
4065
4065
|
server_info: "name `sealnet-mcp` (the npm package and its binary); version = `package.json::version`, injected at build time (tsup `define`), never a source literal. The state directory, the keychain service and the handoff directory keep the name `seal-mcp`: they are where existing state lives.",
|
|
4066
4066
|
progress: "When a `tools/call` carries `_meta.progressToken`, `seal_share` and `seal_open mode=file` send `notifications/progress` with `progress` = ciphertext bytes done (upload: confirmed by storage) and `total` = ciphertext bytes in all; at most one per second, `progress` strictly increasing, the last one at `progress = total`."
|
|
4067
4067
|
},
|
|
4068
|
+
server_instructions: {
|
|
4069
|
+
text: "SEAL moves files and secrets between people and agents without their content entering this conversation. When someone wants a file, folder or secret sent to them, to another machine or to another agent, call seal_share with its path and do not open, print or Read it first. When you need an API key, password, file or folder from the user, or they offer or ask how to give you one, call seal_request right away instead of explaining other ways or asking them to paste or upload it. Open a SEAL link someone gave you with seal_open (mode=file for secrets and large files).",
|
|
4070
|
+
note: "The `instructions` of the `initialize` result (SPEC-AGENTS \xA78.1). Hosts that defer MCP tools behind a tool search (Claude Code) show the model only tool names until it searches, but put these instructions into the system prompt: this is the one text a model reads before it decides to look for a tool, or reads the file it was asked to send."
|
|
4071
|
+
},
|
|
4068
4072
|
tools: {
|
|
4069
4073
|
seal_share: {
|
|
4070
4074
|
title: "Share a file via SEAL",
|
|
@@ -7507,7 +7511,6 @@ var upload_default = {
|
|
|
7507
7511
|
HEDGE_MIN_INFLIGHT_MS: 3e3,
|
|
7508
7512
|
HEDGE_LAG_FACTOR: 3,
|
|
7509
7513
|
HEDGE_POLL_MS: 1e3,
|
|
7510
|
-
HEDGE_MAX_CONCURRENT: 1,
|
|
7511
7514
|
LIVENESS_SILENCE_MS: 3e4,
|
|
7512
7515
|
RETRY_BACKOFF_MS: [1e3, 3e3, 7e3, 15e3, 3e4],
|
|
7513
7516
|
RETRY_JITTER_RATIO: 0.2,
|
|
@@ -8802,7 +8805,6 @@ var DEFAULT_TRANSPORT_POLICY = {
|
|
|
8802
8805
|
hedgeMinInflightMs: upload_default.upload.HEDGE_MIN_INFLIGHT_MS,
|
|
8803
8806
|
hedgeLagFactor: upload_default.upload.HEDGE_LAG_FACTOR,
|
|
8804
8807
|
hedgePollMs: upload_default.upload.HEDGE_POLL_MS,
|
|
8805
|
-
hedgeMaxConcurrent: upload_default.upload.HEDGE_MAX_CONCURRENT,
|
|
8806
8808
|
livenessSilenceMs: upload_default.upload.LIVENESS_SILENCE_MS,
|
|
8807
8809
|
verifyPollBackoffMs: upload_default.upload.VERIFY_POLL_BACKOFF_MS,
|
|
8808
8810
|
verifyFallbackWaitMs: upload_default.upload.VERIFY_FALLBACK_WAIT_MS,
|
|
@@ -9124,7 +9126,6 @@ async function multipartUploadStream(options) {
|
|
|
9124
9126
|
let lastRoundRate = null;
|
|
9125
9127
|
let roomWaiters = [];
|
|
9126
9128
|
const fullPartPace = [];
|
|
9127
|
-
let hedgesInFlight = 0;
|
|
9128
9129
|
const partsInFlight = /* @__PURE__ */ new Set();
|
|
9129
9130
|
let lastSocketActivityAt = performance.now();
|
|
9130
9131
|
let socketActivityObservable = false;
|
|
@@ -9169,10 +9170,10 @@ async function multipartUploadStream(options) {
|
|
|
9169
9170
|
roundBytes = 0;
|
|
9170
9171
|
roundDeliveries = 0;
|
|
9171
9172
|
}
|
|
9172
|
-
function hedgeDue(item, lastLaunchAt
|
|
9173
|
+
function hedgeDue(item, lastLaunchAt) {
|
|
9173
9174
|
const inFlightMs = performance.now() - lastLaunchAt;
|
|
9174
9175
|
if (inFlightMs < policy.hedgeMinInflightMs) return false;
|
|
9175
|
-
const flowsNow = runningParts.size
|
|
9176
|
+
const flowsNow = runningParts.size;
|
|
9176
9177
|
const peers = fullPartPace.filter((p) => p.flows >= flowsNow).map((p) => p.rate);
|
|
9177
9178
|
if (peers.length === 0) return false;
|
|
9178
9179
|
peers.sort((a, b) => a - b);
|
|
@@ -9294,135 +9295,80 @@ async function multipartUploadStream(options) {
|
|
|
9294
9295
|
}
|
|
9295
9296
|
async function hedgedPut(item, presignedUrl) {
|
|
9296
9297
|
const t0 = performance.now();
|
|
9297
|
-
let controllers = [];
|
|
9298
|
-
const detachFns = [];
|
|
9299
9298
|
let hedgeTicker = null;
|
|
9300
9299
|
let hedgeCount = 0;
|
|
9301
|
-
let liveHedges = 0;
|
|
9302
|
-
let currentHedge = null;
|
|
9303
9300
|
let lastLaunchAt = t0;
|
|
9304
|
-
let
|
|
9305
|
-
|
|
9306
|
-
let reconnect = () => {
|
|
9307
|
-
};
|
|
9308
|
-
const launchCopy = async (isHedge) => {
|
|
9309
|
-
const ctl = new AbortController();
|
|
9310
|
-
controllers.push(ctl);
|
|
9311
|
-
if (isHedge) currentHedge = ctl;
|
|
9312
|
-
unsentByCopy.set(ctl, true);
|
|
9313
|
-
lastSocketActivityAt = performance.now();
|
|
9314
|
-
if (runSignal) {
|
|
9315
|
-
if (runSignal.aborted) {
|
|
9316
|
-
ctl.abort();
|
|
9317
|
-
} else {
|
|
9318
|
-
const onAbort = () => ctl.abort();
|
|
9319
|
-
runSignal.addEventListener("abort", onAbort, { once: true });
|
|
9320
|
-
detachFns.push(() => runSignal.removeEventListener("abort", onAbort));
|
|
9321
|
-
}
|
|
9322
|
-
}
|
|
9323
|
-
try {
|
|
9324
|
-
const outcome = await transportPut(
|
|
9325
|
-
item.ciphertext,
|
|
9326
|
-
item.contentMd5,
|
|
9327
|
-
item.partNumber,
|
|
9328
|
-
presignedUrl,
|
|
9329
|
-
ctl.signal,
|
|
9330
|
-
{
|
|
9331
|
-
onSocketActivity: (loaded, total) => {
|
|
9332
|
-
lastSocketActivityAt = performance.now();
|
|
9333
|
-
unsentByCopy.set(ctl, loaded < total);
|
|
9334
|
-
},
|
|
9335
|
-
onDeadline: () => reconnect("copy deadline")
|
|
9336
|
-
}
|
|
9337
|
-
);
|
|
9338
|
-
return validatePutOutcome(item.partNumber, outcome);
|
|
9339
|
-
} finally {
|
|
9340
|
-
unsentByCopy.delete(ctl);
|
|
9341
|
-
}
|
|
9301
|
+
let current = null;
|
|
9302
|
+
let replace = () => {
|
|
9342
9303
|
};
|
|
9343
9304
|
const inFlight = {
|
|
9344
|
-
reconnect: (why) =>
|
|
9345
|
-
hasUnsentBytes: () =>
|
|
9305
|
+
reconnect: (why) => replace(why, false),
|
|
9306
|
+
hasUnsentBytes: () => current?.unsent ?? false
|
|
9346
9307
|
};
|
|
9347
9308
|
partsInFlight.add(inFlight);
|
|
9348
9309
|
try {
|
|
9349
9310
|
const etag = await new Promise((resolve5, reject) => {
|
|
9350
|
-
let pending = 0;
|
|
9351
9311
|
let settled = false;
|
|
9352
|
-
const
|
|
9353
|
-
|
|
9354
|
-
|
|
9355
|
-
|
|
9356
|
-
|
|
9357
|
-
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
|
|
9364
|
-
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
|
|
9369
|
-
|
|
9370
|
-
|
|
9371
|
-
|
|
9372
|
-
|
|
9373
|
-
|
|
9374
|
-
|
|
9375
|
-
|
|
9376
|
-
|
|
9377
|
-
|
|
9378
|
-
|
|
9312
|
+
const settle = (outcome) => {
|
|
9313
|
+
if (settled) return;
|
|
9314
|
+
settled = true;
|
|
9315
|
+
outcome();
|
|
9316
|
+
};
|
|
9317
|
+
const launch = () => {
|
|
9318
|
+
const ctl = new AbortController();
|
|
9319
|
+
const onUploadEnd = () => ctl.abort();
|
|
9320
|
+
if (runSignal?.aborted) ctl.abort();
|
|
9321
|
+
else runSignal?.addEventListener("abort", onUploadEnd, { once: true });
|
|
9322
|
+
const copy = { ctl, unsent: true, ended: Promise.resolve() };
|
|
9323
|
+
current = copy;
|
|
9324
|
+
lastLaunchAt = performance.now();
|
|
9325
|
+
lastSocketActivityAt = lastLaunchAt;
|
|
9326
|
+
copy.ended = transportPut(item.ciphertext, item.contentMd5, item.partNumber, presignedUrl, ctl.signal, {
|
|
9327
|
+
onSocketActivity: (loaded, total) => {
|
|
9328
|
+
lastSocketActivityAt = performance.now();
|
|
9329
|
+
copy.unsent = loaded < total;
|
|
9330
|
+
},
|
|
9331
|
+
onDeadline: () => replace("copy deadline", false)
|
|
9332
|
+
}).then(
|
|
9333
|
+
(outcome) => {
|
|
9334
|
+
if (current !== copy) return;
|
|
9335
|
+
try {
|
|
9336
|
+
const confirmed = validatePutOutcome(item.partNumber, outcome);
|
|
9337
|
+
settle(() => resolve5(confirmed));
|
|
9338
|
+
} catch (err2) {
|
|
9339
|
+
settle(() => reject(err2));
|
|
9379
9340
|
}
|
|
9380
|
-
|
|
9381
|
-
|
|
9341
|
+
},
|
|
9342
|
+
(err2) => {
|
|
9343
|
+
if (current === copy) settle(() => reject(toUploadError(err2, `Failed to upload part ${item.partNumber}`)));
|
|
9382
9344
|
}
|
|
9345
|
+
).finally(() => {
|
|
9346
|
+
copy.unsent = false;
|
|
9347
|
+
runSignal?.removeEventListener("abort", onUploadEnd);
|
|
9383
9348
|
});
|
|
9384
9349
|
};
|
|
9385
|
-
|
|
9386
|
-
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
-
|
|
9393
|
-
|
|
9394
|
-
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
|
|
9350
|
+
replace = (why, spendsTicket) => {
|
|
9351
|
+
const old = current;
|
|
9352
|
+
if (settled || old === null || signal?.aborted) return;
|
|
9353
|
+
current = null;
|
|
9354
|
+
hedgeCount = spendsTicket ? hedgeCount + 1 : 0;
|
|
9355
|
+
log3.debug(`${spendsTicket ? "replace" : "reconnect"} part=${item.partNumber} (${why})`);
|
|
9356
|
+
old.ctl.abort();
|
|
9357
|
+
void old.ended.then(() => {
|
|
9358
|
+
if (settled) return;
|
|
9359
|
+
if (runSignal?.aborted) {
|
|
9360
|
+
settle(() => reject(new UploadError("Upload aborted", "ABORTED", void 0, item.partNumber)));
|
|
9361
|
+
} else {
|
|
9362
|
+
launch();
|
|
9363
|
+
}
|
|
9364
|
+
});
|
|
9399
9365
|
};
|
|
9400
|
-
|
|
9366
|
+
launch();
|
|
9401
9367
|
hedgeTicker = setInterval(() => {
|
|
9402
|
-
if (settled || signal?.aborted)
|
|
9403
|
-
if (hedgeTicker !== null) {
|
|
9404
|
-
clearInterval(hedgeTicker);
|
|
9405
|
-
hedgeTicker = null;
|
|
9406
|
-
}
|
|
9407
|
-
return;
|
|
9408
|
-
}
|
|
9368
|
+
if (settled || signal?.aborted || current === null) return;
|
|
9409
9369
|
if (hedgeCount >= HEDGE_MAX_PER_PART) return;
|
|
9410
|
-
if (!hedgeDue(item, lastLaunchAt
|
|
9411
|
-
|
|
9412
|
-
if (currentHedge !== null) {
|
|
9413
|
-
currentHedge.abort();
|
|
9414
|
-
currentHedge = null;
|
|
9415
|
-
}
|
|
9416
|
-
return;
|
|
9417
|
-
}
|
|
9418
|
-
hedgeCount++;
|
|
9419
|
-
liveHedges++;
|
|
9420
|
-
hedgesInFlight++;
|
|
9421
|
-
lastLaunchAt = performance.now();
|
|
9422
|
-
log3.debug(
|
|
9423
|
-
`hedge launched part=${item.partNumber} copy=${hedgeCount + 1} after ${Math.round(performance.now() - t0)}ms`
|
|
9424
|
-
);
|
|
9425
|
-
run("hedge");
|
|
9370
|
+
if (!hedgeDue(item, lastLaunchAt)) return;
|
|
9371
|
+
replace(`slower than its peers after ${Math.round(performance.now() - t0)}ms`, true);
|
|
9426
9372
|
}, policy.hedgePollMs);
|
|
9427
9373
|
});
|
|
9428
9374
|
const tPut = performance.now();
|
|
@@ -9433,17 +9379,15 @@ async function multipartUploadStream(options) {
|
|
|
9433
9379
|
clock.delivered();
|
|
9434
9380
|
lastSocketActivityAt = tPut;
|
|
9435
9381
|
log3.debug(
|
|
9436
|
-
`part=${item.partNumber}/${totalParts} put=${Math.round(tPut - t0)}ms size=${item.ciphertext.length}${hedgeCount > 0 ? `
|
|
9382
|
+
`part=${item.partNumber}/${totalParts} put=${Math.round(tPut - t0)}ms size=${item.ciphertext.length}${hedgeCount > 0 ? ` replaced\xD7${hedgeCount}` : ""}`
|
|
9437
9383
|
);
|
|
9438
9384
|
report("uploading");
|
|
9439
9385
|
} finally {
|
|
9440
9386
|
partsInFlight.delete(inFlight);
|
|
9441
|
-
|
|
9387
|
+
replace = () => {
|
|
9442
9388
|
};
|
|
9443
9389
|
if (hedgeTicker !== null) clearInterval(hedgeTicker);
|
|
9444
|
-
|
|
9445
|
-
for (const ctl of controllers) ctl.abort();
|
|
9446
|
-
for (const detach of detachFns) detach();
|
|
9390
|
+
current?.ctl.abort();
|
|
9447
9391
|
}
|
|
9448
9392
|
}
|
|
9449
9393
|
const controlFetch = (url, init3, timeoutMs) => policyFetch(url, init3, timeoutMs, runSignal);
|
|
@@ -9548,6 +9492,10 @@ async function multipartUploadStream(options) {
|
|
|
9548
9492
|
item.round = round;
|
|
9549
9493
|
item.flowsAtStart = runningParts.size;
|
|
9550
9494
|
let url = presignedUrlCache.get(item.partNumber);
|
|
9495
|
+
if (!url && presignPrefetchInFlight) {
|
|
9496
|
+
await presignPrefetchInFlight;
|
|
9497
|
+
url = presignedUrlCache.get(item.partNumber);
|
|
9498
|
+
}
|
|
9551
9499
|
presignedUrlCache.delete(item.partNumber);
|
|
9552
9500
|
schedulePresignPrefetch(item.partNumber + 1);
|
|
9553
9501
|
await retrying(
|
|
@@ -13772,7 +13720,7 @@ function proFileGetOutputToWire(out) {
|
|
|
13772
13720
|
}
|
|
13773
13721
|
|
|
13774
13722
|
// src/server.ts
|
|
13775
|
-
var SERVER_VERSION = "0.2.
|
|
13723
|
+
var SERVER_VERSION = "0.2.3";
|
|
13776
13724
|
var toolMeta = (name) => {
|
|
13777
13725
|
const { title, description, annotations } = seal_mcp_v1_default.tools[name];
|
|
13778
13726
|
return { title, description, annotations };
|
|
@@ -13840,7 +13788,7 @@ async function createServer(options) {
|
|
|
13840
13788
|
};
|
|
13841
13789
|
const mcp = new McpServer(
|
|
13842
13790
|
{ name: "sealnet-mcp", version: SERVER_VERSION },
|
|
13843
|
-
{ capabilities: { tools: {} } }
|
|
13791
|
+
{ capabilities: { tools: {} }, instructions: seal_mcp_v1_default.server_instructions.text }
|
|
13844
13792
|
);
|
|
13845
13793
|
const disableClipboard = process.env.SEAL_MCP_DISABLE_CLIPBOARD === "1";
|
|
13846
13794
|
mcp.registerTool(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sealnet-mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"mcpName": "net.seal/mcp",
|
|
5
5
|
"description": "Model Context Protocol server for SEAL — model never holds capability by default (handoff mode); explicit opt-in to forward mode with strict TTL/recipient policy.",
|
|
6
6
|
"type": "module",
|