@mastra/mcp-docs-server 1.2.25-alpha.3 → 1.2.25-alpha.6
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/docs/mastra-platform/studio.md +32 -0
- package/.docs/docs/observability/feedback.md +12 -0
- package/.docs/docs/studio/auth.md +2 -0
- package/.docs/models/gateways/netlify.md +10 -1
- package/.docs/models/gateways/openrouter.md +2 -1
- package/.docs/models/gateways/vercel.md +375 -376
- package/.docs/models/index.md +1 -1
- package/.docs/models/providers/cloudflare-workers-ai.md +2 -1
- package/.docs/models/providers/crossmodel.md +4 -3
- package/.docs/models/providers/digitalocean.md +1 -1
- package/.docs/models/providers/edenai.md +4 -3
- package/.docs/models/providers/greenpt.md +3 -1
- package/.docs/models/providers/kilo.md +7 -6
- package/.docs/models/providers/llmgateway-providers.md +2 -3
- package/.docs/models/providers/llmgateway.md +1 -1
- package/.docs/models/providers/nano-gpt.md +6 -8
- package/.docs/models/providers/nearai.md +10 -15
- package/.docs/models/providers/ofox.md +2 -2
- package/.docs/models/providers/opencode-go.md +7 -7
- package/.docs/models/providers/zenmux.md +0 -1
- package/.docs/reference/client-js/observability.md +18 -0
- package/.docs/reference/code-sdk/mount-agent-controller.md +20 -0
- package/.docs/reference/coding-agent/build-base-prompt.md +1 -1
- package/.docs/reference/observability/feedback.md +30 -8
- package/.docs/reference/observability/tracing/interfaces.md +195 -8
- package/.docs/reference/observability/tracing/spans.md +2 -2
- package/.docs/reference/voice/voice.connect.md +38 -29
- package/package.json +4 -4
|
@@ -53,7 +53,7 @@ For ClickHouse vNext, the method records the complete predicate and waits for li
|
|
|
53
53
|
|
|
54
54
|
### `SpanTypeMap`
|
|
55
55
|
|
|
56
|
-
Mapping of span types to their corresponding attribute interfaces.
|
|
56
|
+
Mapping of span types to their corresponding attribute interfaces. The list below is abbreviated. The `SpanTypeMap` interface in `@mastra/core/observability` is the complete one.
|
|
57
57
|
|
|
58
58
|
```typescript
|
|
59
59
|
interface SpanTypeMap {
|
|
@@ -61,6 +61,7 @@ interface SpanTypeMap {
|
|
|
61
61
|
WORKFLOW_RUN: WorkflowRunAttributes
|
|
62
62
|
MODEL_GENERATION: ModelGenerationAttributes
|
|
63
63
|
MODEL_STEP: ModelStepAttributes
|
|
64
|
+
MODEL_INFERENCE: ModelInferenceAttributes
|
|
64
65
|
MODEL_CHUNK: ModelChunkAttributes
|
|
65
66
|
TOOL_CALL: ToolCallAttributes
|
|
66
67
|
CLIENT_TOOL_CALL: ClientToolCallAttributes
|
|
@@ -85,6 +86,70 @@ interface SpanTypeMap {
|
|
|
85
86
|
|
|
86
87
|
This mapping defines which attribute interface is used for each span type when creating or processing spans.
|
|
87
88
|
|
|
89
|
+
### `SpanInputMap` and `SpanOutputMap`
|
|
90
|
+
|
|
91
|
+
Mapping of the span types whose `input` and `output` Mastra writes itself with a fixed shape. Every other span type keeps `any`: tool arguments and workflow data are caller-defined, `MODEL_CHUNK` carries several chunk shapes on one span type, and `GENERIC` is the escape hatch for custom spans.
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
interface SpanInputMap {
|
|
95
|
+
AGENT_RUN: AgentRunInput
|
|
96
|
+
MODEL_GENERATION: ModelGenerationInput
|
|
97
|
+
MODEL_STEP: ModelStepInput
|
|
98
|
+
MODEL_INFERENCE: ModelStepInput
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
interface SpanOutputMap {
|
|
102
|
+
AGENT_RUN: AgentRunOutput
|
|
103
|
+
MODEL_GENERATION: ModelGenerationOutput
|
|
104
|
+
MODEL_STEP: ModelStepOutput
|
|
105
|
+
MODEL_INFERENCE: ModelStepResult
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** The mapped shape when the map lists the type, otherwise `any` */
|
|
109
|
+
type SpanInput<TType extends SpanType> = TType extends keyof SpanInputMap
|
|
110
|
+
? SpanInputMap[TType]
|
|
111
|
+
: any
|
|
112
|
+
type SpanOutput<TType extends SpanType> = TType extends keyof SpanOutputMap
|
|
113
|
+
? SpanOutputMap[TType]
|
|
114
|
+
: any
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Narrow a span by its type to read the typed payload. On a stored `SpanRecord`, use `isSpanRecordOfType`:
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
import { SpanType, isSpanRecordOfType } from '@mastra/core/observability'
|
|
121
|
+
|
|
122
|
+
if (isSpanRecordOfType(span, SpanType.MODEL_GENERATION)) {
|
|
123
|
+
span.input?.messages // MessageListInput
|
|
124
|
+
span.attributes?.usage // UsageStats | undefined
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
To pick a renderer without checking shapes yourself, describe the payload. The tag is derived at read time from `spanType` and the value's shape. Nothing is stored.
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import {
|
|
132
|
+
describeSpanError,
|
|
133
|
+
describeSpanInput,
|
|
134
|
+
describeSpanOutput,
|
|
135
|
+
} from '@mastra/core/observability'
|
|
136
|
+
|
|
137
|
+
const input = describeSpanInput(span)
|
|
138
|
+
// { type: 'text' | 'messages' | 'agent-run-resume' | 'json'; value } | undefined
|
|
139
|
+
|
|
140
|
+
const output = describeSpanOutput(span)
|
|
141
|
+
// { type: 'interrupted' | 'agent-run-result' | 'model-generation-result' | 'model-step-result' | 'text' | 'json'; value } | undefined
|
|
142
|
+
|
|
143
|
+
switch (output?.type) {
|
|
144
|
+
case 'interrupted':
|
|
145
|
+
return output.value.status // 'suspended' | 'aborted'
|
|
146
|
+
case 'model-generation-result':
|
|
147
|
+
return output.value.text
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
describeSpanError(span) // SpanErrorInfo | undefined
|
|
151
|
+
```
|
|
152
|
+
|
|
88
153
|
### Span
|
|
89
154
|
|
|
90
155
|
Span interface, used internally for tracing.
|
|
@@ -107,8 +172,8 @@ interface Span<TType extends SpanType> {
|
|
|
107
172
|
|
|
108
173
|
attributes?: SpanTypeMap[TType]
|
|
109
174
|
metadata?: Record<string, any>
|
|
110
|
-
input?:
|
|
111
|
-
output?:
|
|
175
|
+
input?: SpanInput<TType>
|
|
176
|
+
output?: SpanOutput<TType>
|
|
112
177
|
errorInfo?: any
|
|
113
178
|
|
|
114
179
|
/** Tags for categorizing traces (only present on root spans) */
|
|
@@ -298,7 +363,7 @@ interface SpanOutputProcessor {
|
|
|
298
363
|
|
|
299
364
|
### `SpanType`
|
|
300
365
|
|
|
301
|
-
AI-specific span types with their associated metadata.
|
|
366
|
+
AI-specific span types with their associated metadata. The list below is abbreviated. The `SpanType` enum in `@mastra/core/observability` is the complete one.
|
|
302
367
|
|
|
303
368
|
```typescript
|
|
304
369
|
enum SpanType {
|
|
@@ -314,6 +379,9 @@ enum SpanType {
|
|
|
314
379
|
/** Single model execution step within a generation (one API call) */
|
|
315
380
|
MODEL_STEP = 'model_step',
|
|
316
381
|
|
|
382
|
+
/** Model provider call within a step - wraps only the inference, excluding processors and tool executions */
|
|
383
|
+
MODEL_INFERENCE = 'model_inference',
|
|
384
|
+
|
|
317
385
|
/** Individual model streaming chunk/event */
|
|
318
386
|
MODEL_CHUNK = 'model_chunk',
|
|
319
387
|
|
|
@@ -627,6 +695,125 @@ interface WorkflowStepAttributes {
|
|
|
627
695
|
}
|
|
628
696
|
```
|
|
629
697
|
|
|
698
|
+
## Span payloads
|
|
699
|
+
|
|
700
|
+
### `AgentRunInput`
|
|
701
|
+
|
|
702
|
+
Input recorded on `AGENT_RUN` spans: the messages the caller passed for a fresh run, or the resume data for a resumed run.
|
|
703
|
+
|
|
704
|
+
```typescript
|
|
705
|
+
type AgentRunInput = MessageListInput | { messages: MessageListInput } | AgentRunResumeInput
|
|
706
|
+
|
|
707
|
+
interface AgentRunResumeInput {
|
|
708
|
+
/** Resume data, kept nested when it names a different tool than the suspended one */
|
|
709
|
+
resumeData?: unknown
|
|
710
|
+
/** Tool the run resumes into */
|
|
711
|
+
toolName?: string
|
|
712
|
+
/** Tool call the run resumes into */
|
|
713
|
+
toolCallId?: string
|
|
714
|
+
[key: string]: unknown
|
|
715
|
+
}
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
### `AgentRunOutput`
|
|
719
|
+
|
|
720
|
+
Output recorded on `AGENT_RUN` spans.
|
|
721
|
+
|
|
722
|
+
```typescript
|
|
723
|
+
type AgentRunOutput = AgentRunResult | InterruptedSpanOutput
|
|
724
|
+
|
|
725
|
+
interface AgentRunResult {
|
|
726
|
+
/** Final response text */
|
|
727
|
+
text?: string
|
|
728
|
+
/** Final structured output */
|
|
729
|
+
object?: unknown
|
|
730
|
+
/** Generated files */
|
|
731
|
+
files?: unknown[]
|
|
732
|
+
/** Tripwire that aborted the run */
|
|
733
|
+
tripwire?: StepTripwireData
|
|
734
|
+
}
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
### `ModelGenerationInput`
|
|
738
|
+
|
|
739
|
+
Input recorded on `MODEL_GENERATION` spans.
|
|
740
|
+
|
|
741
|
+
Mastra's own loop records the normalized model messages, system messages first. SDK agents record the raw messages the caller passed, so `messages` keeps the full `MessageListInput` shape.
|
|
742
|
+
|
|
743
|
+
```typescript
|
|
744
|
+
interface ModelGenerationInput {
|
|
745
|
+
/** Messages sent to the model */
|
|
746
|
+
messages: MessageListInput
|
|
747
|
+
/** Output schema, when structured output was requested */
|
|
748
|
+
schema?: unknown
|
|
749
|
+
}
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
### `ModelGenerationOutput`
|
|
753
|
+
|
|
754
|
+
Output recorded on `MODEL_GENERATION` spans: a `ModelGenerationResult` when the generation finishes, or an `InterruptedSpanOutput` when the run stops first. Every field of `ModelGenerationResult` is optional: a durable run records only `text`.
|
|
755
|
+
|
|
756
|
+
```typescript
|
|
757
|
+
type ModelGenerationOutput = ModelGenerationResult | InterruptedSpanOutput
|
|
758
|
+
|
|
759
|
+
interface ModelGenerationResult {
|
|
760
|
+
text?: string
|
|
761
|
+
object?: unknown
|
|
762
|
+
reasoning?: unknown
|
|
763
|
+
reasoningText?: string
|
|
764
|
+
files?: unknown[]
|
|
765
|
+
sources?: unknown[]
|
|
766
|
+
toolCalls?: unknown[]
|
|
767
|
+
warnings?: unknown[]
|
|
768
|
+
}
|
|
769
|
+
```
|
|
770
|
+
|
|
771
|
+
### `ModelStepInput`
|
|
772
|
+
|
|
773
|
+
Input recorded on `MODEL_STEP` and `MODEL_INFERENCE` spans: a shallow preview of what the step sent to the model.
|
|
774
|
+
|
|
775
|
+
```typescript
|
|
776
|
+
type ModelStepInput = ModelStepMessage[] | Record<string, unknown> | string
|
|
777
|
+
|
|
778
|
+
interface ModelStepMessage {
|
|
779
|
+
/** Message role (e.g., 'system', 'user', 'assistant', 'tool') */
|
|
780
|
+
role: string
|
|
781
|
+
/** Message text, with non-text parts summarized */
|
|
782
|
+
content: string
|
|
783
|
+
}
|
|
784
|
+
```
|
|
785
|
+
|
|
786
|
+
### `ModelStepOutput`
|
|
787
|
+
|
|
788
|
+
Output recorded on `MODEL_STEP` spans. A finished step records a `ModelStepResult`, which is the step output without `usage` (that lives on the attributes). A step cut short by a suspension or an abort records an `InterruptedSpanOutput` instead. `MODEL_INFERENCE` spans always record a `ModelStepResult`.
|
|
789
|
+
|
|
790
|
+
```typescript
|
|
791
|
+
type ModelStepOutput = ModelStepResult | InterruptedSpanOutput
|
|
792
|
+
|
|
793
|
+
interface ModelStepResult {
|
|
794
|
+
text?: string
|
|
795
|
+
toolCalls?: unknown[]
|
|
796
|
+
steps?: unknown[]
|
|
797
|
+
object?: unknown
|
|
798
|
+
}
|
|
799
|
+
```
|
|
800
|
+
|
|
801
|
+
### `InterruptedSpanOutput`
|
|
802
|
+
|
|
803
|
+
Output recorded on `AGENT_RUN`, `MODEL_GENERATION` and `MODEL_STEP` spans when the run stops before the span's own result exists: a durable run suspended, or the caller aborted. `MODEL_INFERENCE` spans never carry it.
|
|
804
|
+
|
|
805
|
+
```typescript
|
|
806
|
+
interface InterruptedSpanOutput {
|
|
807
|
+
status: 'suspended' | 'aborted'
|
|
808
|
+
/** Why the run stopped */
|
|
809
|
+
reason?: string
|
|
810
|
+
/** Tool that suspended the run */
|
|
811
|
+
toolName?: string
|
|
812
|
+
/** Tool call that suspended the run */
|
|
813
|
+
toolCallId?: string
|
|
814
|
+
}
|
|
815
|
+
```
|
|
816
|
+
|
|
630
817
|
## Options types
|
|
631
818
|
|
|
632
819
|
### `StartSpanOptions`
|
|
@@ -648,7 +835,7 @@ interface StartSpanOptions<TType extends SpanType> {
|
|
|
648
835
|
metadata?: Record<string, any>
|
|
649
836
|
|
|
650
837
|
/** Input data */
|
|
651
|
-
input?:
|
|
838
|
+
input?: SpanInput<TType>
|
|
652
839
|
|
|
653
840
|
/** Parent span */
|
|
654
841
|
parent?: AnySpan
|
|
@@ -674,10 +861,10 @@ interface UpdateSpanOptions<TType extends SpanType> {
|
|
|
674
861
|
metadata?: Record<string, any>
|
|
675
862
|
|
|
676
863
|
/** Input data */
|
|
677
|
-
input?:
|
|
864
|
+
input?: SpanInput<TType>
|
|
678
865
|
|
|
679
866
|
/** Output data */
|
|
680
|
-
output?:
|
|
867
|
+
output?: SpanOutput<TType>
|
|
681
868
|
}
|
|
682
869
|
```
|
|
683
870
|
|
|
@@ -688,7 +875,7 @@ Options for ending spans.
|
|
|
688
875
|
```typescript
|
|
689
876
|
interface EndSpanOptions<TType extends SpanType> {
|
|
690
877
|
/** Output data */
|
|
691
|
-
output?:
|
|
878
|
+
output?: SpanOutput<TType>
|
|
692
879
|
|
|
693
880
|
/** Span metadata */
|
|
694
881
|
metadata?: Record<string, any>
|
|
@@ -35,10 +35,10 @@ interface BaseSpan<TType extends SpanType> {
|
|
|
35
35
|
metadata?: Record<string, any>
|
|
36
36
|
|
|
37
37
|
/** Input passed at the start of the span */
|
|
38
|
-
input?:
|
|
38
|
+
input?: SpanInput<TType>
|
|
39
39
|
|
|
40
40
|
/** Output generated at the end of the span */
|
|
41
|
-
output?:
|
|
41
|
+
output?: SpanOutput<TType>
|
|
42
42
|
|
|
43
43
|
/** Error information if span failed */
|
|
44
44
|
errorInfo?: {
|
|
@@ -13,27 +13,14 @@ import { OpenAIRealtimeVoice } from '@mastra/voice-openai-realtime'
|
|
|
13
13
|
import Speaker from '@mastra/node-speaker'
|
|
14
14
|
|
|
15
15
|
const speaker = new Speaker({
|
|
16
|
-
sampleRate:
|
|
17
|
-
channels: 1,
|
|
18
|
-
bitDepth: 16,
|
|
16
|
+
sampleRate: 24000,
|
|
17
|
+
channels: 1,
|
|
18
|
+
bitDepth: 16,
|
|
19
19
|
})
|
|
20
20
|
|
|
21
|
-
// Initialize a real-time voice provider
|
|
22
21
|
const voice = new OpenAIRealtimeVoice({
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
apiKey: process.env.OPENAI_API_KEY,
|
|
26
|
-
options: {
|
|
27
|
-
sessionConfig: {
|
|
28
|
-
turn_detection: {
|
|
29
|
-
type: 'server_vad',
|
|
30
|
-
threshold: 0.6,
|
|
31
|
-
silence_duration_ms: 1200,
|
|
32
|
-
},
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
speaker: 'alloy', // Default voice
|
|
22
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
23
|
+
speaker: 'alloy',
|
|
37
24
|
})
|
|
38
25
|
// Connect to the real-time service
|
|
39
26
|
await voice.connect()
|
|
@@ -41,11 +28,6 @@ await voice.connect()
|
|
|
41
28
|
voice.on('speaker', stream => {
|
|
42
29
|
stream.pipe(speaker)
|
|
43
30
|
})
|
|
44
|
-
// With connection options
|
|
45
|
-
await voice.connect({
|
|
46
|
-
timeout: 10000, // 10 seconds timeout
|
|
47
|
-
reconnect: true,
|
|
48
|
-
})
|
|
49
31
|
```
|
|
50
32
|
|
|
51
33
|
## Parameters
|
|
@@ -58,19 +40,46 @@ Returns a `Promise<void>` that resolves when the connection is successfully esta
|
|
|
58
40
|
|
|
59
41
|
## Provider-specific options
|
|
60
42
|
|
|
61
|
-
|
|
43
|
+
Connection configuration depends on the real-time voice provider.
|
|
62
44
|
|
|
63
45
|
### OpenAI Realtime
|
|
64
46
|
|
|
65
|
-
|
|
47
|
+
`connect()` accepts an optional `requestContext` for tool execution:
|
|
48
|
+
|
|
49
|
+
**options.requestContext** (`RequestContext`): Runtime context passed to tools called during the session.
|
|
50
|
+
|
|
51
|
+
See [Request context](https://mastra.ai/docs/server/request-context) for how to populate runtime values.
|
|
52
|
+
|
|
53
|
+
Set `connectTimeoutMs` in the `OpenAIRealtimeVoice` constructor, not in the `connect()` call:
|
|
54
|
+
|
|
55
|
+
**connectTimeoutMs** (`number`): Connection handshake deadline in milliseconds. Must be a positive, finite number no greater than 2,147,483,647. Applies only to connection setup, not to an established session. (Default: `15000`)
|
|
56
|
+
|
|
57
|
+
## Connection failures
|
|
58
|
+
|
|
59
|
+
For OpenAI Realtime, `connect()` waits for both the WebSocket to open and the server to create a session. It rejects if the connection fails, the server reports an error during the handshake, or the socket closes before the session is ready. A silent handshake times out after 15,000 milliseconds by default.
|
|
60
|
+
|
|
61
|
+
Catch connection failures directly. An `error` event listener doesn't replace handling the rejected promise:
|
|
66
62
|
|
|
67
|
-
|
|
63
|
+
```typescript
|
|
64
|
+
import { OpenAIRealtimeVoice } from '@mastra/voice-openai-realtime'
|
|
65
|
+
|
|
66
|
+
const voice = new OpenAIRealtimeVoice({
|
|
67
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
68
|
+
connectTimeoutMs: 30_000,
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
await voice.connect()
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.error('Could not connect to the realtime service:', error)
|
|
75
|
+
}
|
|
76
|
+
```
|
|
68
77
|
|
|
69
|
-
|
|
78
|
+
A failed handshake closes its socket and clears its pending waits. You can retry with `connect()` on the same instance.
|
|
70
79
|
|
|
71
80
|
## Using with `CompositeVoice`
|
|
72
81
|
|
|
73
|
-
When using `CompositeVoice`, the `connect()` method
|
|
82
|
+
When using `CompositeVoice`, the `connect()` method forwards its options to the configured real-time provider. It throws if no real-time provider is configured:
|
|
74
83
|
|
|
75
84
|
```typescript
|
|
76
85
|
import { CompositeVoice } from '@mastra/core/voice'
|
|
@@ -86,7 +95,7 @@ await voice.connect()
|
|
|
86
95
|
## Notes
|
|
87
96
|
|
|
88
97
|
- This method is only implemented by real-time voice providers that support speech-to-speech capabilities
|
|
89
|
-
-
|
|
98
|
+
- Providers that inherit the base `connect()` implementation log a debug message and resolve without establishing a connection
|
|
90
99
|
- The connection must be established before using other real-time methods like `send()` or `answer()`
|
|
91
100
|
- When you're done with the voice instance, call `close()` to properly clean up resources
|
|
92
101
|
- Some providers may automatically reconnect on connection loss, depending on their implementation
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/mcp-docs-server",
|
|
3
|
-
"version": "1.2.25-alpha.
|
|
3
|
+
"version": "1.2.25-alpha.6",
|
|
4
4
|
"description": "MCP server for accessing Mastra.ai documentation, changelogs, and news.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"jsdom": "^26.1.0",
|
|
28
28
|
"local-pkg": "^1.1.2",
|
|
29
29
|
"zod": "^4.4.3",
|
|
30
|
-
"@mastra/core": "1.66.0-alpha.
|
|
30
|
+
"@mastra/core": "1.66.0-alpha.3",
|
|
31
31
|
"@mastra/mcp": "^1.17.3"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
"tsx": "^4.23.1",
|
|
45
45
|
"typescript": "^7.0.2",
|
|
46
46
|
"vitest": "4.1.10",
|
|
47
|
-
"@internal/lint": "0.0.131",
|
|
48
47
|
"@internal/types-builder": "0.0.106",
|
|
49
|
-
"@
|
|
48
|
+
"@internal/lint": "0.0.131",
|
|
49
|
+
"@mastra/core": "1.66.0-alpha.3"
|
|
50
50
|
},
|
|
51
51
|
"homepage": "https://mastra.ai",
|
|
52
52
|
"repository": {
|