@mastra/mcp-docs-server 1.2.7-alpha.3 → 1.2.7-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/agent-builder/overview.md +4 -3
- package/.docs/docs/agent-controller/overview.md +2 -1
- package/.docs/docs/agents/a2a.md +2 -1
- package/.docs/docs/agents/guardrails.md +2 -1
- package/.docs/docs/agents/overview.md +2 -2
- package/.docs/docs/agents/skills.md +1 -1
- package/.docs/docs/agents/supervisor-agents.md +2 -1
- package/.docs/docs/browser/overview.md +2 -1
- package/.docs/docs/capabilities/channels/discord.md +98 -0
- package/.docs/docs/capabilities/channels/other-adapters.md +68 -0
- package/.docs/docs/capabilities/channels/overview.md +257 -0
- package/.docs/docs/capabilities/channels/slack.md +225 -0
- package/.docs/docs/capabilities/channels/teams.md +100 -0
- package/.docs/docs/capabilities/channels/telegram.md +98 -0
- package/.docs/docs/capabilities/channels/whatsapp.md +99 -0
- package/.docs/docs/evals/datasets/overview.md +2 -1
- package/.docs/docs/evals/datasets/running-experiments.md +2 -0
- package/.docs/docs/evals/overview.md +4 -1
- package/.docs/docs/getting-started/file-based-agents.md +114 -0
- package/.docs/docs/long-running-agents/signals.md +4 -1
- package/.docs/docs/mastra-platform/observability.md +5 -1
- package/.docs/docs/memory/observational-memory.md +2 -1
- package/.docs/docs/memory/overview.md +2 -0
- package/.docs/docs/memory/semantic-recall.md +1 -1
- package/.docs/docs/memory/working-memory.md +3 -3
- package/.docs/docs/studio/overview.md +1 -1
- package/.docs/docs/voice/livekit.md +100 -3
- package/.docs/docs/workflows/control-flow.md +0 -2
- package/.docs/docs/workflows/overview.md +2 -3
- package/.docs/docs/workspace/overview.md +2 -1
- package/.docs/docs/workspace/sandbox.md +2 -0
- package/.docs/guides/getting-started/quickstart.md +3 -1
- package/.docs/guides/guide/chef-michel.md +0 -2
- package/.docs/guides/guide/slack-assistant.md +2 -2
- package/.docs/guides/guide/stock-agent.md +0 -2
- package/.docs/models/environment-variables.md +1 -0
- package/.docs/models/gateways/openrouter.md +3 -2
- package/.docs/models/gateways/vercel.md +3 -1
- package/.docs/models/index.md +1 -1
- package/.docs/models/providers/google.md +2 -1
- package/.docs/models/providers/llmgateway.md +180 -181
- package/.docs/models/providers/neon.md +40 -29
- package/.docs/models/providers/opencode.md +2 -1
- package/.docs/models/providers/wandb.md +21 -14
- package/.docs/models/providers/xai.md +2 -1
- package/.docs/models/providers/zenifra.md +73 -0
- package/.docs/models/providers.md +1 -0
- package/.docs/reference/agents/channels.md +2 -2
- package/.docs/reference/channels/channel-provider.md +1 -1
- package/.docs/reference/channels/slack-provider.md +2 -2
- package/.docs/reference/cli/mastra.md +1 -0
- package/.docs/reference/file-based-agents/config.md +97 -0
- package/.docs/reference/file-based-agents/instructions.md +54 -0
- package/.docs/reference/file-based-agents/memory.md +58 -0
- package/.docs/reference/file-based-agents/observability.md +32 -0
- package/.docs/reference/file-based-agents/processors.md +56 -0
- package/.docs/reference/file-based-agents/server.md +37 -0
- package/.docs/reference/file-based-agents/skills.md +56 -0
- package/.docs/reference/file-based-agents/storage.md +30 -0
- package/.docs/reference/file-based-agents/studio.md +56 -0
- package/.docs/reference/file-based-agents/subagents.md +123 -0
- package/.docs/reference/file-based-agents/tools.md +63 -0
- package/.docs/reference/file-based-agents/workflows.md +52 -0
- package/.docs/reference/file-based-agents/workspace.md +74 -0
- package/.docs/reference/index.md +15 -0
- package/.docs/reference/memory/memory-class.md +1 -1
- package/.docs/reference/memory/serialized-memory-config.md +1 -1
- package/.docs/reference/memory/summarizeConversation.md +99 -0
- package/.docs/reference/memory/summarizeThread.md +93 -0
- package/.docs/reference/project-structure.md +1 -1
- package/.docs/reference/pubsub/lease-provider.md +1 -1
- package/.docs/reference/storage/clickhouse.md +32 -0
- package/.docs/reference/storage/composite.md +27 -1
- package/.docs/reference/storage/retention.md +11 -0
- package/.docs/reference/voice/livekit.md +272 -8
- package/CHANGELOG.md +7 -0
- package/package.json +5 -5
- package/.docs/docs/agents/channels.md +0 -225
- package/.docs/docs/agents/file-based-agents.md +0 -297
|
@@ -130,4 +130,4 @@ When the configured pub/sub backend doesn't implement `LeaseProvider`, the runti
|
|
|
130
130
|
- [PubSub](https://mastra.ai/reference/pubsub/base): The event delivery contract, separate from leasing
|
|
131
131
|
- [RedisStreamsPubSub](https://mastra.ai/reference/pubsub/redis-streams): The built-in backend that implements `LeaseProvider`
|
|
132
132
|
- [Signals](https://mastra.ai/docs/long-running-agents/signals): The runtime that uses leasing to coordinate thread runs across processes
|
|
133
|
-
- [Channels](https://mastra.ai/docs/
|
|
133
|
+
- [Channels](https://mastra.ai/docs/capabilities/channels/overview): Uses leasing to coordinate agent runs in serverless and multi-instance deployments
|
|
@@ -101,6 +101,38 @@ const observabilityStore = new ObservabilityStorageClickhouse({
|
|
|
101
101
|
|
|
102
102
|
New projects should use `ObservabilityStorageClickhouseVNext` instead.
|
|
103
103
|
|
|
104
|
+
### Migrating from legacy to vNext
|
|
105
|
+
|
|
106
|
+
To migrate historical spans from the legacy `mastra_ai_spans` table to the vNext schema, run:
|
|
107
|
+
|
|
108
|
+
**npm**:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
npx mastra migrate
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**pnpm**:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
pnpm dlx mastra migrate
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Yarn**:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
yarn dlx mastra migrate
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Bun**:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
bun x mastra migrate
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The migration copies span data from `mastra_ai_spans` into `mastra_span_events` in day-sized batches. It handles column mapping, deduplicates legacy rows, and preserves the original table as a backup. After migration, traces appear in Studio through the vNext adapter.
|
|
133
|
+
|
|
134
|
+
> **Note:** The legacy table is not deleted. Drop it manually after verifying the migration.
|
|
135
|
+
|
|
104
136
|
### ClickHouse for every domain
|
|
105
137
|
|
|
106
138
|
`ClickhouseStoreVNext` backs the `memory`, `workflows`, and `observability` domains with ClickHouse and uses the vNext observability adapter automatically. Use it when you want ClickHouse to back the entire application without wiring a composite store manually.
|
|
@@ -156,6 +156,32 @@ export const mastra = new Mastra({
|
|
|
156
156
|
})
|
|
157
157
|
```
|
|
158
158
|
|
|
159
|
+
### Disabling a domain
|
|
160
|
+
|
|
161
|
+
Set a domain to `false` to disable it. A disabled domain doesn't fall back to `default`, so data for that domain isn't persisted:
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
import { MastraCompositeStore } from '@mastra/core/storage'
|
|
165
|
+
import { PostgresStore } from '@mastra/pg'
|
|
166
|
+
import { Mastra } from '@mastra/core'
|
|
167
|
+
|
|
168
|
+
const pgStore = new PostgresStore({
|
|
169
|
+
id: 'pg',
|
|
170
|
+
connectionString: process.env.DATABASE_URL,
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
export const mastra = new Mastra({
|
|
174
|
+
storage: new MastraCompositeStore({
|
|
175
|
+
id: 'composite',
|
|
176
|
+
default: pgStore,
|
|
177
|
+
domains: {
|
|
178
|
+
// don't persist traces and spans
|
|
179
|
+
observability: false,
|
|
180
|
+
},
|
|
181
|
+
}),
|
|
182
|
+
})
|
|
183
|
+
```
|
|
184
|
+
|
|
159
185
|
## Options
|
|
160
186
|
|
|
161
187
|
**id** (`string`): Unique identifier for this storage instance.
|
|
@@ -164,7 +190,7 @@ export const mastra = new Mastra({
|
|
|
164
190
|
|
|
165
191
|
**disableInit** (`boolean`): When true, automatic initialization is disabled. You must call init() explicitly.
|
|
166
192
|
|
|
167
|
-
**domains** (`object`): Individual domain overrides. Each domain can come from a different storage adapter. These take precedence over both editor and default storage.
|
|
193
|
+
**domains** (`object`): Individual domain overrides. Each domain can come from a different storage adapter. These take precedence over both editor and default storage. Set a domain to false to disable it entirely; a disabled domain does not fall back to editor or default.
|
|
168
194
|
|
|
169
195
|
**domains.memory** (`MemoryStorage`): Storage for threads, messages, and resources.
|
|
170
196
|
|
|
@@ -105,6 +105,8 @@ Deletes rows older than their configured `maxAge` across every domain that has a
|
|
|
105
105
|
|
|
106
106
|
`prune()` is designed to be safe on tables with millions of rows. It deletes in bounded, batched chunks — each batch is its own transaction — so it never takes a long lock or bloats the transaction log. It never runs a `VACUUM`.
|
|
107
107
|
|
|
108
|
+
Pass `options.retention` to replace the configured policies for that call only — for example to skip a domain (keep chat history) or prune more aggressively than the standing config. The store's configured `retention` is unchanged.
|
|
109
|
+
|
|
108
110
|
Anchor-column indexes are created lazily on the first `prune()` call for each table with a policy — never at `init()` — so deployments that don't configure retention pay no extra index write or disk overhead. The first prune of an existing large table pays a one-time index build; subsequent prunes reuse the index.
|
|
109
111
|
|
|
110
112
|
```typescript
|
|
@@ -116,6 +118,13 @@ const results = await storage.prune({
|
|
|
116
118
|
for (const r of results) {
|
|
117
119
|
console.log(`${r.domain}.${r.table}: deleted ${r.deleted}, done=${r.done}`)
|
|
118
120
|
}
|
|
121
|
+
|
|
122
|
+
// One-off pass with different policies (configured retention untouched):
|
|
123
|
+
await storage.prune({
|
|
124
|
+
retention: {
|
|
125
|
+
observability: { spans: { maxAge: '1d' } },
|
|
126
|
+
},
|
|
127
|
+
})
|
|
119
128
|
```
|
|
120
129
|
|
|
121
130
|
Returns: `Promise<PruneResult[]>`
|
|
@@ -130,6 +139,8 @@ Returns: `Promise<PruneResult[]>`
|
|
|
130
139
|
|
|
131
140
|
**signal** (`AbortSignal`): Cooperative cancellation. The batch loop checks it between batches and stops cleanly, returning partial results with done: false.
|
|
132
141
|
|
|
142
|
+
**retention** (`RetentionConfig`): Replaces the store's configured retention policies for this call only — e.g. to skip a domain or prune more aggressively. The configured retention is unchanged.
|
|
143
|
+
|
|
133
144
|
##### PruneResult
|
|
134
145
|
|
|
135
146
|
Each result describes one table's progress:
|
|
@@ -6,10 +6,11 @@ The `@mastra/livekit` package connects Mastra agents to the LiveKit Agents frame
|
|
|
6
6
|
|
|
7
7
|
See [Using LiveKit with Mastra](https://mastra.ai/docs/voice/livekit) for setup and concepts.
|
|
8
8
|
|
|
9
|
-
The package has
|
|
9
|
+
The package has three entry points:
|
|
10
10
|
|
|
11
|
-
- `@mastra/livekit`: server-side APIs — [`liveKitConnectionRoute()`](#livekitconnectionroute), [`dispatchVoiceSession()`](#dispatchvoicesession), [`pipeAgentReplyToWriter()`](#pipeagentreplytowriter),
|
|
12
|
-
- `@mastra/livekit/worker`: the worker runtime — [`createLiveKitWorker()`](#createlivekitworker), [`runLiveKitWorker()`](#runlivekitworker),
|
|
11
|
+
- `@mastra/livekit`: server-side APIs — [`liveKitConnectionRoute()`](#livekitconnectionroute), [`dispatchVoiceSession()`](#dispatchvoicesession), [`pipeAgentReplyToWriter()`](#pipeagentreplytowriter), [`serializeSessionMetadata()`](#livekitsessionmetadata), and [`createEndCallTool()`](#createendcalltool). Import these from Mastra server code. This entry never loads the LiveKit agents runtime.
|
|
12
|
+
- `@mastra/livekit/worker`: the worker runtime — [`createLiveKitWorker()`](#createlivekitworker), [`runLiveKitWorker()`](#runlivekitworker), [`chatContextToMessages()`](#chatcontexttomessages), and the session helpers [`speakGreeting()`](#speakgreeting), [`waitForAgentDoneSpeaking()`](#waitforagentdonespeaking), and [`runEndCall()`](#runendcall). Import it only from the worker entry file.
|
|
13
|
+
- `@mastra/livekit/plugin`: the LLM-component plugin — [`MastraLLM`](#mastrallm) and [`createRemoteAgentReplyGenerator()`](#createremoteagentreplygenerator). Import it in workers that build their own `voice.AgentSession`. `createRemoteAgentReplyGenerator()` is also exported from `@mastra/livekit/worker` because it plugs into `createLiveKitWorker()`'s `generate` option; `MastraLLM` is plugin-only.
|
|
13
14
|
|
|
14
15
|
## `createLiveKitWorker()`
|
|
15
16
|
|
|
@@ -49,9 +50,9 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
|
49
50
|
|
|
50
51
|
**generate** (`VoiceReplyGenerator`): Lowest-level escape hatch: supply any reply generator directly (a custom workflow, remote bridge, and so on).
|
|
51
52
|
|
|
52
|
-
**stt** (`STT | string`): Speech-to-text: a LiveKit plugin instance or an inference model string such as 'deepgram/nova-3'.
|
|
53
|
+
**stt** (`STT | string`): Speech-to-text: a LiveKit plugin instance or an inference model string such as 'deepgram/nova-3'. For per-call selection, set the configuration.stt resolver — it takes precedence, with this option as the fallback.
|
|
53
54
|
|
|
54
|
-
**tts** (`TTS | string`): Text-to-speech: a LiveKit plugin instance or an inference model string such as 'cartesia/sonic-3'.
|
|
55
|
+
**tts** (`TTS | string`): Text-to-speech: a LiveKit plugin instance or an inference model string such as 'cartesia/sonic-3'. For per-call selection, set the configuration.tts resolver — it takes precedence, with this option as the fallback.
|
|
55
56
|
|
|
56
57
|
**vad** (`VAD | 'silero' | false`): Voice activity detection. 'silero' loads the Silero VAD from @livekit/agents-plugin-silero during prewarm. Pass an instance to bring your own, or false to disable. (Default: `'silero'`)
|
|
57
58
|
|
|
@@ -65,9 +66,23 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
|
65
66
|
|
|
66
67
|
**toolFeedback** (`(toolCall) => string | undefined`): Called when the Mastra agent starts a tool call mid-reply. Return a short phrase to speak while the tool runs.
|
|
67
68
|
|
|
68
|
-
**
|
|
69
|
+
**onTurnComplete** (`(ctx: VoiceTurnCompleteContext) => void | Promise<void>`): Called once per turn after the reply finished streaming to text-to-speech. Runs off the audio path and is not awaited. The context carries the produced reply (text, toolCalls, interrupted, usage) and the resolved memory mapping.
|
|
69
70
|
|
|
70
|
-
**
|
|
71
|
+
**configuration** (`LiveKitWorkerConfiguration`): Grouped conversation and compliance configuration: the opening greeting and AI disclosure, consent requirements, agent-initiated hang-up, and per-call STT/TTS selection.
|
|
72
|
+
|
|
73
|
+
**configuration.greeting** (`GreetingConfiguration`): The opening greeting and AI disclosure: text (a fixed string or a per-call resolver for per-tenant greetings), allowInterruptions, awaitPlayout, persist, and periodic re-disclosure via repeatEvery and repeatText.
|
|
74
|
+
|
|
75
|
+
**configuration.consentPolicy** (`ConsentConfiguration`): The call's consent policy, as named requirements (starting with summaryStorage). Declarative only — the worker blocks nothing by itself. Capture grants at runtime with createConsentTool and enforce them in your own code; the declared policy surfaces on onCallEnd for cross-checking.
|
|
76
|
+
|
|
77
|
+
**configuration.endCall** (`EndCallConfiguration`): Agent-initiated hang-up: the worker watches each turn for the end-call tool (pair with createEndCallTool), waits for the agent's closing words to play out, then disconnects — running onCallEnd on the way out.
|
|
78
|
+
|
|
79
|
+
**configuration.stt** (`(context: VoiceCallContext) => STT | string | undefined`): Per-call speech-to-text: a resolver invoked once per call (post-connect) with { metadata, requestContext, roomName, ctx }, returning anything the top-level stt option accepts. Return undefined to fall back to the top-level stt. Cache plugin instances across calls — the resolver runs during call setup.
|
|
80
|
+
|
|
81
|
+
**configuration.tts** (`(context: VoiceCallContext) => TTS | string | undefined`): Per-call text-to-speech: a resolver invoked once per call (post-connect) with { metadata, requestContext, roomName, ctx }, returning anything the top-level tts option accepts — one voice or language per tenant. Return undefined to fall back to the top-level tts. Cache plugin instances across calls.
|
|
82
|
+
|
|
83
|
+
**greeting** (`string`): Static greeting spoken when the session starts. Deprecated: prefer configuration.greeting.text.
|
|
84
|
+
|
|
85
|
+
**persistGreeting** (`boolean`): Save the spoken greeting to the memory thread as an assistant message, making the saved thread a faithful call transcript. Only applies when a greeting is set and memory is enabled. Deprecated: prefer configuration.greeting.persist. (Default: `true`)
|
|
71
86
|
|
|
72
87
|
**observability** (`boolean`): Trace each call when the Mastra instance has observability configured. Opens a voice call span per session: every turn's agent run nests under it, LiveKit's STT, TTS, end-of-utterance, VAD, and LLM latency metrics become child spans, and the span closes with a per-model usage roll-up. Pass false to disable. (Default: `true`)
|
|
73
88
|
|
|
@@ -129,7 +144,256 @@ export default createLiveKitWorker({
|
|
|
129
144
|
})
|
|
130
145
|
```
|
|
131
146
|
|
|
132
|
-
Returns: `VoiceTurnMessage[]`, where each entry is `{ role: 'system' | 'user' | 'assistant'; content: string }`.
|
|
147
|
+
Returns: `VoiceTurnMessage[]`, where each entry is `{ role: 'system' | 'user' | 'assistant'; content: string; id?: string }`.
|
|
148
|
+
|
|
149
|
+
## `MastraLLM`
|
|
150
|
+
|
|
151
|
+
A standard LiveKit LLM plugin (`llm.LLM`) backed by a Mastra agent. Use it when you build the `voice.AgentSession` yourself and want Mastra in the `llm` slot; [`createLiveKitWorker()`](#createlivekitworker) is the managed alternative. See [Use Mastra as the LLM component](https://mastra.ai/docs/voice/livekit) for how to choose.
|
|
152
|
+
|
|
153
|
+
With `remote`, the plugin streams each turn from your Mastra server over HTTP using Server-Sent Events (SSE). The agent loop, tools, and memory run server-side, and interrupting the agent aborts the server-side generation.
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import { voice } from '@livekit/agents'
|
|
157
|
+
import { MastraLLM } from '@mastra/livekit/plugin'
|
|
158
|
+
|
|
159
|
+
const session = new voice.AgentSession({
|
|
160
|
+
llm: new MastraLLM({
|
|
161
|
+
remote: { baseUrl: process.env.MASTRA_URL!, agentId: 'support' },
|
|
162
|
+
memory: { thread: callId, resource: userId },
|
|
163
|
+
}),
|
|
164
|
+
stt: 'deepgram/nova-3',
|
|
165
|
+
tts: 'cartesia/sonic-3',
|
|
166
|
+
// Required with `memory`: LiveKit enables preemptive generation by default.
|
|
167
|
+
turnHandling: { preemptiveGeneration: { enabled: false } },
|
|
168
|
+
})
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
The plugin reports `provider` as `mastra` and `model` as the agent id, so LiveKit metrics and fallback adapters identify it like any other LLM.
|
|
172
|
+
|
|
173
|
+
### Constructor options
|
|
174
|
+
|
|
175
|
+
Provide exactly one reply source: `remote`, `agent`, or `generate`.
|
|
176
|
+
|
|
177
|
+
**remote** (`RemoteMastraAgentOptions`): Remote Mastra server reached over HTTP. Takes the same connection options as createRemoteAgentReplyGenerator(): baseUrl, agentId, apiPrefix, headers, fetch, timeoutMs, retries, body.
|
|
178
|
+
|
|
179
|
+
**agent** (`Agent`): In-process Mastra agent. Session ownership without a second deployment.
|
|
180
|
+
|
|
181
|
+
**generate** (`VoiceReplyGenerator`): Custom reply source. A generate source owns its own hooks; toolFeedback, onToolCall, and onTurnComplete below only apply to the remote and agent sources.
|
|
182
|
+
|
|
183
|
+
**memory** (`{ thread: string; resource?: string } | false`): Conversation persistence, resolved per call (for example from the SIP caller identity). When set, only messages new since the agent last spoke are sent each turn and Mastra Memory supplies history. When omitted, the full LiveKit chat context is sent every turn. (Default: `false`)
|
|
184
|
+
|
|
185
|
+
**requestContext** (`RequestContext | Record<string, unknown>`): Request context forwarded to generation (tenant, dialed number, and so on).
|
|
186
|
+
|
|
187
|
+
**toolFeedback** (`(toolCall: VoiceToolCall) => string | undefined`): Return a short phrase to speak while a server-side tool runs.
|
|
188
|
+
|
|
189
|
+
**onToolCall** (`(toolCall: VoiceToolCall) => void`): Called as each tool call starts, mid-stream. Pair with runEndCall() to implement your own agent-initiated hang-up flow.
|
|
190
|
+
|
|
191
|
+
**onTurnComplete** (`(ctx: VoiceTurnCompleteContext) => void | Promise<void>`): Called once per turn after the reply finished streaming, off the audio path and not awaited. The context carries the produced reply: text, toolCalls, interrupted, and usage.
|
|
192
|
+
|
|
193
|
+
> **Warning:** Don't combine `memory` with the session's `preemptiveGeneration` option, which LiveKit enables by default in sessions you build yourself. A speculative turn that completes before LiveKit discards it persists a user message and a never-spoken reply to the thread. Set `turnHandling: { preemptiveGeneration: { enabled: false } }` on the session. Stateless mode (no `memory`) works with preemptive generation.
|
|
194
|
+
|
|
195
|
+
### Tools run on the Mastra agent
|
|
196
|
+
|
|
197
|
+
Tools are defined and executed server-side on the Mastra agent. The plugin never forwards LiveKit tool definitions: if the session passes a non-empty `toolCtx`, it logs a one-time warning naming the ignored tools. Every tool must complete server-side — a tool that requires approval or client-side execution fails the turn with a descriptive error instead of hanging the call.
|
|
198
|
+
|
|
199
|
+
Tool activity reaches the worker through `toolFeedback`, `onToolCall`, and `onTurnComplete`.
|
|
200
|
+
|
|
201
|
+
### Instructions
|
|
202
|
+
|
|
203
|
+
LiveKit injects your `voice.Agent`'s `instructions` into the chat context of every request. The plugin drops them: the server-side Mastra agent's own instructions are authoritative. To change the prompt, change the Mastra agent.
|
|
204
|
+
|
|
205
|
+
### Interrupted turns
|
|
206
|
+
|
|
207
|
+
When the user interrupts a reply:
|
|
208
|
+
|
|
209
|
+
1. The plugin cancels the stream. The server aborts generation and persists nothing from that turn.
|
|
210
|
+
2. LiveKit records the part the user actually heard in its chat context, flagged as interrupted.
|
|
211
|
+
3. On the next turn, the plugin re-sends that heard-only fragment, ordered before the new user message, so the memory thread backfills to match the call. Messages carry LiveKit's message ids and the server deduplicates by id, so retries and re-sends stay idempotent.
|
|
212
|
+
|
|
213
|
+
A user who hangs up immediately after interrupting leaves that final fragment unrecorded. When the transcript must capture it, reconcile immediately from the session event; the shared message id means the next turn's re-send upserts instead of duplicating:
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
import { voice } from '@livekit/agents'
|
|
217
|
+
import { MastraClient } from '@mastra/client-js'
|
|
218
|
+
|
|
219
|
+
const client = new MastraClient({ baseUrl: process.env.MASTRA_URL! })
|
|
220
|
+
|
|
221
|
+
session.on(voice.AgentSessionEventTypes.ConversationItemAdded, ({ item }) => {
|
|
222
|
+
if (item.type !== 'message' || item.role !== 'assistant' || !item.interrupted) return
|
|
223
|
+
void client.saveMessageToMemory({
|
|
224
|
+
agentId: 'support',
|
|
225
|
+
messages: [
|
|
226
|
+
{
|
|
227
|
+
id: item.id,
|
|
228
|
+
threadId: callId,
|
|
229
|
+
resourceId: userId,
|
|
230
|
+
role: 'assistant',
|
|
231
|
+
content: item.textContent ?? '',
|
|
232
|
+
type: 'text',
|
|
233
|
+
createdAt: new Date(),
|
|
234
|
+
},
|
|
235
|
+
],
|
|
236
|
+
})
|
|
237
|
+
})
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Usage metrics
|
|
241
|
+
|
|
242
|
+
When the server reports token usage for a turn, the plugin feeds it to LiveKit, so the session's `metrics_collected` events carry time-to-first-token, duration, and token counts like any LLM plugin. The same usage object (`promptTokens`, `completionTokens`, `promptCachedTokens`, `totalTokens`) arrives on `onTurnComplete` as `result.usage`.
|
|
243
|
+
|
|
244
|
+
### Errors and timeouts
|
|
245
|
+
|
|
246
|
+
The transport throws LiveKit's `APIError` types (`APIStatusError`, `APIConnectionError`, `APITimeoutError`), so the session's retry policy (`connOptions.maxRetry`) and `FallbackAdapter` failover work unchanged. A turn is never retried after its first token — a voice reply is better failed fast than replayed half-heard.
|
|
247
|
+
|
|
248
|
+
A connect and first-token watchdog uses the session's `connOptions.timeoutMs` (10 seconds by default), so a server that accepts the connection but never streams can't cause indefinite dead air.
|
|
249
|
+
|
|
250
|
+
If the Mastra server goes down mid-call, each reply attempt fails with a typed error after its retries, and LiveKit closes the session after several consecutive failed replies. Restore the server before that budget runs out and the call recovers on the next turn.
|
|
251
|
+
|
|
252
|
+
### Message content
|
|
253
|
+
|
|
254
|
+
Message extraction is text-only: image content is dropped, and audio content is included only through its transcript. Voice pipelines aren't affected, but items you inject into the chat context yourself must carry text.
|
|
255
|
+
|
|
256
|
+
## `createRemoteAgentReplyGenerator()`
|
|
257
|
+
|
|
258
|
+
Builds a reply generator that runs the agent loop on a **remote** Mastra server over HTTP/SSE. `MastraLLM`'s `remote` mode uses it internally. Use it directly through `createLiveKitWorker`'s `generate` option to run the batteries-included worker against a remote server:
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
import { createLiveKitWorker, createRemoteAgentReplyGenerator } from '@mastra/livekit/worker'
|
|
262
|
+
import { mastra } from './index'
|
|
263
|
+
|
|
264
|
+
export default createLiveKitWorker({
|
|
265
|
+
mastra, // local instance for logger and worker config; replies come from the remote server
|
|
266
|
+
generate: createRemoteAgentReplyGenerator({
|
|
267
|
+
baseUrl: process.env.MASTRA_URL!,
|
|
268
|
+
agentId: 'support',
|
|
269
|
+
}),
|
|
270
|
+
memory: ({ metadata, roomName }) => ({ thread: metadata.threadId ?? roomName }),
|
|
271
|
+
stt: 'deepgram/nova-3',
|
|
272
|
+
tts: 'cartesia/sonic-3',
|
|
273
|
+
})
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
On the `generate` path the worker-level `toolFeedback` and `onTurnComplete` options don't apply, and the worker's end-call detection doesn't fire; pass the hooks to the generator instead.
|
|
277
|
+
|
|
278
|
+
Cancelling a turn (barge-in) tears down the HTTP request, which aborts generation on the server. Errors are thrown as LiveKit `APIError` types; `retries` applies to the initial connection only — a turn is never retried after its first chunk.
|
|
279
|
+
|
|
280
|
+
Returns: `VoiceReplyGenerator`.
|
|
281
|
+
|
|
282
|
+
### Options
|
|
283
|
+
|
|
284
|
+
**baseUrl** (`string`): Base URL of the remote Mastra server, for example https\://my-app.example.com.
|
|
285
|
+
|
|
286
|
+
**agentId** (`string`): The agent's registered key or id on the remote Mastra instance.
|
|
287
|
+
|
|
288
|
+
**apiPrefix** (`string`): Path prefix for the Mastra API. (Default: `'/api'`)
|
|
289
|
+
|
|
290
|
+
**headers** (`Record<string, string> | () => Record<string, string> | Promise<Record<string, string>>`): Static headers, or a resolver invoked per turn — for example to mint a fresh authorization token.
|
|
291
|
+
|
|
292
|
+
**fetch** (`typeof fetch`): Injectable fetch implementation for tests or proxies. (Default: `globalThis.fetch`)
|
|
293
|
+
|
|
294
|
+
**timeoutMs** (`number`): Connect and first-token timeout in milliseconds. When used through MastraLLM, defaults to the session's connOptions.timeoutMs instead. (Default: `10000`)
|
|
295
|
+
|
|
296
|
+
**retries** (`number`): Initial-connection retry attempts, before the first chunk only. When used through MastraLLM, the LiveKit session owns retries and this is forced to 0. (Default: `2`)
|
|
297
|
+
|
|
298
|
+
**body** (`Record<string, unknown>`): Extra fields merged into each stream request body.
|
|
299
|
+
|
|
300
|
+
**toolFeedback** (`(toolCall: VoiceToolCall) => string | undefined`): Return a short phrase to speak while a server-side tool runs.
|
|
301
|
+
|
|
302
|
+
**onToolCall** (`(toolCall: VoiceToolCall) => void`): Called as each tool call starts, mid-stream.
|
|
303
|
+
|
|
304
|
+
**onTurnComplete** (`(ctx: VoiceTurnCompleteContext) => void | Promise<void>`): Called once per turn after the reply finished streaming, off the audio path.
|
|
305
|
+
|
|
306
|
+
## `speakGreeting()`
|
|
307
|
+
|
|
308
|
+
Speaks an opening greeting on a session you own, honoring interruption and playout options. Returns the LiveKit `SpeechHandle`, or `undefined` when there's no greeting text. `createLiveKitWorker()` uses it internally for its `greeting` configuration.
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
import { speakGreeting } from '@mastra/livekit/worker'
|
|
312
|
+
|
|
313
|
+
await speakGreeting(session, {
|
|
314
|
+
text: "You've reached support. You're speaking with an AI assistant.",
|
|
315
|
+
allowInterruptions: false,
|
|
316
|
+
awaitPlayout: true,
|
|
317
|
+
})
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Parameters
|
|
321
|
+
|
|
322
|
+
**session** (`voice.AgentSession`): The session to speak on.
|
|
323
|
+
|
|
324
|
+
**greeting** (`{ text?: string; allowInterruptions?: boolean; awaitPlayout?: boolean }`): The greeting text and playout options. When awaitPlayout is true, the returned promise resolves after the greeting finished playing (or was interrupted).
|
|
325
|
+
|
|
326
|
+
## `waitForAgentDoneSpeaking()`
|
|
327
|
+
|
|
328
|
+
Resolves once the agent is no longer producing or playing a reply — its state has left `thinking` and `speaking`. Resolves immediately when the agent is already idle, and always resolves within `maxWaitMs` (30 seconds by default) as a safety cap. Use it before tearing a session down so closing words play out instead of being cut off.
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
import { waitForAgentDoneSpeaking } from '@mastra/livekit/worker'
|
|
332
|
+
|
|
333
|
+
await waitForAgentDoneSpeaking(session)
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
## `runEndCall()`
|
|
337
|
+
|
|
338
|
+
Ends the call after the agent asked to: waits for the agent's closing words to finish, speaks an optional final `message` non-interruptibly, then deletes the room (hanging up the caller, SIP included) and shuts the job down, which runs registered shutdown callbacks.
|
|
339
|
+
|
|
340
|
+
Pair it with [`MastraLLM`](#mastrallm)'s `onToolCall` and an [end-call tool](#createendcalltool) on the server-side agent to rebuild agent-initiated hang-up on a session you own:
|
|
341
|
+
|
|
342
|
+
```typescript
|
|
343
|
+
import { MastraLLM } from '@mastra/livekit/plugin'
|
|
344
|
+
import { DEFAULT_END_CALL_TOOL, runEndCall } from '@mastra/livekit/worker'
|
|
345
|
+
|
|
346
|
+
let ending = false
|
|
347
|
+
|
|
348
|
+
const llm = new MastraLLM({
|
|
349
|
+
remote: { baseUrl: process.env.MASTRA_URL!, agentId: 'support' },
|
|
350
|
+
onToolCall: ({ toolName }) => {
|
|
351
|
+
if (toolName !== DEFAULT_END_CALL_TOOL || ending) return
|
|
352
|
+
ending = true
|
|
353
|
+
void runEndCall(session, ctx, {}, console)
|
|
354
|
+
},
|
|
355
|
+
})
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
The exported constants `DEFAULT_END_CALL_TOOL` (`'endCall'`), `DEFAULT_END_CALL_REASON`, and `DEFAULT_END_CALL_MAX_WAIT_MS` (30000) hold the defaults.
|
|
359
|
+
|
|
360
|
+
### Parameters
|
|
361
|
+
|
|
362
|
+
**session** (`voice.AgentSession`): The session whose agent is finishing its closing words.
|
|
363
|
+
|
|
364
|
+
**ctx** (`JobContext`): The LiveKit job context used to delete the room and shut down.
|
|
365
|
+
|
|
366
|
+
**config** (`{ message?: string; reason?: string; maxWaitMs?: number; drainMs?: number }`): Optional final message spoken before hang-up, the shutdown reason to record, the safety cap on waiting for closing words, and the post-playout drain (default 800ms) that lets audio buffered at the caller finish playing before the room is deleted — LiveKit's playout accounting is worker-local, so hanging up the instant it clears clips the goodbye.
|
|
367
|
+
|
|
368
|
+
**logger** (`{ warn: (message: string, ...args: unknown[]) => void }`): Receives warnings when teardown steps fail. Pass your logger or console.
|
|
369
|
+
|
|
370
|
+
## `createEndCallTool()`
|
|
371
|
+
|
|
372
|
+
Builds the Mastra tool an agent calls to end the call itself: say goodbye, then hang up. The tool only signals intent (and runs optional bookkeeping) — the worker owns the actual hang-up. It lives on the server-safe root entry, so add it to agents defined in server code.
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
import { Agent } from '@mastra/core/agent'
|
|
376
|
+
import { createEndCallTool } from '@mastra/livekit'
|
|
377
|
+
|
|
378
|
+
const supportAgent = new Agent({
|
|
379
|
+
id: 'support',
|
|
380
|
+
name: 'Support',
|
|
381
|
+
instructions:
|
|
382
|
+
'Help the caller. When everything is wrapped up, say goodbye and call endCall as your final action.',
|
|
383
|
+
model: 'openai/gpt-5-mini',
|
|
384
|
+
tools: { endCall: createEndCallTool() },
|
|
385
|
+
})
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
With `createLiveKitWorker()`, set `configuration: { endCall: {} }` and the worker watches for the tool and hangs up. On a session you own, rebuild the hang-up with [`runEndCall()`](#runendcall).
|
|
389
|
+
|
|
390
|
+
### Options
|
|
391
|
+
|
|
392
|
+
**id** (`string`): Tool id the agent calls to end the call. Must match the name the worker watches for (the worker's configuration.endCall.tool, or your own onToolCall check). (Default: `'endCall'`)
|
|
393
|
+
|
|
394
|
+
**description** (`string`): Override the description the model sees when deciding to call the tool.
|
|
395
|
+
|
|
396
|
+
**onEndCall** (`(request: { reason?: string; resourceId?: string; threadId?: string }) => void | Promise<void>`): Bookkeeping hook called when the agent invokes the tool — record the reason or mark the call resolved. Runs inside the turn; keep it quick. It does not hang up the call.
|
|
133
397
|
|
|
134
398
|
## `liveKitConnectionRoute()`
|
|
135
399
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# @mastra/mcp-docs-server
|
|
2
2
|
|
|
3
|
+
## 1.2.7-alpha.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [[`e955965`](https://github.com/mastra-ai/mastra/commit/e955965dce575a903e37cf054d28ea99aa48785e), [`860ef7e`](https://github.com/mastra-ai/mastra/commit/860ef7e77d92b63469cbe5857aa1e626197e43e9), [`17e818c`](https://github.com/mastra-ai/mastra/commit/17e818c51a958ba90641b1a959dc38faf8c034e9), [`4451dfe`](https://github.com/mastra-ai/mastra/commit/4451dfe857428e7abcc0261a507a2e186dae6d47), [`1d39058`](https://github.com/mastra-ai/mastra/commit/1d39058e548efd691799985d5c8af2737f1c3bd2)]:
|
|
8
|
+
- @mastra/core@1.51.0-alpha.2
|
|
9
|
+
|
|
3
10
|
## 1.2.7-alpha.2
|
|
4
11
|
|
|
5
12
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/mcp-docs-server",
|
|
3
|
-
"version": "1.2.7-alpha.
|
|
3
|
+
"version": "1.2.7-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",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"jsdom": "^26.1.0",
|
|
29
29
|
"local-pkg": "^1.1.2",
|
|
30
30
|
"zod": "^4.4.3",
|
|
31
|
-
"@mastra/
|
|
32
|
-
"@mastra/
|
|
31
|
+
"@mastra/mcp": "^1.13.1",
|
|
32
|
+
"@mastra/core": "1.51.0-alpha.2"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@hono/node-server": "^1.19.11",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
"tsx": "^4.22.4",
|
|
46
46
|
"typescript": "^6.0.3",
|
|
47
47
|
"vitest": "4.1.9",
|
|
48
|
+
"@internal/lint": "0.0.113",
|
|
48
49
|
"@internal/types-builder": "0.0.88",
|
|
49
|
-
"@mastra/core": "1.
|
|
50
|
-
"@internal/lint": "0.0.113"
|
|
50
|
+
"@mastra/core": "1.51.0-alpha.2"
|
|
51
51
|
},
|
|
52
52
|
"homepage": "https://mastra.ai",
|
|
53
53
|
"repository": {
|