@mastra/mcp 0.14.4 → 0.14.5-alpha.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 +9 -0
- package/dist/index.cjs +94 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +94 -0
- package/dist/index.js.map +1 -1
- package/dist/server/server.d.ts +37 -1
- package/dist/server/server.d.ts.map +1 -1
- package/package.json +6 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @mastra/mcp
|
|
2
2
|
|
|
3
|
+
## 0.14.5-alpha.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- add flag to skip sessions and streaming in serverless mcp ([#10927](https://github.com/mastra-ai/mastra/pull/10927))
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`b685c9c`](https://github.com/mastra-ai/mastra/commit/b685c9c0b89f49e0d4542c4ac72569682db69794)]:
|
|
10
|
+
- @mastra/core@0.24.7-alpha.2
|
|
11
|
+
|
|
3
12
|
## 0.14.4
|
|
4
13
|
|
|
5
14
|
### Patch Changes
|
package/dist/index.cjs
CHANGED
|
@@ -2970,6 +2970,7 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2970
2970
|
* @param options.options.onsessioninitialized - Callback when a new session is initialized
|
|
2971
2971
|
* @param options.options.enableJsonResponse - If true, return JSON instead of SSE streaming
|
|
2972
2972
|
* @param options.options.eventStore - Event store for message resumability
|
|
2973
|
+
* @param options.options.serverless - If true, run in stateless mode without session management (ideal for serverless environments)
|
|
2973
2974
|
*
|
|
2974
2975
|
* @throws {MastraError} If HTTP connection setup fails
|
|
2975
2976
|
*
|
|
@@ -2995,6 +2996,25 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2995
2996
|
*
|
|
2996
2997
|
* httpServer.listen(1234);
|
|
2997
2998
|
* ```
|
|
2999
|
+
*
|
|
3000
|
+
* @example Serverless mode (Cloudflare Workers, Vercel Edge, etc.)
|
|
3001
|
+
* ```typescript
|
|
3002
|
+
* export default {
|
|
3003
|
+
* async fetch(request: Request) {
|
|
3004
|
+
* const url = new URL(request.url);
|
|
3005
|
+
* if (url.pathname === '/mcp') {
|
|
3006
|
+
* await server.startHTTP({
|
|
3007
|
+
* url,
|
|
3008
|
+
* httpPath: '/mcp',
|
|
3009
|
+
* req: request,
|
|
3010
|
+
* res: response,
|
|
3011
|
+
* options: { serverless: true },
|
|
3012
|
+
* });
|
|
3013
|
+
* }
|
|
3014
|
+
* return new Response('Not found', { status: 404 });
|
|
3015
|
+
* },
|
|
3016
|
+
* };
|
|
3017
|
+
* ```
|
|
2998
3018
|
*/
|
|
2999
3019
|
async startHTTP({
|
|
3000
3020
|
url,
|
|
@@ -3010,6 +3030,12 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
3010
3030
|
res.end();
|
|
3011
3031
|
return;
|
|
3012
3032
|
}
|
|
3033
|
+
const isStatelessMode = options?.serverless || options && "sessionIdGenerator" in options && options.sessionIdGenerator === void 0;
|
|
3034
|
+
if (isStatelessMode) {
|
|
3035
|
+
this.logger.debug("startHTTP: Running in stateless mode (serverless or sessionIdGenerator: undefined)");
|
|
3036
|
+
await this.handleServerlessRequest(req, res);
|
|
3037
|
+
return;
|
|
3038
|
+
}
|
|
3013
3039
|
const mergedOptions = {
|
|
3014
3040
|
sessionIdGenerator: () => crypto$1.randomUUID(),
|
|
3015
3041
|
// default: enabled
|
|
@@ -3151,6 +3177,74 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
3151
3177
|
}
|
|
3152
3178
|
}
|
|
3153
3179
|
}
|
|
3180
|
+
/**
|
|
3181
|
+
* Handles a stateless, serverless HTTP request without session management.
|
|
3182
|
+
*
|
|
3183
|
+
* This method bypasses all session/transport state and handles each request independently.
|
|
3184
|
+
* For serverless environments (Cloudflare Workers, Vercel Edge, etc.) where
|
|
3185
|
+
* persistent connections and session state cannot be maintained across requests.
|
|
3186
|
+
*
|
|
3187
|
+
* Each request gets a fresh transport and server instance that are discarded after the response.
|
|
3188
|
+
*
|
|
3189
|
+
* @param req - Incoming HTTP request
|
|
3190
|
+
* @param res - HTTP response object
|
|
3191
|
+
* @private
|
|
3192
|
+
*/
|
|
3193
|
+
async handleServerlessRequest(req, res) {
|
|
3194
|
+
try {
|
|
3195
|
+
this.logger.debug(`handleServerlessRequest: Received ${req.method} request`);
|
|
3196
|
+
const body = req.method === "POST" ? await new Promise((resolve, reject) => {
|
|
3197
|
+
let data = "";
|
|
3198
|
+
req.on("data", (chunk) => data += chunk);
|
|
3199
|
+
req.on("end", () => {
|
|
3200
|
+
try {
|
|
3201
|
+
resolve(JSON.parse(data));
|
|
3202
|
+
} catch (e) {
|
|
3203
|
+
reject(new Error(`Invalid JSON in request body: ${e instanceof Error ? e.message : String(e)}`));
|
|
3204
|
+
}
|
|
3205
|
+
});
|
|
3206
|
+
req.on("error", reject);
|
|
3207
|
+
}) : void 0;
|
|
3208
|
+
this.logger.debug(`handleServerlessRequest: Processing ${req.method} request`, {
|
|
3209
|
+
method: body?.method,
|
|
3210
|
+
id: body?.id
|
|
3211
|
+
});
|
|
3212
|
+
const transientServer = this.createServerInstance();
|
|
3213
|
+
const tempTransport = new streamableHttp_js.StreamableHTTPServerTransport({
|
|
3214
|
+
sessionIdGenerator: void 0,
|
|
3215
|
+
enableJsonResponse: true
|
|
3216
|
+
});
|
|
3217
|
+
await transientServer.connect(tempTransport);
|
|
3218
|
+
await tempTransport.handleRequest(req, res, body);
|
|
3219
|
+
this.logger.debug(`handleServerlessRequest: Completed ${body?.method} request`, { id: body?.id });
|
|
3220
|
+
} catch (error$1) {
|
|
3221
|
+
const mastraError = new error.MastraError(
|
|
3222
|
+
{
|
|
3223
|
+
id: "MCP_SERVER_SERVERLESS_REQUEST_FAILED",
|
|
3224
|
+
domain: error.ErrorDomain.MCP,
|
|
3225
|
+
category: error.ErrorCategory.USER,
|
|
3226
|
+
text: "Failed to handle serverless MCP request"
|
|
3227
|
+
},
|
|
3228
|
+
error$1
|
|
3229
|
+
);
|
|
3230
|
+
this.logger.trackException(mastraError);
|
|
3231
|
+
this.logger.error("handleServerlessRequest: Error handling request:", { error: mastraError });
|
|
3232
|
+
if (!res.headersSent) {
|
|
3233
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
3234
|
+
res.end(
|
|
3235
|
+
JSON.stringify({
|
|
3236
|
+
jsonrpc: "2.0",
|
|
3237
|
+
error: {
|
|
3238
|
+
code: -32603,
|
|
3239
|
+
message: "Internal server error",
|
|
3240
|
+
data: error$1 instanceof Error ? error$1.message : String(error$1)
|
|
3241
|
+
},
|
|
3242
|
+
id: null
|
|
3243
|
+
})
|
|
3244
|
+
);
|
|
3245
|
+
}
|
|
3246
|
+
}
|
|
3247
|
+
}
|
|
3154
3248
|
/**
|
|
3155
3249
|
* Establishes the SSE connection for the MCP server.
|
|
3156
3250
|
*
|