@mastra/mcp 1.17.0-alpha.0 → 1.17.0-alpha.2
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 +100 -0
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/types.d.ts +29 -0
- package/dist/client/types.d.ts.map +1 -1
- package/dist/docs/SKILL.md +3 -3
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/{docs-server-auth-fga.md → docs-auth-fga.md} +27 -1
- package/dist/docs/references/{docs-mcp-overview.md → docs-connections-mcp.md} +1 -1
- package/dist/docs/references/docs-connections-overview.md +5 -5
- package/dist/docs/references/reference-editor-tools.md +1 -1
- package/dist/docs/references/reference-tools-mcp-client.md +2 -0
- package/dist/docs/references/reference-tools-mcp-server.md +97 -4
- package/dist/index.cjs +330 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +333 -62
- package/dist/index.js.map +1 -1
- package/dist/server/mrtrElicitation.d.ts +39 -0
- package/dist/server/mrtrElicitation.d.ts.map +1 -0
- package/dist/server/promptActions.d.ts +8 -1
- package/dist/server/promptActions.d.ts.map +1 -1
- package/dist/server/resourceActions.d.ts +8 -1
- package/dist/server/resourceActions.d.ts.map +1 -1
- package/dist/server/server.d.ts +86 -18
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/toolActions.d.ts +8 -1
- package/dist/server/toolActions.d.ts.map +1 -1
- package/dist/server/types.d.ts +29 -1
- package/dist/server/types.d.ts.map +1 -1
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -5031,7 +5031,7 @@ const allowsEval = /* @__PURE__*/ cached(() => {
|
|
|
5031
5031
|
return false;
|
|
5032
5032
|
}
|
|
5033
5033
|
});
|
|
5034
|
-
function isPlainObject(o) {
|
|
5034
|
+
function isPlainObject$1(o) {
|
|
5035
5035
|
if (isObject(o) === false) return false;
|
|
5036
5036
|
const ctor = o.constructor;
|
|
5037
5037
|
if (ctor === void 0) return true;
|
|
@@ -5042,7 +5042,7 @@ function isPlainObject(o) {
|
|
|
5042
5042
|
return true;
|
|
5043
5043
|
}
|
|
5044
5044
|
function shallowClone(o) {
|
|
5045
|
-
if (isPlainObject(o)) return { ...o };
|
|
5045
|
+
if (isPlainObject$1(o)) return { ...o };
|
|
5046
5046
|
if (Array.isArray(o)) return [...o];
|
|
5047
5047
|
if (o instanceof Map) return new Map(o);
|
|
5048
5048
|
if (o instanceof Set) return new Set(o);
|
|
@@ -5125,7 +5125,7 @@ function omit(schema, mask) {
|
|
|
5125
5125
|
}));
|
|
5126
5126
|
}
|
|
5127
5127
|
function extend(schema, shape) {
|
|
5128
|
-
if (!isPlainObject(shape)) throw new Error("Invalid input to extend: expected a plain object");
|
|
5128
|
+
if (!isPlainObject$1(shape)) throw new Error("Invalid input to extend: expected a plain object");
|
|
5129
5129
|
const checks = schema._zod.def.checks;
|
|
5130
5130
|
if (checks && checks.length > 0) {
|
|
5131
5131
|
const existingShape = schema._zod.def.shape;
|
|
@@ -5141,7 +5141,7 @@ function extend(schema, shape) {
|
|
|
5141
5141
|
} }));
|
|
5142
5142
|
}
|
|
5143
5143
|
function safeExtend(schema, shape) {
|
|
5144
|
-
if (!isPlainObject(shape)) throw new Error("Invalid input to safeExtend: expected a plain object");
|
|
5144
|
+
if (!isPlainObject$1(shape)) throw new Error("Invalid input to safeExtend: expected a plain object");
|
|
5145
5145
|
return clone(schema, mergeDefs(schema._zod.def, { get shape() {
|
|
5146
5146
|
const _shape = {
|
|
5147
5147
|
...schema._zod.def.shape,
|
|
@@ -6826,7 +6826,7 @@ function mergeValues(a, b) {
|
|
|
6826
6826
|
valid: true,
|
|
6827
6827
|
data: a
|
|
6828
6828
|
};
|
|
6829
|
-
if (isPlainObject(a) && isPlainObject(b)) {
|
|
6829
|
+
if (isPlainObject$1(a) && isPlainObject$1(b)) {
|
|
6830
6830
|
const bKeys = Object.keys(b);
|
|
6831
6831
|
const sharedKeys = Object.keys(a).filter((key) => bKeys.indexOf(key) !== -1);
|
|
6832
6832
|
const newObj = {
|
|
@@ -6994,7 +6994,7 @@ const $ZodRecord = /*@__PURE__*/ $constructor("$ZodRecord", (inst, def) => {
|
|
|
6994
6994
|
$ZodType.init(inst, def);
|
|
6995
6995
|
inst._zod.parse = (payload, ctx) => {
|
|
6996
6996
|
const input = payload.value;
|
|
6997
|
-
if (!isPlainObject(input)) {
|
|
6997
|
+
if (!isPlainObject$1(input)) {
|
|
6998
6998
|
payload.issues.push({
|
|
6999
6999
|
expected: "record",
|
|
7000
7000
|
code: "invalid_type",
|
|
@@ -21322,44 +21322,21 @@ function extractModelTextFromToolContent(content) {
|
|
|
21322
21322
|
* `toModelOutput` can read MCP `content` without changing the execute return shape.
|
|
21323
21323
|
*/
|
|
21324
21324
|
const MCP_CALL_TOOL_CONTENT = Symbol.for("mastra.mcp.callToolContent");
|
|
21325
|
-
function
|
|
21326
|
-
|
|
21327
|
-
|
|
21328
|
-
|
|
21329
|
-
|
|
21330
|
-
|
|
21331
|
-
if (!reservation) return;
|
|
21332
|
-
const index = queue.indexOf(reservation);
|
|
21333
|
-
if (index !== -1) queue.splice(index, 1);
|
|
21334
|
-
}
|
|
21335
|
-
function attachMcpCallToolContent(structuredContent, content, scalarMcpContentQueue, reservation) {
|
|
21336
|
-
if (structuredContent !== null && typeof structuredContent === "object") {
|
|
21337
|
-
removeScalarMcpContentReservation(scalarMcpContentQueue, reservation);
|
|
21338
|
-
Object.defineProperty(structuredContent, MCP_CALL_TOOL_CONTENT, {
|
|
21339
|
-
value: content,
|
|
21340
|
-
enumerable: false,
|
|
21341
|
-
configurable: true
|
|
21342
|
-
});
|
|
21343
|
-
return structuredContent;
|
|
21344
|
-
}
|
|
21345
|
-
if (reservation) {
|
|
21346
|
-
reservation.output = structuredContent;
|
|
21347
|
-
reservation.content = content;
|
|
21348
|
-
reservation.ready = true;
|
|
21349
|
-
}
|
|
21325
|
+
function attachMcpCallToolContent(structuredContent, content) {
|
|
21326
|
+
if (structuredContent !== null && typeof structuredContent === "object") Object.defineProperty(structuredContent, MCP_CALL_TOOL_CONTENT, {
|
|
21327
|
+
value: content,
|
|
21328
|
+
enumerable: false,
|
|
21329
|
+
configurable: true
|
|
21330
|
+
});
|
|
21350
21331
|
return structuredContent;
|
|
21351
21332
|
}
|
|
21352
|
-
function getMcpCallToolContent(output
|
|
21353
|
-
if (output
|
|
21354
|
-
|
|
21355
|
-
if (attached !== void 0) return attached;
|
|
21356
|
-
}
|
|
21357
|
-
const index = scalarMcpContentQueue.findIndex((entry) => entry.ready && Object.is(entry.output, output));
|
|
21358
|
-
if (index !== -1) return scalarMcpContentQueue.splice(index, 1)[0]?.content;
|
|
21333
|
+
function getMcpCallToolContent(output) {
|
|
21334
|
+
if (output === null || typeof output !== "object") return void 0;
|
|
21335
|
+
return output[MCP_CALL_TOOL_CONTENT];
|
|
21359
21336
|
}
|
|
21360
|
-
function createStructuredToolToModelOutput(
|
|
21337
|
+
function createStructuredToolToModelOutput() {
|
|
21361
21338
|
return (output) => {
|
|
21362
|
-
const modelText = extractModelTextFromToolContent(getMcpCallToolContent(output
|
|
21339
|
+
const modelText = extractModelTextFromToolContent(getMcpCallToolContent(output));
|
|
21363
21340
|
if (modelText !== void 0) return {
|
|
21364
21341
|
type: "text",
|
|
21365
21342
|
value: modelText
|
|
@@ -21483,12 +21460,14 @@ var InternalMastraMCPClient = class extends _mastra_core_base.MastraBase {
|
|
|
21483
21460
|
"io.modelcontextprotocol/ui": {}
|
|
21484
21461
|
}
|
|
21485
21462
|
};
|
|
21463
|
+
const versionNegotiation = server.protocolVersion === void 0 ? void 0 : { mode: server.protocolVersion === "auto" ? "auto" : { pin: server.protocolVersion } };
|
|
21486
21464
|
this.client = new _modelcontextprotocol_client.Client({
|
|
21487
21465
|
name,
|
|
21488
21466
|
version
|
|
21489
21467
|
}, {
|
|
21490
21468
|
capabilities: clientCapabilities,
|
|
21491
|
-
...server.jsonSchemaValidator ? { jsonSchemaValidator: server.jsonSchemaValidator } : {}
|
|
21469
|
+
...server.jsonSchemaValidator ? { jsonSchemaValidator: server.jsonSchemaValidator } : {},
|
|
21470
|
+
...versionNegotiation ? { versionNegotiation } : {}
|
|
21492
21471
|
});
|
|
21493
21472
|
this.setupLogging();
|
|
21494
21473
|
if (hasRoots) this.setupRootsHandler();
|
|
@@ -21656,7 +21635,7 @@ var InternalMastraMCPClient = class extends _mastra_core_base.MastraBase {
|
|
|
21656
21635
|
this.markNeedsAuth(streamableTransport);
|
|
21657
21636
|
throw error;
|
|
21658
21637
|
}
|
|
21659
|
-
if (isUrlPolicyError(error)) throw error;
|
|
21638
|
+
if (isUrlPolicyError(error) || this.serverConfig.protocolVersion === "2026-07-28") throw error;
|
|
21660
21639
|
const status = error instanceof _modelcontextprotocol_client.SdkHttpError ? error.status : void 0;
|
|
21661
21640
|
if (status !== void 0 && !SSE_FALLBACK_STATUS_CODES.includes(status)) throw error;
|
|
21662
21641
|
shouldTrySSE = true;
|
|
@@ -22207,7 +22186,6 @@ var InternalMastraMCPClient = class extends _mastra_core_base.MastraBase {
|
|
|
22207
22186
|
...toolMeta ? { _meta: toolMeta } : {},
|
|
22208
22187
|
...annotations ? { annotations } : {}
|
|
22209
22188
|
} } : {};
|
|
22210
|
-
const scalarMcpContentQueue = [];
|
|
22211
22189
|
const mastraTool = (0, _mastra_core_tools.createTool)({
|
|
22212
22190
|
id: `${this.name}_${tool.name}`,
|
|
22213
22191
|
description: tool.description || "",
|
|
@@ -22223,11 +22201,10 @@ var InternalMastraMCPClient = class extends _mastra_core_base.MastraBase {
|
|
|
22223
22201
|
forwardInstructions: this.forwardInstructions,
|
|
22224
22202
|
instructionsMaxLength: this.instructionsMaxLength
|
|
22225
22203
|
},
|
|
22226
|
-
...tool.outputSchema ? { toModelOutput: createStructuredToolToModelOutput(
|
|
22204
|
+
...tool.outputSchema ? { toModelOutput: createStructuredToolToModelOutput() } : {},
|
|
22227
22205
|
execute: async (input, context) => {
|
|
22228
22206
|
if (serverMeta.connectFirst) await this.connect();
|
|
22229
22207
|
const operationContext = context?.requestContext ?? null;
|
|
22230
|
-
const scalarMcpContentReservation = tool.outputSchema ? reserveScalarMcpContent(scalarMcpContentQueue) : void 0;
|
|
22231
22208
|
return this.operationContextStore.run(operationContext, async () => {
|
|
22232
22209
|
const executeToolCall = async () => {
|
|
22233
22210
|
this.log("debug", `Executing tool: ${tool.name}`, {
|
|
@@ -22263,8 +22240,7 @@ var InternalMastraMCPClient = class extends _mastra_core_base.MastraBase {
|
|
|
22263
22240
|
});
|
|
22264
22241
|
}
|
|
22265
22242
|
this.log("debug", `Tool executed successfully: ${tool.name}`);
|
|
22266
|
-
if (res.structuredContent !== void 0) return attachMcpCallToolContent(res.structuredContent, res.content
|
|
22267
|
-
removeScalarMcpContentReservation(scalarMcpContentQueue, scalarMcpContentReservation);
|
|
22243
|
+
if (res.structuredContent !== void 0) return attachMcpCallToolContent(res.structuredContent, res.content);
|
|
22268
22244
|
return res;
|
|
22269
22245
|
};
|
|
22270
22246
|
const failedTransport = this.transport;
|
|
@@ -22284,7 +22260,6 @@ var InternalMastraMCPClient = class extends _mastra_core_base.MastraBase {
|
|
|
22284
22260
|
reconnectError: reconnectError instanceof Error ? reconnectError.stack : String(reconnectError),
|
|
22285
22261
|
toolArgs: input
|
|
22286
22262
|
});
|
|
22287
|
-
removeScalarMcpContentReservation(scalarMcpContentQueue, scalarMcpContentReservation);
|
|
22288
22263
|
throw reconnectError;
|
|
22289
22264
|
}
|
|
22290
22265
|
}
|
|
@@ -22292,7 +22267,6 @@ var InternalMastraMCPClient = class extends _mastra_core_base.MastraBase {
|
|
|
22292
22267
|
error: e instanceof Error ? e.stack : JSON.stringify(e, null, 2),
|
|
22293
22268
|
toolArgs: input
|
|
22294
22269
|
});
|
|
22295
|
-
removeScalarMcpContentReservation(scalarMcpContentQueue, scalarMcpContentReservation);
|
|
22296
22270
|
throw e;
|
|
22297
22271
|
}
|
|
22298
22272
|
});
|
|
@@ -24320,7 +24294,7 @@ var streamSSE = (c, cb, onError) => {
|
|
|
24320
24294
|
return c.newResponse(stream.responseReadable);
|
|
24321
24295
|
};
|
|
24322
24296
|
//#endregion
|
|
24323
|
-
//#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@modelcontextprotocol/sdk/1.29.0/
|
|
24297
|
+
//#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@modelcontextprotocol/sdk/1.29.0/7d2f0982429dbe53f84f7249d02074ef571f5d1c95137997d9ed2dfe102a137b/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
|
|
24324
24298
|
const RELATED_TASK_META_KEY = "io.modelcontextprotocol/related-task";
|
|
24325
24299
|
/**
|
|
24326
24300
|
* Assert 'object' type schema.
|
|
@@ -26151,7 +26125,7 @@ union([
|
|
|
26151
26125
|
CreateTaskResultSchema
|
|
26152
26126
|
]);
|
|
26153
26127
|
//#endregion
|
|
26154
|
-
//#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@/hono-mcp-server-sse-transport/0.0.7/
|
|
26128
|
+
//#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@/hono-mcp-server-sse-transport/0.0.7/d5ae5a23aa2b79db7055621f11a7cbc8d27f7caba1eeb308ab2cf5bcb1a8e5b8/node_modules/hono-mcp-server-sse-transport/build/sse.js
|
|
26155
26129
|
const MAXIMUM_MESSAGE_SIZE = 4 * 1024 * 1024;
|
|
26156
26130
|
var SSETransport = class {
|
|
26157
26131
|
messageUrl;
|
|
@@ -26226,6 +26200,132 @@ var SSETransport = class {
|
|
|
26226
26200
|
}
|
|
26227
26201
|
};
|
|
26228
26202
|
//#endregion
|
|
26203
|
+
//#region src/server/mrtrElicitation.ts
|
|
26204
|
+
/**
|
|
26205
|
+
* Elicitation on the 2026-07-28 protocol revision (multi-round-trip requests).
|
|
26206
|
+
*
|
|
26207
|
+
* The modern era has no server→client request channel, so `server.elicitInput()`
|
|
26208
|
+
* throws there by design. Instead, the `tools/call` handler must RETURN an
|
|
26209
|
+
* `input_required` result carrying the embedded elicitation request; the client
|
|
26210
|
+
* answers it locally and RETRIES the call with the response attached
|
|
26211
|
+
* (`inputResponses`). This module keeps the promise-shaped
|
|
26212
|
+
* `elicitation.sendRequest()` API tools already use by replaying the tool:
|
|
26213
|
+
*
|
|
26214
|
+
* 1. Each `sendRequest` call is assigned a deterministic sequence key.
|
|
26215
|
+
* 2. If the current (retried) request carries an answer for that key — either in
|
|
26216
|
+
* this round's `inputResponses` or in the accumulated `requestState` from
|
|
26217
|
+
* prior rounds — the promise resolves with it immediately.
|
|
26218
|
+
* 3. Otherwise a {@link ElicitationReplayInterrupt} is thrown; the `tools/call`
|
|
26219
|
+
* handler converts it into an {@link InputRequiredResult} return, and the
|
|
26220
|
+
* client's retry re-executes the tool from the top.
|
|
26221
|
+
*
|
|
26222
|
+
* Consequences tools must live with on the modern leg:
|
|
26223
|
+
* - Code before an unanswered elicitation re-executes on every round; keep side
|
|
26224
|
+
* effects idempotent or place them after the last elicitation.
|
|
26225
|
+
* - Elicitation order must be deterministic for a given input, since answers are
|
|
26226
|
+
* matched by call sequence.
|
|
26227
|
+
*/
|
|
26228
|
+
const ELICIT_KEY_PREFIX = "mastra_elicit_";
|
|
26229
|
+
/**
|
|
26230
|
+
* Thrown by the replay-based `sendRequest` when the current round carries no
|
|
26231
|
+
* answer for the elicitation. Never surfaces to tools or clients: the
|
|
26232
|
+
* `tools/call` handler converts it into an `input_required` result.
|
|
26233
|
+
*/
|
|
26234
|
+
var ElicitationReplayInterrupt = class extends Error {
|
|
26235
|
+
key;
|
|
26236
|
+
params;
|
|
26237
|
+
answered;
|
|
26238
|
+
constructor(key, params, answered) {
|
|
26239
|
+
super(`Elicitation '${key}' requires client input (multi-round-trip)`);
|
|
26240
|
+
this.key = key;
|
|
26241
|
+
this.params = params;
|
|
26242
|
+
this.answered = answered;
|
|
26243
|
+
this.name = "ElicitationReplayInterrupt";
|
|
26244
|
+
}
|
|
26245
|
+
};
|
|
26246
|
+
const isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26247
|
+
const looksLikeElicitResult = (value) => isPlainObject(value) && typeof value.action === "string";
|
|
26248
|
+
/**
|
|
26249
|
+
* Decodes the accumulated prior-round answers from the request's opaque
|
|
26250
|
+
* `requestState` echo. The state round-trips through the client, so it is
|
|
26251
|
+
* attacker-controlled input on re-entry — but its only content is the client's
|
|
26252
|
+
* own past elicitation answers, which are untrusted user input either way, so
|
|
26253
|
+
* tampering grants the client nothing it does not already control. Anything
|
|
26254
|
+
* that does not parse as a map of elicitation results is discarded.
|
|
26255
|
+
*/
|
|
26256
|
+
const decodePriorAnswers = (extra) => {
|
|
26257
|
+
const raw = extra.mcpReq.requestState();
|
|
26258
|
+
if (typeof raw !== "string" || raw.length === 0) return {};
|
|
26259
|
+
try {
|
|
26260
|
+
const parsed = JSON.parse(raw);
|
|
26261
|
+
if (!isPlainObject(parsed)) return {};
|
|
26262
|
+
const answers = {};
|
|
26263
|
+
for (const [key, value] of Object.entries(parsed)) if (key.startsWith(ELICIT_KEY_PREFIX) && looksLikeElicitResult(value)) answers[key] = value;
|
|
26264
|
+
return answers;
|
|
26265
|
+
} catch {
|
|
26266
|
+
return {};
|
|
26267
|
+
}
|
|
26268
|
+
};
|
|
26269
|
+
/** This round's bare responses that answer our elicitation keys. */
|
|
26270
|
+
const currentRoundAnswers = (extra) => {
|
|
26271
|
+
const answers = {};
|
|
26272
|
+
for (const [key, value] of Object.entries(extra.mcpReq.inputResponses ?? {})) if (key.startsWith(ELICIT_KEY_PREFIX) && looksLikeElicitResult(value)) answers[key] = value;
|
|
26273
|
+
return answers;
|
|
26274
|
+
};
|
|
26275
|
+
/**
|
|
26276
|
+
* Whether this request is served on the 2026-07-28 era. Modern clients always
|
|
26277
|
+
* attach the reserved per-request `_meta` envelope (the 2026 codec enforces the
|
|
26278
|
+
* required keys at dispatch); legacy requests never carry it.
|
|
26279
|
+
*/
|
|
26280
|
+
const isModernEraRequest = (extra) => extra.mcpReq.envelope !== void 0;
|
|
26281
|
+
/**
|
|
26282
|
+
* Builds the replay-based {@link ElicitationActions} for one modern-era tool
|
|
26283
|
+
* execution. Answers already provided by the client resolve immediately; the
|
|
26284
|
+
* first unanswered elicitation throws {@link ElicitationReplayInterrupt}.
|
|
26285
|
+
*
|
|
26286
|
+
* The interrupt is also reported through `onInterrupt` before it is thrown:
|
|
26287
|
+
* tool wrappers (e.g. Mastra's tool builder) re-wrap thrown errors, so the
|
|
26288
|
+
* `tools/call` handler cannot rely on `instanceof` on whatever escapes the
|
|
26289
|
+
* tool — the out-of-band capture is the authoritative signal.
|
|
26290
|
+
*/
|
|
26291
|
+
const createReplayElicitation = (extra, onInterrupt) => {
|
|
26292
|
+
const prior = decodePriorAnswers(extra);
|
|
26293
|
+
const current = currentRoundAnswers(extra);
|
|
26294
|
+
const answered = {
|
|
26295
|
+
...prior,
|
|
26296
|
+
...current
|
|
26297
|
+
};
|
|
26298
|
+
let sequence = 0;
|
|
26299
|
+
return { sendRequest: async (request) => {
|
|
26300
|
+
const key = `${ELICIT_KEY_PREFIX}${sequence++}`;
|
|
26301
|
+
const answer = answered[key];
|
|
26302
|
+
if (answer !== void 0) return answer;
|
|
26303
|
+
const interrupt = new ElicitationReplayInterrupt(key, request, answered);
|
|
26304
|
+
onInterrupt(interrupt);
|
|
26305
|
+
throw interrupt;
|
|
26306
|
+
} };
|
|
26307
|
+
};
|
|
26308
|
+
/**
|
|
26309
|
+
* Converts a caught {@link ElicitationReplayInterrupt} into the
|
|
26310
|
+
* `input_required` result the `tools/call` handler returns to the client.
|
|
26311
|
+
* Prior answers travel in `requestState` because each retry only carries the
|
|
26312
|
+
* current round's `inputResponses`.
|
|
26313
|
+
*/
|
|
26314
|
+
const replayInterruptToInputRequired = (interrupt) => {
|
|
26315
|
+
const params = {
|
|
26316
|
+
mode: "form",
|
|
26317
|
+
...interrupt.params
|
|
26318
|
+
};
|
|
26319
|
+
return {
|
|
26320
|
+
resultType: "input_required",
|
|
26321
|
+
inputRequests: { [interrupt.key]: {
|
|
26322
|
+
method: "elicitation/create",
|
|
26323
|
+
params
|
|
26324
|
+
} },
|
|
26325
|
+
...Object.keys(interrupt.answered).length > 0 ? { requestState: JSON.stringify(interrupt.answered) } : {}
|
|
26326
|
+
};
|
|
26327
|
+
};
|
|
26328
|
+
//#endregion
|
|
26229
26329
|
//#region src/server/notificationBroadcast.ts
|
|
26230
26330
|
/**
|
|
26231
26331
|
* Sends a notification to every active server instance (the main stdio/SSE
|
|
@@ -26282,6 +26382,7 @@ var ServerPromptActions = class {
|
|
|
26282
26382
|
getLogger;
|
|
26283
26383
|
getSdkServers;
|
|
26284
26384
|
clearDefinedPrompts;
|
|
26385
|
+
getModernEraNotifier;
|
|
26285
26386
|
/**
|
|
26286
26387
|
* @internal
|
|
26287
26388
|
*/
|
|
@@ -26289,6 +26390,7 @@ var ServerPromptActions = class {
|
|
|
26289
26390
|
this.getLogger = dependencies.getLogger;
|
|
26290
26391
|
this.getSdkServers = dependencies.getSdkServers;
|
|
26291
26392
|
this.clearDefinedPrompts = dependencies.clearDefinedPrompts;
|
|
26393
|
+
this.getModernEraNotifier = dependencies.getModernEraNotifier;
|
|
26292
26394
|
}
|
|
26293
26395
|
/**
|
|
26294
26396
|
* Notifies clients that the overall list of available prompts has changed.
|
|
@@ -26307,6 +26409,7 @@ var ServerPromptActions = class {
|
|
|
26307
26409
|
async notifyListChanged() {
|
|
26308
26410
|
this.getLogger().info("Prompt list change externally notified. Clearing definedPrompts and sending notification.");
|
|
26309
26411
|
this.clearDefinedPrompts();
|
|
26412
|
+
this.getModernEraNotifier?.()?.promptsChanged();
|
|
26310
26413
|
await broadcastNotification({
|
|
26311
26414
|
servers: this.getSdkServers(),
|
|
26312
26415
|
send: (server) => server.sendPromptListChanged(),
|
|
@@ -26333,6 +26436,7 @@ var ServerResourceActions = class {
|
|
|
26333
26436
|
getSubscribedServers;
|
|
26334
26437
|
getLogger;
|
|
26335
26438
|
getSdkServers;
|
|
26439
|
+
getModernEraNotifier;
|
|
26336
26440
|
/**
|
|
26337
26441
|
* @internal
|
|
26338
26442
|
*/
|
|
@@ -26340,6 +26444,7 @@ var ServerResourceActions = class {
|
|
|
26340
26444
|
this.getSubscribedServers = dependencies.getSubscribedServers;
|
|
26341
26445
|
this.getLogger = dependencies.getLogger;
|
|
26342
26446
|
this.getSdkServers = dependencies.getSdkServers;
|
|
26447
|
+
this.getModernEraNotifier = dependencies.getModernEraNotifier;
|
|
26343
26448
|
}
|
|
26344
26449
|
/**
|
|
26345
26450
|
* Notifies subscribed clients that a specific resource has been updated.
|
|
@@ -26359,6 +26464,7 @@ var ServerResourceActions = class {
|
|
|
26359
26464
|
* ```
|
|
26360
26465
|
*/
|
|
26361
26466
|
async notifyUpdated({ uri }) {
|
|
26467
|
+
this.getModernEraNotifier?.()?.resourceUpdated(uri);
|
|
26362
26468
|
const subscribedServers = this.getSubscribedServers(uri);
|
|
26363
26469
|
if (subscribedServers.length === 0) {
|
|
26364
26470
|
this.getLogger().debug(`Resource ${uri} was updated, but no active subscriptions for it.`);
|
|
@@ -26391,6 +26497,7 @@ var ServerResourceActions = class {
|
|
|
26391
26497
|
*/
|
|
26392
26498
|
async notifyListChanged() {
|
|
26393
26499
|
this.getLogger().info("Resource list change externally notified. Sending notification.");
|
|
26500
|
+
this.getModernEraNotifier?.()?.resourcesChanged();
|
|
26394
26501
|
await broadcastNotification({
|
|
26395
26502
|
servers: this.getSdkServers(),
|
|
26396
26503
|
send: (server) => server.sendResourceListChanged(),
|
|
@@ -26416,6 +26523,7 @@ var ServerToolActions = class {
|
|
|
26416
26523
|
getSdkServers;
|
|
26417
26524
|
addTools;
|
|
26418
26525
|
removeTools;
|
|
26526
|
+
getModernEraNotifier;
|
|
26419
26527
|
/**
|
|
26420
26528
|
* @internal
|
|
26421
26529
|
*/
|
|
@@ -26424,6 +26532,7 @@ var ServerToolActions = class {
|
|
|
26424
26532
|
this.getSdkServers = dependencies.getSdkServers;
|
|
26425
26533
|
this.addTools = dependencies.addTools;
|
|
26426
26534
|
this.removeTools = dependencies.removeTools;
|
|
26535
|
+
this.getModernEraNotifier = dependencies.getModernEraNotifier;
|
|
26427
26536
|
}
|
|
26428
26537
|
/**
|
|
26429
26538
|
* Registers new tools on the running server and notifies connected clients
|
|
@@ -26482,6 +26591,7 @@ var ServerToolActions = class {
|
|
|
26482
26591
|
*/
|
|
26483
26592
|
async notifyListChanged() {
|
|
26484
26593
|
this.getLogger().info("Tool list changed. Sending notification.");
|
|
26594
|
+
this.getModernEraNotifier?.()?.toolsChanged();
|
|
26485
26595
|
await broadcastNotification({
|
|
26486
26596
|
servers: this.getSdkServers(),
|
|
26487
26597
|
send: (server) => server.sendToolListChanged(),
|
|
@@ -26522,6 +26632,14 @@ const LOG_LEVEL_SEVERITY = {
|
|
|
26522
26632
|
alert: 6,
|
|
26523
26633
|
emergency: 7
|
|
26524
26634
|
};
|
|
26635
|
+
const ACCEPTED_MODERN_ERA_HTTP_OPTION_KEYS = /* @__PURE__ */ new Set([
|
|
26636
|
+
"allowedHosts",
|
|
26637
|
+
"allowedOrigins",
|
|
26638
|
+
"enableDnsRebindingProtection",
|
|
26639
|
+
"serverless",
|
|
26640
|
+
"serverlessStreaming",
|
|
26641
|
+
"sessionIdGenerator"
|
|
26642
|
+
]);
|
|
26525
26643
|
/**
|
|
26526
26644
|
* MCPServer exposes Mastra tools, agents, and workflows as a Model Context Protocol (MCP) server.
|
|
26527
26645
|
*
|
|
@@ -26555,6 +26673,8 @@ var MCPServer = class extends _mastra_core_mcp.MCPServerBase {
|
|
|
26555
26673
|
stdioTransport;
|
|
26556
26674
|
sseTransport;
|
|
26557
26675
|
sseHonoTransports;
|
|
26676
|
+
/** Auth info for the in-flight Hono SSE message POST, keyed by session id. */
|
|
26677
|
+
sseHonoAuthInfo = /* @__PURE__ */ new Map();
|
|
26558
26678
|
streamableHTTPTransports = /* @__PURE__ */ new Map();
|
|
26559
26679
|
httpServerInstances = /* @__PURE__ */ new Map();
|
|
26560
26680
|
resourceOptions;
|
|
@@ -26566,6 +26686,12 @@ var MCPServer = class extends _mastra_core_mcp.MCPServerBase {
|
|
|
26566
26686
|
fga;
|
|
26567
26687
|
subscriptionsByInstance = /* @__PURE__ */ new WeakMap();
|
|
26568
26688
|
loggingLevels = /* @__PURE__ */ new WeakMap();
|
|
26689
|
+
protocolVersion;
|
|
26690
|
+
cacheHints;
|
|
26691
|
+
modernEraHandler;
|
|
26692
|
+
modernEraNodeHandler;
|
|
26693
|
+
stdioHandle;
|
|
26694
|
+
stdioServerInstance;
|
|
26569
26695
|
/**
|
|
26570
26696
|
* Provides methods to notify clients about resource changes.
|
|
26571
26697
|
*
|
|
@@ -26717,6 +26843,8 @@ var MCPServer = class extends _mastra_core_mcp.MCPServerBase {
|
|
|
26717
26843
|
*/
|
|
26718
26844
|
constructor(opts) {
|
|
26719
26845
|
super(opts);
|
|
26846
|
+
this.protocolVersion = opts.protocolVersion;
|
|
26847
|
+
this.cacheHints = opts.cacheHints;
|
|
26720
26848
|
this.resourceOptions = this.mergeAppResources(opts.resources, opts.appResources);
|
|
26721
26849
|
this.hasUiResources = !!opts.appResources && Object.keys(opts.appResources).length > 0;
|
|
26722
26850
|
this.promptOptions = opts.prompts;
|
|
@@ -26742,7 +26870,8 @@ var MCPServer = class extends _mastra_core_mcp.MCPServerBase {
|
|
|
26742
26870
|
}, {
|
|
26743
26871
|
capabilities,
|
|
26744
26872
|
...this.instructions ? { instructions: this.instructions } : {},
|
|
26745
|
-
...this.jsonSchemaValidator ? { jsonSchemaValidator: this.jsonSchemaValidator } : {}
|
|
26873
|
+
...this.jsonSchemaValidator ? { jsonSchemaValidator: this.jsonSchemaValidator } : {},
|
|
26874
|
+
...this.servesModernEra() && this.cacheHints ? { cacheHints: this.cacheHints } : {}
|
|
26746
26875
|
});
|
|
26747
26876
|
this.logger.info("Initialized MCPServer", {
|
|
26748
26877
|
name: this.name,
|
|
@@ -26753,23 +26882,27 @@ var MCPServer = class extends _mastra_core_mcp.MCPServerBase {
|
|
|
26753
26882
|
});
|
|
26754
26883
|
this.sseHonoTransports = /* @__PURE__ */ new Map();
|
|
26755
26884
|
this.registerHandlersOnServer(this.server);
|
|
26885
|
+
const getModernEraNotifier = () => this.servesModernEra() ? this.modernEraHandler?.notify : void 0;
|
|
26756
26886
|
this.resources = new ServerResourceActions({
|
|
26757
26887
|
getSubscribedServers: (uri) => this.getAllSdkServers().filter((server) => this.subscriptionsByInstance.get(server)?.has(uri)),
|
|
26758
26888
|
getLogger: () => this.logger,
|
|
26759
|
-
getSdkServers: () => this.getAllSdkServers()
|
|
26889
|
+
getSdkServers: () => this.getAllSdkServers(),
|
|
26890
|
+
getModernEraNotifier
|
|
26760
26891
|
});
|
|
26761
26892
|
this.prompts = new ServerPromptActions({
|
|
26762
26893
|
getLogger: () => this.logger,
|
|
26763
26894
|
getSdkServers: () => this.getAllSdkServers(),
|
|
26764
26895
|
clearDefinedPrompts: () => {
|
|
26765
26896
|
this.definedPrompts = void 0;
|
|
26766
|
-
}
|
|
26897
|
+
},
|
|
26898
|
+
getModernEraNotifier
|
|
26767
26899
|
});
|
|
26768
26900
|
this.toolActions = new ServerToolActions({
|
|
26769
26901
|
getLogger: () => this.logger,
|
|
26770
26902
|
getSdkServers: () => this.getAllSdkServers(),
|
|
26771
26903
|
addTools: (tools) => this.addTools(tools),
|
|
26772
|
-
removeTools: (toolIds) => this.removeTools(toolIds)
|
|
26904
|
+
removeTools: (toolIds) => this.removeTools(toolIds),
|
|
26905
|
+
getModernEraNotifier
|
|
26773
26906
|
});
|
|
26774
26907
|
this.elicitation = { sendRequest: async (request, options) => {
|
|
26775
26908
|
return this.handleElicitationRequest(request, void 0, options);
|
|
@@ -26785,7 +26918,69 @@ var MCPServer = class extends _mastra_core_mcp.MCPServerBase {
|
|
|
26785
26918
|
* cannot receive notifications.
|
|
26786
26919
|
*/
|
|
26787
26920
|
getAllSdkServers() {
|
|
26788
|
-
return [
|
|
26921
|
+
return [
|
|
26922
|
+
this.server,
|
|
26923
|
+
this.stdioServerInstance,
|
|
26924
|
+
...this.httpServerInstances.values()
|
|
26925
|
+
].filter((server) => server?.transport !== void 0);
|
|
26926
|
+
}
|
|
26927
|
+
/**
|
|
26928
|
+
* Whether the server is pinned to the `2026-07-28` protocol revision.
|
|
26929
|
+
* When false (the default), all behavior is byte-identical to the legacy era.
|
|
26930
|
+
*/
|
|
26931
|
+
servesModernEra() {
|
|
26932
|
+
return this.protocolVersion === "2026-07-28";
|
|
26933
|
+
}
|
|
26934
|
+
assertModernEraHTTPOptions(options) {
|
|
26935
|
+
if (!options) return;
|
|
26936
|
+
const incompatibleOptions = new Set(Object.keys(options).filter((option) => !ACCEPTED_MODERN_ERA_HTTP_OPTION_KEYS.has(option)));
|
|
26937
|
+
if (options.sessionIdGenerator !== void 0) incompatibleOptions.add("sessionIdGenerator");
|
|
26938
|
+
if (options.serverless === false) incompatibleOptions.add("serverless");
|
|
26939
|
+
if (options.serverlessStreaming === false) incompatibleOptions.add("serverlessStreaming");
|
|
26940
|
+
if (incompatibleOptions.size === 0) return;
|
|
26941
|
+
const names = [...incompatibleOptions].sort();
|
|
26942
|
+
throw new _mastra_core_error.MastraError({
|
|
26943
|
+
id: "MCP_SERVER_MODERN_HTTP_OPTIONS_INCOMPATIBLE",
|
|
26944
|
+
domain: _mastra_core_error.ErrorDomain.MCP,
|
|
26945
|
+
category: _mastra_core_error.ErrorCategory.USER,
|
|
26946
|
+
text: `startHTTP options ${names.map((name) => `"${name}"`).join(", ")} are incompatible with protocolVersion "2026-07-28"`,
|
|
26947
|
+
details: { incompatibleOptions: names.join(", ") }
|
|
26948
|
+
});
|
|
26949
|
+
}
|
|
26950
|
+
validateHTTPRequestHeaders(req, res, options) {
|
|
26951
|
+
if (!options?.enableDnsRebindingProtection) return true;
|
|
26952
|
+
if (options.allowedHosts?.length) {
|
|
26953
|
+
if (!(0, _modelcontextprotocol_node.hostHeaderValidation)(options.allowedHosts.map((host) => new URL(`http://${host}`).hostname))(req, res)) return false;
|
|
26954
|
+
}
|
|
26955
|
+
if (options.allowedOrigins?.length) {
|
|
26956
|
+
if (!(0, _modelcontextprotocol_node.originValidation)(options.allowedOrigins.map((origin) => new URL(origin).hostname))(req, res)) return false;
|
|
26957
|
+
}
|
|
26958
|
+
return true;
|
|
26959
|
+
}
|
|
26960
|
+
/**
|
|
26961
|
+
* Lazily creates the dual-era HTTP handler used when `protocolVersion: '2026-07-28'`
|
|
26962
|
+
* is set: modern (per-request envelope) clients are served natively and legacy
|
|
26963
|
+
* clients are served through the SDK's built-in stateless fallback, both from the
|
|
26964
|
+
* same endpoint. Each request gets a fresh server instance from
|
|
26965
|
+
* `createServerInstance()`, so all registered handlers apply to both eras.
|
|
26966
|
+
*/
|
|
26967
|
+
getModernEraHandler() {
|
|
26968
|
+
if (!this.modernEraHandler) this.modernEraHandler = (0, _modelcontextprotocol_server.createMcpHandler)(() => this.createServerInstance(), {
|
|
26969
|
+
legacy: "stateless",
|
|
26970
|
+
onerror: (error) => {
|
|
26971
|
+
this.logger.error("MCP handler error", { error: error.toString() });
|
|
26972
|
+
}
|
|
26973
|
+
});
|
|
26974
|
+
return this.modernEraHandler;
|
|
26975
|
+
}
|
|
26976
|
+
/**
|
|
26977
|
+
* Node `(req, res)` adapter over the dual-era handler's web-standard `fetch`.
|
|
26978
|
+
*/
|
|
26979
|
+
getModernEraNodeHandler() {
|
|
26980
|
+
if (!this.modernEraNodeHandler) this.modernEraNodeHandler = (0, _modelcontextprotocol_node.toNodeHandler)(this.getModernEraHandler(), { onerror: (error) => {
|
|
26981
|
+
this.logger.error("MCP Node handler adapter error", { error: error.toString() });
|
|
26982
|
+
} });
|
|
26983
|
+
return this.modernEraNodeHandler;
|
|
26789
26984
|
}
|
|
26790
26985
|
/**
|
|
26791
26986
|
* Determines whether a log message at the given level should be sent to the
|
|
@@ -27022,7 +27217,8 @@ var MCPServer = class extends _mastra_core_mcp.MCPServerBase {
|
|
|
27022
27217
|
}, {
|
|
27023
27218
|
capabilities,
|
|
27024
27219
|
...this.instructions ? { instructions: this.instructions } : {},
|
|
27025
|
-
...this.jsonSchemaValidator ? { jsonSchemaValidator: this.jsonSchemaValidator } : {}
|
|
27220
|
+
...this.jsonSchemaValidator ? { jsonSchemaValidator: this.jsonSchemaValidator } : {},
|
|
27221
|
+
...this.servesModernEra() && this.cacheHints ? { cacheHints: this.cacheHints } : {}
|
|
27026
27222
|
});
|
|
27027
27223
|
this.registerHandlersOnServer(serverInstance);
|
|
27028
27224
|
return serverInstance;
|
|
@@ -27065,6 +27261,7 @@ var MCPServer = class extends _mastra_core_mcp.MCPServerBase {
|
|
|
27065
27261
|
serverInstance.setRequestHandler("tools/call", async (request, ctx) => {
|
|
27066
27262
|
const startTime = Date.now();
|
|
27067
27263
|
const extra = toMCPRequestHandlerExtra(ctx);
|
|
27264
|
+
let replayInterrupt;
|
|
27068
27265
|
try {
|
|
27069
27266
|
const tool = this.convertedTools[request.params.name];
|
|
27070
27267
|
if (!tool) {
|
|
@@ -27104,11 +27301,20 @@ var MCPServer = class extends _mastra_core_mcp.MCPServerBase {
|
|
|
27104
27301
|
isError: true
|
|
27105
27302
|
};
|
|
27106
27303
|
}
|
|
27107
|
-
const sessionElicitation =
|
|
27304
|
+
const sessionElicitation = isModernEraRequest(extra) ? createReplayElicitation(extra, (interrupt) => {
|
|
27305
|
+
replayInterrupt = interrupt;
|
|
27306
|
+
}) : { sendRequest: async (request, options) => {
|
|
27108
27307
|
return this.handleElicitationRequest(request, serverInstance, options);
|
|
27109
27308
|
} };
|
|
27110
27309
|
const proxiedContext = await this.createProxiedRequestContext(extra);
|
|
27111
27310
|
const sessionLog = async (level, message, data) => {
|
|
27311
|
+
if (this.servesModernEra()) {
|
|
27312
|
+
await extra.mcpReq.log(level, {
|
|
27313
|
+
message,
|
|
27314
|
+
...data
|
|
27315
|
+
}, this.name);
|
|
27316
|
+
return;
|
|
27317
|
+
}
|
|
27112
27318
|
if (!this.shouldSendLog(serverInstance, level)) return;
|
|
27113
27319
|
await extra.sendNotification({
|
|
27114
27320
|
method: "notifications/message",
|
|
@@ -27198,6 +27404,10 @@ var MCPServer = class extends _mastra_core_mcp.MCPServerBase {
|
|
|
27198
27404
|
}];
|
|
27199
27405
|
return response;
|
|
27200
27406
|
} catch (error) {
|
|
27407
|
+
if (replayInterrupt !== void 0) {
|
|
27408
|
+
this.logger.debug(`CallTool: Tool '${request.params.name}' requires client input (multi-round-trip).`, { key: replayInterrupt.key });
|
|
27409
|
+
return replayInterruptToInputRequired(replayInterrupt);
|
|
27410
|
+
}
|
|
27201
27411
|
const duration = Date.now() - startTime;
|
|
27202
27412
|
if (error instanceof Error && "issues" in error && Array.isArray(error.issues)) {
|
|
27203
27413
|
const issues = error.issues;
|
|
@@ -27613,6 +27823,17 @@ var MCPServer = class extends _mastra_core_mcp.MCPServerBase {
|
|
|
27613
27823
|
* ```
|
|
27614
27824
|
*/
|
|
27615
27825
|
async startStdio() {
|
|
27826
|
+
if (this.servesModernEra()) {
|
|
27827
|
+
this.stdioHandle = (0, _modelcontextprotocol_server_stdio.serveStdio)(() => {
|
|
27828
|
+
const serverInstance = this.createServerInstance();
|
|
27829
|
+
this.stdioServerInstance = serverInstance;
|
|
27830
|
+
return serverInstance;
|
|
27831
|
+
}, { onerror: (error) => {
|
|
27832
|
+
this.logger.error("MCP stdio handler error", { error: error.toString() });
|
|
27833
|
+
} });
|
|
27834
|
+
this.logger.info("Started MCP Server (stdio, 2026-07-28 dual-era)");
|
|
27835
|
+
return;
|
|
27836
|
+
}
|
|
27616
27837
|
this.stdioTransport = new _modelcontextprotocol_server_stdio.StdioServerTransport();
|
|
27617
27838
|
try {
|
|
27618
27839
|
await this.server.connect(this.stdioTransport);
|
|
@@ -27731,7 +27952,7 @@ var MCPServer = class extends _mastra_core_mcp.MCPServerBase {
|
|
|
27731
27952
|
* export default app;
|
|
27732
27953
|
* ```
|
|
27733
27954
|
*/
|
|
27734
|
-
async startHonoSSE({ url, ssePath, messagePath, context }) {
|
|
27955
|
+
async startHonoSSE({ url, ssePath, messagePath, context, authInfo }) {
|
|
27735
27956
|
const honoContext = context;
|
|
27736
27957
|
try {
|
|
27737
27958
|
if (url.pathname === ssePath) return streamSSE(honoContext, async (stream) => {
|
|
@@ -27746,6 +27967,8 @@ var MCPServer = class extends _mastra_core_mcp.MCPServerBase {
|
|
|
27746
27967
|
this.logger.debug("Received message for sessionId", { sessionId });
|
|
27747
27968
|
if (!sessionId) return honoContext.text("No sessionId provided", 400);
|
|
27748
27969
|
if (!this.sseHonoTransports.has(sessionId)) return honoContext.text(`No transport found for sessionId ${sessionId}`, 400);
|
|
27970
|
+
if (authInfo) this.sseHonoAuthInfo.set(sessionId, authInfo);
|
|
27971
|
+
else this.sseHonoAuthInfo.delete(sessionId);
|
|
27749
27972
|
const message = await this.sseHonoTransports.get(sessionId)?.handlePostMessage(honoContext);
|
|
27750
27973
|
if (!message) return honoContext.text("Transport not found", 400);
|
|
27751
27974
|
return message;
|
|
@@ -27845,6 +28068,34 @@ var MCPServer = class extends _mastra_core_mcp.MCPServerBase {
|
|
|
27845
28068
|
res.end();
|
|
27846
28069
|
return;
|
|
27847
28070
|
}
|
|
28071
|
+
if (this.servesModernEra()) this.assertModernEraHTTPOptions(options);
|
|
28072
|
+
if (!this.validateHTTPRequestHeaders(req, res, options)) return;
|
|
28073
|
+
if (this.servesModernEra()) {
|
|
28074
|
+
try {
|
|
28075
|
+
await this.getModernEraNodeHandler()(req, res);
|
|
28076
|
+
} catch (error) {
|
|
28077
|
+
const mastraError = new _mastra_core_error.MastraError({
|
|
28078
|
+
id: "MCP_SERVER_HTTP_CONNECTION_FAILED",
|
|
28079
|
+
domain: _mastra_core_error.ErrorDomain.MCP,
|
|
28080
|
+
category: _mastra_core_error.ErrorCategory.USER,
|
|
28081
|
+
text: "Failed to handle MCP request on the 2026-07-28 protocol path"
|
|
28082
|
+
}, error);
|
|
28083
|
+
this.logger.trackException(mastraError);
|
|
28084
|
+
this.logger.error("Error handling HTTP request (2026-07-28 path)", { error: mastraError });
|
|
28085
|
+
if (!res.headersSent) {
|
|
28086
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
28087
|
+
res.end(JSON.stringify({
|
|
28088
|
+
jsonrpc: "2.0",
|
|
28089
|
+
error: {
|
|
28090
|
+
code: -32603,
|
|
28091
|
+
message: "Internal server error"
|
|
28092
|
+
},
|
|
28093
|
+
id: null
|
|
28094
|
+
}));
|
|
28095
|
+
}
|
|
28096
|
+
}
|
|
28097
|
+
return;
|
|
28098
|
+
}
|
|
27848
28099
|
if (options?.serverless || options && "sessionIdGenerator" in options && options.sessionIdGenerator === void 0) {
|
|
27849
28100
|
this.logger.debug("Running in stateless mode");
|
|
27850
28101
|
const enableJsonResponse = options?.enableJsonResponse ?? !options?.serverlessStreaming;
|
|
@@ -28098,12 +28349,22 @@ var MCPServer = class extends _mastra_core_mcp.MCPServerBase {
|
|
|
28098
28349
|
stream.onAbort(() => {
|
|
28099
28350
|
this.logger.debug("SSE Transport aborted with sessionId:", { sessionId });
|
|
28100
28351
|
this.sseHonoTransports.delete(sessionId);
|
|
28352
|
+
this.sseHonoAuthInfo.delete(sessionId);
|
|
28101
28353
|
});
|
|
28102
28354
|
try {
|
|
28103
28355
|
await this.server.connect(sseTransport);
|
|
28356
|
+
const onmessage = sseTransport.onmessage?.bind(sseTransport);
|
|
28357
|
+
if (onmessage) sseTransport.onmessage = (message, extra) => {
|
|
28358
|
+
const authInfo = this.sseHonoAuthInfo.get(sessionId);
|
|
28359
|
+
onmessage(message, authInfo ? {
|
|
28360
|
+
...extra,
|
|
28361
|
+
authInfo
|
|
28362
|
+
} : extra);
|
|
28363
|
+
};
|
|
28104
28364
|
this.server.onclose = async () => {
|
|
28105
28365
|
this.logger.debug("SSE Transport closed with sessionId:", { sessionId });
|
|
28106
28366
|
this.sseHonoTransports.delete(sessionId);
|
|
28367
|
+
this.sseHonoAuthInfo.delete(sessionId);
|
|
28107
28368
|
await this.server.close();
|
|
28108
28369
|
};
|
|
28109
28370
|
while (true) {
|
|
@@ -28143,6 +28404,16 @@ var MCPServer = class extends _mastra_core_mcp.MCPServerBase {
|
|
|
28143
28404
|
*/
|
|
28144
28405
|
async close() {
|
|
28145
28406
|
try {
|
|
28407
|
+
if (this.stdioHandle) {
|
|
28408
|
+
await this.stdioHandle.close();
|
|
28409
|
+
this.stdioHandle = void 0;
|
|
28410
|
+
this.stdioServerInstance = void 0;
|
|
28411
|
+
}
|
|
28412
|
+
if (this.modernEraHandler) {
|
|
28413
|
+
await this.modernEraHandler.close();
|
|
28414
|
+
this.modernEraHandler = void 0;
|
|
28415
|
+
this.modernEraNodeHandler = void 0;
|
|
28416
|
+
}
|
|
28146
28417
|
if (this.stdioTransport) {
|
|
28147
28418
|
await this.stdioTransport.close?.();
|
|
28148
28419
|
this.stdioTransport = void 0;
|