@namzu/sdk 40.0.0 → 42.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/CHANGELOG.md +236 -0
- package/dist/agents/ReactiveAgent.d.ts.map +1 -1
- package/dist/agents/ReactiveAgent.js +3 -0
- package/dist/agents/ReactiveAgent.js.map +1 -1
- package/dist/agents/SupervisorAgent.d.ts.map +1 -1
- package/dist/agents/SupervisorAgent.js +11 -0
- package/dist/agents/SupervisorAgent.js.map +1 -1
- package/dist/agents/runAgent.d.ts +14 -0
- package/dist/agents/runAgent.d.ts.map +1 -1
- package/dist/agents/runAgent.js +3 -0
- package/dist/agents/runAgent.js.map +1 -1
- package/dist/bridge/a2a/mapper.d.ts.map +1 -1
- package/dist/bridge/a2a/mapper.js +8 -0
- package/dist/bridge/a2a/mapper.js.map +1 -1
- package/dist/bridge/sse/mapper.d.ts.map +1 -1
- package/dist/bridge/sse/mapper.js +11 -0
- package/dist/bridge/sse/mapper.js.map +1 -1
- package/dist/connector/index.d.ts +2 -2
- package/dist/connector/index.d.ts.map +1 -1
- package/dist/connector/index.js +1 -1
- package/dist/connector/index.js.map +1 -1
- package/dist/connector/mcp/adapter.d.ts.map +1 -1
- package/dist/connector/mcp/adapter.js +92 -4
- package/dist/connector/mcp/adapter.js.map +1 -1
- package/dist/connector/mcp/audio-admission.d.ts +17 -0
- package/dist/connector/mcp/audio-admission.d.ts.map +1 -0
- package/dist/connector/mcp/audio-admission.js +171 -0
- package/dist/connector/mcp/audio-admission.js.map +1 -0
- package/dist/connector/mcp/client.d.ts +252 -1
- package/dist/connector/mcp/client.d.ts.map +1 -1
- package/dist/connector/mcp/client.js +611 -39
- package/dist/connector/mcp/client.js.map +1 -1
- package/dist/connector/mcp/envelope.d.ts +91 -0
- package/dist/connector/mcp/envelope.d.ts.map +1 -0
- package/dist/connector/mcp/envelope.js +173 -0
- package/dist/connector/mcp/envelope.js.map +1 -0
- package/dist/connector/mcp/era.d.ts +130 -0
- package/dist/connector/mcp/era.d.ts.map +1 -0
- package/dist/connector/mcp/era.js +304 -0
- package/dist/connector/mcp/era.js.map +1 -0
- package/dist/connector/mcp/errors.d.ts +106 -0
- package/dist/connector/mcp/errors.d.ts.map +1 -0
- package/dist/connector/mcp/errors.js +154 -0
- package/dist/connector/mcp/errors.js.map +1 -0
- package/dist/connector/mcp/http-sse.d.ts +11 -0
- package/dist/connector/mcp/http-sse.d.ts.map +1 -1
- package/dist/connector/mcp/http-sse.js +21 -6
- package/dist/connector/mcp/http-sse.js.map +1 -1
- package/dist/connector/mcp/index.d.ts +7 -0
- package/dist/connector/mcp/index.d.ts.map +1 -1
- package/dist/connector/mcp/index.js +10 -0
- package/dist/connector/mcp/index.js.map +1 -1
- package/dist/connector/mcp/streamable-http.d.ts +83 -0
- package/dist/connector/mcp/streamable-http.d.ts.map +1 -1
- package/dist/connector/mcp/streamable-http.js +177 -11
- package/dist/connector/mcp/streamable-http.js.map +1 -1
- package/dist/connector/mcp/x-mcp-header.d.ts +56 -0
- package/dist/connector/mcp/x-mcp-header.d.ts.map +1 -0
- package/dist/connector/mcp/x-mcp-header.js +254 -0
- package/dist/connector/mcp/x-mcp-header.js.map +1 -0
- package/dist/constants/mcp/index.d.ts +123 -15
- package/dist/constants/mcp/index.d.ts.map +1 -1
- package/dist/constants/mcp/index.js +135 -16
- package/dist/constants/mcp/index.js.map +1 -1
- package/dist/manager/agent/lifecycle.d.ts.map +1 -1
- package/dist/manager/agent/lifecycle.js +43 -0
- package/dist/manager/agent/lifecycle.js.map +1 -1
- package/dist/prompt/coding-agent-doctrine.d.ts +20 -0
- package/dist/prompt/coding-agent-doctrine.d.ts.map +1 -1
- package/dist/prompt/coding-agent-doctrine.js +19 -3
- package/dist/prompt/coding-agent-doctrine.js.map +1 -1
- package/dist/prompt/index.d.ts +1 -1
- package/dist/prompt/index.d.ts.map +1 -1
- package/dist/prompt/index.js +1 -1
- package/dist/prompt/index.js.map +1 -1
- package/dist/public-runtime.d.ts +7 -4
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +16 -4
- package/dist/public-runtime.js.map +1 -1
- package/dist/public-tools.d.ts +1 -1
- package/dist/public-tools.d.ts.map +1 -1
- package/dist/public-tools.js +4 -2
- package/dist/public-tools.js.map +1 -1
- package/dist/registry/tool/execute.d.ts.map +1 -1
- package/dist/registry/tool/execute.js +10 -1
- package/dist/registry/tool/execute.js.map +1 -1
- package/dist/runtime/bidi/session.d.ts +11 -0
- package/dist/runtime/bidi/session.d.ts.map +1 -1
- package/dist/runtime/bidi/session.js +2 -0
- package/dist/runtime/bidi/session.js.map +1 -1
- package/dist/runtime/query/executor.d.ts +6 -0
- package/dist/runtime/query/executor.d.ts.map +1 -1
- package/dist/runtime/query/executor.js +6 -0
- package/dist/runtime/query/executor.js.map +1 -1
- package/dist/runtime/query/guardrail-presets.d.ts +187 -1
- package/dist/runtime/query/guardrail-presets.d.ts.map +1 -1
- package/dist/runtime/query/guardrail-presets.js +298 -0
- package/dist/runtime/query/guardrail-presets.js.map +1 -1
- package/dist/runtime/query/index.d.ts +14 -0
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +3 -0
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/runtime/query/tooling.d.ts +2 -0
- package/dist/runtime/query/tooling.d.ts.map +1 -1
- package/dist/runtime/query/tooling.js +3 -0
- package/dist/runtime/query/tooling.js.map +1 -1
- package/dist/sandbox/provider/local.d.ts.map +1 -1
- package/dist/sandbox/provider/local.js +46 -3
- package/dist/sandbox/provider/local.js.map +1 -1
- package/dist/scheduler/local.d.ts.map +1 -1
- package/dist/scheduler/local.js +8 -0
- package/dist/scheduler/local.js.map +1 -1
- package/dist/store/run/disk.d.ts +35 -1
- package/dist/store/run/disk.d.ts.map +1 -1
- package/dist/store/run/disk.js +100 -0
- package/dist/store/run/disk.js.map +1 -1
- package/dist/tools/coordinator/agent.d.ts.map +1 -1
- package/dist/tools/coordinator/agent.js +17 -2
- package/dist/tools/coordinator/agent.js.map +1 -1
- package/dist/tools/coordinator/index.d.ts.map +1 -1
- package/dist/tools/coordinator/index.js +17 -3
- package/dist/tools/coordinator/index.js.map +1 -1
- package/dist/tools/untrusted-envelope.d.ts +35 -0
- package/dist/tools/untrusted-envelope.d.ts.map +1 -1
- package/dist/tools/untrusted-envelope.js +91 -3
- package/dist/tools/untrusted-envelope.js.map +1 -1
- package/dist/types/agent/base.d.ts +23 -0
- package/dist/types/agent/base.d.ts.map +1 -1
- package/dist/types/agent/scheduler.d.ts +20 -0
- package/dist/types/agent/scheduler.d.ts.map +1 -1
- package/dist/types/agent/task.d.ts +39 -0
- package/dist/types/agent/task.d.ts.map +1 -1
- package/dist/types/connector/mcp.d.ts +205 -0
- package/dist/types/connector/mcp.d.ts.map +1 -1
- package/dist/types/run/events.d.ts +56 -0
- package/dist/types/run/events.d.ts.map +1 -1
- package/dist/types/run/events.js.map +1 -1
- package/dist/types/run/store.d.ts +41 -0
- package/dist/types/run/store.d.ts.map +1 -1
- package/dist/types/sandbox/index.d.ts +68 -1
- package/dist/types/sandbox/index.d.ts.map +1 -1
- package/dist/types/sandbox/index.js.map +1 -1
- package/dist/types/tool/index.d.ts +19 -0
- package/dist/types/tool/index.d.ts.map +1 -1
- package/dist/types/tool/index.js.map +1 -1
- package/package.json +1 -1
- package/src/agents/ReactiveAgent.ts +3 -0
- package/src/agents/SupervisorAgent.ts +11 -0
- package/src/agents/runAgent.ts +18 -0
- package/src/bridge/a2a/mapper.ts +8 -0
- package/src/bridge/sse/mapper.ts +11 -0
- package/src/connector/index.ts +27 -0
- package/src/connector/mcp/adapter.ts +103 -4
- package/src/connector/mcp/audio-admission.ts +173 -0
- package/src/connector/mcp/client.ts +694 -45
- package/src/connector/mcp/envelope.ts +235 -0
- package/src/connector/mcp/era.ts +400 -0
- package/src/connector/mcp/errors.ts +171 -0
- package/src/connector/mcp/http-sse.ts +23 -6
- package/src/connector/mcp/index.ts +37 -0
- package/src/connector/mcp/streamable-http.ts +199 -11
- package/src/connector/mcp/x-mcp-header.ts +322 -0
- package/src/constants/mcp/index.ts +145 -16
- package/src/manager/agent/lifecycle.ts +51 -0
- package/src/prompt/coding-agent-doctrine.ts +31 -4
- package/src/prompt/index.ts +1 -0
- package/src/public-runtime.ts +42 -0
- package/src/public-tools.ts +8 -2
- package/src/registry/tool/execute.ts +9 -1
- package/src/runtime/bidi/session.ts +13 -0
- package/src/runtime/query/executor.ts +13 -0
- package/src/runtime/query/guardrail-presets.ts +356 -0
- package/src/runtime/query/index.ts +17 -0
- package/src/runtime/query/tooling.ts +5 -0
- package/src/sandbox/provider/local.ts +45 -2
- package/src/scheduler/local.ts +8 -0
- package/src/store/run/disk.ts +108 -0
- package/src/tools/coordinator/agent.ts +17 -2
- package/src/tools/coordinator/index.ts +17 -3
- package/src/tools/untrusted-envelope.ts +94 -3
- package/src/types/agent/base.ts +24 -0
- package/src/types/agent/scheduler.ts +21 -0
- package/src/types/agent/task.ts +41 -0
- package/src/types/connector/mcp.ts +205 -1
- package/src/types/run/events.ts +56 -0
- package/src/types/run/store.ts +42 -0
- package/src/types/sandbox/index.ts +69 -1
- package/src/types/tool/index.ts +20 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import { JSON_RPC_METHOD_NOT_FOUND, MCP_LEGACY_VERSIONS, MCP_META_SERVER_INFO, MCP_MODERN_HTTP_FALLBACK_STATUSES, MCP_MODERN_VERSIONS, MCP_SUPPORTED_PROTOCOL_VERSIONS, } from '../../constants/mcp/index.js';
|
|
2
|
+
import { MCPHttpStatusError, MCPProtocolError, isHeaderMismatchError, isMissingRequiredClientCapabilityError, isUnsupportedProtocolVersionError, protocolErrorFromReply, } from './errors.js';
|
|
3
|
+
/**
|
|
4
|
+
* Is this the answer of a server that speaks the modern protocol?
|
|
5
|
+
*
|
|
6
|
+
* The spec is explicit that a fallback MUST NOT be keyed to one specific
|
|
7
|
+
* error code, because a legacy server refuses an unknown method with
|
|
8
|
+
* whatever its implementation happens to use — commonly `-32601`, commonly
|
|
9
|
+
* `-32602`, sometimes something else entirely, sometimes silence. So the
|
|
10
|
+
* question is never "was this `-32601`?"; it is "did the peer answer in a
|
|
11
|
+
* vocabulary only a modern server has?" — which is what these three codes
|
|
12
|
+
* are. Everything else, including a code this client has never seen, means
|
|
13
|
+
* fall back.
|
|
14
|
+
*/
|
|
15
|
+
export function isRecognizedModernError(error) {
|
|
16
|
+
return (isUnsupportedProtocolVersionError(error) ||
|
|
17
|
+
isMissingRequiredClientCapabilityError(error) ||
|
|
18
|
+
isHeaderMismatchError(error));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Read a failed HTTP response for evidence of a modern server.
|
|
22
|
+
*
|
|
23
|
+
* `400`, `404` and `405` are the statuses a legacy origin answers a modern
|
|
24
|
+
* request with — and also the statuses a MODERN origin uses for a request
|
|
25
|
+
* it understands but will not serve. The body decides. A `404` whose body
|
|
26
|
+
* is a JSON-RPC `-32601` is a modern server saying "no such method", which
|
|
27
|
+
* the spec calls out precisely so it is not mistaken for the `404` of an
|
|
28
|
+
* origin that has never heard of the protocol.
|
|
29
|
+
*
|
|
30
|
+
* `-32601` counts ONLY on a `404`. On a `400` or `405` it is an ordinary
|
|
31
|
+
* unimplemented-method answer that any server of any era can send, and
|
|
32
|
+
* reading it as proof of modernity there would strand this client on a
|
|
33
|
+
* legacy origin with no way back.
|
|
34
|
+
*/
|
|
35
|
+
export function classifyModernHttpFailure(status, bodyText) {
|
|
36
|
+
if (!MCP_MODERN_HTTP_FALLBACK_STATUSES.includes(status))
|
|
37
|
+
return { kind: 'legacy' };
|
|
38
|
+
let parsed;
|
|
39
|
+
try {
|
|
40
|
+
parsed = JSON.parse(bodyText);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// An HTML error page, an empty body, a proxy's plain-text notice:
|
|
44
|
+
// none of them are a server answering in JSON-RPC at all.
|
|
45
|
+
return { kind: 'legacy' };
|
|
46
|
+
}
|
|
47
|
+
if (typeof parsed !== 'object' || parsed === null)
|
|
48
|
+
return { kind: 'legacy' };
|
|
49
|
+
const error = parsed.error;
|
|
50
|
+
if (!error)
|
|
51
|
+
return { kind: 'legacy' };
|
|
52
|
+
const reason = protocolErrorFromReply(error);
|
|
53
|
+
if (isRecognizedModernError(reason))
|
|
54
|
+
return { kind: 'modern', error: reason };
|
|
55
|
+
if (status === 404 &&
|
|
56
|
+
reason instanceof MCPProtocolError &&
|
|
57
|
+
reason.code === JSON_RPC_METHOD_NOT_FOUND) {
|
|
58
|
+
return { kind: 'modern', error: reason };
|
|
59
|
+
}
|
|
60
|
+
return { kind: 'legacy' };
|
|
61
|
+
}
|
|
62
|
+
/** A cache that remembers nothing outside this object. */
|
|
63
|
+
export function createMcpEraCache() {
|
|
64
|
+
const entries = new Map();
|
|
65
|
+
return {
|
|
66
|
+
get: (key) => entries.get(key),
|
|
67
|
+
set: (key, era) => {
|
|
68
|
+
entries.set(key, era);
|
|
69
|
+
},
|
|
70
|
+
delete: (key) => {
|
|
71
|
+
entries.delete(key);
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The cache every `MCPClient` shares unless it was given its own.
|
|
77
|
+
*
|
|
78
|
+
* Process-wide on purpose: two clients reaching the same origin should not
|
|
79
|
+
* each pay a probe. Injectable on purpose too — a suite that shared this
|
|
80
|
+
* one would leak era state between cases and become order-dependent, which
|
|
81
|
+
* is the failure mode a conformance suite can least afford.
|
|
82
|
+
*/
|
|
83
|
+
export const defaultMcpEraCache = createMcpEraCache();
|
|
84
|
+
/**
|
|
85
|
+
* What a cached era belongs to: an HTTP origin, or a stdio process
|
|
86
|
+
* identity.
|
|
87
|
+
*
|
|
88
|
+
* Path and query are deliberately dropped from an HTTP URL. Era is a
|
|
89
|
+
* property of the server behind the origin, not of one endpoint on it, and
|
|
90
|
+
* keying per URL would re-probe every path of the same deployment.
|
|
91
|
+
*
|
|
92
|
+
* Two things the key deliberately does and does not fold together:
|
|
93
|
+
*
|
|
94
|
+
* - `streamable_http` and `streamable-http` are two spellings of ONE
|
|
95
|
+
* transport, so they key together. An origin probed under one spelling is
|
|
96
|
+
* the same origin under the other, and keying them apart would probe it
|
|
97
|
+
* twice and let one half of the process believe something the other half
|
|
98
|
+
* had already disproved.
|
|
99
|
+
* - `http-sse` keys APART from those two, on the same origin. It is the
|
|
100
|
+
* 2024-11-05 transport and is never probed at all, so it records a legacy
|
|
101
|
+
* era it never tested; a Streamable HTTP client reading that entry would
|
|
102
|
+
* skip its own probe on the strength of an answer nobody asked for.
|
|
103
|
+
*/
|
|
104
|
+
export function mcpEraCacheKey(transport) {
|
|
105
|
+
if (transport.type === 'stdio') {
|
|
106
|
+
// JSON rather than a joined string: an argument containing the
|
|
107
|
+
// separator would otherwise make two different commands share a key.
|
|
108
|
+
// `cwd` is part of the process identity because a relative command or
|
|
109
|
+
// script path resolves against it — `node ./dist/server.js` run in two
|
|
110
|
+
// directories is two servers, and they need not be the same revision.
|
|
111
|
+
// `env` is not: it is where credentials live, and a key is a string
|
|
112
|
+
// this process keeps in a Map for its lifetime.
|
|
113
|
+
return `stdio ${JSON.stringify([transport.cwd ?? '', transport.command, ...(transport.args ?? [])])}`;
|
|
114
|
+
}
|
|
115
|
+
const family = transport.type === 'http-sse' ? 'http-sse' : 'streamable-http';
|
|
116
|
+
try {
|
|
117
|
+
return `${family} ${new URL(transport.url).origin}`;
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// A URL this client cannot parse is one the transport will fail on
|
|
121
|
+
// anyway; keying by the raw string keeps this function total.
|
|
122
|
+
return `${family} ${transport.url}`;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const NEWEST_LEGACY = MCP_LEGACY_VERSIONS[0];
|
|
126
|
+
const NEWEST_MODERN = MCP_MODERN_VERSIONS[0];
|
|
127
|
+
const LEGACY_ERA = { kind: 'legacy', version: NEWEST_LEGACY };
|
|
128
|
+
function isModernVersion(version) {
|
|
129
|
+
return MCP_MODERN_VERSIONS.includes(version);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* The newest version both sides can speak, or `undefined` when there is
|
|
133
|
+
* none.
|
|
134
|
+
*
|
|
135
|
+
* Intersection, never "take the server's newest": offering a version this
|
|
136
|
+
* client has not implemented produces a malformed exchange later instead of
|
|
137
|
+
* a clean negotiation failure now.
|
|
138
|
+
*/
|
|
139
|
+
function newestMutuallySupported(offered) {
|
|
140
|
+
const mutual = offered.filter((version) => typeof version === 'string' && MCP_SUPPORTED_PROTOCOL_VERSIONS.includes(version));
|
|
141
|
+
// Every version is a `YYYY-MM-DD` literal, so lexicographic order is
|
|
142
|
+
// chronological order.
|
|
143
|
+
return mutual.sort().at(-1);
|
|
144
|
+
}
|
|
145
|
+
function supportedVersionsFrom(data) {
|
|
146
|
+
const supported = data?.supported;
|
|
147
|
+
return Array.isArray(supported) ? supported : [];
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Is this success reply actually a `DiscoverResult`?
|
|
151
|
+
*
|
|
152
|
+
* Strict on purpose. The spec says a `2xx` means modern, but a `2xx` whose
|
|
153
|
+
* body is not a discover result is not evidence of anything — it is a
|
|
154
|
+
* legacy server that answers unknown methods with `{}` rather than an
|
|
155
|
+
* error, and treating that as a modern origin would leave the client
|
|
156
|
+
* sending `_meta` to a peer that has never heard of it. A reply with no
|
|
157
|
+
* version list is not proof, so it is not taken as proof.
|
|
158
|
+
*/
|
|
159
|
+
function asDiscoverResult(result) {
|
|
160
|
+
if (typeof result !== 'object' || result === null)
|
|
161
|
+
return undefined;
|
|
162
|
+
const candidate = result;
|
|
163
|
+
if (!Array.isArray(candidate.supportedVersions))
|
|
164
|
+
return undefined;
|
|
165
|
+
if (candidate.supportedVersions.length === 0)
|
|
166
|
+
return undefined;
|
|
167
|
+
return candidate;
|
|
168
|
+
}
|
|
169
|
+
/** The server info a modern peer carries under the reserved `_meta` key. */
|
|
170
|
+
export function serverInfoFromDiscover(discover) {
|
|
171
|
+
const info = discover?._meta?.[MCP_META_SERVER_INFO];
|
|
172
|
+
if (typeof info !== 'object' || info === null)
|
|
173
|
+
return undefined;
|
|
174
|
+
const { name, version } = info;
|
|
175
|
+
if (typeof name !== 'string' || name.length === 0)
|
|
176
|
+
return undefined;
|
|
177
|
+
return typeof version === 'string' ? { name, version } : { name };
|
|
178
|
+
}
|
|
179
|
+
function disjointVersionsError(serverName, offered) {
|
|
180
|
+
const theirs = offered.length > 0 ? offered.map((v) => String(v)).join(', ') : '(none named)';
|
|
181
|
+
return new Error(`MCP server "${serverName}" supports no protocol version this client speaks ` +
|
|
182
|
+
`(server: ${theirs}; supported: ${MCP_SUPPORTED_PROTOCOL_VERSIONS.join(', ')}).`);
|
|
183
|
+
}
|
|
184
|
+
function classifyAnswer(answer, attempted, serverName) {
|
|
185
|
+
if (answer.kind === 'timeout')
|
|
186
|
+
return { kind: 'legacy' };
|
|
187
|
+
if (answer.kind === 'result') {
|
|
188
|
+
const discover = asDiscoverResult(answer.result);
|
|
189
|
+
if (!discover)
|
|
190
|
+
return { kind: 'legacy' };
|
|
191
|
+
const chosen = newestMutuallySupported(discover.supportedVersions ?? []);
|
|
192
|
+
if (chosen === undefined) {
|
|
193
|
+
return {
|
|
194
|
+
kind: 'refuse',
|
|
195
|
+
error: disjointVersionsError(serverName, discover.supportedVersions ?? []),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
// A discover result that lists only legacy revisions is a server
|
|
199
|
+
// telling us, in the modern vocabulary, that it wants the legacy
|
|
200
|
+
// handshake. Believe it rather than insisting on the era its
|
|
201
|
+
// answering `server/discover` implied.
|
|
202
|
+
if (!isModernVersion(chosen))
|
|
203
|
+
return { kind: 'legacy' };
|
|
204
|
+
if (chosen !== attempted)
|
|
205
|
+
return { kind: 'retry', version: chosen };
|
|
206
|
+
return { kind: 'modern', era: { kind: 'modern', version: chosen }, discover };
|
|
207
|
+
}
|
|
208
|
+
const { error } = answer;
|
|
209
|
+
if (isUnsupportedProtocolVersionError(error)) {
|
|
210
|
+
const offered = supportedVersionsFrom(error.data);
|
|
211
|
+
const chosen = newestMutuallySupported(offered);
|
|
212
|
+
if (chosen === undefined) {
|
|
213
|
+
return { kind: 'refuse', error: disjointVersionsError(serverName, offered) };
|
|
214
|
+
}
|
|
215
|
+
// The best both sides can do is a legacy revision, so stop probing and
|
|
216
|
+
// go and shake hands — the server named the era it wants.
|
|
217
|
+
if (!isModernVersion(chosen))
|
|
218
|
+
return { kind: 'legacy' };
|
|
219
|
+
// A server that refuses the very version it lists as supported is
|
|
220
|
+
// contradicting itself, and retrying the same version would be a
|
|
221
|
+
// round trip spent asking a question already answered. It answered in
|
|
222
|
+
// the modern vocabulary, so the era is settled at that version and
|
|
223
|
+
// the request that failed is somebody else's problem to retry.
|
|
224
|
+
if (chosen === attempted) {
|
|
225
|
+
return { kind: 'modern', era: { kind: 'modern', version: attempted } };
|
|
226
|
+
}
|
|
227
|
+
return { kind: 'retry', version: chosen };
|
|
228
|
+
}
|
|
229
|
+
// `-32021` and `-32020` are answers only a modern server can give: it
|
|
230
|
+
// understood the request and objected to its capabilities or its
|
|
231
|
+
// headers. The era is settled even though this particular probe failed.
|
|
232
|
+
if (isRecognizedModernError(error)) {
|
|
233
|
+
return { kind: 'modern', era: { kind: 'modern', version: attempted } };
|
|
234
|
+
}
|
|
235
|
+
if (error instanceof MCPHttpStatusError) {
|
|
236
|
+
const verdict = classifyModernHttpFailure(error.status, error.bodyText);
|
|
237
|
+
if (verdict.kind === 'legacy')
|
|
238
|
+
return { kind: 'legacy' };
|
|
239
|
+
if (isUnsupportedProtocolVersionError(verdict.error)) {
|
|
240
|
+
return classifyAnswer({ kind: 'error', error: verdict.error }, attempted, serverName);
|
|
241
|
+
}
|
|
242
|
+
return { kind: 'modern', era: { kind: 'modern', version: attempted } };
|
|
243
|
+
}
|
|
244
|
+
// A refused connection, a DNS failure, a malformed reply: none of these
|
|
245
|
+
// say anything about the era. Falling back means the legacy handshake
|
|
246
|
+
// meets the same failure and reports it in its own words, which is a
|
|
247
|
+
// better error than "the probe could not decide".
|
|
248
|
+
return { kind: 'legacy' };
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Decide which era a peer speaks, probing at most twice.
|
|
252
|
+
*
|
|
253
|
+
* Modern first, per the spec's own guidance and because the alternative is
|
|
254
|
+
* worse than a wasted round trip: a legacy server handed an era-ambiguous
|
|
255
|
+
* method processes it under legacy semantics and fails confusingly, where a
|
|
256
|
+
* probe fails cleanly. The cache makes the cost one round trip per origin
|
|
257
|
+
* or per command rather than one per connection.
|
|
258
|
+
*
|
|
259
|
+
* The two probes are NOT the same algorithm — an HTTP probe reads a status
|
|
260
|
+
* and a body, a stdio probe reads a reply or a silence — but both reduce to
|
|
261
|
+
* one {@link McpEraProbe} answer, so this state machine is written once and
|
|
262
|
+
* neither transport carries a copy of it.
|
|
263
|
+
*/
|
|
264
|
+
export async function resolveMcpEra(input) {
|
|
265
|
+
const { cache, key, probe, probeSupported, serverName } = input;
|
|
266
|
+
if (!probeSupported)
|
|
267
|
+
return { era: LEGACY_ERA, probes: 0, fromCache: false };
|
|
268
|
+
const cached = cache.get(key);
|
|
269
|
+
if (cached?.kind === 'legacy')
|
|
270
|
+
return { era: cached, probes: 0, fromCache: true };
|
|
271
|
+
const start = cached?.kind === 'modern' ? cached.version : NEWEST_MODERN;
|
|
272
|
+
let probes = 0;
|
|
273
|
+
const run = async (version) => {
|
|
274
|
+
probes++;
|
|
275
|
+
return classifyAnswer(await probe(version), version, serverName);
|
|
276
|
+
};
|
|
277
|
+
let outcome = await run(start);
|
|
278
|
+
// Exactly one retry, and only ever at a version drawn from BOTH the
|
|
279
|
+
// server's list and this client's. There is no loop here to run away.
|
|
280
|
+
if (outcome.kind === 'retry')
|
|
281
|
+
outcome = await run(outcome.version);
|
|
282
|
+
if (outcome.kind === 'retry')
|
|
283
|
+
outcome = { kind: 'legacy' };
|
|
284
|
+
if (outcome.kind === 'refuse')
|
|
285
|
+
throw outcome.error;
|
|
286
|
+
if (outcome.kind === 'modern') {
|
|
287
|
+
cache.set(key, outcome.era);
|
|
288
|
+
return {
|
|
289
|
+
era: outcome.era,
|
|
290
|
+
...(outcome.discover ? { discover: outcome.discover } : {}),
|
|
291
|
+
probes,
|
|
292
|
+
fromCache: false,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
// A cached modern answer that no longer holds is replaced rather than
|
|
296
|
+
// left in place to be believed again: a stale assumption costs exactly
|
|
297
|
+
// one probe, once, and the next connection goes straight to the legacy
|
|
298
|
+
// handshake. The version recorded on a legacy entry is only the one this
|
|
299
|
+
// client OFFERS — which revision a legacy connection settles on is
|
|
300
|
+
// decided by `initialize`, every time, and is never read from here.
|
|
301
|
+
cache.set(key, LEGACY_ERA);
|
|
302
|
+
return { era: LEGACY_ERA, probes, fromCache: false };
|
|
303
|
+
}
|
|
304
|
+
//# sourceMappingURL=era.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"era.js","sourceRoot":"","sources":["../../../src/connector/mcp/era.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { MCPInputRequest, MCPJsonRpcError } from '../../types/connector/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* A JSON-RPC error reply from an MCP peer, with its `code` and `data`
|
|
4
|
+
* preserved.
|
|
5
|
+
*
|
|
6
|
+
* `MCPClient.handleMessage` used to flatten every error reply into
|
|
7
|
+
* `new Error('MCP error {code}: {message}')`, which threw away the one
|
|
8
|
+
* thing a caller needs to react to it programmatically. Era negotiation
|
|
9
|
+
* reads `code === -32022` and `data.supported`; header recovery reads
|
|
10
|
+
* `-32020`; the capability path reads `-32021` and `data.requiredCapabilities`.
|
|
11
|
+
* None of that is recoverable from a formatted string.
|
|
12
|
+
*
|
|
13
|
+
* A subclass of `Error`, never a replacement: every existing catch site that
|
|
14
|
+
* treats the rejection as a plain `Error` keeps working unchanged, and
|
|
15
|
+
* `.message` keeps its original `MCP error {code}: {message}` text so no
|
|
16
|
+
* existing log line or string-matching test is disturbed.
|
|
17
|
+
*/
|
|
18
|
+
export declare class MCPProtocolError extends Error {
|
|
19
|
+
readonly code: number;
|
|
20
|
+
readonly data?: unknown;
|
|
21
|
+
constructor(code: number, message: string, data?: unknown);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A JSON-RPC error reply whose `code` was missing or not an integer.
|
|
25
|
+
*
|
|
26
|
+
* A well-formed peer never sends this; a malformed one must not be mistaken
|
|
27
|
+
* for a recognized protocol error, because era negotiation and the recovery
|
|
28
|
+
* paths key their fallback behaviour on exactly which modern error code (or
|
|
29
|
+
* none) came back. Named distinctly from `MCPProtocolError` so that no
|
|
30
|
+
* `is*Error` predicate below can ever match it.
|
|
31
|
+
*/
|
|
32
|
+
export declare class MCPMalformedErrorReplyError extends Error {
|
|
33
|
+
constructor(receivedCode: unknown, message: unknown);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* An HTTP response that was not a success, with the body it carried.
|
|
37
|
+
*
|
|
38
|
+
* The body is the reason this type exists. A status alone cannot tell a
|
|
39
|
+
* legacy origin apart from a modern one: a modern server answers an unknown
|
|
40
|
+
* method with `404` and a JSON-RPC `-32601` body specifically so a client
|
|
41
|
+
* can distinguish it from the `404` of a server that has never heard of the
|
|
42
|
+
* modern protocol. Discarding the body — which this transport used to do —
|
|
43
|
+
* makes that distinction unreachable and turns every `404` into a fallback.
|
|
44
|
+
*
|
|
45
|
+
* `.message` is unchanged from the plain `Error` this replaces, so existing
|
|
46
|
+
* logs and assertions that match on the text are undisturbed.
|
|
47
|
+
*/
|
|
48
|
+
export declare class MCPHttpStatusError extends Error {
|
|
49
|
+
readonly status: number;
|
|
50
|
+
readonly statusText: string;
|
|
51
|
+
readonly bodyText: string;
|
|
52
|
+
constructor(where: string, status: number, statusText: string, bodyText: string);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Build the rejection reason for a JSON-RPC error reply.
|
|
56
|
+
*
|
|
57
|
+
* The wire message is cast to `MCPJsonRpcMessage` at the transport boundary
|
|
58
|
+
* without validation (see `JSON.parse(...) as MCPJsonRpcMessage` in
|
|
59
|
+
* `stdio.ts`, `http-sse.ts`, `streamable-http.ts`), so `error.code` is only
|
|
60
|
+
* a `number` by declared type — a misbehaving peer can still send anything.
|
|
61
|
+
* Guarding here, once, keeps that distrust out of `handleMessage`.
|
|
62
|
+
*/
|
|
63
|
+
export declare function protocolErrorFromReply(error: MCPJsonRpcError): Error;
|
|
64
|
+
/** A modern server answered that it does not speak the requested protocol version. */
|
|
65
|
+
export declare function isUnsupportedProtocolVersionError(error: unknown): error is MCPProtocolError;
|
|
66
|
+
/** A modern server answered that this client lacks a capability the request required. */
|
|
67
|
+
export declare function isMissingRequiredClientCapabilityError(error: unknown): error is MCPProtocolError;
|
|
68
|
+
/** A modern server rejected a request's `Mcp-Param-*` headers as stale against its current schema. */
|
|
69
|
+
export declare function isHeaderMismatchError(error: unknown): error is MCPProtocolError;
|
|
70
|
+
/**
|
|
71
|
+
* A server answered that the resource, prompt or tool a request named does
|
|
72
|
+
* not exist — the current spec's `-32002`, or the older `-32602` a
|
|
73
|
+
* pre-2025-06-18 server may still use for the same condition (see
|
|
74
|
+
* {@link RESOURCE_NOT_FOUND_CODES}).
|
|
75
|
+
*/
|
|
76
|
+
export declare function isResourceNotFoundError(error: unknown): error is MCPProtocolError;
|
|
77
|
+
/**
|
|
78
|
+
* A result named a `resultType` this client does not recognize.
|
|
79
|
+
*
|
|
80
|
+
* The spec's own words: "A resultType of any value unrecognized by the
|
|
81
|
+
* client MUST be considered invalid." Accepting it silently would mean
|
|
82
|
+
* reading fields from a shape a future revision defines as if they meant
|
|
83
|
+
* what they mean today, or finding none and returning an empty result with
|
|
84
|
+
* no diagnostic. Refusing it is the only reading that MUST leaves open.
|
|
85
|
+
*/
|
|
86
|
+
export declare class MCPInvalidResultTypeError extends Error {
|
|
87
|
+
readonly resultType: unknown;
|
|
88
|
+
constructor(resultType: unknown);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* A tool call asked this client for input it has no way to supply.
|
|
92
|
+
*
|
|
93
|
+
* namzu declares `clientCapabilities: {}`, so MRTR rule 7 means a
|
|
94
|
+
* CONFORMING server never sends an `inputRequests` this client did not
|
|
95
|
+
* declare support for. This is the defensive path: a non-conforming
|
|
96
|
+
* server's demand, or a second `input_required` after the one automatic
|
|
97
|
+
* retry the spec allows for the `requestState`-only case. Carries the raw
|
|
98
|
+
* `inputRequests` so a caller — `mcpToolToToolDefinition`'s `execute`, or a
|
|
99
|
+
* host calling `MCPClient.callTool` directly — can name what was asked for
|
|
100
|
+
* without this class knowing what a `ToolResult` is.
|
|
101
|
+
*/
|
|
102
|
+
export declare class MCPInputRequiredError extends Error {
|
|
103
|
+
readonly inputRequests: readonly MCPInputRequest[];
|
|
104
|
+
constructor(inputRequests: readonly MCPInputRequest[]);
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/connector/mcp/errors.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAYtF;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;gBAEX,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO;CAMzD;AAED;;;;;;;;GAQG;AACH,qBAAa,2BAA4B,SAAQ,KAAK;gBACzC,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO;CAInD;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;gBAEb,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAO/E;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,eAAe,GAAG,KAAK,CAMpE;AAED,sFAAsF;AACtF,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAE3F;AAED,yFAAyF;AACzF,wBAAgB,sCAAsC,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAEhG;AAED,sGAAsG;AACtG,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAE/E;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAEjF;AAED;;;;;;;;GAQG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;IACnD,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;gBAEhB,UAAU,EAAE,OAAO;CAK/B;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAC/C,QAAQ,CAAC,aAAa,EAAE,SAAS,eAAe,EAAE,CAAA;gBAEtC,aAAa,EAAE,SAAS,eAAe,EAAE;CAUrD"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { RESOURCE_NOT_FOUND_CODES } from '../../constants/mcp/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* The 2026-07-28 error codes a modern MCP server answers with. Kept private
|
|
4
|
+
* to this module: callers narrow on the predicates below rather than
|
|
5
|
+
* comparing magic numbers, so era negotiation, header recovery and the
|
|
6
|
+
* capability path never need to know the numbers themselves.
|
|
7
|
+
*/
|
|
8
|
+
const UNSUPPORTED_PROTOCOL_VERSION_CODE = -32022;
|
|
9
|
+
const MISSING_REQUIRED_CLIENT_CAPABILITY_CODE = -32021;
|
|
10
|
+
const HEADER_MISMATCH_CODE = -32020;
|
|
11
|
+
/**
|
|
12
|
+
* A JSON-RPC error reply from an MCP peer, with its `code` and `data`
|
|
13
|
+
* preserved.
|
|
14
|
+
*
|
|
15
|
+
* `MCPClient.handleMessage` used to flatten every error reply into
|
|
16
|
+
* `new Error('MCP error {code}: {message}')`, which threw away the one
|
|
17
|
+
* thing a caller needs to react to it programmatically. Era negotiation
|
|
18
|
+
* reads `code === -32022` and `data.supported`; header recovery reads
|
|
19
|
+
* `-32020`; the capability path reads `-32021` and `data.requiredCapabilities`.
|
|
20
|
+
* None of that is recoverable from a formatted string.
|
|
21
|
+
*
|
|
22
|
+
* A subclass of `Error`, never a replacement: every existing catch site that
|
|
23
|
+
* treats the rejection as a plain `Error` keeps working unchanged, and
|
|
24
|
+
* `.message` keeps its original `MCP error {code}: {message}` text so no
|
|
25
|
+
* existing log line or string-matching test is disturbed.
|
|
26
|
+
*/
|
|
27
|
+
export class MCPProtocolError extends Error {
|
|
28
|
+
code;
|
|
29
|
+
data;
|
|
30
|
+
constructor(code, message, data) {
|
|
31
|
+
super(`MCP error ${code}: ${message}`);
|
|
32
|
+
this.name = 'MCPProtocolError';
|
|
33
|
+
this.code = code;
|
|
34
|
+
this.data = data;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* A JSON-RPC error reply whose `code` was missing or not an integer.
|
|
39
|
+
*
|
|
40
|
+
* A well-formed peer never sends this; a malformed one must not be mistaken
|
|
41
|
+
* for a recognized protocol error, because era negotiation and the recovery
|
|
42
|
+
* paths key their fallback behaviour on exactly which modern error code (or
|
|
43
|
+
* none) came back. Named distinctly from `MCPProtocolError` so that no
|
|
44
|
+
* `is*Error` predicate below can ever match it.
|
|
45
|
+
*/
|
|
46
|
+
export class MCPMalformedErrorReplyError extends Error {
|
|
47
|
+
constructor(receivedCode, message) {
|
|
48
|
+
super(`MCP error reply had a malformed code (${JSON.stringify(receivedCode)}): ${message}`);
|
|
49
|
+
this.name = 'MCPMalformedErrorReplyError';
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* An HTTP response that was not a success, with the body it carried.
|
|
54
|
+
*
|
|
55
|
+
* The body is the reason this type exists. A status alone cannot tell a
|
|
56
|
+
* legacy origin apart from a modern one: a modern server answers an unknown
|
|
57
|
+
* method with `404` and a JSON-RPC `-32601` body specifically so a client
|
|
58
|
+
* can distinguish it from the `404` of a server that has never heard of the
|
|
59
|
+
* modern protocol. Discarding the body — which this transport used to do —
|
|
60
|
+
* makes that distinction unreachable and turns every `404` into a fallback.
|
|
61
|
+
*
|
|
62
|
+
* `.message` is unchanged from the plain `Error` this replaces, so existing
|
|
63
|
+
* logs and assertions that match on the text are undisturbed.
|
|
64
|
+
*/
|
|
65
|
+
export class MCPHttpStatusError extends Error {
|
|
66
|
+
status;
|
|
67
|
+
statusText;
|
|
68
|
+
bodyText;
|
|
69
|
+
constructor(where, status, statusText, bodyText) {
|
|
70
|
+
super(`${where}: HTTP ${status}: ${statusText}`);
|
|
71
|
+
this.name = 'MCPHttpStatusError';
|
|
72
|
+
this.status = status;
|
|
73
|
+
this.statusText = statusText;
|
|
74
|
+
this.bodyText = bodyText;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Build the rejection reason for a JSON-RPC error reply.
|
|
79
|
+
*
|
|
80
|
+
* The wire message is cast to `MCPJsonRpcMessage` at the transport boundary
|
|
81
|
+
* without validation (see `JSON.parse(...) as MCPJsonRpcMessage` in
|
|
82
|
+
* `stdio.ts`, `http-sse.ts`, `streamable-http.ts`), so `error.code` is only
|
|
83
|
+
* a `number` by declared type — a misbehaving peer can still send anything.
|
|
84
|
+
* Guarding here, once, keeps that distrust out of `handleMessage`.
|
|
85
|
+
*/
|
|
86
|
+
export function protocolErrorFromReply(error) {
|
|
87
|
+
const code = error.code;
|
|
88
|
+
if (typeof code !== 'number' || !Number.isInteger(code)) {
|
|
89
|
+
return new MCPMalformedErrorReplyError(code, error.message);
|
|
90
|
+
}
|
|
91
|
+
return new MCPProtocolError(code, error.message, error.data);
|
|
92
|
+
}
|
|
93
|
+
/** A modern server answered that it does not speak the requested protocol version. */
|
|
94
|
+
export function isUnsupportedProtocolVersionError(error) {
|
|
95
|
+
return error instanceof MCPProtocolError && error.code === UNSUPPORTED_PROTOCOL_VERSION_CODE;
|
|
96
|
+
}
|
|
97
|
+
/** A modern server answered that this client lacks a capability the request required. */
|
|
98
|
+
export function isMissingRequiredClientCapabilityError(error) {
|
|
99
|
+
return error instanceof MCPProtocolError && error.code === MISSING_REQUIRED_CLIENT_CAPABILITY_CODE;
|
|
100
|
+
}
|
|
101
|
+
/** A modern server rejected a request's `Mcp-Param-*` headers as stale against its current schema. */
|
|
102
|
+
export function isHeaderMismatchError(error) {
|
|
103
|
+
return error instanceof MCPProtocolError && error.code === HEADER_MISMATCH_CODE;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* A server answered that the resource, prompt or tool a request named does
|
|
107
|
+
* not exist — the current spec's `-32002`, or the older `-32602` a
|
|
108
|
+
* pre-2025-06-18 server may still use for the same condition (see
|
|
109
|
+
* {@link RESOURCE_NOT_FOUND_CODES}).
|
|
110
|
+
*/
|
|
111
|
+
export function isResourceNotFoundError(error) {
|
|
112
|
+
return error instanceof MCPProtocolError && RESOURCE_NOT_FOUND_CODES.includes(error.code);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* A result named a `resultType` this client does not recognize.
|
|
116
|
+
*
|
|
117
|
+
* The spec's own words: "A resultType of any value unrecognized by the
|
|
118
|
+
* client MUST be considered invalid." Accepting it silently would mean
|
|
119
|
+
* reading fields from a shape a future revision defines as if they meant
|
|
120
|
+
* what they mean today, or finding none and returning an empty result with
|
|
121
|
+
* no diagnostic. Refusing it is the only reading that MUST leaves open.
|
|
122
|
+
*/
|
|
123
|
+
export class MCPInvalidResultTypeError extends Error {
|
|
124
|
+
resultType;
|
|
125
|
+
constructor(resultType) {
|
|
126
|
+
super(`MCP result carried an unrecognized resultType: ${JSON.stringify(resultType)}`);
|
|
127
|
+
this.name = 'MCPInvalidResultTypeError';
|
|
128
|
+
this.resultType = resultType;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* A tool call asked this client for input it has no way to supply.
|
|
133
|
+
*
|
|
134
|
+
* namzu declares `clientCapabilities: {}`, so MRTR rule 7 means a
|
|
135
|
+
* CONFORMING server never sends an `inputRequests` this client did not
|
|
136
|
+
* declare support for. This is the defensive path: a non-conforming
|
|
137
|
+
* server's demand, or a second `input_required` after the one automatic
|
|
138
|
+
* retry the spec allows for the `requestState`-only case. Carries the raw
|
|
139
|
+
* `inputRequests` so a caller — `mcpToolToToolDefinition`'s `execute`, or a
|
|
140
|
+
* host calling `MCPClient.callTool` directly — can name what was asked for
|
|
141
|
+
* without this class knowing what a `ToolResult` is.
|
|
142
|
+
*/
|
|
143
|
+
export class MCPInputRequiredError extends Error {
|
|
144
|
+
inputRequests;
|
|
145
|
+
constructor(inputRequests) {
|
|
146
|
+
const methods = inputRequests.map((request) => request.method);
|
|
147
|
+
super(methods.length > 0
|
|
148
|
+
? `MCP tool call requires input this client cannot supply: ${methods.join(', ')}`
|
|
149
|
+
: 'MCP tool call requires input this client cannot supply');
|
|
150
|
+
this.name = 'MCPInputRequiredError';
|
|
151
|
+
this.inputRequests = inputRequests;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/connector/mcp/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,8 @@ export declare class HttpSseTransport implements MCPTransport {
|
|
|
13
13
|
private postUrl;
|
|
14
14
|
private log;
|
|
15
15
|
private readonly timeoutMs;
|
|
16
|
+
/** Defaults to the ambient global `fetch`; never read again once captured. */
|
|
17
|
+
private readonly fetchImpl;
|
|
16
18
|
constructor(config: MCPHttpSseTransportConfig, log?: Logger);
|
|
17
19
|
connect(): Promise<void>;
|
|
18
20
|
close(): Promise<void>;
|
|
@@ -31,6 +33,15 @@ export declare class HttpSseTransport implements MCPTransport {
|
|
|
31
33
|
onClose(handler: () => void): void;
|
|
32
34
|
onError(handler: (error: Error) => void): void;
|
|
33
35
|
isConnected(): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* `extra` comes from `MCPTransportSendOptions.headers` — the client's
|
|
38
|
+
* per-send authority — and is merged over this transport's own static
|
|
39
|
+
* config headers so a caller's value wins on a collision. See
|
|
40
|
+
* {@link StreamableHttpTransport}'s method of the same name, which this
|
|
41
|
+
* mirrors; the HTTP-SSE POST had no equivalent merge until now, so a
|
|
42
|
+
* per-request header or bearer token silently never reached the wire.
|
|
43
|
+
*/
|
|
44
|
+
private buildHeaders;
|
|
34
45
|
private beginSend;
|
|
35
46
|
private assertCurrent;
|
|
36
47
|
private isCurrent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-sse.d.ts","sourceRoot":"","sources":["../../../src/connector/mcp/http-sse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"http-sse.d.ts","sourceRoot":"","sources":["../../../src/connector/mcp/http-sse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEX,yBAAyB,EACzB,iBAAiB,EACjB,YAAY,EACZ,uBAAuB,EACvB,MAAM,gCAAgC,CAAA;AAEvC,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,uBAAuB,CAAA;AAqBlE,qBAAa,gBAAiB,YAAW,YAAY;IAgBnD,OAAO,CAAC,QAAQ,CAAC,MAAM;IAfxB,OAAO,CAAC,eAAe,CAAkD;IACzE,OAAO,CAAC,aAAa,CAAwB;IAC7C,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,eAAe,CAA+B;IACtD,OAAO,CAAC,UAAU,CAAI;IACtB,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,GAAG,CAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,8EAA8E;IAC9E,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;gBAGtB,MAAM,EAAE,yBAAyB,EAClD,GAAG,CAAC,EAAE,MAAM;IAaP,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAUxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAa5B;;;;;;;;OAQG;IACH,OAAO,CAAC,aAAa;IAMf,IAAI,CAAC,OAAO,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IA2CxF,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,GAAG,IAAI;IAI9D,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI;IAIlC,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAI9C,WAAW,IAAI,OAAO;IAItB;;;;;;;OAOG;IACH,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,SAAS;IAyBjB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,SAAS;YAIH,QAAQ;YAUR,SAAS;CA+CvB"}
|