@mastra/mcp 2.0.0-alpha.4 → 2.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/dist/client/client.d.ts +11 -0
- package/dist/client/client.d.ts.map +1 -1
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/reference-tools-mcp-server.md +8 -0
- package/dist/index.cjs +203 -115
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +204 -116
- package/dist/index.js.map +1 -1
- package/dist/server/server.d.ts +17 -0
- package/dist/server/server.d.ts.map +1 -1
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -18,7 +18,7 @@ import { makeCoreTool } from "@mastra/core/utils";
|
|
|
18
18
|
import { PromptSchema } from "@modelcontextprotocol/core";
|
|
19
19
|
import { RESOURCE_MIME_TYPE, RESOURCE_URI_META_KEY } from "@modelcontextprotocol/ext-apps";
|
|
20
20
|
import { hostHeaderValidation, originValidation, toNodeHandler } from "@modelcontextprotocol/node";
|
|
21
|
-
import { ProtocolError, ProtocolErrorCode as ProtocolErrorCode$1, Server, createMcpHandler, createRequestStateCodec, inputRequired, inputResponse, specTypeSchemas } from "@modelcontextprotocol/server";
|
|
21
|
+
import { CLIENT_INFO_META_KEY, PROTOCOL_VERSION_META_KEY, ProtocolError, ProtocolErrorCode as ProtocolErrorCode$1, Server, createMcpHandler, createRequestStateCodec, inputRequired, inputResponse, specTypeSchemas } from "@modelcontextprotocol/server";
|
|
22
22
|
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
23
23
|
//#region \0rolldown/runtime.js
|
|
24
24
|
var __defProp$3 = Object.defineProperty;
|
|
@@ -23251,21 +23251,23 @@ var InternalMastraMCPClient = class extends MastraBase {
|
|
|
23251
23251
|
}
|
|
23252
23252
|
async connectStdio(command) {
|
|
23253
23253
|
this.log("debug", `Using Stdio transport for command: ${command}`);
|
|
23254
|
+
const transport = new StdioClientTransport({
|
|
23255
|
+
command,
|
|
23256
|
+
args: this.serverConfig.args,
|
|
23257
|
+
env: this.buildStdioEnv(),
|
|
23258
|
+
stderr: this.serverConfig.stderr,
|
|
23259
|
+
cwd: this.serverConfig.cwd
|
|
23260
|
+
});
|
|
23254
23261
|
try {
|
|
23255
|
-
this.transport
|
|
23256
|
-
command,
|
|
23257
|
-
args: this.serverConfig.args,
|
|
23258
|
-
env: this.buildStdioEnv(),
|
|
23259
|
-
stderr: this.serverConfig.stderr,
|
|
23260
|
-
cwd: this.serverConfig.cwd
|
|
23261
|
-
});
|
|
23262
|
-
await this.client.connect(this.transport, {
|
|
23262
|
+
await this.client.connect(transport, {
|
|
23263
23263
|
timeout: this.serverConfig.timeout ?? this.timeout,
|
|
23264
23264
|
prior: this.priorDiscovery
|
|
23265
23265
|
});
|
|
23266
|
+
this.transport = transport;
|
|
23266
23267
|
this.log("debug", `Successfully connected to MCP server via Stdio`);
|
|
23267
23268
|
} catch (e) {
|
|
23268
23269
|
this.log("error", e instanceof Error ? e.stack || e.message : JSON.stringify(e));
|
|
23270
|
+
await transport.close().catch(() => {});
|
|
23269
23271
|
throw e;
|
|
23270
23272
|
}
|
|
23271
23273
|
}
|
|
@@ -23448,11 +23450,20 @@ var InternalMastraMCPClient = class extends MastraBase {
|
|
|
23448
23450
|
this.clientConnectionOnClose = connectionOnClose;
|
|
23449
23451
|
this.client.onclose = connectionOnClose;
|
|
23450
23452
|
} catch (e) {
|
|
23453
|
+
if (!this.transport) this.unregisterProcessHooks();
|
|
23451
23454
|
this.isConnected = null;
|
|
23452
23455
|
this.priorDiscovery = void 0;
|
|
23453
23456
|
reject(e);
|
|
23454
23457
|
}
|
|
23455
23458
|
});
|
|
23459
|
+
this.registerProcessHooks();
|
|
23460
|
+
return this.isConnected;
|
|
23461
|
+
}
|
|
23462
|
+
/**
|
|
23463
|
+
* Installs the process-exit and signal handlers that tear this client down when the
|
|
23464
|
+
* host process goes away. Idempotent, so repeated connects add at most one of each.
|
|
23465
|
+
*/
|
|
23466
|
+
registerProcessHooks() {
|
|
23456
23467
|
if (!this.exitHookUnsubscribe) this.exitHookUnsubscribe = asyncExitHook(async () => {
|
|
23457
23468
|
this.log("debug", `Disconnecting MCP server during exit`);
|
|
23458
23469
|
await this.disconnect();
|
|
@@ -23465,7 +23476,25 @@ var InternalMastraMCPClient = class extends MastraBase {
|
|
|
23465
23476
|
this.sigHupHandler = () => gracefulExit();
|
|
23466
23477
|
process.on("SIGHUP", this.sigHupHandler);
|
|
23467
23478
|
}
|
|
23468
|
-
|
|
23479
|
+
}
|
|
23480
|
+
/**
|
|
23481
|
+
* Removes whatever {@link registerProcessHooks} installed. Keyed on the handlers this
|
|
23482
|
+
* client actually registered rather than on connection state, so a client that never
|
|
23483
|
+
* reached a transport still releases its process listeners.
|
|
23484
|
+
*/
|
|
23485
|
+
unregisterProcessHooks() {
|
|
23486
|
+
if (this.exitHookUnsubscribe) {
|
|
23487
|
+
this.exitHookUnsubscribe();
|
|
23488
|
+
this.exitHookUnsubscribe = void 0;
|
|
23489
|
+
}
|
|
23490
|
+
if (this.sigTermHandler) {
|
|
23491
|
+
process.off("SIGTERM", this.sigTermHandler);
|
|
23492
|
+
this.sigTermHandler = void 0;
|
|
23493
|
+
}
|
|
23494
|
+
if (this.sigHupHandler) {
|
|
23495
|
+
process.off("SIGHUP", this.sigHupHandler);
|
|
23496
|
+
this.sigHupHandler = void 0;
|
|
23497
|
+
}
|
|
23469
23498
|
}
|
|
23470
23499
|
/**
|
|
23471
23500
|
* Gets the stderr stream of the child process, if using stdio transport with `stderr: 'pipe'`.
|
|
@@ -23510,6 +23539,7 @@ var InternalMastraMCPClient = class extends MastraBase {
|
|
|
23510
23539
|
this.closePendingAuthTransport();
|
|
23511
23540
|
if (!this.transport) {
|
|
23512
23541
|
await this.detachStaleClientTransport();
|
|
23542
|
+
this.unregisterProcessHooks();
|
|
23513
23543
|
this.log("debug", "Disconnect called but no transport was connected.");
|
|
23514
23544
|
return;
|
|
23515
23545
|
}
|
|
@@ -23527,18 +23557,7 @@ var InternalMastraMCPClient = class extends MastraBase {
|
|
|
23527
23557
|
this.transport = void 0;
|
|
23528
23558
|
this.isConnected = null;
|
|
23529
23559
|
this.serverInstructions = void 0;
|
|
23530
|
-
|
|
23531
|
-
this.exitHookUnsubscribe();
|
|
23532
|
-
this.exitHookUnsubscribe = void 0;
|
|
23533
|
-
}
|
|
23534
|
-
if (this.sigTermHandler) {
|
|
23535
|
-
process.off("SIGTERM", this.sigTermHandler);
|
|
23536
|
-
this.sigTermHandler = void 0;
|
|
23537
|
-
}
|
|
23538
|
-
if (this.sigHupHandler) {
|
|
23539
|
-
process.off("SIGHUP", this.sigHupHandler);
|
|
23540
|
-
this.sigHupHandler = void 0;
|
|
23541
|
-
}
|
|
23560
|
+
this.unregisterProcessHooks();
|
|
23542
23561
|
}
|
|
23543
23562
|
}
|
|
23544
23563
|
/**
|
|
@@ -26396,6 +26415,95 @@ var MCPServer = class extends MCPServerBase {
|
|
|
26396
26415
|
this.registerPromptHandlers(server);
|
|
26397
26416
|
return server;
|
|
26398
26417
|
}
|
|
26418
|
+
/**
|
|
26419
|
+
* Registers `method` under an `MCP_SERVER_REQUEST` span, so every request the
|
|
26420
|
+
* server answers is recorded — including the list and read methods that never
|
|
26421
|
+
* reach a tool, and requests that fail before any work is done.
|
|
26422
|
+
*/
|
|
26423
|
+
setTracedHandler(server, method, handler) {
|
|
26424
|
+
server.setRequestHandler(method, async (request, ctx) => {
|
|
26425
|
+
const params = request.params;
|
|
26426
|
+
let requestContext;
|
|
26427
|
+
try {
|
|
26428
|
+
requestContext = await toRequestContext(ctx, this.mapAuthInfoToUser);
|
|
26429
|
+
} catch (error) {
|
|
26430
|
+
this.startRequestSpan(method, params, {
|
|
26431
|
+
server,
|
|
26432
|
+
ctx
|
|
26433
|
+
})?.error({ error });
|
|
26434
|
+
throw error;
|
|
26435
|
+
}
|
|
26436
|
+
const requestSpan = this.startRequestSpan(method, params, {
|
|
26437
|
+
server,
|
|
26438
|
+
ctx,
|
|
26439
|
+
requestContext
|
|
26440
|
+
});
|
|
26441
|
+
let reportedError;
|
|
26442
|
+
return this.traceRequest(requestSpan, () => handler(request, ctx, {
|
|
26443
|
+
requestSpan,
|
|
26444
|
+
requestContext,
|
|
26445
|
+
reportError: (error) => {
|
|
26446
|
+
reportedError = error;
|
|
26447
|
+
}
|
|
26448
|
+
}), () => reportedError);
|
|
26449
|
+
});
|
|
26450
|
+
}
|
|
26451
|
+
/**
|
|
26452
|
+
* Opens the span for one served request. `connection` is absent for
|
|
26453
|
+
* {@link executeTool}, which is called in-process and negotiates nothing.
|
|
26454
|
+
*/
|
|
26455
|
+
startRequestSpan(method, params, connection) {
|
|
26456
|
+
const envelope = connection?.ctx?.mcpReq.envelope;
|
|
26457
|
+
const protocolVersion = envelope?.[PROTOCOL_VERSION_META_KEY] ?? connection?.server?.getNegotiatedProtocolVersion();
|
|
26458
|
+
const client = envelope?.[CLIENT_INFO_META_KEY] ?? connection?.server?.getClientVersion();
|
|
26459
|
+
const target = params?.name ?? params?.uri;
|
|
26460
|
+
const targetName = typeof target === "string" ? target : void 0;
|
|
26461
|
+
return getOrCreateSpan({
|
|
26462
|
+
type: SpanType.MCP_SERVER_REQUEST,
|
|
26463
|
+
name: targetName ? `${method} ${targetName}` : method,
|
|
26464
|
+
entityType: EntityType.MCP_SERVER,
|
|
26465
|
+
entityId: this.id,
|
|
26466
|
+
entityName: this.name,
|
|
26467
|
+
input: params,
|
|
26468
|
+
attributes: {
|
|
26469
|
+
mcpMethod: method,
|
|
26470
|
+
targetName,
|
|
26471
|
+
mcpServer: this.name,
|
|
26472
|
+
serverVersion: this.version,
|
|
26473
|
+
mcpProtocolVersion: typeof protocolVersion === "string" ? protocolVersion : void 0,
|
|
26474
|
+
clientName: client?.name,
|
|
26475
|
+
clientVersion: client?.version
|
|
26476
|
+
},
|
|
26477
|
+
tracingContext: {},
|
|
26478
|
+
requestContext: connection?.requestContext,
|
|
26479
|
+
mastra: this.mastra
|
|
26480
|
+
});
|
|
26481
|
+
}
|
|
26482
|
+
/**
|
|
26483
|
+
* Runs `fn` under a request span. Only the protocol's own `isError` marks a
|
|
26484
|
+
* failure; the rest of a result is opaque handler output that may legitimately
|
|
26485
|
+
* carry any field. A thrown error ends the whole span tree and is rethrown.
|
|
26486
|
+
*/
|
|
26487
|
+
async traceRequest(requestSpan, fn, getReportedError) {
|
|
26488
|
+
try {
|
|
26489
|
+
const result = await fn();
|
|
26490
|
+
const errorResult = result;
|
|
26491
|
+
if (errorResult?.isError) requestSpan?.error({ error: getReportedError?.() ?? new MastraError({
|
|
26492
|
+
id: "MCP_SERVER_REQUEST_FAILED",
|
|
26493
|
+
domain: ErrorDomain.MCP,
|
|
26494
|
+
category: ErrorCategory.USER,
|
|
26495
|
+
text: errorResult.content?.map((c) => c.text).filter(Boolean).join("\n")
|
|
26496
|
+
}) });
|
|
26497
|
+
else requestSpan?.end({ output: result });
|
|
26498
|
+
return result;
|
|
26499
|
+
} catch (error) {
|
|
26500
|
+
requestSpan?.error({
|
|
26501
|
+
error,
|
|
26502
|
+
endTree: true
|
|
26503
|
+
});
|
|
26504
|
+
throw error;
|
|
26505
|
+
}
|
|
26506
|
+
}
|
|
26399
26507
|
/** Answers a suspended round: one keyed form derived from the handler's `resumeSchema`. */
|
|
26400
26508
|
async inputRequired(ctx, requestContext, suspension) {
|
|
26401
26509
|
const payload = suspension.suspendPayload;
|
|
@@ -26420,9 +26528,8 @@ var MCPServer = class extends MCPServerBase {
|
|
|
26420
26528
|
})
|
|
26421
26529
|
});
|
|
26422
26530
|
}
|
|
26423
|
-
async serverRequest(ctx, method, name, args, resumeSchema) {
|
|
26531
|
+
async serverRequest(ctx, requestContext, method, name, args, resumeSchema) {
|
|
26424
26532
|
const argsHash = hashArguments(args);
|
|
26425
|
-
const requestContext = await toRequestContext(ctx, this.mapAuthInfoToUser);
|
|
26426
26533
|
const continuation = readContinuation(ctx, requestContext, {
|
|
26427
26534
|
method,
|
|
26428
26535
|
name,
|
|
@@ -26448,11 +26555,10 @@ var MCPServer = class extends MCPServerBase {
|
|
|
26448
26555
|
};
|
|
26449
26556
|
}
|
|
26450
26557
|
registerToolHandlers(server) {
|
|
26451
|
-
|
|
26452
|
-
|
|
26453
|
-
return { tools: (await this.authorizedToolEntries(requestContext)).map(([name, tool]) => this.toMCPTool(name, tool)) };
|
|
26558
|
+
this.setTracedHandler(server, "tools/list", async (_request, _ctx, trace) => {
|
|
26559
|
+
return { tools: (await this.authorizedToolEntries(trace.requestContext)).map(([name, tool]) => this.toMCPTool(name, tool)) };
|
|
26454
26560
|
});
|
|
26455
|
-
|
|
26561
|
+
this.setTracedHandler(server, "tools/call", async (request, ctx, trace) => {
|
|
26456
26562
|
const name = request.params.name;
|
|
26457
26563
|
const tool = this.convertedTools[name];
|
|
26458
26564
|
if (!tool) {
|
|
@@ -26461,43 +26567,25 @@ var MCPServer = class extends MCPServerBase {
|
|
|
26461
26567
|
}
|
|
26462
26568
|
const args = request.params.arguments ?? {};
|
|
26463
26569
|
const argsHash = hashArguments(args);
|
|
26464
|
-
const requestContext =
|
|
26570
|
+
const requestContext = trace.requestContext;
|
|
26465
26571
|
const continuation = readContinuation(ctx, requestContext, {
|
|
26466
26572
|
method: "tools/call",
|
|
26467
26573
|
name,
|
|
26468
26574
|
argsHash
|
|
26469
26575
|
});
|
|
26470
26576
|
const mcp = toToolExecutionContext(ctx, this.name);
|
|
26471
|
-
const span = getOrCreateSpan({
|
|
26472
|
-
type: SpanType.TOOL_CALL,
|
|
26473
|
-
name: `tool: '${name}'`,
|
|
26474
|
-
input: args,
|
|
26475
|
-
entityType: EntityType.TOOL,
|
|
26476
|
-
entityId: name,
|
|
26477
|
-
entityName: name,
|
|
26478
|
-
attributes: {
|
|
26479
|
-
toolType: "tool",
|
|
26480
|
-
toolDescription: tool.description
|
|
26481
|
-
},
|
|
26482
|
-
requestContext,
|
|
26483
|
-
mastra: this.mastra
|
|
26484
|
-
});
|
|
26485
26577
|
const startedAt = Date.now();
|
|
26486
26578
|
try {
|
|
26487
26579
|
await this.enforceToolExecutionFGA(name, requestContext);
|
|
26488
|
-
if (continuation && continuation.outcome !== "accept") {
|
|
26489
|
-
span?.end({ attributes: { success: false } });
|
|
26490
|
-
return errorResult(`Tool '${name}' was ${continuation.outcome === "decline" ? "declined" : "cancelled"}`);
|
|
26491
|
-
}
|
|
26580
|
+
if (continuation && continuation.outcome !== "accept") return errorResult(`Tool '${name}' was ${continuation.outcome === "decline" ? "declined" : "cancelled"}`);
|
|
26492
26581
|
const execution = await this.runTool(name, tool, args, {
|
|
26493
26582
|
requestContext,
|
|
26494
26583
|
mcp,
|
|
26495
|
-
tracingContext: { currentSpan:
|
|
26584
|
+
tracingContext: { currentSpan: trace.requestSpan },
|
|
26496
26585
|
resumeData: continuation?.resumeData,
|
|
26497
26586
|
suspendPayload: continuation?.suspendPayload
|
|
26498
26587
|
});
|
|
26499
26588
|
if (execution.status === "suspended") {
|
|
26500
|
-
span?.end({ attributes: { success: true } });
|
|
26501
26589
|
this.logger.debug(`Tool '${name}' requires client input.`);
|
|
26502
26590
|
return this.inputRequired(ctx, requestContext, {
|
|
26503
26591
|
method: "tools/call",
|
|
@@ -26509,17 +26597,9 @@ var MCPServer = class extends MCPServerBase {
|
|
|
26509
26597
|
});
|
|
26510
26598
|
}
|
|
26511
26599
|
const result = this.toCallToolResult(name, tool, execution.output);
|
|
26512
|
-
span?.end({
|
|
26513
|
-
output: execution.output,
|
|
26514
|
-
attributes: { success: !result.isError }
|
|
26515
|
-
});
|
|
26516
26600
|
this.logger.info(`Tool '${name}' finished in ${Date.now() - startedAt}ms.`);
|
|
26517
26601
|
return result;
|
|
26518
26602
|
} catch (error) {
|
|
26519
|
-
span?.error({
|
|
26520
|
-
error,
|
|
26521
|
-
attributes: { success: false }
|
|
26522
|
-
});
|
|
26523
26603
|
if (error instanceof ProtocolError) throw error;
|
|
26524
26604
|
this.logger.error("Tool execution failed", {
|
|
26525
26605
|
tool: name,
|
|
@@ -26531,6 +26611,7 @@ var MCPServer = class extends MCPServerBase {
|
|
|
26531
26611
|
category: ErrorCategory.USER,
|
|
26532
26612
|
details: { toolName: name }
|
|
26533
26613
|
}, error);
|
|
26614
|
+
trace.reportError(mastraError);
|
|
26534
26615
|
return errorResult(JSON.stringify(mastraError.toJSON()));
|
|
26535
26616
|
}
|
|
26536
26617
|
});
|
|
@@ -26546,6 +26627,7 @@ var MCPServer = class extends MCPServerBase {
|
|
|
26546
26627
|
const output = await tool.execute(args, {
|
|
26547
26628
|
toolCallId: "",
|
|
26548
26629
|
messages: [],
|
|
26630
|
+
skipToolSpan: true,
|
|
26549
26631
|
requestContext: options.requestContext,
|
|
26550
26632
|
tracingContext: options.tracingContext,
|
|
26551
26633
|
abortSignal: options.mcp?.extra.signal,
|
|
@@ -26599,19 +26681,19 @@ var MCPServer = class extends MCPServerBase {
|
|
|
26599
26681
|
const options = this.resourceOptions;
|
|
26600
26682
|
const hasAppResources = this.appResourceList.length > 0;
|
|
26601
26683
|
if (!options && !hasAppResources) return;
|
|
26602
|
-
const listResources = async (ctx) => [...this.appResourceList, ...await options?.listResources({
|
|
26684
|
+
const listResources = async (ctx, requestContext) => [...this.appResourceList, ...await options?.listResources({
|
|
26603
26685
|
extra: toToolExecutionContext(ctx, this.name).extra,
|
|
26604
|
-
requestContext
|
|
26686
|
+
requestContext
|
|
26605
26687
|
}) ?? []];
|
|
26606
|
-
|
|
26607
|
-
|
|
26688
|
+
this.setTracedHandler(server, "resources/list", async (_request, ctx, trace) => ({ resources: await listResources(ctx, trace.requestContext) }));
|
|
26689
|
+
this.setTracedHandler(server, "resources/read", async (request, ctx, trace) => {
|
|
26608
26690
|
const uri = request.params.uri;
|
|
26609
|
-
const resource = (await listResources(ctx)).find((r) => r.uri === uri);
|
|
26691
|
+
const resource = (await listResources(ctx, trace.requestContext)).find((r) => r.uri === uri);
|
|
26610
26692
|
if (!resource) throw new ProtocolError(ProtocolErrorCode$1.InvalidParams, `Resource not found: ${uri}`);
|
|
26611
26693
|
const html = this.appResourceHtml.get(uri);
|
|
26612
26694
|
if (html !== void 0) return { contents: [this.resourceContents(resource, { text: html })] };
|
|
26613
26695
|
if (!options) throw new ProtocolError(ProtocolErrorCode$1.InvalidParams, `Resource not found: ${uri}`);
|
|
26614
|
-
const { request: serverRequest, continuation, suspended, argsHash } = await this.serverRequest(ctx, "resources/read", uri, {}, options.resumeSchema);
|
|
26696
|
+
const { request: serverRequest, continuation, suspended, argsHash } = await this.serverRequest(ctx, trace.requestContext, "resources/read", uri, {}, options.resumeSchema);
|
|
26615
26697
|
if (continuation && continuation.outcome !== "accept") throw new ProtocolError(ProtocolErrorCode$1.InvalidParams, `Reading '${uri}' was ${continuation.outcome}ed`);
|
|
26616
26698
|
const result = await options.getResourceContent({
|
|
26617
26699
|
uri,
|
|
@@ -26629,9 +26711,9 @@ var MCPServer = class extends MCPServerBase {
|
|
|
26629
26711
|
if (result === void 0) throw new Error(`Resource '${uri}' returned no content`);
|
|
26630
26712
|
return { contents: (Array.isArray(result) ? result : [result]).map((content) => this.resourceContents(resource, content)) };
|
|
26631
26713
|
});
|
|
26632
|
-
if (options?.resourceTemplates)
|
|
26714
|
+
if (options?.resourceTemplates) this.setTracedHandler(server, "resources/templates/list", async (_request, ctx, trace) => ({ resourceTemplates: await options.resourceTemplates({
|
|
26633
26715
|
extra: toToolExecutionContext(ctx, this.name).extra,
|
|
26634
|
-
requestContext:
|
|
26716
|
+
requestContext: trace.requestContext
|
|
26635
26717
|
}) }));
|
|
26636
26718
|
}
|
|
26637
26719
|
resourceContents(resource, content) {
|
|
@@ -26653,22 +26735,22 @@ var MCPServer = class extends MCPServerBase {
|
|
|
26653
26735
|
registerPromptHandlers(server) {
|
|
26654
26736
|
const options = this.promptOptions;
|
|
26655
26737
|
if (!options) return;
|
|
26656
|
-
const listPrompts = async (ctx) => {
|
|
26738
|
+
const listPrompts = async (ctx, requestContext) => {
|
|
26657
26739
|
const prompts = await options.listPrompts({
|
|
26658
26740
|
extra: toToolExecutionContext(ctx, this.name).extra,
|
|
26659
|
-
requestContext
|
|
26741
|
+
requestContext
|
|
26660
26742
|
});
|
|
26661
26743
|
for (const prompt of prompts) PromptSchema.parse(prompt);
|
|
26662
26744
|
return prompts;
|
|
26663
26745
|
};
|
|
26664
|
-
|
|
26746
|
+
this.setTracedHandler(server, "prompts/list", async (_request, ctx, trace) => ({ prompts: await listPrompts(ctx, trace.requestContext) }));
|
|
26665
26747
|
if (!options.getPromptMessages) return;
|
|
26666
|
-
|
|
26748
|
+
this.setTracedHandler(server, "prompts/get", async (request, ctx, trace) => {
|
|
26667
26749
|
const { name, arguments: args } = request.params;
|
|
26668
|
-
const prompt = (await listPrompts(ctx)).find((p) => p.name === name);
|
|
26750
|
+
const prompt = (await listPrompts(ctx, trace.requestContext)).find((p) => p.name === name);
|
|
26669
26751
|
if (!prompt) throw new ProtocolError(ProtocolErrorCode$1.InvalidParams, `Prompt "${name}" not found`);
|
|
26670
26752
|
for (const arg of prompt.arguments ?? []) if (arg.required && (args?.[arg.name] === void 0 || args?.[arg.name] === null)) throw new ProtocolError(ProtocolErrorCode$1.InvalidParams, `Missing required argument: ${arg.name}`);
|
|
26671
|
-
const { request: serverRequest, continuation, suspended, argsHash } = await this.serverRequest(ctx, "prompts/get", name, args ?? {}, options.resumeSchema);
|
|
26753
|
+
const { request: serverRequest, continuation, suspended, argsHash } = await this.serverRequest(ctx, trace.requestContext, "prompts/get", name, args ?? {}, options.resumeSchema);
|
|
26672
26754
|
if (continuation && continuation.outcome !== "accept") throw new ProtocolError(ProtocolErrorCode$1.InvalidParams, `Prompt "${name}" was ${continuation.outcome}ed`);
|
|
26673
26755
|
const messages = await options.getPromptMessages({
|
|
26674
26756
|
name,
|
|
@@ -26881,52 +26963,58 @@ var MCPServer = class extends MCPServerBase {
|
|
|
26881
26963
|
* arguments with `resumeData` and `suspendPayload`.
|
|
26882
26964
|
*/
|
|
26883
26965
|
async executeTool(toolId, args, executionContext = {}) {
|
|
26884
|
-
const tool = this.convertedTools[toolId];
|
|
26885
|
-
if (!tool) {
|
|
26886
|
-
this.logger.warn("Unknown tool requested", {
|
|
26887
|
-
tool: toolId,
|
|
26888
|
-
server: this.name
|
|
26889
|
-
});
|
|
26890
|
-
throw new MastraError({
|
|
26891
|
-
id: "MCP_SERVER_TOOL_EXECUTE_PREPARATION_FAILED",
|
|
26892
|
-
domain: ErrorDomain.MCP,
|
|
26893
|
-
category: ErrorCategory.USER,
|
|
26894
|
-
text: `Unknown tool: ${toolId}`,
|
|
26895
|
-
details: { toolId }
|
|
26896
|
-
});
|
|
26897
|
-
}
|
|
26898
26966
|
const requestContext = executionContext.requestContext ?? new RequestContext();
|
|
26899
|
-
|
|
26900
|
-
|
|
26901
|
-
|
|
26902
|
-
|
|
26903
|
-
|
|
26904
|
-
|
|
26905
|
-
|
|
26906
|
-
|
|
26907
|
-
|
|
26908
|
-
|
|
26909
|
-
|
|
26910
|
-
|
|
26911
|
-
|
|
26912
|
-
|
|
26913
|
-
|
|
26914
|
-
|
|
26915
|
-
|
|
26916
|
-
|
|
26917
|
-
|
|
26918
|
-
|
|
26919
|
-
|
|
26920
|
-
|
|
26921
|
-
|
|
26922
|
-
|
|
26923
|
-
|
|
26924
|
-
|
|
26925
|
-
}
|
|
26926
|
-
|
|
26927
|
-
|
|
26928
|
-
|
|
26929
|
-
|
|
26967
|
+
const requestSpan = this.startRequestSpan("tools/call", {
|
|
26968
|
+
name: toolId,
|
|
26969
|
+
arguments: args
|
|
26970
|
+
}, { requestContext });
|
|
26971
|
+
return this.traceRequest(requestSpan, async () => {
|
|
26972
|
+
const tool = this.convertedTools[toolId];
|
|
26973
|
+
if (!tool) {
|
|
26974
|
+
this.logger.warn("Unknown tool requested", {
|
|
26975
|
+
tool: toolId,
|
|
26976
|
+
server: this.name
|
|
26977
|
+
});
|
|
26978
|
+
throw new MastraError({
|
|
26979
|
+
id: "MCP_SERVER_TOOL_EXECUTE_PREPARATION_FAILED",
|
|
26980
|
+
domain: ErrorDomain.MCP,
|
|
26981
|
+
category: ErrorCategory.USER,
|
|
26982
|
+
text: `Unknown tool: ${toolId}`,
|
|
26983
|
+
details: { toolId }
|
|
26984
|
+
});
|
|
26985
|
+
}
|
|
26986
|
+
await this.enforceToolExecutionFGA(toolId, requestContext);
|
|
26987
|
+
try {
|
|
26988
|
+
const execution = await this.runTool(toolId, tool, args, {
|
|
26989
|
+
requestContext,
|
|
26990
|
+
tracingContext: { currentSpan: requestSpan },
|
|
26991
|
+
resumeData: executionContext.resumeData,
|
|
26992
|
+
suspendPayload: executionContext.suspendPayload
|
|
26993
|
+
});
|
|
26994
|
+
if (execution.status === "completed" && isValidationError(execution.output)) throw new MastraError({
|
|
26995
|
+
id: "MCP_SERVER_TOOL_INVALID_INPUT",
|
|
26996
|
+
domain: ErrorDomain.MCP,
|
|
26997
|
+
category: ErrorCategory.USER,
|
|
26998
|
+
text: execution.output.message,
|
|
26999
|
+
details: { toolId }
|
|
27000
|
+
});
|
|
27001
|
+
this.logger.info("Tool executed successfully", { tool: toolId });
|
|
27002
|
+
return execution;
|
|
27003
|
+
} catch (error) {
|
|
27004
|
+
if (error instanceof MastraError && error.id === "MCP_SERVER_TOOL_INVALID_INPUT") throw error;
|
|
27005
|
+
const mastraError = new MastraError({
|
|
27006
|
+
id: "MCP_SERVER_TOOL_EXECUTE_FAILED",
|
|
27007
|
+
domain: ErrorDomain.MCP,
|
|
27008
|
+
category: ErrorCategory.USER,
|
|
27009
|
+
details: {
|
|
27010
|
+
toolId,
|
|
27011
|
+
args: JSON.stringify(args)
|
|
27012
|
+
}
|
|
27013
|
+
}, error);
|
|
27014
|
+
this.logger.trackException(mastraError);
|
|
27015
|
+
throw mastraError;
|
|
27016
|
+
}
|
|
27017
|
+
});
|
|
26930
27018
|
}
|
|
26931
27019
|
/** Reads an `ui://` app resource; application resources require a protocol request. */
|
|
26932
27020
|
async readResource(uri) {
|