@mastra/express 0.0.2-beta.1 → 0.0.2-beta.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/README.md CHANGED
@@ -1,465 +1,71 @@
1
- # @mastra/pg
1
+ # @mastra/express
2
2
 
3
- PostgreSQL implementation for Mastra, providing both vector similarity search (using pgvector) and general storage capabilities with connection pooling and transaction support.
3
+ Express server adapter for Mastra, enabling you to run Mastra with the [Express](https://expressjs.com) framework.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- npm install @mastra/pg
8
+ npm install @mastra/express express
9
9
  ```
10
10
 
11
- ## Prerequisites
12
-
13
- - PostgreSQL server with pgvector extension installed (if using vector store)
14
- - PostgreSQL 11 or higher
15
-
16
11
  ## Usage
17
12
 
18
- ### Vector Store
19
-
20
- #### Basic Configuration
21
-
22
- PgVector supports multiple connection methods:
23
-
24
- **1. Connection String (Recommended)**
25
-
26
13
  ```typescript
27
- import { PgVector } from '@mastra/pg';
14
+ import express from 'express';
15
+ import { MastraServer } from '@mastra/express';
16
+ import { mastra } from './mastra';
28
17
 
29
- const vectorStore = new PgVector({
30
- connectionString: 'postgresql://user:pass@localhost:5432/db',
31
- });
32
- ```
18
+ const app = express();
19
+ const server = new MastraServer({ app, mastra });
33
20
 
34
- **2. Host/Port/Database Configuration**
21
+ await server.init();
35
22
 
36
- ```typescript
37
- const vectorStore = new PgVector({
38
- host: 'localhost',
39
- port: 5432,
40
- database: 'mydb',
41
- user: 'postgres',
42
- password: 'password',
43
- });
44
- ```
45
-
46
- > **Note:** PgVector also supports advanced configurations like Google Cloud SQL Connector via `pg.ClientConfig`.
47
-
48
- #### Advanced Options
49
-
50
- ```typescript
51
- const vectorStore = new PgVector({
52
- connectionString: 'postgresql://user:pass@localhost:5432/db',
53
- schemaName: 'custom_schema', // Use custom schema (default: public)
54
- max: 30, // Max pool connections (default: 20)
55
- idleTimeoutMillis: 60000, // Idle timeout (default: 30000)
56
- pgPoolOptions: {
57
- // Additional pg pool options
58
- connectionTimeoutMillis: 5000,
59
- allowExitOnIdle: true,
60
- },
23
+ app.listen(3000, () => {
24
+ console.log('Server running on http://localhost:3000');
61
25
  });
62
26
  ```
63
27
 
64
- #### Usage Example
65
-
66
- ```typescript
67
- // Create a new table with vector support
68
- await vectorStore.createIndex({
69
- indexName: 'my_vectors',
70
- dimension: 1536,
71
- metric: 'cosine',
72
- // Optional: Configure index type and parameters
73
- indexConfig: {
74
- type: 'hnsw', // 'ivfflat' (default), 'hnsw', or 'flat'
75
- hnsw: {
76
- m: 16, // Number of connections per layer (default: 8)
77
- efConstruction: 64 // Size of dynamic list (default: 32)
78
- }
79
- }
80
- });
81
-
82
- // Add vectors
83
- const ids = await vectorStore.upsert({
84
- indexName: 'my_vectors',
85
- vectors: [[0.1, 0.2, ...], [0.3, 0.4, ...]],
86
- metadata: [{ text: 'doc1' }, { text: 'doc2' }],
87
- });
28
+ ## Adding Custom Routes
88
29
 
89
- // Query vectors
90
- const results = await vectorStore.query({
91
- indexName: 'my_vectors',
92
- queryVector: [0.1, 0.2, ...],
93
- topK: 10, // topK
94
- filter: { text: 'doc1' }, // filter
95
- includeVector: false, // includeVector
96
- minScore: 0.5, // minScore
97
- });
98
-
99
- // Clean up
100
- await vectorStore.disconnect();
101
- ```
102
-
103
- ### Storage
30
+ Add routes directly to the Express app with access to Mastra context:
104
31
 
105
32
  ```typescript
106
- import { PostgresStore } from '@mastra/pg';
107
-
108
- const store = new PostgresStore({
109
- host: 'localhost',
110
- port: 5432,
111
- database: 'mastra',
112
- user: 'postgres',
113
- password: 'postgres',
33
+ // Routes added after init() have access to Mastra context
34
+ app.get('/health', (req, res) => {
35
+ const mastraInstance = res.locals.mastra;
36
+ const agents = Object.keys(mastraInstance.listAgents());
37
+ res.json({ status: 'ok', agents });
114
38
  });
115
-
116
- // Create a thread
117
- await store.saveThread({
118
- id: 'thread-123',
119
- resourceId: 'resource-456',
120
- title: 'My Thread',
121
- metadata: { key: 'value' },
122
- });
123
-
124
- // Add messages to thread
125
- await store.saveMessages([
126
- {
127
- id: 'msg-789',
128
- threadId: 'thread-123',
129
- role: 'user',
130
- type: 'text',
131
- content: [{ type: 'text', text: 'Hello' }],
132
- },
133
- ]);
134
-
135
- // Query threads and messages
136
- const savedThread = await store.getThread('thread-123');
137
- const messages = await store.getMessages('thread-123');
138
- ```
139
-
140
- ## Configuration
141
-
142
- ### Connection Methods
143
-
144
- Both `PgVector` and `PostgresStore` support multiple connection methods:
145
-
146
- 1. **Connection String**
147
-
148
- ```typescript
149
- {
150
- connectionString: 'postgresql://user:pass@localhost:5432/db';
151
- }
152
- ```
153
-
154
- 2. **Host/Port/Database**
155
- ```typescript
156
- {
157
- host: 'localhost',
158
- port: 5432,
159
- database: 'mydb',
160
- user: 'postgres',
161
- password: 'password'
162
- }
163
- ```
164
-
165
- > **Advanced:** Also supports `pg.ClientConfig` for use cases like Google Cloud SQL Connector with IAM authentication.
166
-
167
- ### Optional Configuration
168
-
169
- - `schemaName`: Custom PostgreSQL schema (default: `public`)
170
- - `ssl`: Enable SSL or provide custom SSL options (`true` | `false` | `ConnectionOptions`)
171
- - `max`: Maximum pool connections (default: `20`)
172
- - `idleTimeoutMillis`: Idle connection timeout (default: `30000`)
173
- - `pgPoolOptions`: Additional pg pool options (PgVector only)
174
-
175
- ### Default Connection Pool Settings
176
-
177
- - Maximum connections: 20
178
- - Idle timeout: 30 seconds
179
- - Connection timeout: 2 seconds
180
-
181
- ## Features
182
-
183
- ### Vector Store Features
184
-
185
- - Vector similarity search with cosine, euclidean, and dot product (inner) metrics
186
- - Advanced metadata filtering with MongoDB-like query syntax
187
- - Minimum score threshold for queries
188
- - Automatic UUID generation for vectors
189
- - Table management (create, list, describe, delete, truncate)
190
- - Configurable vector index types:
191
- - **IVFFlat** (default): Balanced speed/accuracy, auto-calculates optimal lists parameter
192
- - **HNSW**: Fastest queries, higher memory usage, best for large datasets
193
- - **Flat**: No index, 100% accuracy, best for small datasets (<1000 vectors)
194
-
195
- ### Storage Features
196
-
197
- - Thread and message storage with JSON support
198
- - Atomic transactions for data consistency
199
- - Efficient batch operations
200
- - Rich metadata support
201
- - Timestamp tracking
202
- - Cascading deletes
203
-
204
- ## Supported Filter Operators
205
-
206
- The following filter operators are supported for metadata queries:
207
-
208
- - Comparison: `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`
209
- - Logical: `$and`, `$or`
210
- - Array: `$in`, `$nin`
211
- - Text: `$regex`, `$like`
212
-
213
- Example filter:
214
-
215
- ```typescript
216
- {
217
- $and: [{ age: { $gt: 25 } }, { tags: { $in: ['tag1', 'tag2'] } }];
218
- }
219
39
  ```
220
40
 
221
- ## Vector Index Configuration
222
-
223
- pgvector supports three index types, each with different performance characteristics:
224
-
225
- ### IVFFlat Index (Default)
226
-
227
- IVFFlat groups vectors into clusters for efficient searching:
41
+ ## Configuration Options
228
42
 
229
43
  ```typescript
230
- await vectorStore.createIndex({
231
- indexName: 'my_vectors',
232
- dimension: 1536,
233
- metric: 'cosine',
234
- indexConfig: {
235
- type: 'ivfflat',
236
- ivf: {
237
- lists: 1000, // Number of clusters (default: auto-calculated as sqrt(rows) * 2)
238
- },
44
+ const server = new MastraServer({
45
+ app,
46
+ mastra,
47
+ prefix: '/api/v2', // Route prefix
48
+ openapiPath: '/openapi.json', // OpenAPI spec endpoint
49
+ bodyLimitOptions: {
50
+ maxSize: 10 * 1024 * 1024, // 10MB
51
+ onError: err => ({ error: 'Payload too large' }),
239
52
  },
53
+ streamOptions: { redact: true }, // Redact sensitive data from streams
240
54
  });
241
55
  ```
242
56
 
243
- - **Best for:** Medium to large datasets (10K-1M vectors)
244
- - **Build time:** Minutes for millions of vectors
245
- - **Query speed:** Fast (tens of milliseconds)
246
- - **Memory:** Moderate
247
- - **Accuracy:** ~95-99%
57
+ ## Context Variables
248
58
 
249
- ### HNSW Index
59
+ Access these in route handlers via `res.locals`:
250
60
 
251
- HNSW builds a graph structure for extremely fast searches:
252
-
253
- ```typescript
254
- await vectorStore.createIndex({
255
- indexName: 'my_vectors',
256
- dimension: 1536,
257
- metric: 'dotproduct', // Recommended for normalized embeddings (OpenAI, etc.)
258
- indexConfig: {
259
- type: 'hnsw',
260
- hnsw: {
261
- m: 16, // Connections per layer (default: 8, range: 2-100)
262
- efConstruction: 64, // Dynamic list size (default: 32, range: 4-1000)
263
- },
264
- },
265
- });
266
- ```
267
-
268
- - **Best for:** Large datasets (100K+ vectors) requiring fastest searches
269
- - **Build time:** Can take hours for large datasets
270
- - **Query speed:** Very fast (milliseconds even for millions)
271
- - **Memory:** High (can be 2-3x vector size)
272
- - **Accuracy:** ~99%
273
-
274
- **Tuning HNSW:**
275
-
276
- - Higher `m`: Better accuracy, more memory (16-32 for high accuracy)
277
- - Higher `efConstruction`: Better index quality, slower builds (64-200 for quality)
278
-
279
- ### Flat Index (No Index)
280
-
281
- Uses sequential scan for 100% accuracy:
282
-
283
- ```typescript
284
- await vectorStore.createIndex({
285
- indexName: 'my_vectors',
286
- dimension: 1536,
287
- metric: 'cosine',
288
- indexConfig: {
289
- type: 'flat',
290
- },
291
- });
292
- ```
293
-
294
- - **Best for:** Small datasets (<1000 vectors) or when 100% accuracy is required
295
- - **Build time:** None
296
- - **Query speed:** Slow for large datasets (linear scan)
297
- - **Memory:** Minimal (just vectors)
298
- - **Accuracy:** 100%
299
-
300
- ### Distance Metrics
301
-
302
- Choose the appropriate metric for your embeddings:
303
-
304
- - **`cosine`** (default): Angular similarity, good for text embeddings
305
- - **`euclidean`**: L2 distance, for unnormalized embeddings
306
- - **`dotproduct`**: Dot product, optimal for normalized embeddings (OpenAI, Cohere)
307
-
308
- ### Index Recreation
309
-
310
- The system automatically detects configuration changes and only rebuilds indexes when necessary, preventing the performance issues from unnecessary recreations.
311
-
312
- **Important behaviors:**
313
-
314
- - If no `indexConfig` is provided, existing indexes are preserved as-is
315
- - If `indexConfig` is provided, indexes are only rebuilt if the configuration differs
316
- - New indexes default to IVFFlat with cosine distance when no config is specified
317
-
318
- ## Vector Store Methods
319
-
320
- - `createIndex({indexName, dimension, metric?, indexConfig?, buildIndex?})`: Create a new table with vector support
321
- - `buildIndex({indexName, metric?, indexConfig?})`: Build or rebuild vector index
322
- - `upsert({indexName, vectors, metadata?, ids?})`: Add or update vectors
323
- - `query({indexName, queryVector, topK?, filter?, includeVector?, minScore?})`: Search for similar vectors
324
- - `listIndexes()`: List all vector-enabled tables
325
- - `describeIndex(indexName)`: Get table statistics and index configuration
326
- - `deleteIndex(indexName)`: Delete a table
327
- - `truncateIndex(indexName)`: Remove all data from a table
328
- - `disconnect()`: Close all database connections
329
-
330
- ## Storage Methods
331
-
332
- - `saveThread(thread)`: Create or update a thread
333
- - `getThread(threadId)`: Get a thread by ID
334
- - `deleteThread(threadId)`: Delete a thread and its messages
335
- - `saveMessages(messages)`: Save multiple messages in a transaction
336
- - `getMessages(threadId)`: Get all messages for a thread
337
- - `deleteMessages(messageIds)`: Delete specific messages
338
-
339
- ## Index Management
340
-
341
- The PostgreSQL store provides comprehensive index management capabilities to optimize query performance.
342
-
343
- ### Automatic Performance Indexes
344
-
345
- PostgreSQL storage automatically creates composite indexes during initialization for common query patterns:
346
-
347
- - `mastra_threads_resourceid_createdat_idx`: (resourceId, createdAt DESC)
348
- - `mastra_messages_thread_id_createdat_idx`: (thread_id, createdAt DESC)
349
- - `mastra_traces_name_starttime_idx`: (name, startTime DESC)
350
- - `mastra_evals_agent_name_created_at_idx`: (agent_name, created_at DESC)
351
-
352
- These indexes significantly improve performance for filtered queries with sorting.
353
-
354
- ### Creating Custom Indexes
355
-
356
- Create additional indexes to optimize specific query patterns:
357
-
358
- ```typescript
359
- // Basic index for common queries
360
- await store.createIndex({
361
- name: 'idx_threads_resource',
362
- table: 'mastra_threads',
363
- columns: ['resourceId'],
364
- });
365
-
366
- // Composite index with sort order for filtering + sorting
367
- await store.createIndex({
368
- name: 'idx_messages_composite',
369
- table: 'mastra_messages',
370
- columns: ['thread_id', 'createdAt DESC'],
371
- });
372
-
373
- // GIN index for JSONB columns (fast JSON queries)
374
- await store.createIndex({
375
- name: 'idx_traces_attributes',
376
- table: 'mastra_traces',
377
- columns: ['attributes'],
378
- method: 'gin',
379
- });
380
- ```
381
-
382
- For more advanced use cases, you can also use:
383
-
384
- - `unique: true` for unique constraints
385
- - `where: 'condition'` for partial indexes
386
- - `method: 'brin'` for time-series data
387
- - `storage: { fillfactor: 90 }` for update-heavy tables
388
- - `concurrent: true` for non-blocking creation (default)
389
-
390
- ### Managing Indexes
391
-
392
- ```typescript
393
- // List all indexes
394
- const allIndexes = await store.listIndexes();
395
-
396
- // List indexes for specific table
397
- const threadIndexes = await store.listIndexes('mastra_threads');
398
-
399
- // Get detailed statistics for an index
400
- const stats = await store.describeIndex('idx_threads_resource');
401
- console.log(stats);
402
- // {
403
- // name: 'idx_threads_resource',
404
- // table: 'mastra_threads',
405
- // columns: ['resourceId', 'createdAt'],
406
- // unique: false,
407
- // size: '128 KB',
408
- // definition: 'CREATE INDEX idx_threads_resource...',
409
- // method: 'btree',
410
- // scans: 1542, // Number of index scans
411
- // tuples_read: 45230, // Tuples read via index
412
- // tuples_fetched: 12050 // Tuples fetched via index
413
- // }
414
-
415
- // Drop an index
416
- await store.dropIndex('idx_threads_status');
417
- ```
418
-
419
- ### Index Types and Use Cases
420
-
421
- | Index Type | Best For | Storage | Speed |
422
- | ------------------- | --------------------------------------- | ---------- | -------------------------- |
423
- | **btree** (default) | Range queries, sorting, general purpose | Moderate | Fast |
424
- | **hash** | Equality comparisons only | Small | Very fast for `=` |
425
- | **gin** | JSONB, arrays, full-text search | Large | Fast for contains |
426
- | **gist** | Geometric data, full-text search | Moderate | Fast for nearest-neighbor |
427
- | **spgist** | Non-balanced data, text patterns | Small | Fast for specific patterns |
428
- | **brin** | Large tables with natural ordering | Very small | Fast for ranges |
429
-
430
- ### Index Options
431
-
432
- - `name` (required): Index name
433
- - `table` (required): Table name
434
- - `columns` (required): Array of column names (can include DESC/ASC)
435
- - `unique`: Create unique index (default: false)
436
- - `concurrent`: Non-blocking index creation (default: true)
437
- - `where`: Partial index condition
438
- - `method`: Index type ('btree' | 'hash' | 'gin' | 'gist' | 'spgist' | 'brin')
439
- - `opclass`: Operator class for GIN/GIST indexes
440
- - `storage`: Storage parameters (e.g., { fillfactor: 90 })
441
- - `tablespace`: Tablespace name for index placement
442
-
443
- ### Monitoring Index Performance
444
-
445
- ```typescript
446
- // Check index usage statistics
447
- const stats = await store.describeIndex('idx_threads_resource');
448
-
449
- // Identify unused indexes
450
- if (stats.scans === 0) {
451
- console.log(`Index ${stats.name} is unused - consider removing`);
452
- await store.dropIndex(stats.name);
453
- }
454
-
455
- // Monitor index efficiency
456
- const efficiency = stats.tuples_fetched / stats.tuples_read;
457
- if (efficiency < 0.5) {
458
- console.log(`Index ${stats.name} has low efficiency: ${efficiency}`);
459
- }
460
- ```
61
+ | Key | Description |
62
+ | ---------------- | --------------------------- |
63
+ | `mastra` | Mastra instance |
64
+ | `requestContext` | Request context map |
65
+ | `abortSignal` | Request cancellation signal |
66
+ | `tools` | Available tools |
461
67
 
462
68
  ## Related Links
463
69
 
464
- - [pgvector Documentation](https://github.com/pgvector/pgvector)
465
- - [PostgreSQL Documentation](https://www.postgresql.org/docs/)
70
+ - [Server Adapters Documentation](https://mastra.ai/docs/v1/server-db/server-adapters)
71
+ - [Express Documentation](https://expressjs.com)
package/dist/index.cjs CHANGED
@@ -163,8 +163,10 @@ var MastraServer = class extends serverAdapter.MastraServer {
163
163
  res.locals.isDev = this.isDev === true;
164
164
  res.locals.customRouteAuthConfig = this.customRouteAuthConfig;
165
165
  const controller = new AbortController();
166
- req.on("close", () => {
167
- controller.abort();
166
+ res.on("close", () => {
167
+ if (!res.writableFinished) {
168
+ controller.abort();
169
+ }
168
170
  });
169
171
  res.locals.abortSignal = controller.signal;
170
172
  next();
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/auth-middleware.ts","../src/index.ts"],"names":["isDevPlaygroundRequest","isProtectedPath","canAccessPublicly","checkRules","defaultAuthConfig","MastraServerBase","redactStreamChunk"],"mappings":"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","file":"index.cjs","sourcesContent":["import {\n canAccessPublicly,\n checkRules,\n defaultAuthConfig,\n isDevPlaygroundRequest,\n isProtectedPath,\n} from '@mastra/server/auth';\nimport type { NextFunction, Request, Response } from 'express';\n\nexport const authenticationMiddleware = async (req: Request, res: Response, next: NextFunction) => {\n const mastra = res.locals.mastra;\n const authConfig = mastra.getServer()?.auth;\n const customRouteAuthConfig = res.locals.customRouteAuthConfig;\n\n if (!authConfig) {\n // No auth config, skip authentication\n return next();\n }\n\n const path = req.path;\n const method = req.method;\n const getHeader = (name: string) => req.headers[name.toLowerCase()] as string | undefined;\n\n if (isDevPlaygroundRequest(path, method, getHeader, authConfig)) {\n // Skip authentication for dev playground requests\n return next();\n }\n\n if (!isProtectedPath(req.path, req.method, authConfig, customRouteAuthConfig)) {\n return next();\n }\n\n // Skip authentication for public routes\n if (canAccessPublicly(req.path, req.method, authConfig)) {\n return next();\n }\n\n // Get token from header or query\n const authHeader = req.headers.authorization;\n let token: string | null = authHeader ? authHeader.replace('Bearer ', '') : null;\n\n if (!token && req.query.apiKey) {\n token = (req.query.apiKey as string) || null;\n }\n\n // Handle missing token\n if (!token) {\n return res.status(401).json({ error: 'Authentication required' });\n }\n\n try {\n // Verify token and get user data\n let user: unknown;\n\n // Client provided verify function\n if (typeof authConfig.authenticateToken === 'function') {\n // Note: Express doesn't have HonoRequest, so we pass the Express Request\n // The auth config function signature accepts HonoRequest, but in practice\n // it should work with any request object that has the necessary properties\n user = await authConfig.authenticateToken(token, req as any);\n } else {\n throw new Error('No token verification method configured');\n }\n\n if (!user) {\n return res.status(401).json({ error: 'Invalid or expired token' });\n }\n\n // Store user in context\n res.locals.requestContext.set('user', user);\n\n return next();\n } catch (err) {\n console.error(err);\n return res.status(401).json({ error: 'Invalid or expired token' });\n }\n};\n\nexport const authorizationMiddleware = async (req: Request, res: Response, next: NextFunction) => {\n const mastra = res.locals.mastra;\n const authConfig = mastra.getServer()?.auth;\n const customRouteAuthConfig = res.locals.customRouteAuthConfig;\n\n if (!authConfig) {\n // No auth config, skip authorization\n return next();\n }\n\n const path = req.path;\n const method = req.method;\n const getHeader = (name: string) => req.headers[name.toLowerCase()] as string | undefined;\n\n if (isDevPlaygroundRequest(path, method, getHeader, authConfig)) {\n // Skip authorization for dev playground requests\n return next();\n }\n\n if (!isProtectedPath(req.path, req.method, authConfig, customRouteAuthConfig)) {\n return next();\n }\n\n // Skip for public routes\n if (canAccessPublicly(path, method, authConfig)) {\n return next();\n }\n\n const user = res.locals.requestContext.get('user');\n\n if ('authorizeUser' in authConfig && typeof authConfig.authorizeUser === 'function') {\n try {\n const isAuthorized = await authConfig.authorizeUser(user, req as any);\n\n if (isAuthorized) {\n return next();\n }\n\n return res.status(403).json({ error: 'Access denied' });\n } catch (err) {\n console.error(err);\n return res.status(500).json({ error: 'Authorization error' });\n }\n }\n\n // Client-provided authorization function\n if ('authorize' in authConfig && typeof authConfig.authorize === 'function') {\n try {\n // Note: The authorize function signature expects ContextWithMastra as 4th param\n // For Express, we pass a compatible object with similar structure\n const context = {\n get: (key: string) => {\n if (key === 'mastra') return res.locals.mastra;\n if (key === 'requestContext') return res.locals.requestContext;\n if (key === 'tools') return res.locals.tools;\n if (key === 'taskStore') return res.locals.taskStore;\n if (key === 'customRouteAuthConfig') return res.locals.customRouteAuthConfig;\n if (key === 'playground') return res.locals.playground;\n if (key === 'isDev') return res.locals.isDev;\n return undefined;\n },\n req: req as any,\n } as any;\n\n const isAuthorized = await authConfig.authorize(path, method, user, context);\n\n if (isAuthorized) {\n return next();\n }\n\n return res.status(403).json({ error: 'Access denied' });\n } catch (err) {\n console.error(err);\n return res.status(500).json({ error: 'Authorization error' });\n }\n }\n\n // Custom rule-based authorization\n if ('rules' in authConfig && authConfig.rules && authConfig.rules.length > 0) {\n const isAuthorized = await checkRules(authConfig.rules, path, method, user);\n\n if (isAuthorized) {\n return next();\n }\n\n return res.status(403).json({ error: 'Access denied' });\n }\n\n // Default rule-based authorization\n if (defaultAuthConfig.rules && defaultAuthConfig.rules.length > 0) {\n const isAuthorized = await checkRules(defaultAuthConfig.rules, path, method, user);\n\n if (isAuthorized) {\n return next();\n }\n }\n\n return res.status(403).json({ error: 'Access denied' });\n};\n","import type { Mastra } from '@mastra/core/mastra';\nimport type { RequestContext } from '@mastra/core/request-context';\nimport type { Tool } from '@mastra/core/tools';\nimport type { InMemoryTaskStore } from '@mastra/server/a2a/store';\nimport type { MCPHttpTransportResult, MCPSseTransportResult } from '@mastra/server/handlers/mcp';\nimport type { ServerRoute } from '@mastra/server/server-adapter';\nimport { MastraServer as MastraServerBase, redactStreamChunk } from '@mastra/server/server-adapter';\nimport type { Application, NextFunction, Request, Response } from 'express';\n\nimport { authenticationMiddleware, authorizationMiddleware } from './auth-middleware';\n\n// Extend Express types to include Mastra context\ndeclare global {\n namespace Express {\n interface Locals {\n mastra: Mastra;\n requestContext: RequestContext;\n abortSignal: AbortSignal;\n tools: Record<string, Tool>;\n taskStore: InMemoryTaskStore;\n customRouteAuthConfig?: Map<string, boolean>;\n playground?: boolean;\n isDev?: boolean;\n }\n }\n}\n\nexport class MastraServer extends MastraServerBase<Application, Request, Response> {\n createContextMiddleware(): (req: Request, res: Response, next: NextFunction) => Promise<void> {\n return async (req: Request, res: Response, next: NextFunction) => {\n // Parse request context from request body and add to context\n let bodyRequestContext: Record<string, any> | undefined;\n let paramsRequestContext: Record<string, any> | undefined;\n\n // Parse request context from request body (POST/PUT)\n if (req.method === 'POST' || req.method === 'PUT') {\n const contentType = req.headers['content-type'];\n if (contentType?.includes('application/json') && req.body) {\n if (req.body.requestContext) {\n bodyRequestContext = req.body.requestContext;\n }\n }\n }\n\n // Parse request context from query params (GET)\n if (req.method === 'GET') {\n try {\n const encodedRequestContext = req.query.requestContext;\n if (typeof encodedRequestContext === 'string') {\n // Try JSON first\n try {\n paramsRequestContext = JSON.parse(encodedRequestContext);\n } catch {\n // Fallback to base64(JSON)\n try {\n const json = Buffer.from(encodedRequestContext, 'base64').toString('utf-8');\n paramsRequestContext = JSON.parse(json);\n } catch {\n // ignore if still invalid\n }\n }\n }\n } catch {\n // ignore query parsing errors\n }\n }\n\n const requestContext = this.mergeRequestContext({ paramsRequestContext, bodyRequestContext });\n\n // Set context in res.locals\n res.locals.requestContext = requestContext;\n res.locals.mastra = this.mastra;\n res.locals.tools = this.tools || {};\n if (this.taskStore) {\n res.locals.taskStore = this.taskStore;\n }\n res.locals.playground = this.playground === true;\n res.locals.isDev = this.isDev === true;\n res.locals.customRouteAuthConfig = this.customRouteAuthConfig;\n const controller = new AbortController();\n req.on('close', () => {\n controller.abort();\n });\n res.locals.abortSignal = controller.signal;\n next();\n };\n }\n async stream(route: ServerRoute, res: Response, result: { fullStream: ReadableStream }): Promise<void> {\n res.setHeader('Content-Type', 'text/plain');\n res.setHeader('Transfer-Encoding', 'chunked');\n\n const streamFormat = route.streamFormat || 'stream';\n\n const readableStream = result instanceof ReadableStream ? result : result.fullStream;\n const reader = readableStream.getReader();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n if (value) {\n // Optionally redact sensitive data (system prompts, tool definitions, API keys) before sending to the client\n const shouldRedact = this.streamOptions?.redact ?? true;\n const outputValue = shouldRedact ? redactStreamChunk(value) : value;\n if (streamFormat === 'sse') {\n res.write(`data: ${JSON.stringify(outputValue)}\\n\\n`);\n } else {\n res.write(JSON.stringify(outputValue) + '\\x1E');\n }\n }\n }\n } catch (error) {\n console.error(error);\n } finally {\n res.end();\n }\n }\n\n async getParams(\n route: ServerRoute,\n request: Request,\n ): Promise<{ urlParams: Record<string, string>; queryParams: Record<string, string>; body: unknown }> {\n const urlParams = request.params;\n const queryParams = request.query;\n const body = await request.body;\n return { urlParams, queryParams: queryParams as Record<string, string>, body };\n }\n\n async sendResponse(route: ServerRoute, response: Response, result: unknown, request?: Request): Promise<void> {\n if (route.responseType === 'json') {\n response.json(result);\n } else if (route.responseType === 'stream') {\n await this.stream(route, response, result as { fullStream: ReadableStream });\n } else if (route.responseType === 'datastream-response') {\n // Handle AI SDK Response objects - pipe Response.body to Express response\n const fetchResponse = result as globalThis.Response;\n fetchResponse.headers.forEach((value, key) => response.setHeader(key, value));\n response.status(fetchResponse.status);\n if (fetchResponse.body) {\n const reader = fetchResponse.body.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n response.write(value);\n }\n } finally {\n response.end();\n }\n } else {\n response.end();\n }\n } else if (route.responseType === 'mcp-http') {\n // MCP Streamable HTTP transport - request is required\n if (!request) {\n response.status(500).json({ error: 'Request object required for MCP transport' });\n return;\n }\n\n const { server, httpPath } = result as MCPHttpTransportResult;\n\n try {\n await server.startHTTP({\n url: new URL(request.url, `http://${request.headers.host}`),\n httpPath,\n req: request,\n res: response,\n });\n // Response handled by startHTTP\n } catch {\n if (!response.headersSent) {\n response.status(500).json({\n jsonrpc: '2.0',\n error: { code: -32603, message: 'Internal server error' },\n id: null,\n });\n }\n }\n } else if (route.responseType === 'mcp-sse') {\n // MCP SSE transport - request is required\n if (!request) {\n response.status(500).json({ error: 'Request object required for MCP transport' });\n return;\n }\n\n const { server, ssePath, messagePath } = result as MCPSseTransportResult;\n\n try {\n await server.startSSE({\n url: new URL(request.url, `http://${request.headers.host}`),\n ssePath,\n messagePath,\n req: request,\n res: response,\n });\n // Response handled by startSSE\n } catch {\n if (!response.headersSent) {\n response.status(500).json({ error: 'Error handling MCP SSE request' });\n }\n }\n } else {\n response.sendStatus(500);\n }\n }\n\n async registerRoute(app: Application, route: ServerRoute, { prefix }: { prefix?: string }): Promise<void> {\n // Determine if body limits should be applied\n const shouldApplyBodyLimit = this.bodyLimitOptions && ['POST', 'PUT', 'PATCH'].includes(route.method.toUpperCase());\n\n // Get the body size limit for this route (route-specific or default)\n const maxSize = route.maxBodySize ?? this.bodyLimitOptions?.maxSize;\n\n // Create middleware array\n const middlewares: Array<(req: Request, res: Response, next: NextFunction) => void> = [];\n\n // Add body limit middleware if needed\n if (shouldApplyBodyLimit && maxSize && this.bodyLimitOptions) {\n const bodyLimitMiddleware = (req: Request, res: Response, next: NextFunction) => {\n const contentLength = req.headers['content-length'];\n if (contentLength && parseInt(contentLength, 10) > maxSize) {\n try {\n const errorResponse = this.bodyLimitOptions!.onError({ error: 'Request body too large' });\n return res.status(413).json(errorResponse);\n } catch {\n return res.status(413).json({ error: 'Request body too large' });\n }\n }\n next();\n };\n middlewares.push(bodyLimitMiddleware);\n }\n\n app[route.method.toLowerCase() as keyof Application](\n `${prefix}${route.path}`,\n ...middlewares,\n async (req: Request, res: Response) => {\n const params = await this.getParams(route, req);\n\n if (params.queryParams) {\n try {\n params.queryParams = await this.parseQueryParams(route, params.queryParams as Record<string, string>);\n } catch (error) {\n console.error('Error parsing query params', error);\n // Zod validation errors should return 400 Bad Request, not 500\n return res.status(400).json({\n error: 'Invalid query parameters',\n details: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n\n if (params.body) {\n try {\n params.body = await this.parseBody(route, params.body);\n } catch (error) {\n console.error('Error parsing body:', error instanceof Error ? error.message : String(error));\n // Zod validation errors should return 400 Bad Request, not 500\n return res.status(400).json({\n error: 'Invalid request body',\n details: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n\n const handlerParams = {\n ...params.urlParams,\n ...params.queryParams,\n ...(typeof params.body === 'object' ? params.body : {}),\n requestContext: res.locals.requestContext,\n mastra: this.mastra,\n tools: res.locals.tools,\n taskStore: res.locals.taskStore,\n abortSignal: res.locals.abortSignal,\n };\n\n try {\n const result = await route.handler(handlerParams);\n await this.sendResponse(route, res, result, req);\n } catch (error) {\n console.error('Error calling handler', error);\n // Check if it's an HTTPException or MastraError with a status code\n let status = 500;\n if (error && typeof error === 'object') {\n // Check for direct status property (HTTPException)\n if ('status' in error) {\n status = (error as any).status;\n }\n // Check for MastraError with status in details\n else if (\n 'details' in error &&\n error.details &&\n typeof error.details === 'object' &&\n 'status' in error.details\n ) {\n status = (error.details as any).status;\n }\n }\n res.status(status).json({ error: error instanceof Error ? error.message : 'Unknown error' });\n }\n },\n );\n }\n\n registerContextMiddleware(): void {\n this.app.use(this.createContextMiddleware());\n }\n\n registerAuthMiddleware(): void {\n const authConfig = this.mastra.getServer()?.auth;\n if (!authConfig) {\n // No auth config, skip registration\n return;\n }\n\n this.app.use(authenticationMiddleware);\n this.app.use(authorizationMiddleware);\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/auth-middleware.ts","../src/index.ts"],"names":["isDevPlaygroundRequest","isProtectedPath","canAccessPublicly","checkRules","defaultAuthConfig","MastraServerBase","redactStreamChunk"],"mappings":"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","file":"index.cjs","sourcesContent":["import {\n canAccessPublicly,\n checkRules,\n defaultAuthConfig,\n isDevPlaygroundRequest,\n isProtectedPath,\n} from '@mastra/server/auth';\nimport type { NextFunction, Request, Response } from 'express';\n\nexport const authenticationMiddleware = async (req: Request, res: Response, next: NextFunction) => {\n const mastra = res.locals.mastra;\n const authConfig = mastra.getServer()?.auth;\n const customRouteAuthConfig = res.locals.customRouteAuthConfig;\n\n if (!authConfig) {\n // No auth config, skip authentication\n return next();\n }\n\n const path = req.path;\n const method = req.method;\n const getHeader = (name: string) => req.headers[name.toLowerCase()] as string | undefined;\n\n if (isDevPlaygroundRequest(path, method, getHeader, authConfig)) {\n // Skip authentication for dev playground requests\n return next();\n }\n\n if (!isProtectedPath(req.path, req.method, authConfig, customRouteAuthConfig)) {\n return next();\n }\n\n // Skip authentication for public routes\n if (canAccessPublicly(req.path, req.method, authConfig)) {\n return next();\n }\n\n // Get token from header or query\n const authHeader = req.headers.authorization;\n let token: string | null = authHeader ? authHeader.replace('Bearer ', '') : null;\n\n if (!token && req.query.apiKey) {\n token = (req.query.apiKey as string) || null;\n }\n\n // Handle missing token\n if (!token) {\n return res.status(401).json({ error: 'Authentication required' });\n }\n\n try {\n // Verify token and get user data\n let user: unknown;\n\n // Client provided verify function\n if (typeof authConfig.authenticateToken === 'function') {\n // Note: Express doesn't have HonoRequest, so we pass the Express Request\n // The auth config function signature accepts HonoRequest, but in practice\n // it should work with any request object that has the necessary properties\n user = await authConfig.authenticateToken(token, req as any);\n } else {\n throw new Error('No token verification method configured');\n }\n\n if (!user) {\n return res.status(401).json({ error: 'Invalid or expired token' });\n }\n\n // Store user in context\n res.locals.requestContext.set('user', user);\n\n return next();\n } catch (err) {\n console.error(err);\n return res.status(401).json({ error: 'Invalid or expired token' });\n }\n};\n\nexport const authorizationMiddleware = async (req: Request, res: Response, next: NextFunction) => {\n const mastra = res.locals.mastra;\n const authConfig = mastra.getServer()?.auth;\n const customRouteAuthConfig = res.locals.customRouteAuthConfig;\n\n if (!authConfig) {\n // No auth config, skip authorization\n return next();\n }\n\n const path = req.path;\n const method = req.method;\n const getHeader = (name: string) => req.headers[name.toLowerCase()] as string | undefined;\n\n if (isDevPlaygroundRequest(path, method, getHeader, authConfig)) {\n // Skip authorization for dev playground requests\n return next();\n }\n\n if (!isProtectedPath(req.path, req.method, authConfig, customRouteAuthConfig)) {\n return next();\n }\n\n // Skip for public routes\n if (canAccessPublicly(path, method, authConfig)) {\n return next();\n }\n\n const user = res.locals.requestContext.get('user');\n\n if ('authorizeUser' in authConfig && typeof authConfig.authorizeUser === 'function') {\n try {\n const isAuthorized = await authConfig.authorizeUser(user, req as any);\n\n if (isAuthorized) {\n return next();\n }\n\n return res.status(403).json({ error: 'Access denied' });\n } catch (err) {\n console.error(err);\n return res.status(500).json({ error: 'Authorization error' });\n }\n }\n\n // Client-provided authorization function\n if ('authorize' in authConfig && typeof authConfig.authorize === 'function') {\n try {\n // Note: The authorize function signature expects ContextWithMastra as 4th param\n // For Express, we pass a compatible object with similar structure\n const context = {\n get: (key: string) => {\n if (key === 'mastra') return res.locals.mastra;\n if (key === 'requestContext') return res.locals.requestContext;\n if (key === 'tools') return res.locals.tools;\n if (key === 'taskStore') return res.locals.taskStore;\n if (key === 'customRouteAuthConfig') return res.locals.customRouteAuthConfig;\n if (key === 'playground') return res.locals.playground;\n if (key === 'isDev') return res.locals.isDev;\n return undefined;\n },\n req: req as any,\n } as any;\n\n const isAuthorized = await authConfig.authorize(path, method, user, context);\n\n if (isAuthorized) {\n return next();\n }\n\n return res.status(403).json({ error: 'Access denied' });\n } catch (err) {\n console.error(err);\n return res.status(500).json({ error: 'Authorization error' });\n }\n }\n\n // Custom rule-based authorization\n if ('rules' in authConfig && authConfig.rules && authConfig.rules.length > 0) {\n const isAuthorized = await checkRules(authConfig.rules, path, method, user);\n\n if (isAuthorized) {\n return next();\n }\n\n return res.status(403).json({ error: 'Access denied' });\n }\n\n // Default rule-based authorization\n if (defaultAuthConfig.rules && defaultAuthConfig.rules.length > 0) {\n const isAuthorized = await checkRules(defaultAuthConfig.rules, path, method, user);\n\n if (isAuthorized) {\n return next();\n }\n }\n\n return res.status(403).json({ error: 'Access denied' });\n};\n","import type { Mastra } from '@mastra/core/mastra';\nimport type { RequestContext } from '@mastra/core/request-context';\nimport type { Tool } from '@mastra/core/tools';\nimport type { InMemoryTaskStore } from '@mastra/server/a2a/store';\nimport type { MCPHttpTransportResult, MCPSseTransportResult } from '@mastra/server/handlers/mcp';\nimport type { ServerRoute } from '@mastra/server/server-adapter';\nimport { MastraServer as MastraServerBase, redactStreamChunk } from '@mastra/server/server-adapter';\nimport type { Application, NextFunction, Request, Response } from 'express';\n\nimport { authenticationMiddleware, authorizationMiddleware } from './auth-middleware';\n\n// Extend Express types to include Mastra context\ndeclare global {\n namespace Express {\n interface Locals {\n mastra: Mastra;\n requestContext: RequestContext;\n abortSignal: AbortSignal;\n tools: Record<string, Tool>;\n taskStore: InMemoryTaskStore;\n customRouteAuthConfig?: Map<string, boolean>;\n playground?: boolean;\n isDev?: boolean;\n }\n }\n}\n\nexport class MastraServer extends MastraServerBase<Application, Request, Response> {\n createContextMiddleware(): (req: Request, res: Response, next: NextFunction) => Promise<void> {\n return async (req: Request, res: Response, next: NextFunction) => {\n // Parse request context from request body and add to context\n let bodyRequestContext: Record<string, any> | undefined;\n let paramsRequestContext: Record<string, any> | undefined;\n\n // Parse request context from request body (POST/PUT)\n if (req.method === 'POST' || req.method === 'PUT') {\n const contentType = req.headers['content-type'];\n if (contentType?.includes('application/json') && req.body) {\n if (req.body.requestContext) {\n bodyRequestContext = req.body.requestContext;\n }\n }\n }\n\n // Parse request context from query params (GET)\n if (req.method === 'GET') {\n try {\n const encodedRequestContext = req.query.requestContext;\n if (typeof encodedRequestContext === 'string') {\n // Try JSON first\n try {\n paramsRequestContext = JSON.parse(encodedRequestContext);\n } catch {\n // Fallback to base64(JSON)\n try {\n const json = Buffer.from(encodedRequestContext, 'base64').toString('utf-8');\n paramsRequestContext = JSON.parse(json);\n } catch {\n // ignore if still invalid\n }\n }\n }\n } catch {\n // ignore query parsing errors\n }\n }\n\n const requestContext = this.mergeRequestContext({ paramsRequestContext, bodyRequestContext });\n\n // Set context in res.locals\n res.locals.requestContext = requestContext;\n res.locals.mastra = this.mastra;\n res.locals.tools = this.tools || {};\n if (this.taskStore) {\n res.locals.taskStore = this.taskStore;\n }\n res.locals.playground = this.playground === true;\n res.locals.isDev = this.isDev === true;\n res.locals.customRouteAuthConfig = this.customRouteAuthConfig;\n const controller = new AbortController();\n // Use res.on('close') instead of req.on('close') because the request's 'close' event\n // fires when the request body is fully consumed (e.g., after express.json() parses it),\n // NOT when the client disconnects. The response's 'close' event fires when the underlying\n // connection is actually closed, which is the correct signal for client disconnection.\n res.on('close', () => {\n // Only abort if the response wasn't successfully completed\n if (!res.writableFinished) {\n controller.abort();\n }\n });\n res.locals.abortSignal = controller.signal;\n next();\n };\n }\n async stream(route: ServerRoute, res: Response, result: { fullStream: ReadableStream }): Promise<void> {\n res.setHeader('Content-Type', 'text/plain');\n res.setHeader('Transfer-Encoding', 'chunked');\n\n const streamFormat = route.streamFormat || 'stream';\n\n const readableStream = result instanceof ReadableStream ? result : result.fullStream;\n const reader = readableStream.getReader();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n if (value) {\n // Optionally redact sensitive data (system prompts, tool definitions, API keys) before sending to the client\n const shouldRedact = this.streamOptions?.redact ?? true;\n const outputValue = shouldRedact ? redactStreamChunk(value) : value;\n if (streamFormat === 'sse') {\n res.write(`data: ${JSON.stringify(outputValue)}\\n\\n`);\n } else {\n res.write(JSON.stringify(outputValue) + '\\x1E');\n }\n }\n }\n } catch (error) {\n console.error(error);\n } finally {\n res.end();\n }\n }\n\n async getParams(\n route: ServerRoute,\n request: Request,\n ): Promise<{ urlParams: Record<string, string>; queryParams: Record<string, string>; body: unknown }> {\n const urlParams = request.params;\n const queryParams = request.query;\n const body = await request.body;\n return { urlParams, queryParams: queryParams as Record<string, string>, body };\n }\n\n async sendResponse(route: ServerRoute, response: Response, result: unknown, request?: Request): Promise<void> {\n if (route.responseType === 'json') {\n response.json(result);\n } else if (route.responseType === 'stream') {\n await this.stream(route, response, result as { fullStream: ReadableStream });\n } else if (route.responseType === 'datastream-response') {\n // Handle AI SDK Response objects - pipe Response.body to Express response\n const fetchResponse = result as globalThis.Response;\n fetchResponse.headers.forEach((value, key) => response.setHeader(key, value));\n response.status(fetchResponse.status);\n if (fetchResponse.body) {\n const reader = fetchResponse.body.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n response.write(value);\n }\n } finally {\n response.end();\n }\n } else {\n response.end();\n }\n } else if (route.responseType === 'mcp-http') {\n // MCP Streamable HTTP transport - request is required\n if (!request) {\n response.status(500).json({ error: 'Request object required for MCP transport' });\n return;\n }\n\n const { server, httpPath } = result as MCPHttpTransportResult;\n\n try {\n await server.startHTTP({\n url: new URL(request.url, `http://${request.headers.host}`),\n httpPath,\n req: request,\n res: response,\n });\n // Response handled by startHTTP\n } catch {\n if (!response.headersSent) {\n response.status(500).json({\n jsonrpc: '2.0',\n error: { code: -32603, message: 'Internal server error' },\n id: null,\n });\n }\n }\n } else if (route.responseType === 'mcp-sse') {\n // MCP SSE transport - request is required\n if (!request) {\n response.status(500).json({ error: 'Request object required for MCP transport' });\n return;\n }\n\n const { server, ssePath, messagePath } = result as MCPSseTransportResult;\n\n try {\n await server.startSSE({\n url: new URL(request.url, `http://${request.headers.host}`),\n ssePath,\n messagePath,\n req: request,\n res: response,\n });\n // Response handled by startSSE\n } catch {\n if (!response.headersSent) {\n response.status(500).json({ error: 'Error handling MCP SSE request' });\n }\n }\n } else {\n response.sendStatus(500);\n }\n }\n\n async registerRoute(app: Application, route: ServerRoute, { prefix }: { prefix?: string }): Promise<void> {\n // Determine if body limits should be applied\n const shouldApplyBodyLimit = this.bodyLimitOptions && ['POST', 'PUT', 'PATCH'].includes(route.method.toUpperCase());\n\n // Get the body size limit for this route (route-specific or default)\n const maxSize = route.maxBodySize ?? this.bodyLimitOptions?.maxSize;\n\n // Create middleware array\n const middlewares: Array<(req: Request, res: Response, next: NextFunction) => void> = [];\n\n // Add body limit middleware if needed\n if (shouldApplyBodyLimit && maxSize && this.bodyLimitOptions) {\n const bodyLimitMiddleware = (req: Request, res: Response, next: NextFunction) => {\n const contentLength = req.headers['content-length'];\n if (contentLength && parseInt(contentLength, 10) > maxSize) {\n try {\n const errorResponse = this.bodyLimitOptions!.onError({ error: 'Request body too large' });\n return res.status(413).json(errorResponse);\n } catch {\n return res.status(413).json({ error: 'Request body too large' });\n }\n }\n next();\n };\n middlewares.push(bodyLimitMiddleware);\n }\n\n app[route.method.toLowerCase() as keyof Application](\n `${prefix}${route.path}`,\n ...middlewares,\n async (req: Request, res: Response) => {\n const params = await this.getParams(route, req);\n\n if (params.queryParams) {\n try {\n params.queryParams = await this.parseQueryParams(route, params.queryParams as Record<string, string>);\n } catch (error) {\n console.error('Error parsing query params', error);\n // Zod validation errors should return 400 Bad Request, not 500\n return res.status(400).json({\n error: 'Invalid query parameters',\n details: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n\n if (params.body) {\n try {\n params.body = await this.parseBody(route, params.body);\n } catch (error) {\n console.error('Error parsing body:', error instanceof Error ? error.message : String(error));\n // Zod validation errors should return 400 Bad Request, not 500\n return res.status(400).json({\n error: 'Invalid request body',\n details: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n\n const handlerParams = {\n ...params.urlParams,\n ...params.queryParams,\n ...(typeof params.body === 'object' ? params.body : {}),\n requestContext: res.locals.requestContext,\n mastra: this.mastra,\n tools: res.locals.tools,\n taskStore: res.locals.taskStore,\n abortSignal: res.locals.abortSignal,\n };\n\n try {\n const result = await route.handler(handlerParams);\n await this.sendResponse(route, res, result, req);\n } catch (error) {\n console.error('Error calling handler', error);\n // Check if it's an HTTPException or MastraError with a status code\n let status = 500;\n if (error && typeof error === 'object') {\n // Check for direct status property (HTTPException)\n if ('status' in error) {\n status = (error as any).status;\n }\n // Check for MastraError with status in details\n else if (\n 'details' in error &&\n error.details &&\n typeof error.details === 'object' &&\n 'status' in error.details\n ) {\n status = (error.details as any).status;\n }\n }\n res.status(status).json({ error: error instanceof Error ? error.message : 'Unknown error' });\n }\n },\n );\n }\n\n registerContextMiddleware(): void {\n this.app.use(this.createContextMiddleware());\n }\n\n registerAuthMiddleware(): void {\n const authConfig = this.mastra.getServer()?.auth;\n if (!authConfig) {\n // No auth config, skip registration\n return;\n }\n\n this.app.use(authenticationMiddleware);\n this.app.use(authorizationMiddleware);\n }\n}\n"]}