@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.
- package/.docs/models/gateways/netlify.md +2 -1
- package/.docs/models/gateways/openrouter.md +2 -1
- package/.docs/models/index.md +1 -1
- package/.docs/models/providers/edenai.md +1 -1
- package/.docs/models/providers/kilo.md +4 -3
- package/.docs/reference/observability/tracing/interfaces.md +38 -2
- package/.docs/reference/observability/tracing/trace-query.md +14 -0
- package/.docs/reference/streaming/ChunkType.md +4 -0
- package/.docs/reference/tools/create-tool.md +2 -0
- package/.docs/reference/tools/mcp-client.md +3 -1
- package/dist/index.d.ts +13 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/logger.d.ts +1 -2
- package/dist/logger.d.ts.map +1 -1
- package/dist/prompts/migration.d.ts +13 -3
- package/dist/prompts/migration.d.ts.map +1 -1
- package/dist/protocol-era.d.ts +29 -0
- package/dist/protocol-era.d.ts.map +1 -0
- package/dist/{src-D-W-bx5t.js → src-CGZ6-uLS.js} +103 -28
- package/dist/src-CGZ6-uLS.js.map +1 -0
- package/dist/stdio.js +1 -1
- package/package.json +7 -6
- package/dist/src-D-W-bx5t.js.map +0 -1
|
@@ -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
|
|
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
|
|
6
6
|
|
|
7
|
-
OpenRouter aggregates models from multiple providers with enhanced features like rate limiting and failover. Access
|
|
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` |
|
package/.docs/models/index.md
CHANGED
|
@@ -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
|
|
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.
|
|
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
|
|
6
6
|
|
|
7
|
-
Access
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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,
|
|
15
|
+
export { runServer, createDocsServer };
|
|
5
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,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
|
|
2
|
-
export {
|
|
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(
|
|
15
|
+
export declare function createLogger(): Logger;
|
|
17
16
|
export declare const logger: Logger;
|
|
18
17
|
//# sourceMappingURL=logger.d.ts.map
|
package/dist/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"
|
|
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 {
|
|
1
|
+
import type { Prompt, PromptMessage } from '@mastra/mcp';
|
|
2
2
|
/**
|
|
3
|
-
* Prompt
|
|
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:
|
|
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,
|
|
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(
|
|
59
|
+
function createLogger() {
|
|
59
60
|
const sendLog = async (level, message, data) => {
|
|
60
|
-
if (!server) return;
|
|
61
61
|
if (!shouldLog(level)) return;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
|
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")
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
1765
|
-
|
|
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,
|
|
1847
|
+
export { writeErrorLog as i, runServer as n, setLogLevel as r, createDocsServer as t };
|
|
1773
1848
|
|
|
1774
|
-
//# sourceMappingURL=src-
|
|
1849
|
+
//# sourceMappingURL=src-CGZ6-uLS.js.map
|