@mastra/mcp-docs-server 0.0.13 → 0.0.14-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/.docs/organized/changelogs/%40mastra%2Fastra.md +34 -34
  2. package/.docs/organized/changelogs/%40mastra%2Fchroma.md +35 -35
  3. package/.docs/organized/changelogs/%40mastra%2Fclickhouse.md +34 -34
  4. package/.docs/organized/changelogs/%40mastra%2Fclient-js.md +39 -39
  5. package/.docs/organized/changelogs/%40mastra%2Fcloud.md +33 -0
  6. package/.docs/organized/changelogs/%40mastra%2Fcloudflare-d1.md +33 -0
  7. package/.docs/organized/changelogs/%40mastra%2Fcloudflare.md +34 -34
  8. package/.docs/organized/changelogs/%40mastra%2Fcore.md +32 -32
  9. package/.docs/organized/changelogs/%40mastra%2Fcouchbase.md +34 -0
  10. package/.docs/organized/changelogs/%40mastra%2Fdeployer-cloudflare.md +38 -38
  11. package/.docs/organized/changelogs/%40mastra%2Fdeployer-netlify.md +38 -38
  12. package/.docs/organized/changelogs/%40mastra%2Fdeployer-vercel.md +39 -39
  13. package/.docs/organized/changelogs/%40mastra%2Fdeployer.md +43 -43
  14. package/.docs/organized/changelogs/%40mastra%2Fevals.md +34 -34
  15. package/.docs/organized/changelogs/%40mastra%2Ffastembed.md +7 -0
  16. package/.docs/organized/changelogs/%40mastra%2Ffirecrawl.md +37 -37
  17. package/.docs/organized/changelogs/%40mastra%2Fgithub.md +34 -34
  18. package/.docs/organized/changelogs/%40mastra%2Flibsql.md +33 -0
  19. package/.docs/organized/changelogs/%40mastra%2Floggers.md +34 -34
  20. package/.docs/organized/changelogs/%40mastra%2Fmcp-docs-server.md +39 -39
  21. package/.docs/organized/changelogs/%40mastra%2Fmcp-registry-registry.md +34 -34
  22. package/.docs/organized/changelogs/%40mastra%2Fmcp.md +49 -49
  23. package/.docs/organized/changelogs/%40mastra%2Fmem0.md +34 -34
  24. package/.docs/organized/changelogs/%40mastra%2Fmemory.md +34 -34
  25. package/.docs/organized/changelogs/%40mastra%2Fmongodb.md +33 -0
  26. package/.docs/organized/changelogs/%40mastra%2Fopensearch.md +35 -1
  27. package/.docs/organized/changelogs/%40mastra%2Fpg.md +34 -34
  28. package/.docs/organized/changelogs/%40mastra%2Fpinecone.md +35 -35
  29. package/.docs/organized/changelogs/%40mastra%2Fplayground-ui.md +45 -45
  30. package/.docs/organized/changelogs/%40mastra%2Fqdrant.md +35 -35
  31. package/.docs/organized/changelogs/%40mastra%2Frag.md +34 -34
  32. package/.docs/organized/changelogs/%40mastra%2Fragie.md +34 -34
  33. package/.docs/organized/changelogs/%40mastra%2Fserver.md +39 -39
  34. package/.docs/organized/changelogs/%40mastra%2Fspeech-azure.md +34 -34
  35. package/.docs/organized/changelogs/%40mastra%2Fspeech-deepgram.md +34 -34
  36. package/.docs/organized/changelogs/%40mastra%2Fspeech-elevenlabs.md +34 -34
  37. package/.docs/organized/changelogs/%40mastra%2Fspeech-google.md +34 -34
  38. package/.docs/organized/changelogs/%40mastra%2Fspeech-ibm.md +34 -34
  39. package/.docs/organized/changelogs/%40mastra%2Fspeech-murf.md +34 -34
  40. package/.docs/organized/changelogs/%40mastra%2Fspeech-openai.md +34 -34
  41. package/.docs/organized/changelogs/%40mastra%2Fspeech-playai.md +34 -34
  42. package/.docs/organized/changelogs/%40mastra%2Fspeech-replicate.md +34 -34
  43. package/.docs/organized/changelogs/%40mastra%2Fspeech-speechify.md +34 -34
  44. package/.docs/organized/changelogs/%40mastra%2Fturbopuffer.md +34 -34
  45. package/.docs/organized/changelogs/%40mastra%2Fupstash.md +34 -34
  46. package/.docs/organized/changelogs/%40mastra%2Fvectorize.md +35 -35
  47. package/.docs/organized/changelogs/%40mastra%2Fvoice-azure.md +34 -34
  48. package/.docs/organized/changelogs/%40mastra%2Fvoice-cloudflare.md +34 -34
  49. package/.docs/organized/changelogs/%40mastra%2Fvoice-deepgram.md +34 -34
  50. package/.docs/organized/changelogs/%40mastra%2Fvoice-elevenlabs.md +34 -34
  51. package/.docs/organized/changelogs/%40mastra%2Fvoice-google.md +34 -34
  52. package/.docs/organized/changelogs/%40mastra%2Fvoice-murf.md +34 -34
  53. package/.docs/organized/changelogs/%40mastra%2Fvoice-openai-realtime.md +34 -34
  54. package/.docs/organized/changelogs/%40mastra%2Fvoice-openai.md +34 -34
  55. package/.docs/organized/changelogs/%40mastra%2Fvoice-playai.md +34 -34
  56. package/.docs/organized/changelogs/%40mastra%2Fvoice-sarvam.md +34 -34
  57. package/.docs/organized/changelogs/%40mastra%2Fvoice-speechify.md +34 -34
  58. package/.docs/organized/changelogs/create-mastra.md +12 -12
  59. package/.docs/organized/changelogs/mastra.md +46 -46
  60. package/.docs/organized/code-examples/a2a.md +202 -0
  61. package/.docs/organized/code-examples/agent-network.md +1 -1
  62. package/.docs/organized/code-examples/agent.md +113 -26
  63. package/.docs/organized/code-examples/ai-sdk-useChat.md +2 -2
  64. package/.docs/organized/code-examples/client-side-tools.md +1 -1
  65. package/.docs/organized/code-examples/crypto-chatbot.md +1 -1
  66. package/.docs/organized/code-examples/fireworks-r1.md +2 -2
  67. package/.docs/organized/code-examples/mcp-configuration.md +579 -0
  68. package/.docs/organized/code-examples/mcp-registry-registry.md +1 -1
  69. package/.docs/organized/code-examples/memory-with-context.md +1 -1
  70. package/.docs/organized/code-examples/memory-with-processors.md +609 -0
  71. package/.docs/organized/code-examples/openapi-spec-writer.md +588 -0
  72. package/.docs/organized/code-examples/quick-start.md +1 -1
  73. package/.docs/raw/agents/dynamic-agents.mdx +47 -0
  74. package/.docs/raw/agents/using-tools-and-mcp.mdx +19 -0
  75. package/.docs/raw/memory/working-memory.mdx +78 -1
  76. package/.docs/raw/reference/cli/mcp-docs-server.mdx +82 -0
  77. package/.docs/raw/reference/deployer/cloudflare.mdx +7 -0
  78. package/.docs/raw/reference/deployer/netlify.mdx +5 -0
  79. package/.docs/raw/reference/deployer/vercel.mdx +6 -0
  80. package/dist/{chunk-OKBMABZO.js → chunk-JWLYN5OI.js} +3 -2
  81. package/dist/prepare-docs/prepare.js +1 -1
  82. package/dist/stdio.js +1 -1
  83. package/package.json +3 -3
@@ -0,0 +1,609 @@
1
+ ### package.json
2
+ ```json
3
+ {
4
+ "name": "memory-with-processors",
5
+ "private": true,
6
+ "version": "0.0.0",
7
+ "type": "module",
8
+ "scripts": {
9
+ "support": "tsx src/support-agent.ts",
10
+ "interview": "tsx src/forgetful-interviewer.ts",
11
+ "tokens": "tsx src/processor-example.ts"
12
+ },
13
+ "dependencies": {
14
+ "@ai-sdk/openai": "latest",
15
+ "@mastra/core": "latest",
16
+ "@mastra/memory": "latest",
17
+ "ai": "^4.3.15",
18
+ "chalk": "^5.4.1",
19
+ "dotenv": "^16.3.1",
20
+ "js-tiktoken": "^1.0.13",
21
+ "tiktoken": "^1.0.13",
22
+ "tsx": "^4.6.2",
23
+ "zod": "^3.24.3"
24
+ },
25
+ "pnpm": {
26
+ "overrides": {
27
+ "@mastra/core": "link:../../packages/core",
28
+ "@mastra/memory": "link:../../packages/memory"
29
+ }
30
+ },
31
+ "packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39"
32
+ }
33
+
34
+ ```
35
+
36
+ ### forgetful-interviewer.ts
37
+ ```typescript
38
+ import 'dotenv/config';
39
+
40
+ import Readline from 'readline';
41
+
42
+ import { openai } from '@ai-sdk/openai';
43
+ import { Agent } from '@mastra/core/agent';
44
+ import type { CoreMessage } from '@mastra/core';
45
+ import { MemoryProcessor, MemoryProcessorOpts } from '@mastra/core/memory';
46
+ import { Memory } from '@mastra/memory';
47
+
48
+ import { makeSend } from './utils';
49
+
50
+ // Custom processor that makes the llm forget any messages that contain keywords
51
+ class ForgetfulProcessor extends MemoryProcessor {
52
+ constructor(private keywords: string[]) {
53
+ super({ name: 'ForgetfulProcessor' });
54
+ }
55
+
56
+ process(messages: CoreMessage[], _opts: MemoryProcessorOpts = {}): CoreMessage[] {
57
+ return messages.map(message => {
58
+ if (message.role === `assistant` || message.role === `user`) {
59
+ const content =
60
+ typeof message.content === `string`
61
+ ? message.content
62
+ : message.content.reduce((msg = ``, current) => {
63
+ if (current.type === `text`) {
64
+ return msg + `\n${current.text}`;
65
+ }
66
+ }, '') || '';
67
+
68
+ const shouldForgetThis = this.keywords.some(keyword => content.toLowerCase().includes(keyword.toLowerCase()));
69
+ console.log(`\n`, { shouldForgetThis, content });
70
+ if (shouldForgetThis && (message.role === `user` || message.role === `assistant`)) {
71
+ return {
72
+ role: 'assistant',
73
+ content: `<forgotten>I'm getting forgetful in my old age. this used to be a ${message.role} message but I forgot it</forgotten>`,
74
+ };
75
+ }
76
+ }
77
+ return message;
78
+ });
79
+ }
80
+ }
81
+
82
+ // Interviewer agent that accidentally forgets your name all the time
83
+ const agent = new Agent({
84
+ name: 'Forgetful Job Interviewer',
85
+ instructions:
86
+ "You are a professional job interviewer for a technology company. Conduct insightful interviews by asking relevant questions about skills, experience, and problem-solving abilities. Respond to candidate answers and ask follow-up questions. Keep the interview professional and engaging. Remember details the candidate shares earlier in the conversation. Sometimes you forget things by accident. The system will show you if you forgot. Don't be embarassed, you can admit when you forget something, you'll know when you do because there will be a message wrapped in <forgetten> tags. Don't refer to the user by their name, it comes across as too eager",
87
+ model: openai('gpt-4o'),
88
+ memory: new Memory({
89
+ processors: [
90
+ // Custom filter to remove messages with certain keywords
91
+ new ForgetfulProcessor(['name']),
92
+ ],
93
+ options: {
94
+ lastMessages: 30,
95
+ semanticRecall: false,
96
+ },
97
+ }),
98
+ });
99
+
100
+ console.log(`
101
+ ╔══════════════════════════════════════════════════════════╗
102
+ ║ ║
103
+ ║ MASTRA MEMORY PROCESSORS DEMO - CONTENT FILTERING ║
104
+ ║ ║
105
+ ║ This example demonstrates: ║
106
+ ║ 1. ToolCallFilter - All tool calls are filtered out ║
107
+ ║ 2. KeywordFilter - Messages with words like: ║
108
+ ║ "confidential", "private", or "sensitive" are ║
109
+ ║ filtered out of the conversation history. ║
110
+ ║ ║
111
+ ║ Try including those words in your responses to see ║
112
+ ║ how the agent "forgets" that information in later ║
113
+ ║ conversation turns. ║
114
+ ║ ║
115
+ ╚══════════════════════════════════════════════════════════╝
116
+ `);
117
+
118
+ const send = makeSend({
119
+ agentName: `\n👔 Forgetful interviewer (can never remember your name)`,
120
+ agent,
121
+ });
122
+
123
+ await send([
124
+ {
125
+ role: 'system',
126
+ content: `Interview starting now. Ask the candidate to introduce themselves and their background.`,
127
+ },
128
+ ]);
129
+
130
+ const rl = Readline.createInterface({
131
+ input: process.stdin,
132
+ output: process.stdout,
133
+ });
134
+
135
+ // Interactive chat loop
136
+ while (true) {
137
+ const prompt: string = await new Promise(res => {
138
+ rl.question('You: ', answer => {
139
+ res(answer);
140
+ });
141
+ });
142
+
143
+ if (prompt.toLowerCase() === 'exit' || prompt.toLowerCase() === 'quit') {
144
+ console.log('Ending interview. Thank you!');
145
+ process.exit(0);
146
+ }
147
+
148
+ await send(prompt);
149
+ }
150
+
151
+ ```
152
+
153
+ ### mastra/agents/index.ts
154
+ ```typescript
155
+ import { openai } from '@ai-sdk/openai';
156
+ import { createTool } from '@mastra/core';
157
+ import { Agent } from '@mastra/core/agent';
158
+ import type { CoreMessage } from '@mastra/core';
159
+ import { MemoryProcessor, MemoryProcessorOpts } from '@mastra/core/memory';
160
+ import { Memory } from '@mastra/memory';
161
+ import { TokenLimiter, ToolCallFilter } from '@mastra/memory/processors';
162
+ import { z } from 'zod';
163
+
164
+ // Custom processor that makes the llm forget any messages that contain keywords
165
+ class ForgetfulProcessor extends MemoryProcessor {
166
+ constructor(private keywords: string[]) {
167
+ super({ name: 'ForgetfulProcessor' });
168
+ }
169
+
170
+ process(messages: CoreMessage[], _opts: MemoryProcessorOpts = {}): CoreMessage[] {
171
+ return messages.map(message => {
172
+ if (message.role === `assistant` || message.role === `user`) {
173
+ const content =
174
+ typeof message.content === `string`
175
+ ? message.content
176
+ : message.content.reduce((msg = ``, current) => {
177
+ if (current.type === `text`) {
178
+ return msg + `\n${current.text}`;
179
+ }
180
+ }, '') || '';
181
+
182
+ const shouldForgetThis = this.keywords.some(keyword => content.toLowerCase().includes(keyword.toLowerCase()));
183
+ console.log(`\n`, { shouldForgetThis, content });
184
+ if (shouldForgetThis && (message.role === `user` || message.role === `assistant`)) {
185
+ return {
186
+ role: 'assistant',
187
+ content: `<forgotten>I'm getting forgetful in my old age. this used to be a ${message.role} message but I forgot it</forgotten>`,
188
+ };
189
+ }
190
+ }
191
+ return message;
192
+ });
193
+ }
194
+ }
195
+
196
+ // Create a technical support agent with token limiting
197
+ const supportMemory = new Memory({
198
+ processors: [
199
+ // Limit history to approximately 2000 tokens to demonstrate truncation
200
+ new TokenLimiter(2000),
201
+ ],
202
+ options: {
203
+ lastMessages: 50,
204
+ semanticRecall: false,
205
+ },
206
+ });
207
+
208
+ // Create the web search tool
209
+ const searchTool = createTool({
210
+ id: 'web-search',
211
+ description: 'Search the web for information',
212
+ inputSchema: z.object({
213
+ query: z.string().describe('The search query'),
214
+ }),
215
+ execute: async ({ context: { query } }) => {
216
+ // Simulate web search results
217
+ return `Search results for "${query}":
218
+ 1. Top result with important information
219
+ 2. Secondary information related to the query
220
+ 3. Additional context that might be helpful`;
221
+ },
222
+ });
223
+
224
+ // Technical support agent with token limiting
225
+ export const supportAgent = new Agent({
226
+ name: 'Technical Support',
227
+ instructions:
228
+ 'You are a technical support agent who helps users solve software problems. You provide clear, step-by-step instructions and ask clarifying questions when needed. You remember details from earlier in the conversation. Your goal is to efficiently resolve user issues.',
229
+ model: openai('gpt-4o-mini'),
230
+ memory: supportMemory,
231
+ tools: { searchTool },
232
+ });
233
+
234
+ // Create an interviewer agent that filters out tool calls and sensitive content
235
+ const interviewMemory = new Memory({
236
+ processors: [
237
+ // Filter out all tool calls to keep conversation focused
238
+ new ToolCallFilter(),
239
+ // Custom filter to remove messages with certain keywords
240
+ new ForgetfulProcessor(['name']),
241
+ ],
242
+ options: {
243
+ lastMessages: 30,
244
+ semanticRecall: false,
245
+ },
246
+ });
247
+
248
+ // Interviewer agent that filters out tool calls and sensitive content
249
+ export const interviewerAgent = new Agent({
250
+ name: 'Forgetful Job Interviewer',
251
+ instructions:
252
+ "You are a professional job interviewer for a technology company. Conduct insightful interviews by asking relevant questions about skills, experience, and problem-solving abilities. Respond to candidate answers and ask follow-up questions. Keep the interview professional and engaging. Remember details the candidate shares earlier in the conversation. Sometimes you forget things by accident. The system will show you if you forgot. Don't be embarassed, you can admit when you forget something, you'll know when you do because there will be a message wrapped in <forgetten> tags. Don't refer to the user by their name, it comes across as too eager",
253
+ model: openai('gpt-4o'),
254
+ memory: interviewMemory,
255
+ });
256
+
257
+ ```
258
+
259
+ ### mastra/index.ts
260
+ ```typescript
261
+ import { Mastra } from '@mastra/core';
262
+
263
+ import { supportAgent, interviewerAgent } from './agents';
264
+
265
+ export const mastra = new Mastra({
266
+ agents: { supportAgent, interviewerAgent },
267
+ });
268
+
269
+ ```
270
+
271
+ ### processor-example.ts
272
+ ```typescript
273
+ import 'dotenv/config';
274
+ import { openai } from '@ai-sdk/openai';
275
+ import { Mastra } from '@mastra/core';
276
+ import { createLogger } from '@mastra/core/logger';
277
+ import { createTool } from '@mastra/core/tools';
278
+ import { Agent } from '@mastra/core/agent';
279
+ import { Memory } from '@mastra/memory';
280
+ import { TokenLimiter } from '@mastra/memory/processors';
281
+ import { readFileSync, existsSync } from 'fs';
282
+ import { resolve } from 'path';
283
+ import chalk from 'chalk';
284
+
285
+ // Create a tool that reads the massive pnpm-lock.yaml file
286
+ const testTool = createTool({
287
+ id: 'read-file',
288
+ description: 'Read a large file to test token limits',
289
+ execute: async () => {
290
+ try {
291
+ // Try multiple possible locations for the pnpm-lock.yaml file
292
+ const possiblePaths = [
293
+ // Root of the project
294
+ resolve(import.meta.dirname, '../../../', 'pnpm-lock.yaml'),
295
+ ];
296
+
297
+ let filePath: string | null = null;
298
+ let fileContent = '';
299
+
300
+ // Find the first file that exists
301
+ for (const path of possiblePaths) {
302
+ if (existsSync(path)) {
303
+ filePath = path;
304
+ fileContent = readFileSync(path, 'utf-8');
305
+ break;
306
+ }
307
+ }
308
+
309
+ // If no file was found, generate a large mock file
310
+ if (!filePath) {
311
+ console.log(chalk.yellow('No suitable large file found. Generating mock content...'));
312
+
313
+ // Create a large mock yaml-like content (about 20K characters)
314
+ fileContent = Array(100)
315
+ .fill(0)
316
+ .map(
317
+ (_, i) =>
318
+ `package-${i}:
319
+ version: "1.0.${i}"
320
+ resolved: "https://registry.npmjs.org/package-${i}/-/package-${i}-1.0.${i}.tgz"
321
+ integrity: "sha512-${Math.random().toString(36).substring(2, 40)}"
322
+ dependencies:
323
+ dep-a: "^2.0.0"
324
+ dep-b: "^3.1.2"
325
+ dep-c: "^0.8.9"
326
+ devDependencies:
327
+ test-lib: "^4.5.2"
328
+ `,
329
+ )
330
+ .join('\n');
331
+ }
332
+
333
+ // Return the first 20K characters (still very token-heavy)
334
+ return `File content (truncated to 20K chars):\n${fileContent.slice(0, 20000)}`;
335
+ } catch (error) {
336
+ console.error('Error reading file:', error);
337
+
338
+ // Return a mock large response as fallback
339
+ return `Error reading file: ${error.message}\n\nGenerating mock content instead: \n${Array(50)
340
+ .fill('This is a large mock file content to test token limiting. ')
341
+ .join('\n')}`;
342
+ }
343
+ },
344
+ });
345
+
346
+ // Create memory with a low token limit to clearly demonstrate limiting
347
+ const memory = new Memory({
348
+ processors: [
349
+ // Set a very low token limit (1000) to clearly demonstrate token limiting
350
+ new TokenLimiter(1000),
351
+ ],
352
+ options: {
353
+ lastMessages: 50,
354
+ },
355
+ });
356
+
357
+ // Create an agent with the test tool
358
+ const tokenTestAgent = new Agent({
359
+ name: 'Token Test Agent',
360
+ instructions: 'You help test token limiting by calling tools that return large amounts of data.',
361
+ model: openai('gpt-4o-mini'),
362
+ memory,
363
+ tools: { testTool },
364
+ });
365
+
366
+ // Create Mastra instance
367
+ const mastra = new Mastra({
368
+ agents: { tokenTestAgent },
369
+ logger: createLogger({ level: 'info' }),
370
+ });
371
+
372
+ // Track token usage
373
+ const tokenHistory: number[] = [];
374
+
375
+ async function sendMessage(message: string) {
376
+ console.log(`\n${chalk.green('You:')} ${message}`);
377
+
378
+ // Get the agent response
379
+ const response = await mastra.getAgent('tokenTestAgent').generate(message, {
380
+ threadId: 'token-test-thread',
381
+ resourceId: 'demo-user',
382
+ });
383
+
384
+ // Display the response
385
+ console.log(`\n${chalk.blue('Agent:')} ${response.text}`);
386
+
387
+ // Track and display token usage
388
+ const tokensUsed = response.usage.totalTokens;
389
+ tokenHistory.push(tokensUsed);
390
+
391
+ // Display token usage information
392
+ console.log(`\n${chalk.yellow('📊 Token Usage:')}`);
393
+ console.log(`${chalk.yellow('├')} Current: ${tokensUsed} tokens`);
394
+ console.log(`${chalk.yellow('├')} Total: ${tokenHistory.reduce((sum, t) => sum + t, 0)} tokens`);
395
+ console.log(`${chalk.yellow('└')} Memory Token Limit: 1000 tokens`);
396
+
397
+ return response;
398
+ }
399
+
400
+ async function main() {
401
+ console.log(
402
+ chalk.cyan(`
403
+ ╔══════════════════════════════════════════════════════════╗
404
+ ║ ║
405
+ ║ TOKEN LIMITER PROCESSOR DEMO ║
406
+ ║ ║
407
+ ║ This example demonstrates how TokenLimiter works with ║
408
+ ║ extremely large tool responses. ║
409
+ ║ ║
410
+ ║ The tool reads a massive pnpm-lock.yaml file and ║
411
+ ║ returns a large chunk of text. If the file can't be ║
412
+ ║ found, it generates mock content. ║
413
+ ║ ║
414
+ ║ Memory token limit: 1000 tokens ║
415
+ ║ ║
416
+ ╚══════════════════════════════════════════════════════════╝
417
+ `),
418
+ );
419
+
420
+ // First message - introduction
421
+ await sendMessage("Hello! I'd like to test the token limiting functionality.");
422
+
423
+ // Second message - ask to call the tool
424
+ await sendMessage(
425
+ "Please use the read-file tool to read the large file. After you do, I'll ask you to summarize what you found.",
426
+ );
427
+
428
+ // Third message - ask about content that might be forgotten due to token limiting
429
+ await sendMessage(
430
+ 'Now, can you tell me what was in the file you just read? And do you remember what I asked in my first message?',
431
+ );
432
+
433
+ // Fourth message - ask about content that should definitely be forgotten
434
+ await sendMessage(
435
+ "Let's see how the token limiter is working. Do you remember the exact contents at the beginning of the file?",
436
+ );
437
+
438
+ console.log(
439
+ chalk.cyan(`
440
+ ═════════════════════════════════════════════════════════════
441
+ DEMO COMPLETE
442
+
443
+ The TokenLimiter processor has prevented the conversation from
444
+ exceeding the 1000 token limit by pruning older messages,
445
+ particularly the large tool response.
446
+
447
+ This ensures that the context window is never exceeded while
448
+ still preserving the most recent and relevant messages.
449
+ ═════════════════════════════════════════════════════════════
450
+ `),
451
+ );
452
+ }
453
+
454
+ main().catch(console.error);
455
+
456
+ ```
457
+
458
+ ### support-agent.ts
459
+ ```typescript
460
+ import 'dotenv/config';
461
+ import { makeSend, searchTool } from './utils';
462
+ import { openai } from '@ai-sdk/openai';
463
+ import { Agent } from '@mastra/core/agent';
464
+ import { Memory } from '@mastra/memory';
465
+ import { TokenLimiter } from '@mastra/memory/processors';
466
+ import { createLogger, Mastra } from '@mastra/core';
467
+
468
+ const memory = new Memory({
469
+ processors: [new TokenLimiter(500)],
470
+ options: {
471
+ lastMessages: 50,
472
+ semanticRecall: true,
473
+ },
474
+ });
475
+
476
+ const techSupport = new Agent({
477
+ name: 'Technical Support',
478
+ instructions:
479
+ 'You are a technical support agent who helps users solve software problems. You provide concise, short, instructions and ask clarifying questions when needed. You remember details from earlier in the conversation. Your goal is to efficiently resolve user issues. Make sure you provide concise responses without tons of text',
480
+ model: openai('gpt-4o-mini'),
481
+ memory,
482
+ tools: { searchTool },
483
+ });
484
+
485
+ const mastra = new Mastra({
486
+ agents: { techSupport },
487
+ logger: createLogger({ level: 'info' }),
488
+ });
489
+
490
+ console.log(`
491
+ ╔══════════════════════════════════════════════════════════╗
492
+ ║ ║
493
+ ║ MASTRA MEMORY PROCESSORS DEMO - TOKEN LIMITING ║
494
+ ║ ║
495
+ ║ This example demonstrates the TokenLimiter processor ║
496
+ ║ which limits memory to a specified token count (500). ║
497
+ ║ As the conversation grows, older messages will be ║
498
+ ║ automatically pruned to stay within the token limit. ║
499
+ ║ ║
500
+ ╚══════════════════════════════════════════════════════════╝
501
+ `);
502
+
503
+ const send = makeSend({
504
+ agentName: `\n 💻 Support Agent`,
505
+ agent: mastra.getAgent(`techSupport`),
506
+ });
507
+
508
+ await send(
509
+ "I'm having trouble with my laptop. It keeps shutting down randomly after about 30 minutes of use. I've had it for about 2 years and this just started happening last week.",
510
+ );
511
+ await send('Can you search for common causes of laptop overheating?');
512
+ await send('Can you search again?');
513
+ await send(
514
+ "The laptop feels quite hot before it shuts down. I'm using a Dell XPS 15 with Windows 11. I usually have multiple browser tabs open and sometimes I'm running Visual Studio Code. The battery seems to drain quickly too.",
515
+ );
516
+ await send(
517
+ "I've tried restarting in safe mode and the problem doesn't happen there. Also, I checked for Windows updates and everything is current. What should I do to fix this issue?",
518
+ );
519
+ await send(
520
+ "I tried cleaning the fans as you suggested, but it's still happening. I also downloaded a temperature monitoring app and it shows the CPU reaching 90°C before shutting down. My friend suggested it might be a failing thermal paste. Do you think I should try replacing the thermal paste myself or take it to a repair shop? I've never opened a laptop before but I'm somewhat technically inclined. Also, is there a way to limit how much CPU power certain applications use?",
521
+ );
522
+ await send(
523
+ 'Can you remind me what was the first thing you suggested I should check? Also, do you think a cooling pad would help with my issue?',
524
+ );
525
+
526
+ ```
527
+
528
+ ### utils.ts
529
+ ```typescript
530
+ import { createTool } from '@mastra/core/tools';
531
+ import { z } from 'zod';
532
+ import { Agent } from '@mastra/core/agent';
533
+ import type { CoreMessage, StreamTextResult } from 'ai';
534
+ import chalk from 'chalk';
535
+ import { randomUUID } from 'node:crypto';
536
+
537
+ export function makeLogger(botName: string) {
538
+ return async function logRes(res: Promise<StreamTextResult<any, any>>) {
539
+ console.log(chalk.bold.blue(botName + `:`));
540
+ for await (const chunk of (await res).fullStream) {
541
+ switch (chunk.type) {
542
+ case 'error':
543
+ console.error(chalk.red(chunk.error));
544
+ break;
545
+ case 'text-delta':
546
+ process.stdout.write(chalk.blue(chunk.textDelta));
547
+ break;
548
+
549
+ case 'tool-call':
550
+ console.log(chalk.cyan(`\n\ntool-call: ${chunk.toolName}`));
551
+ break;
552
+ case 'tool-result':
553
+ console.log(chalk.cyan(`\ntool-result: ${JSON.stringify(chunk.result)}\n\n`));
554
+ }
555
+ }
556
+ console.log(`\n\n`);
557
+ return {
558
+ usage: (await res).usage,
559
+ messages: (await (await res).response).messages,
560
+ };
561
+ };
562
+ }
563
+
564
+ export function makeSend({ agentName, agent }: { agentName: string; agent: Agent }) {
565
+ const threadId = randomUUID();
566
+ const resourceId = 'DEMO_USER_1';
567
+
568
+ const log = makeLogger(agentName);
569
+ function logQ(message: string | CoreMessage[]) {
570
+ if (typeof message !== 'string') return message;
571
+ console.log(
572
+ chalk.red(`\n${chalk.bold(`🐵 You:`)}\n${message}
573
+ `),
574
+ );
575
+ return message;
576
+ }
577
+ let totalTokens = 0;
578
+ async function logStats(res: { usage: any; messages: any }) {
579
+ // console.log(chalk.green(`Completion had ${res.messages.length} messages`));
580
+ // console.log(chalk.green(`Usage: ${JSON.stringify(await res.usage, null, 2)}`));
581
+ totalTokens += (await res.usage).totalTokens;
582
+ }
583
+ process.on(`exit`, () => {
584
+ console.log(chalk.green.bold(`Total token usage: ${totalTokens}`));
585
+ });
586
+ return async function send(prompt: string | CoreMessage[]) {
587
+ await logStats(
588
+ await log(
589
+ agent.stream(logQ(prompt), {
590
+ threadId,
591
+ resourceId,
592
+ }),
593
+ ),
594
+ );
595
+ };
596
+ }
597
+
598
+ export const searchTool = createTool({
599
+ id: 'web-search',
600
+ description: 'Search the web for information',
601
+ inputSchema: z.object({
602
+ query: z.string().describe('The search query'),
603
+ }),
604
+ execute: async () => {
605
+ return `Not much found unfortunately. You'll probably have to turn it off an on again.`;
606
+ },
607
+ });
608
+
609
+ ```