@mastra/mcp-docs-server 1.2.19-alpha.3 → 1.2.19
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/channels.md +28 -1
- package/.docs/docs/deployment/cloud-providers.md +1 -0
- package/.docs/docs/deployment/mastra-server.md +19 -0
- package/.docs/docs/deployment/overview.md +1 -0
- package/.docs/docs/deployment/workers.md +2 -2
- package/.docs/docs/evals/overview.md +33 -1
- package/.docs/docs/harness/durable-agents.md +1 -1
- package/.docs/docs/mastra-platform/api.md +54 -0
- package/.docs/docs/mastra-platform/deploy.md +101 -0
- package/.docs/docs/mastra-platform/observability.md +3 -1
- package/.docs/docs/mastra-platform/server.md +6 -11
- package/.docs/docs/mastra-platform/studio.md +8 -10
- package/.docs/docs/memory/semantic-recall.md +19 -0
- package/.docs/docs/observability/feedback.md +14 -0
- package/.docs/docs/observability/integrations/exporters/mastra-storage.md +19 -14
- package/.docs/docs/observability/metrics/overview.md +31 -44
- package/.docs/docs/sandbox/overview.md +43 -0
- package/.docs/docs/server/middleware.md +30 -0
- package/.docs/docs/server/server-adapters.md +109 -34
- package/.docs/docs/storage.md +2 -0
- package/.docs/docs/subagents.md +6 -6
- package/.docs/integrations/channels/github.md +56 -9
- package/.docs/integrations/channels/imessage.md +150 -8
- package/.docs/integrations/databases/elasticsearch.md +156 -0
- package/.docs/integrations/databases/libsql.md +16 -0
- package/.docs/integrations/databases/mongodb.md +1 -1
- package/.docs/integrations/databases/postgresql.md +26 -0
- package/.docs/integrations/databases/valkey.md +99 -0
- package/.docs/integrations/deploy/kubernetes-helm.md +332 -0
- package/.docs/integrations/deploy/kubernetes.md +1 -1
- package/.docs/integrations/deploy/render.md +47 -61
- package/.docs/integrations/sandboxes/daytona.md +52 -0
- package/.docs/integrations/sandboxes/e2b-desktop.md +128 -0
- package/.docs/integrations/sandboxes/e2b.md +6 -0
- package/.docs/integrations/sandboxes/vercel.md +2 -2
- package/.docs/integrations/tools/parallel.md +240 -0
- package/.docs/integrations.md +5 -0
- package/.docs/models/environment-variables.md +9 -0
- package/.docs/models/gateways/merge-gateway.md +2 -1
- package/.docs/models/gateways/netlify.md +12 -6
- package/.docs/models/gateways/openrouter.md +9 -11
- package/.docs/models/gateways/vercel.md +7 -6
- package/.docs/models/index.md +1 -1
- package/.docs/models/providers/agentrouter.md +17 -34
- package/.docs/models/providers/agnes.md +75 -0
- package/.docs/models/providers/aixy.md +73 -0
- package/.docs/models/providers/aki-io.md +14 -13
- package/.docs/models/providers/chutes.md +2 -2
- package/.docs/models/providers/cline-pass.md +4 -2
- package/.docs/models/providers/crof.md +3 -8
- package/.docs/models/providers/crossmodel.md +56 -55
- package/.docs/models/providers/deepseek.md +9 -10
- package/.docs/models/providers/digitalocean.md +1 -1
- package/.docs/models/providers/edenai.md +14 -13
- package/.docs/models/providers/evroc.md +3 -2
- package/.docs/models/providers/gmicloud.md +6 -4
- package/.docs/models/providers/huggingface.md +2 -1
- package/.docs/models/providers/hyper.md +6 -6
- package/.docs/models/providers/inceptron.md +2 -2
- package/.docs/models/providers/iteracompute.md +73 -0
- package/.docs/models/providers/kilo.md +31 -28
- package/.docs/models/providers/llmgateway-providers.md +20 -9
- package/.docs/models/providers/llmgateway.md +3 -5
- package/.docs/models/providers/llmtech.md +73 -0
- package/.docs/models/providers/nano-gpt.md +24 -13
- package/.docs/models/providers/neosmith.md +104 -0
- package/.docs/models/providers/nvidia.md +3 -1
- package/.docs/models/providers/ofox.md +114 -110
- package/.docs/models/providers/openai.md +2 -2
- package/.docs/models/providers/opencode-go.md +26 -24
- package/.docs/models/providers/opencode.md +1 -1
- package/.docs/models/providers/opper.md +112 -0
- package/.docs/models/providers/pendra.md +78 -0
- package/.docs/models/providers/requesty.md +1 -1
- package/.docs/models/providers/scaleway.md +2 -1
- package/.docs/models/providers/standardcompute.md +73 -0
- package/.docs/models/providers/vivgrid.md +2 -1
- package/.docs/models/providers/wandb.md +2 -1
- package/.docs/models/providers/zai.md +2 -1
- package/.docs/models/providers.md +9 -0
- package/.docs/reference/agents/channels.md +1 -1
- package/.docs/reference/ai-sdk/handle-chat-stream.md +11 -0
- package/.docs/reference/ai-sdk/with-sse-heartbeat.md +47 -0
- package/.docs/reference/cli/mastra.md +10 -4
- package/.docs/reference/client-js/observability.md +1 -1
- package/.docs/reference/index.md +5 -0
- package/.docs/reference/observability/feedback.md +4 -0
- package/.docs/reference/observability/metrics/automatic-metrics.md +1 -1
- package/.docs/reference/observability/metrics/queries.md +462 -0
- package/.docs/reference/pubsub/valkey-streams.md +84 -0
- package/.docs/reference/rag/vector-databases.md +4 -4
- package/.docs/reference/server/elysia-adapter.md +184 -0
- package/.docs/reference/server/express-adapter.md +6 -8
- package/.docs/reference/server/hono-adapter.md +19 -6
- package/.docs/reference/storage/turso.md +88 -0
- package/.docs/reference/streaming/ChunkType.md +29 -1
- package/.docs/reference/streaming/agents/stream.md +1 -3
- package/.docs/reference/tools/mcp-client.md +41 -9
- package/.docs/reference/vectors/mongodb.md +11 -11
- package/.docs/reference/vectors/pg.md +2 -0
- package/.docs/reference/workspace/local-sandbox.md +2 -0
- package/.docs/reference/workspace/platform-sandbox.md +3 -1
- package/.docs/reference/workspace/sandbox.md +143 -3
- package/.docs/reference/workspace/workspace-class.md +13 -1
- package/CHANGELOG.md +88 -0
- package/package.json +6 -6
- package/.docs/docs/observability/metrics/querying.md +0 -314
|
@@ -74,7 +74,7 @@ export const mastra = new Mastra({
|
|
|
74
74
|
})
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
After the agent has created a memory thread, subscribe that thread to a PR.
|
|
77
|
+
After the agent has created a memory thread, subscribe that thread to a PR. Choose `review` mode when the thread only needs code revisions, authorized latest PR comments, and observable review-thread-state updates:
|
|
78
78
|
|
|
79
79
|
```typescript
|
|
80
80
|
await githubSignals.subscribeThreadToPR({
|
|
@@ -85,19 +85,66 @@ await githubSignals.subscribeThreadToPR({
|
|
|
85
85
|
repo: 'web-app',
|
|
86
86
|
number: 42,
|
|
87
87
|
},
|
|
88
|
+
mode: 'review',
|
|
88
89
|
})
|
|
89
90
|
```
|
|
90
91
|
|
|
91
92
|
The provider syncs the PR immediately, stores the subscription, and starts polling every five minutes. Set `pollIntervalMs` in the `GithubSignals` constructor to change the interval. If the process restarts, call `startPollingForThread()` for each persisted thread subscription to resume polling.
|
|
92
93
|
|
|
93
|
-
|
|
94
|
+
A thread has one current GitHub Signals subscription. Subscribing it to another PR replaces the existing subscription.
|
|
94
95
|
|
|
95
|
-
|
|
96
|
+
## Subscription modes
|
|
96
97
|
|
|
97
|
-
|
|
98
|
-
- A change in unresolved review threads.
|
|
99
|
-
- Continuous integration (CI) checks that start, fail, or recover.
|
|
100
|
-
- Merge conflicts that appear or are resolved.
|
|
101
|
-
- A state change to closed, reopened, or merged.
|
|
98
|
+
GitHub Signals supports two subscription modes:
|
|
102
99
|
|
|
103
|
-
|
|
100
|
+
- `review`: Follows new head revisions, authorized latest PR comments, and observable review-thread-state changes, including when all review threads become resolved.
|
|
101
|
+
- `working`: Follows all actionable PR activity detected by the provider. Comment-bearing notifications remain subject to existing authorization gates. This is the default when `mode` is omitted and for stored subscriptions without a valid mode.
|
|
102
|
+
|
|
103
|
+
The following table shows the observable behavior of each mode:
|
|
104
|
+
|
|
105
|
+
| Pull request activity | `working` | `review` |
|
|
106
|
+
| ----------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
107
|
+
| First observation | Sends a baseline notification | Saves all cursors without notifying unless the PR is closed or merged; then notifies and removes the subscription |
|
|
108
|
+
| New commit or force-push | Notifies when the latest comment author is authorized | Notifies without requiring a comment author |
|
|
109
|
+
| New authorized latest PR comment | Notifies | Notifies |
|
|
110
|
+
| Observable review-thread-state change | Notifies while unresolved threads remain | Notifies, including when all review threads become resolved |
|
|
111
|
+
| Continuous integration checks start, fail, or recover | Notifies | Saves the new state without notifying |
|
|
112
|
+
| Merge conflicts appear or resolve | Notifies | Saves the new state without notifying |
|
|
113
|
+
| Other actionable aggregate PR activity | Notifies when applicable authorization checks pass | Saves the new state without notifying |
|
|
114
|
+
| PR closes without merging | Notifies and keeps the subscription | Notifies and removes the subscription |
|
|
115
|
+
| PR reopens | Notifies | Doesn't notify because the earlier close removed the subscription |
|
|
116
|
+
| PR merges | Notifies and removes the subscription | Notifies and removes the subscription |
|
|
117
|
+
|
|
118
|
+
Review mode uses the latest generic PR comment exposed by `gitcrawl`. The snapshot doesn't distinguish general PR conversation from inline review comments. Comment notifications require an authorized author because they include comment content. Review-state notifications contain only provider-generated state summaries and aren't author-gated.
|
|
119
|
+
|
|
120
|
+
The review-state cursor includes the unresolved thread count and the latest unresolved thread timestamp. It reports when the count reaches zero, but it can't report replies on threads that are already resolved.
|
|
121
|
+
|
|
122
|
+
During subscription, a PR already known to be closed or merged isn't stored and doesn't send an activity notification. Otherwise, review mode silently saves its first available non-terminal snapshot, including when the subscribe-time snapshot fails and a later poll supplies the first observation. If the first available poll snapshot or a later snapshot is closed or merged, the provider sends a terminal notification and removes the subscription. It doesn't follow a later reopen unless you subscribe again.
|
|
123
|
+
|
|
124
|
+
## Subscription tools
|
|
125
|
+
|
|
126
|
+
The provider adds `github_subscribe_pr` and `github_unsubscribe_pr` tools to the agent. Pass `mode` when subscribing:
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"owner": "acme",
|
|
131
|
+
"repo": "web-app",
|
|
132
|
+
"number": 42,
|
|
133
|
+
"mode": "review"
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Omitting `mode` selects `working`. Don't subscribe for a one-off PR inspection.
|
|
138
|
+
|
|
139
|
+
## MastraCode commands
|
|
140
|
+
|
|
141
|
+
In MastraCode, use the spaced `--mode` flag with a PR number, `owner/repo#number`, or full GitHub PR URL:
|
|
142
|
+
|
|
143
|
+
```text
|
|
144
|
+
/github subscribe 42 --mode review
|
|
145
|
+
/github acme/web-app#42 --mode working
|
|
146
|
+
/github unsubscribe 42
|
|
147
|
+
/github debug
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
MastraCode rejects `--mode=review`, missing or repeated mode values, unknown modes, and mode flags on unsubscribe. `/github debug` shows the stored mode and displays absent or invalid legacy values as `working`.
|
|
@@ -2,10 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
# iMessage
|
|
4
4
|
|
|
5
|
-
iMessage channels let a Mastra agent receive direct messages and group messages from iMessage. Mastra handles the agent wiring
|
|
5
|
+
iMessage channels let a Mastra agent receive direct messages and group messages from iMessage. Two vendor-maintained adapters connect Mastra to iMessage: [Photon](https://app.photon.codes) and [Linq](https://linqapp.com). Mastra handles the agent wiring and the webhook route; the adapter docs cover number provisioning, credentials, and webhook registration.
|
|
6
|
+
|
|
7
|
+
## Choose an adapter
|
|
8
|
+
|
|
9
|
+
Both adapters follow the same Mastra wiring, so pick the provider first:
|
|
10
|
+
|
|
11
|
+
- **Photon**: Hosted or self-hosted iMessage service. Supports webhooks and a [gateway listener](#gateway-listener) that streams messages over an open connection.
|
|
12
|
+
- **Linq**: Hosted iMessage, RCS, and SMS API. Webhook-driven, with tapback reactions and media mapped in both directions.
|
|
6
13
|
|
|
7
14
|
## Install the adapter
|
|
8
15
|
|
|
16
|
+
**Photon**:
|
|
17
|
+
|
|
9
18
|
Install the Photon iMessage adapter:
|
|
10
19
|
|
|
11
20
|
**npm**:
|
|
@@ -32,9 +41,87 @@ yarn add @photon-ai/chat-adapter-imessage
|
|
|
32
41
|
bun add @photon-ai/chat-adapter-imessage
|
|
33
42
|
```
|
|
34
43
|
|
|
44
|
+
**Linq**:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm install @photon-ai/chat-adapter-imessage
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Tab 3**:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pnpm add @photon-ai/chat-adapter-imessage
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Tab 4**:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
yarn add @photon-ai/chat-adapter-imessage
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Tab 5**:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
bun add @photon-ai/chat-adapter-imessage
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Tab 6**:
|
|
69
|
+
|
|
70
|
+
Install the Linq Chat SDK adapter:
|
|
71
|
+
|
|
72
|
+
**npm**:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npm install @linqapp/chat-sdk-adapter
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**pnpm**:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
pnpm add @linqapp/chat-sdk-adapter
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Yarn**:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
yarn add @linqapp/chat-sdk-adapter
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Bun**:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
bun add @linqapp/chat-sdk-adapter
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Tab 7**:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
npm install @linqapp/chat-sdk-adapter
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Tab 8**:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
pnpm add @linqapp/chat-sdk-adapter
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Tab 9**:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
yarn add @linqapp/chat-sdk-adapter
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Tab 10**:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
bun add @linqapp/chat-sdk-adapter
|
|
118
|
+
```
|
|
119
|
+
|
|
35
120
|
## Agent configuration
|
|
36
121
|
|
|
37
|
-
Add
|
|
122
|
+
Add the adapter factory to the agent's `channels.adapters` object:
|
|
123
|
+
|
|
124
|
+
**Photon**:
|
|
38
125
|
|
|
39
126
|
```typescript
|
|
40
127
|
import { Agent } from '@mastra/core/agent'
|
|
@@ -57,6 +144,35 @@ export const imessageAgent = new Agent({
|
|
|
57
144
|
})
|
|
58
145
|
```
|
|
59
146
|
|
|
147
|
+
`threadContext: { maxMessages: 0 }` skips the platform history lookup Mastra runs when an agent is first mentioned in a group chat, which the Photon adapter can't perform.
|
|
148
|
+
|
|
149
|
+
**Linq**:
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
import { Agent } from '@mastra/core/agent'
|
|
153
|
+
import { createLinqAdapter } from '@linqapp/chat-sdk-adapter'
|
|
154
|
+
|
|
155
|
+
export const imessageAgent = new Agent({
|
|
156
|
+
id: 'imessage-agent',
|
|
157
|
+
name: 'iMessage Agent',
|
|
158
|
+
instructions: 'Answer questions and help with tasks over iMessage.',
|
|
159
|
+
model: 'openai/gpt-5.6-sol',
|
|
160
|
+
channels: {
|
|
161
|
+
adapters: {
|
|
162
|
+
imessage: {
|
|
163
|
+
adapter: createLinqAdapter({
|
|
164
|
+
apiKey: process.env.LINQ_API_KEY!,
|
|
165
|
+
signingSecret: process.env.LINQ_WEBHOOK_SECRET!,
|
|
166
|
+
}),
|
|
167
|
+
toolDisplay: 'text',
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
})
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
`createLinqAdapter()` takes the credentials directly: `apiKey` is your Linq API key and `signingSecret` comes from the [webhook subscription](#webhook-url). The Linq adapter can fetch thread history, so the default `threadContext` behavior works.
|
|
175
|
+
|
|
60
176
|
Register the agent on the Mastra instance:
|
|
61
177
|
|
|
62
178
|
```typescript
|
|
@@ -70,10 +186,14 @@ export const mastra = new Mastra({
|
|
|
70
186
|
|
|
71
187
|
Use `imessage` as the adapter key. Mastra derives the webhook path and the `platform` value on `requestContext` from this key.
|
|
72
188
|
|
|
73
|
-
`toolDisplay: 'text'` describes tool calls in the message, since iMessage has no interactive cards for Approve and Deny actions.
|
|
189
|
+
`toolDisplay: 'text'` describes tool calls in the message, since iMessage has no interactive cards for Approve and Deny actions. Both adapters need it: Photon has no card rendering, and Linq flattens cards to plain text where buttons show their labels but can't trigger actions.
|
|
190
|
+
|
|
191
|
+
> **Warning:** Text rendering can't submit approval decisions. A tool with `requireApproval: true` stays suspended until a UI or API action, such as Studio, submits an explicit approval or decline, so avoid approval-gated tools on iMessage agents unless another surface handles the decision. See [Tool approval](https://mastra.ai/docs/channels).
|
|
74
192
|
|
|
75
193
|
## Adapter setup
|
|
76
194
|
|
|
195
|
+
**Photon**:
|
|
196
|
+
|
|
77
197
|
Follow the [Photon iMessage adapter docs](https://github.com/photon-hq/vercel-chat-adapter-imessage) for iMessage-specific setup, including number provisioning, hosted and self-hosted modes, and webhook registration. The adapter picks its mode from the environment variables you set.
|
|
78
198
|
|
|
79
199
|
For the hosted service, create a project at [app.photon.codes](https://app.photon.codes) and use the project credentials:
|
|
@@ -94,6 +214,17 @@ IMESSAGE_PHONE=+15551234567
|
|
|
94
214
|
|
|
95
215
|
`IMESSAGE_PHONE` is optional and routes messages when a self-hosted server has several numbers. You can also pass these values to `createiMessageAdapter()` directly, including a `credentials` function that resolves the project ID and secret at first use from a secret store.
|
|
96
216
|
|
|
217
|
+
**Linq**:
|
|
218
|
+
|
|
219
|
+
Follow the [Linq API docs](https://docs.linqapp.com/) for Linq-specific setup, including phone number provisioning and API keys. Create a Linq account, copy your API key, and set the credentials the agent configuration reads:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
LINQ_API_KEY=your-linq-api-key
|
|
223
|
+
LINQ_WEBHOOK_SECRET=your-webhook-signing-secret
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
`LINQ_WEBHOOK_SECRET` is the signing secret returned when you create a webhook subscription in the next section. The adapter also accepts a `baseURL` option to target a different Linq API base URL, such as a sandbox.
|
|
227
|
+
|
|
97
228
|
## Webhook URL
|
|
98
229
|
|
|
99
230
|
Mastra generates the iMessage webhook route from the agent ID and adapter key:
|
|
@@ -108,13 +239,25 @@ Use your public Mastra server URL as the base URL:
|
|
|
108
239
|
https://your-app.example.com/api/agents/imessage-agent/channels/imessage/webhook
|
|
109
240
|
```
|
|
110
241
|
|
|
242
|
+
**Photon**:
|
|
243
|
+
|
|
111
244
|
Register this URL in the [Photon dashboard](https://app.photon.codes), then set the signing secret it returns as `IMESSAGE_WEBHOOK_SECRET`. The secret is shown once at registration. The adapter verifies the signature on every delivery and rejects requests that don't match. Webhooks are available in hosted mode only.
|
|
112
245
|
|
|
113
|
-
|
|
246
|
+
**Linq**:
|
|
247
|
+
|
|
248
|
+
Create a [webhook subscription](https://docs.linqapp.com/guides/webhooks/subscriptions/) with this URL as the target and subscribe to at least these events:
|
|
249
|
+
|
|
250
|
+
- `message.received`
|
|
251
|
+
- `reaction.added`
|
|
252
|
+
- `reaction.removed`
|
|
253
|
+
|
|
254
|
+
Set the `signing_secret` the subscription returns as `LINQ_WEBHOOK_SECRET`. The secret is shown once at creation and can't be retrieved later. The adapter verifies the HMAC signature on every delivery, checks for replayed requests, and rejects requests that don't match.
|
|
255
|
+
|
|
256
|
+
> **Note:** Both providers deliver to public HTTPS endpoints only, not to `http://` or private addresses like `localhost`. For local development, use a tunnel as described in the [Channels overview](https://mastra.ai/docs/channels).
|
|
114
257
|
|
|
115
258
|
## Duplicate deliveries
|
|
116
259
|
|
|
117
|
-
Photon
|
|
260
|
+
Photon and Linq retry failed deliveries with backoff and deliver at least once, so the same message can arrive twice. Chat SDK drops the repeat using the channel state adapter, and Mastra's default keeps those dedup keys in memory. That covers a single long-running server.
|
|
118
261
|
|
|
119
262
|
A repeat can still reach the agent after a restart, or on serverless where the retry is routed to a different instance. Pass a shared state adapter on `channels.state` so dedup keys are visible everywhere. Install one alongside the adapter:
|
|
120
263
|
|
|
@@ -154,7 +297,6 @@ channels: {
|
|
|
154
297
|
toolDisplay: 'text',
|
|
155
298
|
},
|
|
156
299
|
},
|
|
157
|
-
threadContext: { maxMessages: 0 },
|
|
158
300
|
state: createRedisState(),
|
|
159
301
|
},
|
|
160
302
|
```
|
|
@@ -163,13 +305,13 @@ This matters most for tools with side effects, where handling the same message t
|
|
|
163
305
|
|
|
164
306
|
## Read receipts
|
|
165
307
|
|
|
166
|
-
iPhone Messages sends a read receipt for every message the agent posts, and the adapter delivers those receipts as inbound messages with no text and no attachments. Mastra skips them, so the agent doesn't answer its own reply in a loop. Their message IDs carry a `:read:` suffix, and they show up as skipped messages at `debug` log level.
|
|
308
|
+
iPhone Messages sends a read receipt for every message the agent posts, and the Photon adapter delivers those receipts as inbound messages with no text and no attachments. Mastra skips them, so the agent doesn't answer its own reply in a loop. Their message IDs carry a `:read:` suffix, and they show up as skipped messages at `debug` log level.
|
|
167
309
|
|
|
168
310
|
The same rule applies to every adapter: an inbound message with neither text nor attachments never starts an agent run. A custom `onDirectMessage`, `onMention`, or `onSubscribedMessage` handler still receives it and can act on it before calling `defaultHandler`.
|
|
169
311
|
|
|
170
312
|
## Gateway listener
|
|
171
313
|
|
|
172
|
-
The adapter can hold an open connection and stream messages in real time instead of receiving webhooks. This works in both hosted and self-hosted modes.
|
|
314
|
+
The Photon adapter can hold an open connection and stream messages in real time instead of receiving webhooks. This works in both hosted and self-hosted modes. The Linq adapter is webhook-driven and has no gateway mode.
|
|
173
315
|
|
|
174
316
|
Mastra starts this listener during initialization and reconnects it if it drops, so no cron job or extra route is needed on a long-running server. Set `gateway: false` on the adapter config to turn it off when you use webhooks:
|
|
175
317
|
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
> Discover all available pages from the documentation index: https://mastra.ai/llms.txt
|
|
2
|
+
|
|
3
|
+
# Elasticsearch
|
|
4
|
+
|
|
5
|
+
The Elasticsearch storage implementation provides agent memory, workflow snapshot, and score storage on top of an Elasticsearch cluster using the official [`@elastic/elasticsearch`](https://github.com/elastic/elasticsearch-js) client. It shares the same connection configuration as `ElasticSearchVector`, so a single cluster (and even a single client instance) can serve both agent memory and semantic recall.
|
|
6
|
+
|
|
7
|
+
`ElasticSearchStore` currently implements the `memory`, `workflows`, and `scores` storage domains.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @mastra/elasticsearch
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
### Using a URL
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { ElasticSearchStore } from '@mastra/elasticsearch'
|
|
21
|
+
|
|
22
|
+
const storage = new ElasticSearchStore({
|
|
23
|
+
id: 'elasticsearch-storage',
|
|
24
|
+
url: 'http://localhost:9200',
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
await storage.init()
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Using authentication
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { ElasticSearchStore } from '@mastra/elasticsearch'
|
|
34
|
+
|
|
35
|
+
const storage = new ElasticSearchStore({
|
|
36
|
+
id: 'elasticsearch-storage',
|
|
37
|
+
url: 'https://my-cluster.example.com:9200',
|
|
38
|
+
auth: { apiKey: process.env.ELASTICSEARCH_API_KEY! },
|
|
39
|
+
})
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`auth` also accepts `{ username, password }` or `{ bearer }`.
|
|
43
|
+
|
|
44
|
+
### Using a pre-configured client
|
|
45
|
+
|
|
46
|
+
For advanced configurations (cloud IDs, TLS options, custom transport), pass a pre-configured client. The same client can be shared with `ElasticSearchVector`:
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import { Client } from '@elastic/elasticsearch'
|
|
50
|
+
import { ElasticSearchStore, ElasticSearchVector } from '@mastra/elasticsearch'
|
|
51
|
+
|
|
52
|
+
const client = new Client({
|
|
53
|
+
node: 'https://my-cluster.example.com:9200',
|
|
54
|
+
auth: { apiKey: process.env.ELASTICSEARCH_API_KEY! },
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
const storage = new ElasticSearchStore({ id: 'elasticsearch-storage', client })
|
|
58
|
+
const vector = new ElasticSearchVector({ id: 'elasticsearch-vector', client })
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
When you provide your own client, `storage.close()` does not close it — you remain responsible for its lifecycle.
|
|
62
|
+
|
|
63
|
+
## Parameters
|
|
64
|
+
|
|
65
|
+
**id** (`string`): Unique identifier for the storage instance
|
|
66
|
+
|
|
67
|
+
**url** (`string`): Elasticsearch node URL (e.g., http\://localhost:9200)
|
|
68
|
+
|
|
69
|
+
**auth** (`ElasticSearchAuth`): Authentication options: { apiKey }, { username, password }, or { bearer }
|
|
70
|
+
|
|
71
|
+
**client** (`Client`): Pre-configured Elasticsearch client (from @elastic/elasticsearch) for advanced setups
|
|
72
|
+
|
|
73
|
+
**disableInit** (`boolean`): Disable automatic initialization; call storage.init() explicitly before use
|
|
74
|
+
|
|
75
|
+
> **Note:** You must provide either `url` or `client`. These options are mutually exclusive.
|
|
76
|
+
|
|
77
|
+
## Additional Notes
|
|
78
|
+
|
|
79
|
+
### Index Structure
|
|
80
|
+
|
|
81
|
+
Each Mastra storage table maps to one Elasticsearch index of the same name (for example `mastra_threads`, `mastra_messages`, `mastra_workflow_snapshot`, `mastra_scorers`). Records are stored as opaque JSON documents with a keyword `key` field, so no index mappings need to be managed manually — indexes are created on first use.
|
|
82
|
+
|
|
83
|
+
### Consistency
|
|
84
|
+
|
|
85
|
+
Elasticsearch search is near-real-time. All writes are performed with an immediate refresh so subsequent reads and searches observe them, and point reads use real-time get-by-ID lookups.
|
|
86
|
+
|
|
87
|
+
### Closing Connections
|
|
88
|
+
|
|
89
|
+
When shutting down your application, close the connection:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
await storage.close()
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
This only closes clients created by `ElasticSearchStore` from a `url`; user-provided clients are left open.
|
|
96
|
+
|
|
97
|
+
## Usage Example
|
|
98
|
+
|
|
99
|
+
### Adding memory to an agent
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import { Memory } from '@mastra/memory'
|
|
103
|
+
import { Agent } from '@mastra/core/agent'
|
|
104
|
+
import { ElasticSearchStore } from '@mastra/elasticsearch'
|
|
105
|
+
|
|
106
|
+
export const elasticsearchAgent = new Agent({
|
|
107
|
+
id: 'elasticsearch-agent',
|
|
108
|
+
name: 'Elasticsearch Agent',
|
|
109
|
+
instructions:
|
|
110
|
+
'You are an AI agent with the ability to automatically recall memories from previous interactions.',
|
|
111
|
+
model: 'openai/gpt-5.6-sol',
|
|
112
|
+
memory: new Memory({
|
|
113
|
+
storage: new ElasticSearchStore({
|
|
114
|
+
id: 'elasticsearch-agent-storage',
|
|
115
|
+
url: process.env.ELASTICSEARCH_URL!,
|
|
116
|
+
auth: { apiKey: process.env.ELASTICSEARCH_API_KEY! },
|
|
117
|
+
}),
|
|
118
|
+
options: {
|
|
119
|
+
lastMessages: 10,
|
|
120
|
+
},
|
|
121
|
+
}),
|
|
122
|
+
})
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Using with Mastra instance
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
import { Mastra } from '@mastra/core'
|
|
129
|
+
import { ElasticSearchStore } from '@mastra/elasticsearch'
|
|
130
|
+
|
|
131
|
+
const storage = new ElasticSearchStore({
|
|
132
|
+
id: 'mastra-storage',
|
|
133
|
+
url: 'http://localhost:9200',
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
const mastra = new Mastra({
|
|
137
|
+
storage, // init() called automatically
|
|
138
|
+
})
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
If using storage directly without Mastra, call `init()` explicitly:
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
import { ElasticSearchStore } from '@mastra/elasticsearch'
|
|
145
|
+
|
|
146
|
+
const storage = new ElasticSearchStore({
|
|
147
|
+
id: 'elasticsearch-storage',
|
|
148
|
+
url: 'http://localhost:9200',
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
await storage.init()
|
|
152
|
+
|
|
153
|
+
// Access domain-specific stores via getStore()
|
|
154
|
+
const memoryStore = await storage.getStore('memory')
|
|
155
|
+
const thread = await memoryStore?.getThreadById({ threadId: '...' })
|
|
156
|
+
```
|
|
@@ -89,12 +89,28 @@ storage: new LibSQLStore({
|
|
|
89
89
|
|
|
90
90
|
> **Warning:** In-memory storage resets when the process changes. Only suitable for development.
|
|
91
91
|
|
|
92
|
+
Embedded replica synced with a remote primary (for example Turso):
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
storage: new LibSQLStore({
|
|
96
|
+
id: 'libsql-storage',
|
|
97
|
+
url: 'file:./replica.db',
|
|
98
|
+
syncUrl: 'libsql://your-db-name.aws-ap-northeast-1.turso.io',
|
|
99
|
+
authToken: process.env.TURSO_AUTH_TOKEN,
|
|
100
|
+
syncInterval: 60,
|
|
101
|
+
})
|
|
102
|
+
```
|
|
103
|
+
|
|
92
104
|
## Options
|
|
93
105
|
|
|
94
106
|
**url** (`string`): Database URL. Use :memory: for in-memory database, file:filename.db for a file database, or a libSQL connection string (e.g., libsql://your-database.turso.io) for remote storage.
|
|
95
107
|
|
|
96
108
|
**authToken** (`string`): Authentication token for remote libSQL databases.
|
|
97
109
|
|
|
110
|
+
**syncUrl** (`string`): URL of the remote primary database to sync from, enabling an embedded replica. Requires a local file: url.
|
|
111
|
+
|
|
112
|
+
**syncInterval** (`number`): Interval in seconds for automatic sync with the remote primary. Only applies when syncUrl is set.
|
|
113
|
+
|
|
98
114
|
## Managed tables
|
|
99
115
|
|
|
100
116
|
The storage implementation creates the core storage tables automatically, including `mastra_notifications` for notification inbox records and delivery metadata.
|
|
@@ -32,7 +32,7 @@ bun add @mastra/mongodb@latest
|
|
|
32
32
|
|
|
33
33
|
## Usage
|
|
34
34
|
|
|
35
|
-
Ensure you have a [MongoDB Atlas Local (via Docker)](https://www.mongodb.com/docs/atlas/cli/current/atlas-cli-deploy-docker/) or [MongoDB Atlas Cloud](https://www.mongodb.com/docs/atlas/cli/current/atlas-cli-getting-started/) instance with
|
|
35
|
+
Ensure you have a [MongoDB Atlas Local (via Docker)](https://www.mongodb.com/docs/atlas/cli/current/atlas-cli-deploy-docker/) or [MongoDB Atlas Cloud](https://www.mongodb.com/docs/atlas/cli/current/atlas-cli-getting-started/) instance with MongoDB Search enabled. MongoDB 7.0+ is recommended.
|
|
36
36
|
|
|
37
37
|
```typescript
|
|
38
38
|
import { MongoDBStore } from '@mastra/mongodb'
|
|
@@ -146,6 +146,32 @@ PostgreSQL supports observability and can handle low trace volumes. Throughput c
|
|
|
146
146
|
- Setting up table partitioning for efficient data retention
|
|
147
147
|
- Migrating observability to [ClickHouse via composite storage](https://mastra.ai/reference/storage/composite) if you need to scale further
|
|
148
148
|
|
|
149
|
+
`PostgresStoreVNext` uses the `event-sourced` [tracing strategy](https://mastra.ai/docs/observability/integrations/exporters/mastra-storage) instead. It writes one row when a span starts and another when it ends, never updating a row in place, and collapses those rows when a trace is read. Writes stay append-only, and traces appear in Studio while the run is still executing.
|
|
150
|
+
|
|
151
|
+
#### Filter suggestions
|
|
152
|
+
|
|
153
|
+
Studio's Traces, Logs, and Metrics pages offer filter values (tags, service names, environments, entity names, metric names and labels) discovered from your observability data. Those values are cached in the database and recomputed in the background when the cache goes stale.
|
|
154
|
+
|
|
155
|
+
To keep the refresh cheap on large datasets, it only scans events from the last 30 days. Values that appear exclusively in older events won't be suggested, though filtering by them still works. Use `discovery` to change the window or how often it refreshes:
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
import { PostgresStoreVNext } from '@mastra/pg'
|
|
159
|
+
|
|
160
|
+
const storage = new PostgresStoreVNext({
|
|
161
|
+
id: 'pg-storage',
|
|
162
|
+
connectionString: process.env.DATABASE_URL,
|
|
163
|
+
observability: {
|
|
164
|
+
connectionString: process.env.OBSERVABILITY_DATABASE_URL,
|
|
165
|
+
discovery: {
|
|
166
|
+
lookbackSeconds: 7 * 24 * 60 * 60, // scan the last 7 days; 0 scans all history
|
|
167
|
+
ttlSeconds: 15 * 60, // refresh at most every 15 minutes
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
})
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Lower `lookbackSeconds` if refreshes are slow, and raise `ttlSeconds` if they run more often than your filter values change. Only one process refreshes a given cache entry at a time, so adding server instances doesn't multiply the work.
|
|
174
|
+
|
|
149
175
|
### Initialization
|
|
150
176
|
|
|
151
177
|
When you pass storage to the Mastra class, `init()` is called automatically before any storage operation:
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
> Discover all available pages from the documentation index: https://mastra.ai/llms.txt
|
|
2
|
+
|
|
3
|
+
# Valkey
|
|
4
|
+
|
|
5
|
+
The Valkey storage implementation provides persistent storage and server-side caching through the [Valkey GLIDE](https://github.com/valkey-io/valkey-glide) client. Use it when your deployment runs Valkey or needs GLIDE features such as native Valkey configuration and authentication.
|
|
6
|
+
|
|
7
|
+
Use [`@mastra/redis`](https://mastra.ai/integrations/databases/redis) for Redis deployments that use the official `redis` client. The packages are tested independently against their respective servers.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
**npm**:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @mastra/valkey
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**pnpm**:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add @mastra/valkey
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Yarn**:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
yarn add @mastra/valkey
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Bun**:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
bun add @mastra/valkey
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { Mastra } from '@mastra/core'
|
|
39
|
+
import { ValkeyStore } from '@mastra/valkey'
|
|
40
|
+
|
|
41
|
+
export const mastra = new Mastra({
|
|
42
|
+
storage: new ValkeyStore({
|
|
43
|
+
id: 'valkey-storage',
|
|
44
|
+
host: 'localhost',
|
|
45
|
+
port: 6379,
|
|
46
|
+
password: process.env.VALKEY_PASSWORD,
|
|
47
|
+
}),
|
|
48
|
+
})
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
You can also provide a native GLIDE configuration:
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { ValkeyStore } from '@mastra/valkey'
|
|
55
|
+
|
|
56
|
+
const storage = new ValkeyStore({
|
|
57
|
+
id: 'valkey-storage',
|
|
58
|
+
config: {
|
|
59
|
+
addresses: [{ host: 'localhost', port: 6379 }],
|
|
60
|
+
useTLS: true,
|
|
61
|
+
},
|
|
62
|
+
})
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
For an existing `GlideClient`, connect it before passing it to `ValkeyStore`. The caller remains responsible for closing injected clients.
|
|
66
|
+
|
|
67
|
+
## Constructor parameters
|
|
68
|
+
|
|
69
|
+
**id** (`string`): Unique identifier for the storage instance.
|
|
70
|
+
|
|
71
|
+
**host** (`string`): Valkey host address. Use with the direct connection fields.
|
|
72
|
+
|
|
73
|
+
**port** (`number`): Valkey port. (Default: `6379`)
|
|
74
|
+
|
|
75
|
+
**username** (`string`): Valkey authentication username. (Default: `default`)
|
|
76
|
+
|
|
77
|
+
**password** (`string`): Valkey authentication password.
|
|
78
|
+
|
|
79
|
+
**db** (`number`): Valkey database number. (Default: `0`)
|
|
80
|
+
|
|
81
|
+
**useTLS** (`boolean`): Enables TLS for direct connections.
|
|
82
|
+
|
|
83
|
+
**config** (`GlideClientConfiguration`): Native GLIDE standalone client configuration.
|
|
84
|
+
|
|
85
|
+
**client** (`GlideClient`): Preconfigured GLIDE standalone client.
|
|
86
|
+
|
|
87
|
+
**disableInit** (`boolean`): Disables automatic storage initialization.
|
|
88
|
+
|
|
89
|
+
Provide exactly one connection form: `client`, `config`, or `host` with its optional direct connection fields.
|
|
90
|
+
|
|
91
|
+
## Closing connections
|
|
92
|
+
|
|
93
|
+
Close clients created by `ValkeyStore` during graceful shutdown:
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
await storage.close()
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`close()` doesn't close an injected `GlideClient`.
|