@mastra/mcp-docs-server 1.0.0-beta.6 → 1.0.0-beta.8

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.
Files changed (88) hide show
  1. package/.docs/organized/changelogs/%40mastra%2Fagent-builder.md +12 -12
  2. package/.docs/organized/changelogs/%40mastra%2Fai-sdk.md +10 -10
  3. package/.docs/organized/changelogs/%40mastra%2Fastra.md +10 -10
  4. package/.docs/organized/changelogs/%40mastra%2Fchroma.md +12 -12
  5. package/.docs/organized/changelogs/%40mastra%2Fclickhouse.md +48 -48
  6. package/.docs/organized/changelogs/%40mastra%2Fclient-js.md +65 -65
  7. package/.docs/organized/changelogs/%40mastra%2Fcloudflare-d1.md +48 -48
  8. package/.docs/organized/changelogs/%40mastra%2Fcloudflare.md +48 -48
  9. package/.docs/organized/changelogs/%40mastra%2Fcodemod.md +6 -0
  10. package/.docs/organized/changelogs/%40mastra%2Fconvex.md +47 -0
  11. package/.docs/organized/changelogs/%40mastra%2Fcore.md +196 -196
  12. package/.docs/organized/changelogs/%40mastra%2Fcouchbase.md +11 -11
  13. package/.docs/organized/changelogs/%40mastra%2Fdeployer-cloud.md +19 -19
  14. package/.docs/organized/changelogs/%40mastra%2Fdeployer.md +27 -27
  15. package/.docs/organized/changelogs/%40mastra%2Fdynamodb.md +48 -48
  16. package/.docs/organized/changelogs/%40mastra%2Felasticsearch.md +9 -0
  17. package/.docs/organized/changelogs/%40mastra%2Flance.md +48 -48
  18. package/.docs/organized/changelogs/%40mastra%2Flibsql.md +48 -48
  19. package/.docs/organized/changelogs/%40mastra%2Floggers.md +40 -40
  20. package/.docs/organized/changelogs/%40mastra%2Fmcp-docs-server.md +16 -16
  21. package/.docs/organized/changelogs/%40mastra%2Fmcp.md +43 -43
  22. package/.docs/organized/changelogs/%40mastra%2Fmemory.md +10 -10
  23. package/.docs/organized/changelogs/%40mastra%2Fmongodb.md +48 -48
  24. package/.docs/organized/changelogs/%40mastra%2Fmssql.md +48 -48
  25. package/.docs/organized/changelogs/%40mastra%2Fopensearch.md +10 -10
  26. package/.docs/organized/changelogs/%40mastra%2Fpg.md +52 -52
  27. package/.docs/organized/changelogs/%40mastra%2Fpinecone.md +10 -10
  28. package/.docs/organized/changelogs/%40mastra%2Fplayground-ui.md +41 -41
  29. package/.docs/organized/changelogs/%40mastra%2Fqdrant.md +10 -10
  30. package/.docs/organized/changelogs/%40mastra%2Freact.md +14 -0
  31. package/.docs/organized/changelogs/%40mastra%2Fs3vectors.md +9 -0
  32. package/.docs/organized/changelogs/%40mastra%2Fserver.md +65 -65
  33. package/.docs/organized/changelogs/%40mastra%2Fturbopuffer.md +10 -10
  34. package/.docs/organized/changelogs/%40mastra%2Fupstash.md +48 -48
  35. package/.docs/organized/changelogs/%40mastra%2Fvectorize.md +10 -10
  36. package/.docs/organized/changelogs/create-mastra.md +7 -7
  37. package/.docs/organized/changelogs/mastra.md +14 -14
  38. package/.docs/organized/code-examples/ai-elements.md +1 -1
  39. package/.docs/organized/code-examples/ai-sdk-useChat.md +1 -1
  40. package/.docs/organized/code-examples/ai-sdk-v5.md +1 -1
  41. package/.docs/organized/code-examples/assistant-ui.md +1 -1
  42. package/.docs/organized/code-examples/bird-checker-with-nextjs-and-eval.md +1 -1
  43. package/.docs/organized/code-examples/bird-checker-with-nextjs.md +1 -1
  44. package/.docs/organized/code-examples/crypto-chatbot.md +1 -1
  45. package/.docs/organized/code-examples/mcp-server-adapters.md +2 -2
  46. package/.docs/organized/code-examples/server-app-access.md +2 -2
  47. package/.docs/organized/code-examples/server-express-adapter.md +87 -0
  48. package/.docs/organized/code-examples/server-hono-adapter.md +85 -0
  49. package/.docs/raw/agents/overview.mdx +2 -111
  50. package/.docs/raw/agents/processors.mdx +1 -1
  51. package/.docs/raw/agents/structured-output.mdx +224 -0
  52. package/.docs/raw/guides/build-your-ui/ai-sdk-ui.mdx +381 -431
  53. package/.docs/raw/guides/getting-started/quickstart.mdx +11 -0
  54. package/.docs/raw/guides/migrations/upgrade-to-v1/workflows.mdx +40 -1
  55. package/.docs/raw/memory/working-memory.mdx +1 -0
  56. package/.docs/raw/observability/tracing/bridges/otel.mdx +25 -1
  57. package/.docs/raw/observability/tracing/exporters/arize.mdx +19 -0
  58. package/.docs/raw/observability/tracing/exporters/langfuse.mdx +63 -0
  59. package/.docs/raw/observability/tracing/exporters/otel.mdx +30 -19
  60. package/.docs/raw/observability/tracing/exporters/posthog.mdx +20 -0
  61. package/.docs/raw/observability/tracing/overview.mdx +6 -1
  62. package/.docs/raw/reference/ai-sdk/chat-route.mdx +127 -0
  63. package/.docs/raw/reference/ai-sdk/handle-chat-stream.mdx +117 -0
  64. package/.docs/raw/reference/ai-sdk/handle-network-stream.mdx +64 -0
  65. package/.docs/raw/reference/ai-sdk/handle-workflow-stream.mdx +116 -0
  66. package/.docs/raw/reference/ai-sdk/network-route.mdx +99 -0
  67. package/.docs/raw/reference/ai-sdk/to-ai-sdk-stream.mdx +289 -0
  68. package/.docs/raw/reference/ai-sdk/workflow-route.mdx +110 -0
  69. package/.docs/raw/reference/observability/tracing/bridges/otel.mdx +27 -0
  70. package/.docs/raw/reference/observability/tracing/exporters/arize.mdx +25 -0
  71. package/.docs/raw/reference/observability/tracing/exporters/langfuse.mdx +43 -0
  72. package/.docs/raw/reference/observability/tracing/exporters/otel.mdx +27 -43
  73. package/.docs/raw/reference/server/create-route.mdx +314 -0
  74. package/.docs/raw/reference/server/express-adapter.mdx +193 -0
  75. package/.docs/raw/reference/server/hono-adapter.mdx +174 -0
  76. package/.docs/raw/reference/server/mastra-server.mdx +316 -0
  77. package/.docs/raw/reference/server/routes.mdx +250 -0
  78. package/.docs/raw/reference/streaming/workflows/timeTravelStream.mdx +170 -0
  79. package/.docs/raw/reference/tools/mcp-client.mdx +54 -1
  80. package/.docs/raw/reference/workflows/run-methods/timeTravel.mdx +310 -0
  81. package/.docs/raw/reference/workflows/run.mdx +14 -0
  82. package/.docs/raw/server-db/custom-adapters.mdx +380 -0
  83. package/.docs/raw/server-db/custom-api-routes.mdx +5 -5
  84. package/.docs/raw/server-db/mastra-server.mdx +11 -32
  85. package/.docs/raw/server-db/server-adapters.mdx +286 -0
  86. package/.docs/raw/workflows/workflow-state.mdx +4 -5
  87. package/CHANGELOG.md +15 -0
  88. package/package.json +4 -4
@@ -117,3 +117,46 @@ const exporter = new LangfuseExporter({
117
117
  - `MODEL_GENERATION` spans → Langfuse generations
118
118
  - All other spans → Langfuse spans
119
119
  - Event spans → Langfuse events
120
+
121
+ ## Prompt Linking
122
+
123
+ Link LLM generations to [Langfuse Prompt Management](https://langfuse.com/docs/prompt-management) using the `withLangfusePrompt` helper:
124
+
125
+ ```typescript
126
+ import { buildTracingOptions } from "@mastra/observability";
127
+ import { withLangfusePrompt } from "@mastra/langfuse";
128
+ import { Langfuse } from "langfuse";
129
+
130
+ const langfuse = new Langfuse({
131
+ publicKey: process.env.LANGFUSE_PUBLIC_KEY!,
132
+ secretKey: process.env.LANGFUSE_SECRET_KEY!,
133
+ });
134
+
135
+ const prompt = await langfuse.getPrompt("customer-support");
136
+
137
+ const agent = new Agent({
138
+ name: "support-agent",
139
+ instructions: prompt.prompt,
140
+ model: openai("gpt-4o"),
141
+ defaultGenerateOptions: {
142
+ tracingOptions: buildTracingOptions(withLangfusePrompt(prompt)),
143
+ },
144
+ });
145
+ ```
146
+
147
+ ### Helper Functions
148
+
149
+ #### `withLangfusePrompt(prompt)`
150
+
151
+ Adds Langfuse prompt metadata to tracing options.
152
+
153
+ ```typescript
154
+ // With Langfuse SDK prompt object
155
+ withLangfusePrompt(prompt)
156
+
157
+ // With manual fields
158
+ withLangfusePrompt({ name: "my-prompt", version: 1 })
159
+ withLangfusePrompt({ id: "prompt-uuid" })
160
+ ```
161
+
162
+ When `metadata.langfuse.prompt` is set on a `MODEL_GENERATION` span (with either `id` alone, or `name` + `version`), the exporter automatically links the generation to the prompt in Langfuse.
@@ -7,12 +7,6 @@ import PropertiesTable from "@site/src/components/PropertiesTable";
7
7
 
8
8
  # OtelExporter
9
9
 
10
- :::warning
11
-
12
- The OtelExporter is currently **experimental**. APIs and configuration options may change in future releases.
13
-
14
- :::
15
-
16
10
  Sends Tracing data to any OpenTelemetry-compatible observability platform using standardized GenAI semantic conventions.
17
11
 
18
12
  ## Constructor
@@ -317,38 +311,6 @@ const exporter = new OtelExporter({
317
311
  });
318
312
  ```
319
313
 
320
- ## Span Mapping
321
-
322
- The exporter maps Mastra AI spans to OpenTelemetry spans following GenAI semantic conventions:
323
-
324
- ### Span Names
325
-
326
- - `MODEL_GENERATION` → `chat {model}` or `tool_selection {model}`
327
- - `TOOL_CALL` → `tool.execute {tool_name}`
328
- - `AGENT_RUN` → `agent.{agent_id}`
329
- - `WORKFLOW_RUN` → `workflow.{workflow_id}`
330
-
331
- ### Span Kinds
332
-
333
- - Root agent/workflow spans → `SERVER`
334
- - LLM calls → `CLIENT`
335
- - Tool calls → `INTERNAL` or `CLIENT`
336
- - Workflow steps → `INTERNAL`
337
-
338
- ### Attributes
339
-
340
- The exporter maps to standard OTEL GenAI attributes:
341
-
342
- | Mastra Attribute | OTEL Attribute |
343
- | ----------------------------------- | -------------------------------- |
344
- | `model` | `gen_ai.request.model` |
345
- | `provider` | `gen_ai.system` |
346
- | `inputTokens` / `promptTokens` | `gen_ai.usage.input_tokens` |
347
- | `outputTokens` / `completionTokens` | `gen_ai.usage.output_tokens` |
348
- | `temperature` | `gen_ai.request.temperature` |
349
- | `maxOutputTokens` | `gen_ai.request.max_tokens` |
350
- | `finishReason` | `gen_ai.response.finish_reasons` |
351
-
352
314
  ## Protocol Requirements
353
315
 
354
316
  Different providers require different OTEL exporter packages:
@@ -360,13 +322,35 @@ Different providers require different OTEL exporter packages:
360
322
  | HTTP/JSON | `@opentelemetry/exporter-trace-otlp-http` | Traceloop, Custom |
361
323
  | Zipkin | `@opentelemetry/exporter-zipkin` | Zipkin collectors |
362
324
 
363
- ## Parent-Child Relationships
364
325
 
365
- The exporter preserves span hierarchy from Mastra's Tracing:
326
+ ## Tags Support
366
327
 
367
- - Uses `parentSpanId` directly from Mastra spans
368
- - Maintains correct nesting for agents, workflows, LLM calls, and tools
369
- - Exports complete traces with all relationships intact
328
+ The OtelExporter supports trace tagging for categorization and filtering. Tags are only applied to root spans and are stored as the `mastra.tags` attribute.
329
+
330
+ ### Usage
331
+
332
+ ```typescript
333
+ const result = await agent.generate({
334
+ messages: [{ role: "user", content: "Hello" }],
335
+ tracingOptions: {
336
+ tags: ["production", "experiment-v2", "user-request"],
337
+ },
338
+ });
339
+ ```
340
+
341
+ ### How Tags Are Stored
342
+
343
+ Tags are stored as a JSON-stringified array in the `mastra.tags` span attribute for maximum backend compatibility:
344
+
345
+ ```json
346
+ {
347
+ "mastra.tags": "[\"production\",\"experiment-v2\",\"user-request\"]"
348
+ }
349
+ ```
350
+
351
+ :::note
352
+ While the OpenTelemetry specification supports native array attributes, many backends (Jaeger, Zipkin, Tempo) have limited array support. JSON strings ensure consistent behavior across all observability platforms.
353
+ :::
370
354
 
371
355
  ## Related
372
356
 
@@ -0,0 +1,314 @@
1
+ ---
2
+ title: "Reference: createRoute() | Server"
3
+ description: "API reference for createRoute() function used to define type-safe routes with validation and OpenAPI generation."
4
+ ---
5
+
6
+ import PropertiesTable from "@site/src/components/PropertiesTable";
7
+
8
+ # createRoute()
9
+
10
+ The `createRoute()` function creates type-safe routes with Zod validation. When an `openapiPath` is configured on the server adapter, it generates OpenAPI schema entries from the supplied Zod schemas.
11
+
12
+ ## Import
13
+
14
+ ```typescript copy
15
+ import { createRoute } from '@mastra/server';
16
+ ```
17
+
18
+ ## Signature
19
+
20
+ ```typescript copy
21
+ function createRoute<TPath, TQuery, TBody, TResponse, TResponseType>(
22
+ config: RouteConfig<TPath, TQuery, TBody, TResponse, TResponseType>
23
+ ): ServerRoute
24
+ ```
25
+
26
+ ## Parameters
27
+
28
+ <PropertiesTable
29
+ content={[
30
+ {
31
+ name: "method",
32
+ type: "'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'ALL'",
33
+ description: "HTTP method",
34
+ isOptional: false,
35
+ },
36
+ {
37
+ name: "path",
38
+ type: "string",
39
+ description: "Route path with optional params (e.g., `/api/items/:id`)",
40
+ isOptional: false,
41
+ },
42
+ {
43
+ name: "responseType",
44
+ type: "'json' | 'stream'",
45
+ description: "Response format. Internal routes may use additional types (`datastream-response`, `mcp-http`, `mcp-sse`).",
46
+ isOptional: false,
47
+ },
48
+ {
49
+ name: "handler",
50
+ type: "ServerRouteHandler",
51
+ description: "Route handler function",
52
+ isOptional: false,
53
+ },
54
+ {
55
+ name: "pathParamSchema",
56
+ type: "ZodSchema",
57
+ description: "Validates URL path parameters",
58
+ isOptional: true,
59
+ },
60
+ {
61
+ name: "queryParamSchema",
62
+ type: "ZodSchema",
63
+ description: "Validates query string parameters",
64
+ isOptional: true,
65
+ },
66
+ {
67
+ name: "bodySchema",
68
+ type: "ZodSchema",
69
+ description: "Validates request body",
70
+ isOptional: true,
71
+ },
72
+ {
73
+ name: "responseSchema",
74
+ type: "ZodSchema",
75
+ description: "Documents response shape for OpenAPI",
76
+ isOptional: true,
77
+ },
78
+ {
79
+ name: "streamFormat",
80
+ type: "'sse' | 'stream'",
81
+ description: "Stream format (when responseType is 'stream')",
82
+ isOptional: true,
83
+ },
84
+ {
85
+ name: "maxBodySize",
86
+ type: "number",
87
+ description: "Override default body size limit in bytes",
88
+ isOptional: true,
89
+ },
90
+ {
91
+ name: "summary",
92
+ type: "string",
93
+ description: "OpenAPI summary",
94
+ isOptional: true,
95
+ },
96
+ {
97
+ name: "description",
98
+ type: "string",
99
+ description: "OpenAPI description",
100
+ isOptional: true,
101
+ },
102
+ {
103
+ name: "tags",
104
+ type: "string[]",
105
+ description: "OpenAPI tags",
106
+ isOptional: true,
107
+ },
108
+ {
109
+ name: "deprecated",
110
+ type: "boolean",
111
+ description: "Mark route as deprecated",
112
+ isOptional: true,
113
+ },
114
+ ]}
115
+ />
116
+
117
+ ## Handler parameters
118
+
119
+ The handler receives validated parameters plus runtime context:
120
+
121
+ ```typescript copy showLineNumbers
122
+ handler: async (params) => {
123
+ // From schemas (typed from Zod)
124
+ params.id; // From pathParamSchema
125
+ params.filter; // From queryParamSchema
126
+ params.name; // From bodySchema
127
+
128
+ // Runtime context (always available)
129
+ params.mastra; // Mastra instance
130
+ params.requestContext; // Request-scoped context
131
+ params.tools; // Available tools
132
+ params.abortSignal; // Request cancellation signal
133
+ params.taskStore; // A2A task storage
134
+ }
135
+ ```
136
+
137
+ ## Return value
138
+
139
+ Returns a `ServerRoute` object that can be registered with an adapter.
140
+
141
+ ## Examples
142
+
143
+ ### GET route with path params
144
+
145
+ ```typescript copy showLineNumbers
146
+ import { createRoute } from '@mastra/server';
147
+ import { z } from 'zod';
148
+
149
+ const getAgent = createRoute({
150
+ method: 'GET',
151
+ path: '/api/agents/:agentId',
152
+ responseType: 'json',
153
+ pathParamSchema: z.object({
154
+ agentId: z.string(),
155
+ }),
156
+ responseSchema: z.object({
157
+ name: z.string(),
158
+ description: z.string().optional(),
159
+ }),
160
+ summary: 'Get agent by ID',
161
+ tags: ['Agents'],
162
+ handler: async ({ agentId, mastra }) => {
163
+ return mastra.getAgent(agentId);
164
+ },
165
+ });
166
+ ```
167
+
168
+ ### POST route with body
169
+
170
+ ```typescript copy showLineNumbers
171
+ const createItem = createRoute({
172
+ method: 'POST',
173
+ path: '/api/items',
174
+ responseType: 'json',
175
+ bodySchema: z.object({
176
+ name: z.string(),
177
+ value: z.number(),
178
+ }),
179
+ responseSchema: z.object({
180
+ id: z.string(),
181
+ name: z.string(),
182
+ value: z.number(),
183
+ }),
184
+ handler: async ({ name, value, mastra }) => {
185
+ // name and value are typed from bodySchema
186
+ return { id: 'new-id', name, value };
187
+ },
188
+ });
189
+ ```
190
+
191
+ ### Query params with coercion
192
+
193
+ ```typescript copy showLineNumbers
194
+ const listItems = createRoute({
195
+ method: 'GET',
196
+ path: '/api/items',
197
+ responseType: 'json',
198
+ queryParamSchema: z.object({
199
+ page: z.coerce.number().default(0),
200
+ limit: z.coerce.number().default(50),
201
+ enabled: z.coerce.boolean().optional(),
202
+ }),
203
+ handler: async ({ page, limit, enabled, mastra }) => {
204
+ // page, limit, enabled are typed and coerced
205
+ return { items: [], page, limit };
206
+ },
207
+ });
208
+ ```
209
+
210
+ ### Streaming route
211
+
212
+ ```typescript copy showLineNumbers
213
+ const streamAgent = createRoute({
214
+ method: 'POST',
215
+ path: '/api/agents/:agentId/stream',
216
+ responseType: 'stream',
217
+ streamFormat: 'sse',
218
+ pathParamSchema: z.object({
219
+ agentId: z.string(),
220
+ }),
221
+ bodySchema: z.object({
222
+ messages: z.array(z.any()),
223
+ }),
224
+ handler: async ({ agentId, messages, mastra, abortSignal }) => {
225
+ const agent = mastra.getAgent(agentId);
226
+ return agent.stream({ messages, abortSignal });
227
+ },
228
+ });
229
+ ```
230
+
231
+ ### Custom body size limit
232
+
233
+ ```typescript copy showLineNumbers
234
+ const uploadRoute = createRoute({
235
+ method: 'POST',
236
+ path: '/api/upload',
237
+ responseType: 'json',
238
+ maxBodySize: 50 * 1024 * 1024, // 50MB
239
+ bodySchema: z.object({
240
+ file: z.string(),
241
+ }),
242
+ handler: async ({ file }) => {
243
+ return { uploaded: true };
244
+ },
245
+ });
246
+ ```
247
+
248
+ ## Schema patterns
249
+
250
+ ### Passthrough for extensibility
251
+
252
+ ```typescript copy
253
+ const bodySchema = z.object({
254
+ required: z.string(),
255
+ }).passthrough(); // Allow unknown fields
256
+ ```
257
+
258
+ ### Date coercion
259
+
260
+ ```typescript copy
261
+ const querySchema = z.object({
262
+ fromDate: z.coerce.date().optional(),
263
+ toDate: z.coerce.date().optional(),
264
+ });
265
+ ```
266
+
267
+ ### Union types
268
+
269
+ ```typescript copy
270
+ const bodySchema = z.object({
271
+ messages: z.union([
272
+ z.array(z.any()),
273
+ z.string(),
274
+ ]),
275
+ });
276
+ ```
277
+
278
+ ## Error handling
279
+
280
+ Throw `HTTPException` to return specific HTTP status codes from handlers:
281
+
282
+ ```typescript copy showLineNumbers
283
+ import { createRoute, HTTPException } from '@mastra/server';
284
+
285
+ const getAgent = createRoute({
286
+ method: 'GET',
287
+ path: '/api/agents/:agentId',
288
+ responseType: 'json',
289
+ pathParamSchema: z.object({ agentId: z.string() }),
290
+ handler: async ({ agentId, mastra }) => {
291
+ const agent = mastra.getAgent(agentId);
292
+ if (!agent) {
293
+ throw new HTTPException(404, { message: `Agent '${agentId}' not found` });
294
+ }
295
+ return agent;
296
+ },
297
+ });
298
+ ```
299
+
300
+ Common status codes:
301
+
302
+ | Code | Meaning |
303
+ |------|---------|
304
+ | 400 | Bad Request |
305
+ | 401 | Unauthorized |
306
+ | 403 | Forbidden |
307
+ | 404 | Not Found |
308
+ | 500 | Internal Server Error |
309
+
310
+ ## Related
311
+
312
+ - [Server Routes](/reference/v1/server/routes) - Default Mastra routes
313
+ - [MastraServer](/reference/v1/server/mastra-server) - Server adapter class
314
+ - [Server Adapters](/docs/v1/server-db/server-adapters) - Using adapters
@@ -0,0 +1,193 @@
1
+ ---
2
+ title: "Reference: Express Adapter | Server"
3
+ description: "API reference for the @mastra/express server adapter."
4
+ ---
5
+
6
+ import Steps from "@site/src/components/Steps";
7
+ import StepItem from "@site/src/components/StepItem";
8
+
9
+ # Express Adapter
10
+
11
+ The `@mastra/express` package provides a server adapter for running Mastra with [Express](https://expressjs.com).
12
+
13
+ :::info
14
+
15
+ For general adapter concepts (constructor options, initialization flow, etc.), see [Server Adapters](/docs/v1/server-db/server-adapters).
16
+
17
+ :::
18
+
19
+ ## Installation
20
+
21
+ <Steps>
22
+
23
+ <StepItem>
24
+
25
+ Install the Express adapter and Express framework:
26
+
27
+ ```bash copy
28
+ npm install @mastra/express express
29
+ ```
30
+
31
+ </StepItem>
32
+
33
+ <StepItem>
34
+
35
+ Create your server file:
36
+
37
+ ```typescript title="server.ts" copy showLineNumbers
38
+ import express from 'express';
39
+ import { MastraServer } from '@mastra/express';
40
+ import { mastra } from './mastra';
41
+
42
+ const app = express();
43
+ app.use(express.json()); // Required for body parsing
44
+
45
+ const server = new MastraServer({ app, mastra });
46
+ await server.init();
47
+
48
+ app.listen(4111, () => {
49
+ console.log('Server running on port 4111');
50
+ });
51
+ ```
52
+
53
+ </StepItem>
54
+
55
+ </Steps>
56
+
57
+ :::note
58
+
59
+ Express requires `express.json()` middleware for JSON body parsing. Add it before creating the `MastraServer`.
60
+
61
+ :::
62
+
63
+ ## Full example
64
+
65
+ ```typescript title="server.ts" copy showLineNumbers
66
+ import express from 'express';
67
+ import { MastraServer } from '@mastra/express';
68
+ import { mastra } from './mastra';
69
+
70
+ const app = express();
71
+ app.use(express.json());
72
+
73
+ const server = new MastraServer({
74
+ app,
75
+ mastra,
76
+ prefix: '/api/v2',
77
+ openapiPath: '/openapi.json',
78
+ bodyLimitOptions: {
79
+ maxSize: 10 * 1024 * 1024, // 10MB
80
+ onError: (err) => ({ error: 'Payload too large', maxSize: '10MB' }),
81
+ },
82
+ streamOptions: { redact: true },
83
+ });
84
+
85
+ await server.init();
86
+
87
+ app.listen(4111);
88
+ ```
89
+
90
+ ## Differences from Hono
91
+
92
+ | Aspect | Express | Hono |
93
+ |--------|---------|------|
94
+ | Body parsing | Requires `express.json()` | Handled by framework |
95
+ | Context storage | `res.locals` | `c.get()` / `c.set()` |
96
+ | Middleware signature | `(req, res, next)` | `(c, next)` |
97
+ | Streaming | `res.write()` / `res.end()` | `stream()` helper |
98
+ | AbortSignal | Created from `req.on('close')` | `c.req.raw.signal` |
99
+
100
+ ## Adding custom routes
101
+
102
+ Add routes directly to the Express app:
103
+
104
+ ```typescript title="server.ts" copy showLineNumbers
105
+ const app = express();
106
+ app.use(express.json());
107
+
108
+ const server = new MastraServer({ app, mastra });
109
+
110
+ // Before init - runs before Mastra middleware
111
+ app.get('/early-health', (req, res) => res.json({ status: 'ok' }));
112
+
113
+ await server.init();
114
+
115
+ // After init - has access to Mastra context
116
+ app.get('/custom', (req, res) => {
117
+ const mastraInstance = res.locals.mastra;
118
+ res.json({ agents: Object.keys(mastraInstance.listAgents()) });
119
+ });
120
+
121
+ app.listen(4111);
122
+ ```
123
+
124
+ :::tip
125
+
126
+ Routes added before `init()` run without Mastra context. Add routes after `init()` to access the Mastra instance and request context.
127
+
128
+ :::
129
+
130
+ ## Accessing context
131
+
132
+ In Express middleware and routes, access Mastra context via `res.locals`:
133
+
134
+ ```typescript copy showLineNumbers
135
+ app.get('/custom', (req, res) => {
136
+ const mastra = res.locals.mastra;
137
+ const requestContext = res.locals.requestContext;
138
+ const abortSignal = res.locals.abortSignal;
139
+
140
+ const agent = mastra.getAgent('myAgent');
141
+ res.json({ agent: agent.name });
142
+ });
143
+ ```
144
+
145
+ Available properties on `res.locals`:
146
+
147
+ | Key | Description |
148
+ |-----|-------------|
149
+ | `mastra` | Mastra instance |
150
+ | `requestContext` | Request context map |
151
+ | `abortSignal` | Request cancellation signal |
152
+ | `tools` | Available tools |
153
+ | `user` | Authenticated user (if auth configured) |
154
+
155
+ ## Adding middleware
156
+
157
+ Add Express middleware before or after `init()`:
158
+
159
+ ```typescript title="server.ts" copy showLineNumbers
160
+ const app = express();
161
+ app.use(express.json());
162
+
163
+ // Middleware before init
164
+ app.use((req, res, next) => {
165
+ console.log(`${req.method} ${req.url}`);
166
+ next();
167
+ });
168
+
169
+ const server = new MastraServer({ app, mastra });
170
+ await server.init();
171
+
172
+ // Middleware after init has access to Mastra context
173
+ app.use((req, res, next) => {
174
+ const mastra = res.locals.mastra;
175
+ // ...
176
+ next();
177
+ });
178
+ ```
179
+
180
+ ## Manual initialization
181
+
182
+ For custom middleware ordering, call each method separately instead of `init()`. See [Server Adapters: Manual initialization](/docs/v1/server-db/server-adapters#manual-initialization) for details.
183
+
184
+ ## Examples
185
+
186
+ - [Express Adapter](https://github.com/mastra-ai/mastra/tree/main/examples/server-express-adapter) - Basic Express server setup
187
+
188
+ ## Related
189
+
190
+ - [Server Adapters](/docs/v1/server-db/server-adapters) - Shared adapter concepts
191
+ - [Hono Adapter](/reference/v1/server/hono-adapter) - Alternative adapter
192
+ - [MastraServer Reference](/reference/v1/server/mastra-server) - Full API reference
193
+ - [createRoute() Reference](/reference/v1/server/create-route) - Creating type-safe custom routes