@novorb/mcp-core 2.1.1 → 3.0.0
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/README.md +82 -161
- package/bin/mcp-core-jest.mjs +112 -0
- package/dist/auth.d.ts +57 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +74 -0
- package/dist/auth.js.map +1 -0
- package/dist/bootstrap.d.ts +129 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +206 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/client-input.d.ts +72 -0
- package/dist/client-input.d.ts.map +1 -0
- package/dist/client-input.js +109 -0
- package/dist/client-input.js.map +1 -0
- package/dist/credential-checks.d.ts +80 -0
- package/dist/credential-checks.d.ts.map +1 -0
- package/dist/credential-checks.js +189 -0
- package/dist/credential-checks.js.map +1 -0
- package/dist/credential-health.d.ts +12 -0
- package/dist/credential-health.d.ts.map +1 -0
- package/dist/credential-health.js +12 -0
- package/dist/credential-health.js.map +1 -0
- package/dist/credential-report.d.ts +46 -0
- package/dist/credential-report.d.ts.map +1 -0
- package/dist/credential-report.js +135 -0
- package/dist/credential-report.js.map +1 -0
- package/dist/credential-status-tool.d.ts +20 -0
- package/dist/credential-status-tool.d.ts.map +1 -0
- package/dist/credential-status-tool.js +33 -0
- package/dist/credential-status-tool.js.map +1 -0
- package/dist/credentials.d.ts +288 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +652 -0
- package/dist/credentials.js.map +1 -0
- package/dist/express-peers.d.ts +29 -0
- package/dist/express-peers.d.ts.map +1 -0
- package/dist/express-peers.js +36 -0
- package/dist/express-peers.js.map +1 -0
- package/dist/express.d.ts +74 -0
- package/dist/express.d.ts.map +1 -0
- package/dist/express.js +164 -0
- package/dist/express.js.map +1 -0
- package/dist/http-client.d.ts +278 -43
- package/dist/http-client.d.ts.map +1 -1
- package/dist/http-client.js +620 -182
- package/dist/http-client.js.map +1 -1
- package/dist/index.d.ts +27 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +49 -10
- package/dist/index.js.map +1 -1
- package/dist/limits.d.ts +28 -0
- package/dist/limits.d.ts.map +1 -0
- package/dist/limits.js +37 -0
- package/dist/limits.js.map +1 -0
- package/dist/list-pagination.d.ts +41 -0
- package/dist/list-pagination.d.ts.map +1 -0
- package/dist/list-pagination.js +104 -0
- package/dist/list-pagination.js.map +1 -0
- package/dist/net.d.ts +112 -0
- package/dist/net.d.ts.map +1 -0
- package/dist/net.js +490 -0
- package/dist/net.js.map +1 -0
- package/dist/notifications.d.ts +78 -0
- package/dist/notifications.d.ts.map +1 -0
- package/dist/notifications.js +173 -0
- package/dist/notifications.js.map +1 -0
- package/dist/pagination.d.ts +236 -5
- package/dist/pagination.d.ts.map +1 -1
- package/dist/pagination.js +393 -6
- package/dist/pagination.js.map +1 -1
- package/dist/prompts.d.ts +70 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +109 -0
- package/dist/prompts.js.map +1 -0
- package/dist/protocol-errors.d.ts +15 -0
- package/dist/protocol-errors.d.ts.map +1 -0
- package/dist/protocol-errors.js +28 -0
- package/dist/protocol-errors.js.map +1 -0
- package/dist/protocol-logging.d.ts +37 -0
- package/dist/protocol-logging.d.ts.map +1 -0
- package/dist/protocol-logging.js +77 -0
- package/dist/protocol-logging.js.map +1 -0
- package/dist/rate-limiter.d.ts +36 -0
- package/dist/rate-limiter.d.ts.map +1 -0
- package/dist/rate-limiter.js +79 -0
- package/dist/rate-limiter.js.map +1 -0
- package/dist/request-state.d.ts +74 -0
- package/dist/request-state.d.ts.map +1 -0
- package/dist/request-state.js +190 -0
- package/dist/request-state.js.map +1 -0
- package/dist/resources.d.ts +181 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +302 -0
- package/dist/resources.js.map +1 -0
- package/dist/result-limits.d.ts +80 -0
- package/dist/result-limits.d.ts.map +1 -0
- package/dist/result-limits.js +248 -0
- package/dist/result-limits.js.map +1 -0
- package/dist/retry.d.ts +79 -23
- package/dist/retry.d.ts.map +1 -1
- package/dist/retry.js +170 -57
- package/dist/retry.js.map +1 -1
- package/dist/sdk/client-stdio.d.ts +6 -0
- package/dist/sdk/client-stdio.d.ts.map +1 -0
- package/dist/sdk/client-stdio.js +6 -0
- package/dist/sdk/client-stdio.js.map +1 -0
- package/dist/sdk/client.d.ts +6 -0
- package/dist/sdk/client.d.ts.map +1 -0
- package/dist/sdk/client.js +6 -0
- package/dist/sdk/client.js.map +1 -0
- package/dist/sdk/express.d.ts +3 -0
- package/dist/sdk/express.d.ts.map +1 -0
- package/dist/sdk/express.js +11 -0
- package/dist/sdk/express.js.map +1 -0
- package/dist/sdk/node.d.ts +6 -0
- package/dist/sdk/node.d.ts.map +1 -0
- package/dist/sdk/node.js +6 -0
- package/dist/sdk/node.js.map +1 -0
- package/dist/sdk/server-stdio.d.ts +6 -0
- package/dist/sdk/server-stdio.d.ts.map +1 -0
- package/dist/sdk/server-stdio.js +6 -0
- package/dist/sdk/server-stdio.js.map +1 -0
- package/dist/sdk/server.d.ts +6 -0
- package/dist/sdk/server.d.ts.map +1 -0
- package/dist/sdk/server.js +6 -0
- package/dist/sdk/server.js.map +1 -0
- package/dist/server.d.ts +88 -36
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +98 -44
- package/dist/server.js.map +1 -1
- package/dist/task-request.d.ts +20 -0
- package/dist/task-request.d.ts.map +1 -0
- package/dist/task-request.js +43 -0
- package/dist/task-request.js.map +1 -0
- package/dist/task-store.d.ts +230 -0
- package/dist/task-store.d.ts.map +1 -0
- package/dist/task-store.js +459 -0
- package/dist/task-store.js.map +1 -0
- package/dist/task-tools.d.ts +115 -0
- package/dist/task-tools.d.ts.map +1 -0
- package/dist/task-tools.js +397 -0
- package/dist/task-tools.js.map +1 -0
- package/dist/testing/client.d.ts +25 -0
- package/dist/testing/client.d.ts.map +1 -0
- package/dist/testing/client.js +11 -0
- package/dist/testing/client.js.map +1 -0
- package/dist/testing/in-memory.d.ts +26 -0
- package/dist/testing/in-memory.d.ts.map +1 -0
- package/dist/testing/in-memory.js +41 -0
- package/dist/testing/in-memory.js.map +1 -0
- package/dist/testing/index.d.ts +20 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +20 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/isolated-dirs.d.ts +27 -0
- package/dist/testing/isolated-dirs.d.ts.map +1 -0
- package/dist/testing/isolated-dirs.js +67 -0
- package/dist/testing/isolated-dirs.js.map +1 -0
- package/dist/testing/logs.d.ts +61 -0
- package/dist/testing/logs.d.ts.map +1 -0
- package/dist/testing/logs.js +113 -0
- package/dist/testing/logs.js.map +1 -0
- package/dist/testing/raw-http.d.ts +25 -0
- package/dist/testing/raw-http.d.ts.map +1 -0
- package/dist/testing/raw-http.js +41 -0
- package/dist/testing/raw-http.js.map +1 -0
- package/dist/testing/raw-peer.d.ts +43 -0
- package/dist/testing/raw-peer.d.ts.map +1 -0
- package/dist/testing/raw-peer.js +101 -0
- package/dist/testing/raw-peer.js.map +1 -0
- package/dist/testing/recording-server.d.ts +38 -0
- package/dist/testing/recording-server.d.ts.map +1 -0
- package/dist/testing/recording-server.js +38 -0
- package/dist/testing/recording-server.js.map +1 -0
- package/dist/testing/server-process.d.ts +76 -0
- package/dist/testing/server-process.d.ts.map +1 -0
- package/dist/testing/server-process.js +241 -0
- package/dist/testing/server-process.js.map +1 -0
- package/dist/testing/tools.d.ts +53 -0
- package/dist/testing/tools.d.ts.map +1 -0
- package/dist/testing/tools.js +98 -0
- package/dist/testing/tools.js.map +1 -0
- package/dist/testing/unit.d.ts +52 -0
- package/dist/testing/unit.d.ts.map +1 -0
- package/dist/testing/unit.js +95 -0
- package/dist/testing/unit.js.map +1 -0
- package/dist/tools.d.ts +205 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +370 -0
- package/dist/tools.js.map +1 -0
- package/dist/transport.d.ts +144 -53
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +305 -122
- package/dist/transport.js.map +1 -1
- package/dist/url-path.d.ts +49 -0
- package/dist/url-path.d.ts.map +1 -0
- package/dist/url-path.js +165 -0
- package/dist/url-path.js.map +1 -0
- package/dist/utils/dataStore.d.ts +143 -0
- package/dist/utils/dataStore.d.ts.map +1 -0
- package/dist/utils/dataStore.js +429 -0
- package/dist/utils/dataStore.js.map +1 -0
- package/dist/utils/envLoader.d.ts +129 -0
- package/dist/utils/envLoader.d.ts.map +1 -0
- package/dist/utils/envLoader.js +399 -0
- package/dist/utils/envLoader.js.map +1 -0
- package/dist/utils/logger.d.ts +181 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +664 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/redact.d.ts +50 -0
- package/dist/utils/redact.d.ts.map +1 -0
- package/dist/utils/redact.js +318 -0
- package/dist/utils/redact.js.map +1 -0
- package/docs/api-reference.md +29 -0
- package/docs/building-a-server.md +63 -0
- package/docs/credentials.md +131 -0
- package/docs/data-store.md +37 -0
- package/docs/env.md +38 -0
- package/docs/features.md +28 -0
- package/docs/http-client.md +116 -0
- package/docs/logger.md +100 -0
- package/docs/migrating-to-v3.md +45 -0
- package/docs/outbound-urls.md +104 -0
- package/docs/pagination.md +45 -0
- package/docs/protocol-features.md +62 -0
- package/docs/resources-prompts-tasks.md +95 -0
- package/docs/sdk.md +33 -0
- package/docs/server.md +68 -0
- package/docs/testing-harness.md +139 -0
- package/docs/testing.md +151 -0
- package/docs/tools.md +88 -0
- package/docs/transport.md +85 -0
- package/examples/testing/tools.integration.test.example.ts +312 -0
- package/examples/testing/tools.unit.test.example.ts +149 -0
- package/package.json +140 -18
- package/dist/logger.d.ts +0 -80
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js +0 -236
- package/dist/logger.js.map +0 -1
package/dist/net.js
ADDED
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @novorb/mcp-core - Guarded outbound fetch (server-side request forgery guard)
|
|
3
|
+
*
|
|
4
|
+
* The one way an MCP server fetches a URL it did not configure itself: a URL from a tool argument, or a
|
|
5
|
+
* URL an upstream API handed back (a download link, a thumbnail, an avatar).
|
|
6
|
+
*
|
|
7
|
+
* - http(s) only, no userinfo, optionally only on `allowedOrigins`.
|
|
8
|
+
* - Public addresses only (`isPublicAddress`), unless the caller opts in with `allowPrivate: true`. An IP
|
|
9
|
+
* literal is checked before anything is sent; a DNS name is checked INSIDE the socket's lookup, on
|
|
10
|
+
* every address it resolves to, so the socket can only connect to an address that passed (no
|
|
11
|
+
* check-then-connect gap, a rebinding name cannot slip through).
|
|
12
|
+
* - Every request gets its own agent (keep-alive off), never Node's global agent: with
|
|
13
|
+
* `NODE_USE_ENV_PROXY` + `HTTP(S)_PROXY` the global agent would hand the request to a proxy, which
|
|
14
|
+
* resolves the name itself and skips the guarded lookup.
|
|
15
|
+
* - Redirects are refused by default; with `redirects: <n>` at most n are followed and every hop is
|
|
16
|
+
* validated again by the same rules (scheme, userinfo, origins, addresses). Caller headers are dropped
|
|
17
|
+
* when a redirect changes origin.
|
|
18
|
+
* - Size cap (declared and streamed), one total time cap (headers and body), the caller's abort signal,
|
|
19
|
+
* and an optional allow-list of content types.
|
|
20
|
+
*
|
|
21
|
+
* const res = await guardedFetch(url, { allowedOrigins: ['https://cdn.example.com'], maxBytes, signal });
|
|
22
|
+
* const bytes = Buffer.from(await res.arrayBuffer());
|
|
23
|
+
*/
|
|
24
|
+
import { lookup as dnsLookup } from 'node:dns';
|
|
25
|
+
import { Agent as HttpAgent, request as httpRequest } from 'node:http';
|
|
26
|
+
import { Agent as HttpsAgent, request as httpsRequest } from 'node:https';
|
|
27
|
+
import { isIP } from 'node:net';
|
|
28
|
+
/** The error code of an address the policy refused (on the URL literal or in the socket lookup). */
|
|
29
|
+
export const ADDRESS_BLOCKED_CODE = 'ERR_ADDRESS_BLOCKED';
|
|
30
|
+
/** A refused or failed guarded fetch. The message never carries the URL (callers add it if they want). */
|
|
31
|
+
export class GuardedFetchError extends Error {
|
|
32
|
+
reason;
|
|
33
|
+
/** `ERR_ADDRESS_BLOCKED` for the address policy, the socket error code for a network error. */
|
|
34
|
+
code;
|
|
35
|
+
/** The HTTP status of a refused redirect. */
|
|
36
|
+
status;
|
|
37
|
+
constructor(reason, message, details = {}) {
|
|
38
|
+
super(message);
|
|
39
|
+
this.name = 'GuardedFetchError';
|
|
40
|
+
this.reason = reason;
|
|
41
|
+
if (details.code !== undefined)
|
|
42
|
+
this.code = details.code;
|
|
43
|
+
if (details.status !== undefined)
|
|
44
|
+
this.status = details.status;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const DEFAULT_MAX_BYTES = 50 * 1024 * 1024;
|
|
48
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
49
|
+
const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);
|
|
50
|
+
const NULL_BODY_STATUSES = new Set([204, 205, 304]);
|
|
51
|
+
const PRIVATE_LITERAL = 'the host is a private, loopback or link-local address';
|
|
52
|
+
const PRIVATE_NAME = 'the host resolves to a private, loopback or link-local address';
|
|
53
|
+
/** The four bytes of a dotted-quad IPv4 address, or undefined. */
|
|
54
|
+
function parseIPv4(text) {
|
|
55
|
+
if (isIP(text) !== 4)
|
|
56
|
+
return undefined;
|
|
57
|
+
return text.split('.').map(Number);
|
|
58
|
+
}
|
|
59
|
+
/** The sixteen bytes of an IPv6 address (zone id dropped, a dotted IPv4 tail allowed), or undefined. */
|
|
60
|
+
function parseIPv6(text) {
|
|
61
|
+
const address = text.split('%')[0];
|
|
62
|
+
if (isIP(address) !== 6)
|
|
63
|
+
return undefined;
|
|
64
|
+
let body = address;
|
|
65
|
+
const tail = [];
|
|
66
|
+
if (body.includes('.')) {
|
|
67
|
+
const cut = body.lastIndexOf(':') + 1;
|
|
68
|
+
const v4 = parseIPv4(body.slice(cut));
|
|
69
|
+
if (!v4)
|
|
70
|
+
return undefined;
|
|
71
|
+
tail.push((v4[0] << 8) | v4[1], (v4[2] << 8) | v4[3]);
|
|
72
|
+
body = body.slice(0, cut);
|
|
73
|
+
if (!body.endsWith('::'))
|
|
74
|
+
body = body.slice(0, -1);
|
|
75
|
+
}
|
|
76
|
+
const halves = body.split('::');
|
|
77
|
+
const words = (part) => (part === '' ? [] : part.split(':').map((w) => Number.parseInt(w, 16)));
|
|
78
|
+
const left = words(halves[0]);
|
|
79
|
+
const right = halves.length > 1 ? words(halves[1]) : [];
|
|
80
|
+
const fill = 8 - tail.length - left.length - right.length;
|
|
81
|
+
const all = halves.length > 1 ? [...left, ...new Array(fill).fill(0), ...right, ...tail] : [...left, ...tail];
|
|
82
|
+
if (all.length !== 8)
|
|
83
|
+
return undefined;
|
|
84
|
+
return all.flatMap((w) => [w >> 8, w & 0xff]);
|
|
85
|
+
}
|
|
86
|
+
/** Whether `bytes` lies in `prefix/bits` (prefix given as bytes, missing bytes zero). */
|
|
87
|
+
function inRange(bytes, prefix, bits) {
|
|
88
|
+
for (let i = 0; i < bits; i += 1) {
|
|
89
|
+
const byte = i >> 3;
|
|
90
|
+
const mask = 0x80 >> (i & 7);
|
|
91
|
+
if (((bytes[byte] ?? 0) & mask) !== ((prefix[byte] ?? 0) & mask))
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
/** IPv4 ranges that are not globally reachable (RFC 6890 and its updates). */
|
|
97
|
+
const BLOCKED_V4 = [
|
|
98
|
+
[[0], 8], // this network
|
|
99
|
+
[[10], 8], // private
|
|
100
|
+
[[100, 64], 10], // carrier-grade NAT
|
|
101
|
+
[[127], 8], // loopback
|
|
102
|
+
[[169, 254], 16], // link-local, cloud metadata
|
|
103
|
+
[[172, 16], 12], // private
|
|
104
|
+
[[192, 0, 0], 24], // IETF protocol assignments
|
|
105
|
+
[[192, 0, 2], 24], // documentation
|
|
106
|
+
[[192, 31, 196], 24], // AS112
|
|
107
|
+
[[192, 52, 193], 24], // AMT
|
|
108
|
+
[[192, 88, 99], 24], // 6to4 relay anycast
|
|
109
|
+
[[192, 168], 16], // private
|
|
110
|
+
[[192, 175, 48], 24], // AS112
|
|
111
|
+
[[198, 18], 15], // benchmarking
|
|
112
|
+
[[198, 51, 100], 24], // documentation
|
|
113
|
+
[[203, 0, 113], 24], // documentation
|
|
114
|
+
[[224], 4], // multicast
|
|
115
|
+
[[240], 4], // reserved, broadcast
|
|
116
|
+
];
|
|
117
|
+
function isPublicV4(bytes) {
|
|
118
|
+
return !BLOCKED_V4.some(([prefix, bits]) => inRange(bytes, prefix, bits));
|
|
119
|
+
}
|
|
120
|
+
/** IPv6 ranges inside global unicast (2000::/3) that are not globally reachable or embed another address. */
|
|
121
|
+
const BLOCKED_V6 = [
|
|
122
|
+
[[0x20, 0x01, 0x00, 0x00], 23], // IETF protocol assignments (Teredo, ORCHID, benchmarking)
|
|
123
|
+
[[0x20, 0x01, 0x0d, 0xb8], 32], // documentation
|
|
124
|
+
[[0x3f, 0xff], 20], // documentation
|
|
125
|
+
];
|
|
126
|
+
function isPublicV6(bytes) {
|
|
127
|
+
const embedded = (from) => isPublicV4(bytes.slice(from, from + 4));
|
|
128
|
+
// ::ffff:a.b.c.d (IPv4-mapped) and 64:ff9b::a.b.c.d (NAT64) reach the embedded IPv4 address.
|
|
129
|
+
if (inRange(bytes, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff], 96))
|
|
130
|
+
return embedded(12);
|
|
131
|
+
if (inRange(bytes, [0x00, 0x64, 0xff, 0x9b], 96))
|
|
132
|
+
return embedded(12);
|
|
133
|
+
// 2002:a.b.c.d::/48 (6to4) tunnels to the embedded IPv4 address.
|
|
134
|
+
if (inRange(bytes, [0x20, 0x02], 16))
|
|
135
|
+
return embedded(2);
|
|
136
|
+
// Only global unicast is public: this drops ::, ::1, ::a.b.c.d, 100::/64, fc00::/7, fe80::/10, fec0::/10, ff00::/8.
|
|
137
|
+
if (!inRange(bytes, [0x20], 3))
|
|
138
|
+
return false;
|
|
139
|
+
return !BLOCKED_V6.some(([prefix, bits]) => inRange(bytes, prefix, bits));
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Whether an IP address is globally reachable. False for loopback, private, link-local (including the
|
|
143
|
+
* cloud metadata address), CGNAT, multicast, reserved and documentation ranges, IPv6 unique local and
|
|
144
|
+
* site-local, the IPv6 forms that embed such an IPv4 address (mapped, compatible, NAT64, 6to4), and for
|
|
145
|
+
* anything that is not an IP address.
|
|
146
|
+
*/
|
|
147
|
+
export function isPublicAddress(address) {
|
|
148
|
+
const v4 = parseIPv4(address);
|
|
149
|
+
if (v4)
|
|
150
|
+
return isPublicV4(v4);
|
|
151
|
+
const v6 = parseIPv6(address);
|
|
152
|
+
return v6 !== undefined && isPublicV6(v6);
|
|
153
|
+
}
|
|
154
|
+
/** The address policy the options select: the custom one, everything (`allowPrivate`), or public only. */
|
|
155
|
+
export function addressPolicy(options = {}) {
|
|
156
|
+
if (options.isAllowedAddress)
|
|
157
|
+
return options.isAllowedAddress;
|
|
158
|
+
if (options.allowPrivate === true)
|
|
159
|
+
return () => true;
|
|
160
|
+
return isPublicAddress;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Normalise origin entries (a comma-separated string or a list; blanks dropped, duplicates removed) to
|
|
164
|
+
* WHATWG origins. Throws a TypeError naming `label` when an entry is not an http(s) URL.
|
|
165
|
+
*/
|
|
166
|
+
export function normalizeOrigins(entries, label = 'allowedOrigins') {
|
|
167
|
+
const list = typeof entries === 'string' ? entries.split(',') : entries;
|
|
168
|
+
const out = [];
|
|
169
|
+
for (const entry of list.map((e) => e.trim()).filter((e) => e !== '')) {
|
|
170
|
+
let origin;
|
|
171
|
+
try {
|
|
172
|
+
const parsed = new URL(entry);
|
|
173
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:')
|
|
174
|
+
throw new Error('scheme');
|
|
175
|
+
origin = parsed.origin;
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
throw new TypeError(`${label}: every entry must be an http(s) origin`);
|
|
179
|
+
}
|
|
180
|
+
if (!out.includes(origin))
|
|
181
|
+
out.push(origin);
|
|
182
|
+
}
|
|
183
|
+
return out;
|
|
184
|
+
}
|
|
185
|
+
/** The URL's host as an address (IPv6 brackets dropped), or undefined for a DNS name. */
|
|
186
|
+
function literalAddress(parsed) {
|
|
187
|
+
const host = parsed.hostname.startsWith('[') ? parsed.hostname.slice(1, -1) : parsed.hostname;
|
|
188
|
+
return isIP(host) ? host : undefined;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* The parsed URL when it may be fetched: http(s), no userinfo, on an allowed origin (when given), and not
|
|
192
|
+
* an IP literal outside the address policy. Throws `GuardedFetchError` otherwise. A DNS name is checked
|
|
193
|
+
* later, inside the socket lookup.
|
|
194
|
+
*/
|
|
195
|
+
export function checkUrl(url, options = {}) {
|
|
196
|
+
let parsed;
|
|
197
|
+
try {
|
|
198
|
+
parsed = new URL(String(url));
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
throw new GuardedFetchError('url', 'invalid URL');
|
|
202
|
+
}
|
|
203
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
|
204
|
+
throw new GuardedFetchError('protocol', 'only http and https URLs are supported');
|
|
205
|
+
}
|
|
206
|
+
if (parsed.username !== '' || parsed.password !== '') {
|
|
207
|
+
throw new GuardedFetchError('credentials', 'credentials in the URL are not allowed');
|
|
208
|
+
}
|
|
209
|
+
if (options.allowedOrigins !== undefined && !normalizeOrigins(options.allowedOrigins).includes(parsed.origin)) {
|
|
210
|
+
throw new GuardedFetchError('origin', `origin ${parsed.origin} is not allowed`);
|
|
211
|
+
}
|
|
212
|
+
const literal = literalAddress(parsed);
|
|
213
|
+
if (literal !== undefined && !addressPolicy(options)(literal)) {
|
|
214
|
+
throw new GuardedFetchError('address', PRIVATE_LITERAL, { code: ADDRESS_BLOCKED_CODE });
|
|
215
|
+
}
|
|
216
|
+
return parsed;
|
|
217
|
+
}
|
|
218
|
+
/** A socket lookup that refuses the name when it resolves to no address or any address fails the policy. */
|
|
219
|
+
export function guardedLookup(base, isAllowedAddress) {
|
|
220
|
+
return (hostname, options, callback) => {
|
|
221
|
+
base(hostname, { ...options, all: true }, (error, result) => {
|
|
222
|
+
if (error) {
|
|
223
|
+
callback(error, '', 4);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const addresses = Array.isArray(result)
|
|
227
|
+
? result
|
|
228
|
+
: [{ address: result, family: isIP(result) || 4 }];
|
|
229
|
+
if (addresses.length === 0 || addresses.some((a) => !isAllowedAddress(a.address))) {
|
|
230
|
+
callback(Object.assign(new Error(PRIVATE_NAME), { code: ADDRESS_BLOCKED_CODE }), '', 4);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if (options.all)
|
|
234
|
+
callback(null, addresses);
|
|
235
|
+
else
|
|
236
|
+
callback(null, addresses[0].address, addresses[0].family);
|
|
237
|
+
});
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* A fresh agent (keep-alive off) for `protocol` whose sockets resolve through `guardedLookup`. Pass it as
|
|
242
|
+
* the `agent` of every `http.request` / `https.request` to a caller-supplied URL (after `checkUrl`, which
|
|
243
|
+
* covers IP literals: Node never calls the lookup for them), and destroy it when the request settles.
|
|
244
|
+
* It never reads the proxy environment, unlike the global agent.
|
|
245
|
+
*/
|
|
246
|
+
export function createGuardedAgent(protocol, options = {}) {
|
|
247
|
+
const lookup = guardedLookup(options.lookup ?? dnsLookup, addressPolicy(options));
|
|
248
|
+
return protocol === 'https:'
|
|
249
|
+
? new HttpsAgent({ keepAlive: false, lookup })
|
|
250
|
+
: new HttpAgent({ keepAlive: false, lookup });
|
|
251
|
+
}
|
|
252
|
+
/** Whether a socket error is (or, wrapped by multi-address connect, contains) the lookup refusal. */
|
|
253
|
+
function isBlocked(error) {
|
|
254
|
+
if (!error || typeof error !== 'object')
|
|
255
|
+
return false;
|
|
256
|
+
if (error.code === ADDRESS_BLOCKED_CODE)
|
|
257
|
+
return true;
|
|
258
|
+
const nested = error.errors;
|
|
259
|
+
return Array.isArray(nested) && nested.some(isBlocked);
|
|
260
|
+
}
|
|
261
|
+
function networkError(error) {
|
|
262
|
+
if (isBlocked(error))
|
|
263
|
+
return new GuardedFetchError('address', PRIVATE_NAME, { code: ADDRESS_BLOCKED_CODE });
|
|
264
|
+
const code = error?.code;
|
|
265
|
+
const name = typeof code === 'string' ? code : 'ERR_NETWORK';
|
|
266
|
+
return new GuardedFetchError('network', `network error (${name})`, { code: name });
|
|
267
|
+
}
|
|
268
|
+
/** The reason the internal signal aborted (a timeout or the caller), as a GuardedFetchError. */
|
|
269
|
+
function abortReason(signal) {
|
|
270
|
+
return signal.reason instanceof GuardedFetchError ? signal.reason : new GuardedFetchError('aborted', 'aborted');
|
|
271
|
+
}
|
|
272
|
+
function tooLarge(maxBytes) {
|
|
273
|
+
return new GuardedFetchError('too-large', `body exceeds ${maxBytes} bytes`);
|
|
274
|
+
}
|
|
275
|
+
/** One request on its own guarded agent; resolves with the response head. */
|
|
276
|
+
function sendHop(url, method, headers, options, signal) {
|
|
277
|
+
if (signal.aborted)
|
|
278
|
+
return Promise.reject(abortReason(signal));
|
|
279
|
+
const agent = createGuardedAgent(url.protocol === 'https:' ? 'https:' : 'http:', options);
|
|
280
|
+
const lookup = guardedLookup(options.lookup ?? dnsLookup, addressPolicy(options));
|
|
281
|
+
return new Promise((resolve, reject) => {
|
|
282
|
+
let settled = false;
|
|
283
|
+
let req;
|
|
284
|
+
const onAbort = () => fail(abortReason(signal));
|
|
285
|
+
const fail = (error) => {
|
|
286
|
+
if (settled)
|
|
287
|
+
return;
|
|
288
|
+
settled = true;
|
|
289
|
+
signal.removeEventListener('abort', onAbort);
|
|
290
|
+
req?.destroy();
|
|
291
|
+
agent.destroy();
|
|
292
|
+
reject(error);
|
|
293
|
+
};
|
|
294
|
+
const send = url.protocol === 'https:' ? httpsRequest : httpRequest;
|
|
295
|
+
try {
|
|
296
|
+
req = send(url, { method, agent, lookup, ...(headers ? { headers } : {}) }, (res) => {
|
|
297
|
+
if (settled) {
|
|
298
|
+
res.resume();
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
settled = true;
|
|
302
|
+
signal.removeEventListener('abort', onAbort);
|
|
303
|
+
resolve({ res, agent });
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
fail(networkError(error));
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
// Stays attached for the life of the request, so a late socket error is never unhandled.
|
|
311
|
+
req.on('error', (error) => fail(networkError(error)));
|
|
312
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
313
|
+
req.end();
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
function contentTypeAllowed(essence, allowed) {
|
|
317
|
+
return allowed.some((entry) => {
|
|
318
|
+
const want = entry.trim().toLowerCase();
|
|
319
|
+
return want.endsWith('/*') ? essence.startsWith(want.slice(0, -1)) : essence === want;
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
function toHeaders(res) {
|
|
323
|
+
const headers = new Headers();
|
|
324
|
+
for (const [name, value] of Object.entries(res.headers)) {
|
|
325
|
+
if (value === undefined)
|
|
326
|
+
continue;
|
|
327
|
+
for (const item of Array.isArray(value) ? value : [value]) {
|
|
328
|
+
try {
|
|
329
|
+
headers.append(name, item);
|
|
330
|
+
}
|
|
331
|
+
catch {
|
|
332
|
+
// A header value fetch's Headers refuses is dropped, never fatal.
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return headers;
|
|
337
|
+
}
|
|
338
|
+
/** The fetch `Response` over a guarded response head; the body keeps the size and time caps. */
|
|
339
|
+
function toResponse(hop, url, redirected, method, maxBytes, signal, release) {
|
|
340
|
+
const { res, agent } = hop;
|
|
341
|
+
const status = res.statusCode ?? 0;
|
|
342
|
+
let finished = false;
|
|
343
|
+
let onAbort = () => undefined;
|
|
344
|
+
const done = () => {
|
|
345
|
+
if (finished)
|
|
346
|
+
return;
|
|
347
|
+
finished = true;
|
|
348
|
+
signal.removeEventListener('abort', onAbort);
|
|
349
|
+
release();
|
|
350
|
+
agent.destroy();
|
|
351
|
+
};
|
|
352
|
+
let body = null;
|
|
353
|
+
if (method === 'HEAD' || NULL_BODY_STATUSES.has(status)) {
|
|
354
|
+
res.resume();
|
|
355
|
+
done();
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
body = new ReadableStream({
|
|
359
|
+
start(controller) {
|
|
360
|
+
let size = 0;
|
|
361
|
+
const fail = (error) => {
|
|
362
|
+
if (finished)
|
|
363
|
+
return;
|
|
364
|
+
done();
|
|
365
|
+
res.destroy();
|
|
366
|
+
controller.error(error);
|
|
367
|
+
};
|
|
368
|
+
onAbort = () => fail(abortReason(signal));
|
|
369
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
370
|
+
res.on('data', (chunk) => {
|
|
371
|
+
if (finished)
|
|
372
|
+
return;
|
|
373
|
+
size += chunk.length;
|
|
374
|
+
if (size > maxBytes)
|
|
375
|
+
fail(tooLarge(maxBytes));
|
|
376
|
+
else
|
|
377
|
+
controller.enqueue(new Uint8Array(chunk));
|
|
378
|
+
});
|
|
379
|
+
res.on('end', () => {
|
|
380
|
+
if (finished)
|
|
381
|
+
return;
|
|
382
|
+
done();
|
|
383
|
+
controller.close();
|
|
384
|
+
});
|
|
385
|
+
res.on('error', (error) => fail(networkError(error)));
|
|
386
|
+
},
|
|
387
|
+
cancel() {
|
|
388
|
+
done();
|
|
389
|
+
res.destroy();
|
|
390
|
+
},
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
const response = new Response(body, { status, statusText: res.statusMessage ?? '', headers: toHeaders(res) });
|
|
394
|
+
Object.defineProperty(response, 'url', { value: url.href });
|
|
395
|
+
Object.defineProperty(response, 'redirected', { value: redirected });
|
|
396
|
+
return response;
|
|
397
|
+
}
|
|
398
|
+
/** A cap option as a finite number at least `min`; a TypeError naming the option otherwise. */
|
|
399
|
+
function requireCap(name, value, min) {
|
|
400
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || value < min) {
|
|
401
|
+
throw new TypeError(`guardedFetch: ${name} must be a finite number >= ${min}`);
|
|
402
|
+
}
|
|
403
|
+
return value;
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Fetch a caller- or upstream-supplied URL under the guard (see the module header). Resolves with a fetch
|
|
407
|
+
* `Response` for any final status (the caller decides what a 404 means); with redirects refused every
|
|
408
|
+
* 3xx is refused. Its body stays under `maxBytes` and the time cap. Rejects with `GuardedFetchError` when
|
|
409
|
+
* the guard refuses or the transfer fails, and with a `TypeError` for a non-finite or negative cap.
|
|
410
|
+
*/
|
|
411
|
+
export async function guardedFetch(input, options = {}) {
|
|
412
|
+
const method = options.method ?? 'GET';
|
|
413
|
+
const redirects = options.redirects ?? 'refuse';
|
|
414
|
+
// A non-finite or negative cap would silently disable it (`hop >= NaN` is never true): refuse it.
|
|
415
|
+
if (redirects !== 'refuse')
|
|
416
|
+
requireCap('redirects', redirects, 0);
|
|
417
|
+
const maxRedirects = redirects === 'refuse' ? 0 : Math.floor(redirects);
|
|
418
|
+
const maxBytes = requireCap('maxBytes', options.maxBytes ?? DEFAULT_MAX_BYTES, 0);
|
|
419
|
+
const timeoutMs = requireCap('timeoutMs', options.timeoutMs ?? DEFAULT_TIMEOUT_MS, 1);
|
|
420
|
+
const urlOptions = {
|
|
421
|
+
...options,
|
|
422
|
+
...(options.allowedOrigins !== undefined ? { allowedOrigins: normalizeOrigins(options.allowedOrigins) } : {}),
|
|
423
|
+
};
|
|
424
|
+
let current = checkUrl(input, urlOptions);
|
|
425
|
+
if (options.signal?.aborted)
|
|
426
|
+
throw new GuardedFetchError('aborted', 'aborted');
|
|
427
|
+
const controller = new AbortController();
|
|
428
|
+
const timer = setTimeout(() => controller.abort(new GuardedFetchError('timeout', `timed out after ${timeoutMs} ms`)), timeoutMs);
|
|
429
|
+
const onCallerAbort = () => controller.abort(new GuardedFetchError('aborted', 'aborted'));
|
|
430
|
+
options.signal?.addEventListener('abort', onCallerAbort, { once: true });
|
|
431
|
+
const release = () => {
|
|
432
|
+
clearTimeout(timer);
|
|
433
|
+
options.signal?.removeEventListener('abort', onCallerAbort);
|
|
434
|
+
};
|
|
435
|
+
let headers = options.headers;
|
|
436
|
+
try {
|
|
437
|
+
for (let hop = 0;; hop++) {
|
|
438
|
+
const sent = await sendHop(current, method, headers, options, controller.signal);
|
|
439
|
+
const { res, agent } = sent;
|
|
440
|
+
const status = res.statusCode ?? 0;
|
|
441
|
+
const refuse = (error) => {
|
|
442
|
+
res.resume();
|
|
443
|
+
agent.destroy();
|
|
444
|
+
throw error;
|
|
445
|
+
};
|
|
446
|
+
const location = res.headers.location;
|
|
447
|
+
// With redirects refused every 3xx is refused (as the gitlab original), with or without Location.
|
|
448
|
+
if (redirects === 'refuse' && status >= 300 && status < 400) {
|
|
449
|
+
refuse(new GuardedFetchError('redirect', `${status} redirect not followed`, { status }));
|
|
450
|
+
}
|
|
451
|
+
if (REDIRECT_STATUSES.has(status) && location) {
|
|
452
|
+
if (hop >= maxRedirects)
|
|
453
|
+
refuse(new GuardedFetchError('redirects', `more than ${maxRedirects} redirects`, { status }));
|
|
454
|
+
let next;
|
|
455
|
+
try {
|
|
456
|
+
next = checkUrl(new URL(location, current), urlOptions);
|
|
457
|
+
}
|
|
458
|
+
catch (error) {
|
|
459
|
+
return refuse(error instanceof GuardedFetchError ? error : new GuardedFetchError('url', 'invalid URL'));
|
|
460
|
+
}
|
|
461
|
+
res.resume();
|
|
462
|
+
agent.destroy();
|
|
463
|
+
// Never carry caller headers (credentials) to another origin.
|
|
464
|
+
if (next.origin !== current.origin)
|
|
465
|
+
headers = undefined;
|
|
466
|
+
current = next;
|
|
467
|
+
continue;
|
|
468
|
+
}
|
|
469
|
+
if (status < 200 || status > 599)
|
|
470
|
+
refuse(new GuardedFetchError('network', `network error (invalid status ${status})`));
|
|
471
|
+
if (status < 300 && options.allowedContentTypes !== undefined) {
|
|
472
|
+
const essence = (res.headers['content-type'] ?? '').split(';')[0].trim().toLowerCase();
|
|
473
|
+
const passes = essence === ''
|
|
474
|
+
? options.allowMissingContentType === true
|
|
475
|
+
: contentTypeAllowed(essence, options.allowedContentTypes);
|
|
476
|
+
if (!passes)
|
|
477
|
+
refuse(new GuardedFetchError('content-type', `content type ${essence || '(none)'} is not allowed`));
|
|
478
|
+
}
|
|
479
|
+
const declared = Number(res.headers['content-length']);
|
|
480
|
+
if (Number.isFinite(declared) && declared > maxBytes)
|
|
481
|
+
refuse(tooLarge(maxBytes));
|
|
482
|
+
return toResponse(sent, current, hop > 0, method, maxBytes, controller.signal, release);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
catch (error) {
|
|
486
|
+
release();
|
|
487
|
+
throw error instanceof GuardedFetchError ? error : networkError(error);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
//# sourceMappingURL=net.js.map
|
package/dist/net.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"net.js","sourceRoot":"","sources":["../src/net.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @novorb/mcp-core - Change notifications (list changed, resource updated) and the server event bus
|
|
3
|
+
*
|
|
4
|
+
* The SDK sources change events from a `ServerEventBus` (`publish` / `subscribe`): `createMcpHandler`
|
|
5
|
+
* serves 2026-07-28 `subscriptions/listen` streams from it (ack, filtering and subscription ids are the
|
|
6
|
+
* SDK's). mcp-core makes that bus process-wide and connects it to every transport, so one call reaches
|
|
7
|
+
* every connection this process serves:
|
|
8
|
+
*
|
|
9
|
+
* const notify = createNotifier(); // or ctx.notify in runMcpServer's setup
|
|
10
|
+
* notify.toolsChanged(); // notifications/tools/list_changed
|
|
11
|
+
* notify.resourceUpdated('gitlab://repo/README.md');
|
|
12
|
+
*
|
|
13
|
+
* Delivery per era (what the SDK can carry; mcp-core adds no transport of its own):
|
|
14
|
+
*
|
|
15
|
+
* | Connection | Delivery |
|
|
16
|
+
* |---|---|
|
|
17
|
+
* | HTTP, 2026-07-28 | `subscriptions/listen` SSE streams on this process (the SDK listen router filters by the client's honored filter) |
|
|
18
|
+
* | stdio, 2026-07-28 | the pinned instance's change notifications, rewritten by the SDK onto the connection's open subscriptions |
|
|
19
|
+
* | stdio, 2025-era | unsolicited notifications on the connection; `resources/updated` only for URIs the client subscribed to |
|
|
20
|
+
* | HTTP, 2025-era stateless | none: every request is answered by a fresh instance and the standalone GET stream is 405, so there is no channel |
|
|
21
|
+
*
|
|
22
|
+
* Multi-instance hosts replace the in-memory bus with a shared one (`setProcessBus`, or `bus` on the
|
|
23
|
+
* transport options). A shared `ServerEventBus` implementation must: fan `publish(event)` out to the
|
|
24
|
+
* listeners of EVERY instance (its own included); return an idempotent unsubscribe from `subscribe`;
|
|
25
|
+
* never throw from `publish` (a failing listener must not stop the others); never echo an event back
|
|
26
|
+
* to the listener that published it from inside that listener; and carry the event value as is
|
|
27
|
+
* (`{ kind }` or `{ kind: 'resource_updated', uri }`, JSON-serialisable). No persistence or replay is
|
|
28
|
+
* needed: listen streams are live and a client re-lists after reconnecting. Events are not addressed to
|
|
29
|
+
* a caller: every open stream that opted in receives them (the SDK event has no principal).
|
|
30
|
+
*/
|
|
31
|
+
import { McpServer, type Server, type ServerEventBus, type ServerNotifier } from '@modelcontextprotocol/server';
|
|
32
|
+
export type { ServerEvent, ServerEventBus, ServerNotifier } from '@modelcontextprotocol/server';
|
|
33
|
+
export { InMemoryServerEventBus } from '@modelcontextprotocol/server';
|
|
34
|
+
/** The process-wide bus every mcp-core transport uses by default (in memory unless replaced). */
|
|
35
|
+
export declare function processBus(): ServerEventBus;
|
|
36
|
+
/**
|
|
37
|
+
* Replace the process bus (a shared pub/sub on multi-instance hosts). Call it before starting the
|
|
38
|
+
* transport; `undefined` restores a fresh in-memory bus on next use.
|
|
39
|
+
*/
|
|
40
|
+
export declare function setProcessBus(bus: ServerEventBus | undefined): void;
|
|
41
|
+
/** The typed publish facade over a bus (the same shape as the SDK's `handler.notify`). */
|
|
42
|
+
export declare function createNotifier(bus?: ServerEventBus): ServerNotifier;
|
|
43
|
+
/** The URIs a 2025-era client subscribed to on this instance (`resources/subscribe`). */
|
|
44
|
+
export declare function resourceSubscriptions(server: McpServer | Server): Set<string>;
|
|
45
|
+
/**
|
|
46
|
+
* Forward bus events to a long-lived instance (a stdio connection): each event becomes the instance's
|
|
47
|
+
* own change notification. Detaches when the instance closes; returns the detach function. A send that
|
|
48
|
+
* fails (not connected, capability not advertised) is dropped: notifications never fail the server.
|
|
49
|
+
*/
|
|
50
|
+
export declare function attachNotifications(server: McpServer | Server, era: 'legacy' | 'modern', bus?: ServerEventBus): () => void;
|
|
51
|
+
/** The kinds of primitive a runtime surface can enable or disable. */
|
|
52
|
+
export type SurfaceKind = 'tool' | 'prompt' | 'resource';
|
|
53
|
+
export interface RuntimeSurface {
|
|
54
|
+
/** Whether `name` is enabled (everything is, until disabled). */
|
|
55
|
+
isEnabled(kind: SurfaceKind, name: string): boolean;
|
|
56
|
+
/** Enable `name` and publish the matching list-changed event (no-op when already enabled). */
|
|
57
|
+
enable(kind: SurfaceKind, name: string): void;
|
|
58
|
+
/** Disable `name` and publish the matching list-changed event (no-op when already disabled). */
|
|
59
|
+
disable(kind: SurfaceKind, name: string): void;
|
|
60
|
+
/** Observe changes (registerTools / registerResources / registerPrompts use it); returns unsubscribe. */
|
|
61
|
+
subscribe(listener: (kind: SurfaceKind, name: string, enabled: boolean) => void): () => void;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Process-level enable/disable state for tools, prompts and resources, so a runtime change works the
|
|
65
|
+
* same in both serving models: per-request HTTP instances read it when they are built, live stdio
|
|
66
|
+
* instances have their SDK handles toggled in place, and ONE list-changed event goes out on the bus.
|
|
67
|
+
* Pass it as `surface` to `registerTools` / `registerResources` / `registerPrompts`.
|
|
68
|
+
*/
|
|
69
|
+
export declare function createRuntimeSurface(notifier?: ServerNotifier): RuntimeSurface;
|
|
70
|
+
/**
|
|
71
|
+
* Bind one SDK handle (a registered tool, prompt, resource or template) to a surface: its `enabled`
|
|
72
|
+
* flag follows the surface, set directly so the instance itself sends no list-changed notification
|
|
73
|
+
* (the surface publishes exactly one on the bus). The binding is released when the instance closes.
|
|
74
|
+
*/
|
|
75
|
+
export declare function bindToSurface(server: McpServer, surface: RuntimeSurface, kind: SurfaceKind, name: string, handle: {
|
|
76
|
+
enabled: boolean;
|
|
77
|
+
}): void;
|
|
78
|
+
//# sourceMappingURL=notifications.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAEL,SAAS,EACT,KAAK,MAAM,EAEX,KAAK,cAAc,EACnB,KAAK,cAAc,EACpB,MAAM,8BAA8B,CAAC;AAGtC,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAChG,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAQtE,iGAAiG;AACjG,wBAAgB,UAAU,IAAI,cAAc,CAG3C;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,SAAS,GAAG,IAAI,CAEnE;AAED,0FAA0F;AAC1F,wBAAgB,cAAc,CAAC,GAAG,GAAE,cAA6B,GAAG,cAAc,CAOjF;AAUD,yFAAyF;AACzF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAI7E;AAiBD;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,GAAG,MAAM,EAC1B,GAAG,EAAE,QAAQ,GAAG,QAAQ,EACxB,GAAG,GAAE,cAA6B,GACjC,MAAM,IAAI,CAqBZ;AAED,sEAAsE;AACtE,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEzD,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACpD,8FAA8F;IAC9F,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,gGAAgG;IAChG,OAAO,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C,yGAAyG;IACzG,SAAS,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAC9F;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,GAAE,cAAiC,GAAG,cAAc,CA4BhG;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GAC3B,IAAI,CAWN"}
|