@mastra/mcp-docs-server 1.2.28 → 1.3.0-alpha.1

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.
@@ -4,7 +4,7 @@
4
4
 
5
5
  # Netlify
6
6
 
7
- Netlify AI Gateway provides unified access to multiple providers with built-in caching and observability. Access 267 models through Mastra's model router.
7
+ Netlify AI Gateway provides unified access to multiple providers with built-in caching and observability. Access 268 models through Mastra's model router.
8
8
 
9
9
  Learn more in the [Netlify documentation](https://docs.netlify.com/build/ai-gateway/overview/).
10
10
 
@@ -279,6 +279,7 @@ ANTHROPIC_API_KEY=ant-...
279
279
  | `openrouter/thinkingmachines/inkling` |
280
280
  | `openrouter/thinkingmachines/inkling-small` |
281
281
  | `openrouter/undi95/remm-slerp-l2-13b` |
282
+ | `openrouter/upstage/solar-mini4` |
282
283
  | `openrouter/upstage/solar-pro4` |
283
284
  | `openrouter/x-ai/grok-4.20` |
284
285
  | `openrouter/x-ai/grok-4.20-multi-agent` |
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ![OpenRouter logo](https://models.dev/logos/openrouter.svg)OpenRouter
6
6
 
7
- OpenRouter aggregates models from multiple providers with enhanced features like rate limiting and failover. Access 382 models through Mastra's model router.
7
+ OpenRouter aggregates models from multiple providers with enhanced features like rate limiting and failover. Access 383 models through Mastra's model router.
8
8
 
9
9
  Learn more in the [OpenRouter documentation](https://openrouter.ai/models).
10
10
 
@@ -389,6 +389,7 @@ ANTHROPIC_API_KEY=ant-...
389
389
  | `thinkingmachines/inkling:free` |
390
390
  | `unbiased/pareto` |
391
391
  | `undi95/remm-slerp-l2-13b` |
392
+ | `upstage/solar-mini4` |
392
393
  | `upstage/solar-pro-3` |
393
394
  | `upstage/solar-pro4` |
394
395
  | `writer/palmyra-x5` |
@@ -4,7 +4,7 @@
4
4
 
5
5
  # Model Providers
6
6
 
7
- Mastra provides a unified interface for working with LLMs across multiple providers, giving you access to 7576 models from 210 providers through a single API.
7
+ Mastra provides a unified interface for working with LLMs across multiple providers, giving you access to 7579 models from 210 providers through a single API.
8
8
 
9
9
  ## Features
10
10
 
@@ -138,7 +138,7 @@ for await (const chunk of stream) {
138
138
  | `edenai/fireworks_ai/gpt-oss-120b` | 131K | | | | | | $0.15 | $0.60 |
139
139
  | `edenai/flexai/DeepSeek-V4-Flash-0731` | 1.0M | | | | | | $0.07 | $0.18 |
140
140
  | `edenai/flexai/gpt-oss-120b` | 131K | | | | | | $0.04 | $0.17 |
141
- | `edenai/flexai/gpt-oss-20b` | 131K | | | | | | $0.03 | $0.13 |
141
+ | `edenai/flexai/gpt-oss-20b` | 131K | | | | | | $0.02 | $0.09 |
142
142
  | `edenai/flexai/Muse-Glimmer-30B` | 131K | | | | | | $0.30 | $1 |
143
143
  | `edenai/flexai/Step-3.7-Flash` | 262K | | | | | | $0.20 | $1 |
144
144
  | `edenai/google/gemini-2.5-flash-image` | 33K | | | | | | $0.30 | $3 |
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ![Kilo Gateway logo](https://models.dev/logos/kilo.svg)Kilo Gateway
6
6
 
7
- Access 389 Kilo Gateway models through Mastra's model router. Authentication is handled automatically using the `KILO_API_KEY` environment variable.
7
+ Access 390 Kilo Gateway models through Mastra's model router. Authentication is handled automatically using the `KILO_API_KEY` environment variable.
8
8
 
9
9
  Learn more in the [Kilo Gateway documentation](https://kilo.ai).
10
10
 
@@ -42,9 +42,9 @@ for await (const chunk of stream) {
42
42
  | `kilo/~anthropic/claude-haiku-latest` | 200K | | | | | | $1 | $5 |
43
43
  | `kilo/~anthropic/claude-opus-latest` | 1.0M | | | | | | $4 | $20 |
44
44
  | `kilo/~anthropic/claude-sonnet-latest` | 1.0M | | | | | | $2 | $10 |
45
- | `kilo/~deepseek/deepseek-flash-latest` | 1.0M | | | | | | $0.08 | $0.60 |
45
+ | `kilo/~deepseek/deepseek-flash-latest` | 1.0M | | | | | | $0.10 | $0.50 |
46
46
  | `kilo/~deepseek/deepseek-pro-latest` | 1.0M | | | | | | $0.40 | $4 |
47
- | `kilo/~deepseek/deepseek-v4-flash-latest` | 1.0M | | | | | | $0.03 | $0.80 |
47
+ | `kilo/~deepseek/deepseek-v4-flash-latest` | 1.0M | | | | | | $0.04 | $0.55 |
48
48
  | `kilo/~google/gemini-flash-latest` | 1.0M | | | | | | $0.75 | $4 |
49
49
  | `kilo/~google/gemini-pro-latest` | 1.0M | | | | | | $2 | $12 |
50
50
  | `kilo/~moonshotai/kimi-latest` | 1.0M | | | | | | $1 | $11 |
@@ -396,6 +396,7 @@ for await (const chunk of stream) {
396
396
  | `kilo/thinkingmachines/inkling-small:free` | 1.0M | | | | | | — | — |
397
397
  | `kilo/unbiased/pareto` | 262K | | | | | | $3 | $8 |
398
398
  | `kilo/undi95/remm-slerp-l2-13b` | 6K | | | | | | $0.35 | $0.65 |
399
+ | `kilo/upstage/solar-mini4` | 524K | | | | | | $0.10 | $0.40 |
399
400
  | `kilo/upstage/solar-pro-3` | 131K | | | | | | $0.15 | $0.60 |
400
401
  | `kilo/upstage/solar-pro4` | 524K | | | | | | $0.30 | $1 |
401
402
  | `kilo/writer/palmyra-x5` | 1.0M | | | | | | $0.60 | $6 |
@@ -136,10 +136,10 @@ import {
136
136
  } from '@mastra/core/observability'
137
137
 
138
138
  const input = describeSpanInput(span)
139
- // { type: 'text' | 'messages' | 'agent-run-resume' | 'json'; value } | undefined
139
+ // { type: 'text' | 'messages' | 'agent-run-resume' | 'processor' | 'json'; value } | undefined
140
140
 
141
141
  const output = describeSpanOutput(span)
142
- // { type: 'interrupted' | 'agent-run-result' | 'model-generation-result' | 'model-step-result' | 'text' | 'json'; value } | undefined
142
+ // { type: 'interrupted' | 'agent-run-result' | 'model-generation-result' | 'model-step-result' | 'processor' | 'text' | 'json'; value } | undefined
143
143
 
144
144
  switch (output?.type) {
145
145
  case 'interrupted':
@@ -151,6 +151,42 @@ switch (output?.type) {
151
151
  describeSpanError(span) // SpanErrorInfo | undefined
152
152
  ```
153
153
 
154
+ ### Processor spans
155
+
156
+ A processor span records which pipeline phase produced it, so a reader narrows its payloads on that phase instead of on the payload's shape. The recorded phase is finer than the one a processor declares: `outputStream` and `outputResult` are separate here, because they record different payloads.
157
+
158
+ ```typescript
159
+ import { describeProcessorPipeline, describeSpanOutput } from '@mastra/core/observability'
160
+
161
+ const output = describeSpanOutput(span)
162
+
163
+ if (output?.type === 'processor') {
164
+ output.value.phase // 'input' | 'inputStep' | 'llmRequest' | 'llmResponse'
165
+ // | 'outputStream' | 'outputResult' | 'outputStep' | 'toolResult' | 'requestError'
166
+ output.value.phaseLabel // 'Tool result'
167
+ if (output.value.phase === 'outputStream') {
168
+ output.value.data.totalChunks // number
169
+ }
170
+ }
171
+ ```
172
+
173
+ `describeProcessorPipeline` reads the attributes Mastra owns and keeps everything else apart, so a reader can show the known fields without repeating them beside a raw JSON view:
174
+
175
+ ```typescript
176
+ const pipeline = describeProcessorPipeline(span)
177
+
178
+ pipeline?.executor // 'workflow' | 'legacy'
179
+ pipeline?.processorIndex // position in the chain
180
+ pipeline?.hookDurationMs // time spent inside the processor hook
181
+ pipeline?.messageListMutations // 'add' | 'addSystem' | 'removeByIds' | 'clear'
182
+ pipeline?.tripwireAbort?.reason // why the processor blocked the run
183
+ pipeline?.rest // attributes this description does not explain
184
+ ```
185
+
186
+ `PROCESSOR_RUN` is absent from `SpanInputMap` and `SpanOutputMap` on purpose: three executors emit processor spans and record different shapes. The payload is narrowed at read time instead, by the phase the span recorded, and narrowing on `phase` narrows `data` to that phase alone.
187
+
188
+ `describeSpanInput` and `describeSpanOutput` return the JSON fallback for a span with no recorded phase, one written by a newer version with a phase this release doesn't know, or an empty payload. `describeProcessorPipeline` returns `undefined` when the phase is missing or unknown, and still describes the pipeline when the payload is empty. The stored payload and the JSON view remain unchanged.
189
+
154
190
  ### Span
155
191
 
156
192
  Span interface, used internally for tracing.
@@ -624,6 +624,20 @@ Keyset cursors are bound to the operation, accepted normalized query, and orderi
624
624
 
625
625
  Numbered-page handoff cursors and delta cursors also bind the authorization state. Changes to the caller's roles or permissions invalidate these cursors and return `409`. If a delta poll returns `409`, reload the numbered pages and resume polling with the new `deltaCursor`. A malformed cursor returns `400`.
626
626
 
627
+ ### Trusted tenant scope
628
+
629
+ Hosts that serve more than one tenant supply a trusted scope outside the query document. The server reads the reserved `organizationId` request-context key, which only server-side authentication can set, and passes `{ organizationId }` to the planner. The scope is carried on the trusted plan and ANDed into every scan: current roots, related spans, scores, feedback, and both discovery routes. A related record from another tenant that shares a `traceId` never qualifies a trace.
630
+
631
+ Hosts that call storage directly can pass a fuller scope to `planTraceQuery()`, `planThreadQuery()`, `planTraceQueryObservedFields()`, and `planTraceQueryValues()`:
632
+
633
+ ```typescript
634
+ const plan = planTraceQuery(parseTraceQueryRequest(request), {
635
+ scope: { organizationId: 'org_123', resourceId: 'project_456' },
636
+ })
637
+ ```
638
+
639
+ `resourceId` is optional and narrows within the organization. Keyset and delta cursors are bound to the scope, so a cursor minted under one scope and reused under another returns `409` before storage runs. A scoped request against an observability store or `@mastra/core` that predates tenant scope returns `501` instead of running unscoped. Stores advertise support through the `trace-query-tenant-scope` feature. Callers can't name `organizationId` or `projectId` in predicates. Without a scope the routes behave as before, so self-hosted installations keep their own tenant model.
640
+
627
641
  Cursor pagination is deterministic, but it isn't a database snapshot. Traces or replacement signals written between page requests can change later pages.
628
642
 
629
643
  PostgreSQL and ClickHouse stop advanced trace and thread queries after 15 seconds by default and return `504` when the database timeout is exceeded. Set `traceQueryTimeoutMs` in the store's vNext observability configuration to an integer from 1 through 300,000 milliseconds to change the timeout. DuckDB doesn't currently provide query-scoped timeout or cancellation through its driver wrapper, so this `504` guarantee doesn't apply to DuckDB.
@@ -136,6 +136,8 @@ A tool is being called.
136
136
 
137
137
  **payload.toolName** (`string`): Name of the tool being called
138
138
 
139
+ **payload.title** (`string`): Human-readable display name for the tool, when the tool defines one
140
+
139
141
  **payload.args** (`Record<string, any>`): Arguments passed to the tool
140
142
 
141
143
  **payload.providerExecuted** (`boolean`): Whether the provider executed the tool
@@ -178,6 +180,8 @@ Signals the start of streaming tool call arguments.
178
180
 
179
181
  **payload.toolName** (`string`): Name of the tool being called
180
182
 
183
+ **payload.title** (`string`): Human-readable display name for the tool, when the tool defines one
184
+
181
185
  **payload.providerExecuted** (`boolean`): Whether the provider executed the tool
182
186
 
183
187
  **payload.dynamic** (`boolean`): Whether the tool call is dynamic
@@ -39,6 +39,8 @@ The first `execute` parameter is the validated value from `inputSchema`. Destruc
39
39
 
40
40
  **id** (`string`): A unique identifier for the tool.
41
41
 
42
+ **title** (`string`): A human-readable display name for the tool. It is not sent to the model. It travels on the tool-call and tool-call-input-streaming-start stream chunks and on the stored tool-invocation part, so chat UIs can read it to label the call. MCP clients receive it as the tool title.
43
+
42
44
  **description** (`string`): A description of what the tool does. This is used by the agent to decide when to use the tool.
43
45
 
44
46
  **inputSchema** (`StandardJSONSchemaV1`): A Standard JSON Schema defining the expected input parameters for the tool's execute function.
@@ -151,6 +151,8 @@ Per the MCP specification: **clients MUST consider tool annotations to be untrus
151
151
 
152
152
  The same annotations are also exposed on the tools returned by `listTools()` and `listToolsets()` under `tool.mcp.annotations`, so you can inspect them when wiring tools into an agent.
153
153
 
154
+ Each tool also carries `tool.title`, set from the server's tool `title` and falling back to `annotations.title`. When the server provides neither, `tool.title` is `undefined` and the tool name is the display fallback, matching the MCP display-name precedence.
155
+
154
156
  ## Server instructions
155
157
 
156
158
  When an MCP server advertises instructions during initialization, `MCPClient` stores them for that server. Forwarding those instructions into an agent's system prompt is **opt-in**: set `forwardInstructions: true` on a server to have agents that use its tools (via `listTools()` or `listToolsets()`) receive its instructions automatically.
@@ -289,7 +291,7 @@ When called without options, the method omits only `durations`; `toolsets`, `err
289
291
 
290
292
  Returns every server's tools as plain, serializable definitions, grouped by server name and keyed by the server's own tool name (without the `serverName_toolName` namespacing that `listTools()` applies).
291
293
 
292
- Unlike `listTools()`, the result contains no functions or references to a live client, so it can be passed through `JSON.stringify` and cached in Redis or a database, as well as a build artifact. Each definition holds the data from the MCP `tools/list` response (name, description, input schema, output schema, annotations, and `_meta`), plus the server name, version, and instructions captured at discovery time.
294
+ Unlike `listTools()`, the result contains no functions or references to a live client, so it can be passed through `JSON.stringify` and cached in Redis or a database, as well as a build artifact. Each definition holds the data from the MCP `tools/list` response (name, title, description, input schema, output schema, annotations, and `_meta`), plus the server name, version, and instructions captured at discovery time.
293
295
 
294
296
  ```typescript
295
297
  const definitions = await mcp.listToolDefinitions()
package/dist/index.d.ts CHANGED
@@ -1,5 +1,16 @@
1
1
  import { MCPServer } from '@mastra/mcp';
2
- declare let server: MCPServer;
2
+ import { MCPServer as LegacyMCPServer } from '@mastra/mcp-legacy';
3
+ import type { ProtocolEra } from './protocol-era.js';
4
+ /**
5
+ * Build the docs server for a protocol era. The same tools and prompts are
6
+ * registered either way; only the protocol implementation differs.
7
+ *
8
+ * `@mastra/mcp` 2.x serves the 2026-07-28 revision. Hosts that still open with
9
+ * a legacy `initialize` handshake get the published `@mastra/mcp` 1.x server
10
+ * (installed under the `@mastra/mcp-legacy` alias) so `npx @mastra/mcp-docs-server`
11
+ * keeps working while editors adopt the new revision.
12
+ */
13
+ declare function createDocsServer(era: ProtocolEra): MCPServer | LegacyMCPServer;
3
14
  declare function runServer(): Promise<void>;
4
- export { runServer, server };
15
+ export { runServer, createDocsServer };
5
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAexC,QAAA,IAAI,MAAM,EAAE,SAAS,CAAC;AAsBtB,iBAAe,SAAS,kBAQvB;AAED,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,SAAS,IAAI,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAIlE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AA8BlD;;;;;;;;GAQG;AACH,iBAAS,gBAAgB,CAAC,GAAG,EAAE,WAAW,+BAEzC;AAED,iBAAe,SAAS,kBAYvB;AAED,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { n as server, t as runServer } from "./src-D-W-bx5t.js";
2
- export { runServer, server };
1
+ import { n as runServer, t as createDocsServer } from "./src-CGZ6-uLS.js";
2
+ export { createDocsServer, runServer };
package/dist/logger.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import type { MCPServer } from '@mastra/mcp';
2
1
  export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'none';
3
2
  export declare function setLogLevel(level: LogLevel): void;
4
3
  export declare function getLogLevel(): LogLevel;
@@ -13,6 +12,6 @@ export interface Logger {
13
12
  emergency: (message: string, error?: any) => Promise<void>;
14
13
  }
15
14
  export declare const writeErrorLog: (message: string, data?: any) => void;
16
- export declare function createLogger(server?: MCPServer): Logger;
15
+ export declare function createLogger(): Logger;
17
16
  export declare const logger: Logger;
18
17
  //# sourceMappingURL=logger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAI7C,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAkCpE,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAEjD;AAED,wBAAgB,WAAW,IAAI,QAAQ,CAEtC;AASD,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D;AAED,eAAO,MAAM,aAAa,YAAa,MAAM,SAAS,GAAG,SA2BxD,CAAC;AAGF,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,CA4FvD;AAGD,eAAO,MAAM,MAAM,QAAiB,CAAC"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAkCpE,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAEjD;AAED,wBAAgB,WAAW,IAAI,QAAQ,CAEtC;AASD,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D;AAED,eAAO,MAAM,aAAa,YAAa,MAAM,SAAS,GAAG,SA2BxD,CAAC;AAIF,wBAAgB,YAAY,IAAI,MAAM,CAuErC;AAGD,eAAO,MAAM,MAAM,QAAiB,CAAC"}
@@ -1,6 +1,16 @@
1
- import type { MCPServerPrompts } from '@mastra/mcp';
1
+ import type { Prompt, PromptMessage } from '@mastra/mcp';
2
2
  /**
3
- * Prompt messages callback that generates contextual migration guidance
3
+ * Prompt callbacks that generate contextual migration guidance.
4
+ *
5
+ * Typed by what the callbacks read rather than by one package's
6
+ * `MCPServerPrompts`, so the same object registers on both the 2026-07-28
7
+ * server and the legacy 1.x server.
4
8
  */
5
- export declare const migrationPromptMessages: MCPServerPrompts;
9
+ export declare const migrationPromptMessages: {
10
+ listPrompts: () => Promise<Prompt[]>;
11
+ getPromptMessages: ({ name, args, }: {
12
+ name: string;
13
+ args?: Record<string, unknown>;
14
+ }) => Promise<PromptMessage[]>;
15
+ };
6
16
  //# sourceMappingURL=migration.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../../src/prompts/migration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAgB,MAAM,aAAa,CAAC;AA8BlE;;GAEG;AACH,eAAO,MAAM,uBAAuB,EAAE,gBAmBrC,CAAC"}
1
+ {"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../../src/prompts/migration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA2BzD;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB;IAClC,WAAW,QAAY,OAAO,CAAC,MAAM,EAAE,CAAC;IAExC,iBAAiB,oBAGd;QACD,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAChC,KAAG,OAAO,CAAC,aAAa,EAAE,CAAC;CAiB7B,CAAC"}
@@ -0,0 +1,29 @@
1
+ import type { Readable } from 'node:stream';
2
+ /**
3
+ * Which MCP protocol family the connecting host speaks.
4
+ *
5
+ * - `legacy`: pre-2026 hosts. They open the connection with an `initialize`
6
+ * request (protocol revisions `2024-11-05` through `2025-11-25`).
7
+ * - `2026-07-28`: hosts on the current revision. They never send `initialize`;
8
+ * their first message is `server/discover` or an envelope-bearing request.
9
+ */
10
+ export type ProtocolEra = 'legacy' | '2026-07-28';
11
+ /**
12
+ * Decide the protocol era from the first JSON-RPC line a host writes to stdin.
13
+ *
14
+ * Anything that is not a legacy `initialize` request is handed to the
15
+ * 2026-07-28 server, which produces the spec-defined error for malformed or
16
+ * unsupported requests. Only a well-formed legacy handshake selects the 1.x
17
+ * server.
18
+ */
19
+ export declare function detectProtocolEra(firstLine: string | undefined): ProtocolEra;
20
+ /**
21
+ * Read up to and including the first newline from `stream`, then push every
22
+ * byte back so the MCP transport that starts afterwards sees the untouched
23
+ * message stream.
24
+ *
25
+ * Resolves with `undefined` if the stream ends before a newline arrives; the
26
+ * partial bytes are dropped because no transport can act on a closed stdin.
27
+ */
28
+ export declare function peekFirstLine(stream: Readable): Promise<string | undefined>;
29
+ //# sourceMappingURL=protocol-era.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol-era.d.ts","sourceRoot":"","sources":["../src/protocol-era.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,YAAY,CAAC;AAElD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAa5E;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA8C3E"}
@@ -1,5 +1,6 @@
1
1
  import fs from "fs/promises";
2
2
  import { MCPServer } from "@mastra/mcp";
3
+ import { MCPServer as MCPServer$1 } from "@mastra/mcp-legacy";
3
4
  import * as fs$1 from "fs";
4
5
  import { existsSync, mkdirSync } from "fs";
5
6
  import * as os$1 from "os";
@@ -55,24 +56,17 @@ const writeErrorLog = (message, data) => {
55
56
  console.error("Failed to write to log file:", err);
56
57
  }
57
58
  };
58
- function createLogger(server) {
59
+ function createLogger() {
59
60
  const sendLog = async (level, message, data) => {
60
- if (!server) return;
61
61
  if (!shouldLog(level)) return;
62
- try {
63
- const sdkServer = server.getServer();
64
- if (!sdkServer) return;
65
- await sdkServer.sendLoggingMessage({
66
- level,
67
- data: {
68
- message,
69
- ...data ? typeof data === "object" ? data : { data } : {}
70
- }
71
- });
72
- } catch (error) {
73
- if (error instanceof Error && (error.message === "Not connected" || error.message.includes("does not support logging") || error.message.includes("Connection closed"))) return;
74
- console.error(`Failed to send ${level} log:`, error instanceof Error ? error.message : error);
75
- }
62
+ console.error(JSON.stringify(data === void 0 ? {
63
+ level,
64
+ message
65
+ } : {
66
+ level,
67
+ message,
68
+ data
69
+ }));
76
70
  };
77
71
  return {
78
72
  debug: async (message, data) => {
@@ -134,7 +128,6 @@ const logger = createLogger();
134
128
  */
135
129
  const migrationPrompts = [{
136
130
  name: "upgrade-to-v1",
137
- version: "v1",
138
131
  description: "Get a guided migration plan for upgrading from Mastra v0.x to v1.0. Provides step-by-step instructions for handling all breaking changes.",
139
132
  arguments: [{
140
133
  name: "area",
@@ -143,17 +136,23 @@ const migrationPrompts = [{
143
136
  }]
144
137
  }, {
145
138
  name: "migration-checklist",
146
- version: "v1",
147
139
  description: "Get a comprehensive checklist for migrating to Mastra v1.0. Lists all breaking changes that need to be addressed."
148
140
  }];
149
141
  /**
150
- * Prompt messages callback that generates contextual migration guidance
142
+ * Prompt callbacks that generate contextual migration guidance.
143
+ *
144
+ * Typed by what the callbacks read rather than by one package's
145
+ * `MCPServerPrompts`, so the same object registers on both the 2026-07-28
146
+ * server and the legacy 1.x server.
151
147
  */
152
148
  const migrationPromptMessages = {
153
149
  listPrompts: async () => migrationPrompts,
154
150
  getPromptMessages: async ({ name, args }) => {
155
151
  if (!migrationPrompts.find((p) => p.name === name)) throw new Error(`Prompt not found: ${name}`);
156
- if (name === "upgrade-to-v1") return getUpgradeToV1Messages(args?.area);
152
+ if (name === "upgrade-to-v1") {
153
+ const area = args?.area;
154
+ return getUpgradeToV1Messages(typeof area === "string" ? area : void 0);
155
+ }
157
156
  if (name === "migration-checklist") return getMigrationChecklistMessages();
158
157
  throw new Error(`No message handler for prompt: ${name}`);
159
158
  }
@@ -218,6 +217,70 @@ Group the checklist by area (Agents, Tools, Workflows, etc.) so I can tackle one
218
217
  }];
219
218
  }
220
219
  //#endregion
220
+ //#region src/protocol-era.ts
221
+ /**
222
+ * Decide the protocol era from the first JSON-RPC line a host writes to stdin.
223
+ *
224
+ * Anything that is not a legacy `initialize` request is handed to the
225
+ * 2026-07-28 server, which produces the spec-defined error for malformed or
226
+ * unsupported requests. Only a well-formed legacy handshake selects the 1.x
227
+ * server.
228
+ */
229
+ function detectProtocolEra(firstLine) {
230
+ if (!firstLine) return "2026-07-28";
231
+ try {
232
+ const message = JSON.parse(firstLine);
233
+ if (message && typeof message === "object" && message.method === "initialize") return "legacy";
234
+ } catch {}
235
+ return "2026-07-28";
236
+ }
237
+ /**
238
+ * Read up to and including the first newline from `stream`, then push every
239
+ * byte back so the MCP transport that starts afterwards sees the untouched
240
+ * message stream.
241
+ *
242
+ * Resolves with `undefined` if the stream ends before a newline arrives; the
243
+ * partial bytes are dropped because no transport can act on a closed stdin.
244
+ */
245
+ function peekFirstLine(stream) {
246
+ return new Promise((resolve, reject) => {
247
+ const chunks = [];
248
+ const detach = () => {
249
+ stream.off("readable", onReadable);
250
+ stream.off("end", onEnd);
251
+ stream.off("error", onError);
252
+ };
253
+ const finish = (line) => {
254
+ detach();
255
+ for (let i = chunks.length - 1; i >= 0; i--) stream.unshift(chunks[i]);
256
+ resolve(line);
257
+ };
258
+ const onReadable = () => {
259
+ let chunk;
260
+ while ((chunk = stream.read()) !== null) {
261
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
262
+ chunks.push(buffer);
263
+ if (buffer.indexOf(10) !== -1) {
264
+ const head = Buffer.concat(chunks);
265
+ finish(head.subarray(0, head.indexOf(10)).toString("utf8"));
266
+ return;
267
+ }
268
+ }
269
+ };
270
+ const onEnd = () => {
271
+ detach();
272
+ resolve(void 0);
273
+ };
274
+ const onError = (error) => {
275
+ detach();
276
+ reject(error);
277
+ };
278
+ stream.on("readable", onReadable);
279
+ stream.on("end", onEnd);
280
+ stream.on("error", onError);
281
+ });
282
+ }
283
+ //#endregion
221
284
  //#region src/utils.ts
222
285
  const mdFileCache = /* @__PURE__ */ new Map();
223
286
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -1742,8 +1805,7 @@ This tool works like a file browser - navigate through directories to find migra
1742
1805
  };
1743
1806
  //#endregion
1744
1807
  //#region src/index.ts
1745
- let server;
1746
- server = new MCPServer({
1808
+ const serverConfig = {
1747
1809
  name: "Mastra Documentation Server",
1748
1810
  version: JSON.parse(await fs.readFile(fromPackageRoot(`package.json`), "utf8")).version,
1749
1811
  tools: {
@@ -1757,18 +1819,31 @@ server = new MCPServer({
1757
1819
  ...embeddedDocsTools
1758
1820
  },
1759
1821
  prompts: migrationPromptMessages
1760
- });
1761
- Object.assign(logger, createLogger(server));
1822
+ };
1823
+ /**
1824
+ * Build the docs server for a protocol era. The same tools and prompts are
1825
+ * registered either way; only the protocol implementation differs.
1826
+ *
1827
+ * `@mastra/mcp` 2.x serves the 2026-07-28 revision. Hosts that still open with
1828
+ * a legacy `initialize` handshake get the published `@mastra/mcp` 1.x server
1829
+ * (installed under the `@mastra/mcp-legacy` alias) so `npx @mastra/mcp-docs-server`
1830
+ * keeps working while editors adopt the new revision.
1831
+ */
1832
+ function createDocsServer(era) {
1833
+ return era === "legacy" ? new MCPServer$1(serverConfig) : new MCPServer(serverConfig);
1834
+ }
1762
1835
  async function runServer() {
1763
1836
  try {
1764
- await server.startStdio();
1765
- logger.info("Started Mastra Docs MCP Server");
1837
+ const era = detectProtocolEra(await peekFirstLine(process.stdin));
1838
+ await createDocsServer(era).startStdio();
1839
+ process.stdin.resume();
1840
+ logger.info("Started Mastra Docs MCP Server", { protocol: era });
1766
1841
  } catch (error) {
1767
1842
  logger.error("Failed to start server", error);
1768
1843
  process.exit(1);
1769
1844
  }
1770
1845
  }
1771
1846
  //#endregion
1772
- export { writeErrorLog as i, server as n, setLogLevel as r, runServer as t };
1847
+ export { writeErrorLog as i, runServer as n, setLogLevel as r, createDocsServer as t };
1773
1848
 
1774
- //# sourceMappingURL=src-D-W-bx5t.js.map
1849
+ //# sourceMappingURL=src-CGZ6-uLS.js.map