@mastra/mcp-docs-server 0.13.2-alpha.1 → 0.13.2-alpha.3

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 (86) hide show
  1. package/.docs/organized/changelogs/%40mastra%2Fastra.md +14 -14
  2. package/.docs/organized/changelogs/%40mastra%2Fchroma.md +14 -14
  3. package/.docs/organized/changelogs/%40mastra%2Fclickhouse.md +14 -14
  4. package/.docs/organized/changelogs/%40mastra%2Fclient-js.md +18 -18
  5. package/.docs/organized/changelogs/%40mastra%2Fcloudflare-d1.md +14 -14
  6. package/.docs/organized/changelogs/%40mastra%2Fcloudflare.md +14 -14
  7. package/.docs/organized/changelogs/%40mastra%2Fcore.md +15 -15
  8. package/.docs/organized/changelogs/%40mastra%2Fcouchbase.md +14 -14
  9. package/.docs/organized/changelogs/%40mastra%2Fdeployer-cloudflare.md +20 -20
  10. package/.docs/organized/changelogs/%40mastra%2Fdeployer-netlify.md +24 -24
  11. package/.docs/organized/changelogs/%40mastra%2Fdeployer-vercel.md +24 -24
  12. package/.docs/organized/changelogs/%40mastra%2Fdeployer.md +22 -22
  13. package/.docs/organized/changelogs/%40mastra%2Fdynamodb.md +21 -21
  14. package/.docs/organized/changelogs/%40mastra%2Flance.md +13 -0
  15. package/.docs/organized/changelogs/%40mastra%2Flibsql.md +14 -14
  16. package/.docs/organized/changelogs/%40mastra%2Fmcp-docs-server.md +17 -17
  17. package/.docs/organized/changelogs/%40mastra%2Fmcp.md +9 -9
  18. package/.docs/organized/changelogs/%40mastra%2Fmemory.md +22 -22
  19. package/.docs/organized/changelogs/%40mastra%2Fmongodb.md +14 -14
  20. package/.docs/organized/changelogs/%40mastra%2Fopensearch.md +13 -0
  21. package/.docs/organized/changelogs/%40mastra%2Fpg.md +14 -14
  22. package/.docs/organized/changelogs/%40mastra%2Fpinecone.md +14 -14
  23. package/.docs/organized/changelogs/%40mastra%2Fplayground-ui.md +27 -27
  24. package/.docs/organized/changelogs/%40mastra%2Fqdrant.md +14 -14
  25. package/.docs/organized/changelogs/%40mastra%2Fserver.md +20 -20
  26. package/.docs/organized/changelogs/%40mastra%2Fturbopuffer.md +14 -14
  27. package/.docs/organized/changelogs/%40mastra%2Fupstash.md +14 -14
  28. package/.docs/organized/changelogs/%40mastra%2Fvectorize.md +14 -14
  29. package/.docs/organized/changelogs/mastra.md +22 -22
  30. package/.docs/organized/code-examples/agent.md +182 -5
  31. package/.docs/organized/code-examples/assistant-ui.md +1 -1
  32. package/.docs/organized/code-examples/bird-checker-with-nextjs-and-eval.md +1 -1
  33. package/.docs/organized/code-examples/bird-checker-with-nextjs.md +1 -1
  34. package/.docs/organized/code-examples/crypto-chatbot.md +2 -2
  35. package/.docs/organized/code-examples/openapi-spec-writer.md +1 -1
  36. package/.docs/raw/agents/using-tools-and-mcp.mdx +3 -2
  37. package/.docs/raw/course/01-first-agent/04-project-structure.md +8 -3
  38. package/.docs/raw/course/01-first-agent/07-creating-your-agent.md +5 -3
  39. package/.docs/raw/course/01-first-agent/08-exporting-your-agent.md +20 -6
  40. package/.docs/raw/course/01-first-agent/11-creating-transactions-tool.md +5 -3
  41. package/.docs/raw/course/01-first-agent/12-connecting-tool-to-agent.md +2 -2
  42. package/.docs/raw/course/04-workflows/01-introduction-to-workflows.md +44 -0
  43. package/.docs/raw/course/04-workflows/02-understanding-steps.md +53 -0
  44. package/.docs/raw/course/04-workflows/03-creating-your-first-step.md +57 -0
  45. package/.docs/raw/course/04-workflows/04-creating-a-second-step.md +58 -0
  46. package/.docs/raw/course/04-workflows/05-chaining-steps-together.md +56 -0
  47. package/.docs/raw/course/04-workflows/06-registering-with-mastra.md +24 -0
  48. package/.docs/raw/course/04-workflows/07-using-playground.md +58 -0
  49. package/.docs/raw/course/04-workflows/08-running-workflows-programmatically.md +77 -0
  50. package/.docs/raw/course/04-workflows/09-adding-a-third-step.md +70 -0
  51. package/.docs/raw/course/04-workflows/10-updating-the-workflow.md +55 -0
  52. package/.docs/raw/course/04-workflows/11-creating-an-ai-agent.md +67 -0
  53. package/.docs/raw/course/04-workflows/12-using-agent-in-workflow.md +91 -0
  54. package/.docs/raw/course/04-workflows/13-creating-ai-enhanced-workflow.md +75 -0
  55. package/.docs/raw/course/04-workflows/14-understanding-parallel-execution.md +38 -0
  56. package/.docs/raw/course/04-workflows/15-creating-parallel-steps.md +115 -0
  57. package/.docs/raw/course/04-workflows/16-building-parallel-workflow.md +100 -0
  58. package/.docs/raw/course/04-workflows/17-testing-parallel-performance.md +40 -0
  59. package/.docs/raw/course/04-workflows/18-understanding-conditional-branching.md +58 -0
  60. package/.docs/raw/course/04-workflows/19-creating-conditional-steps.md +128 -0
  61. package/.docs/raw/course/04-workflows/20-building-conditional-workflow.md +60 -0
  62. package/.docs/raw/course/04-workflows/21-testing-conditional-logic.md +58 -0
  63. package/.docs/raw/course/04-workflows/22-conclusion.md +58 -0
  64. package/.docs/raw/deployment/cloud-providers/digital-ocean.mdx +111 -0
  65. package/.docs/raw/deployment/cloud-providers/index.mdx +15 -0
  66. package/.docs/raw/memory/working-memory.mdx +56 -0
  67. package/.docs/raw/networks-vnext/complex-task-execution.mdx +137 -0
  68. package/.docs/raw/networks-vnext/overview.mdx +85 -0
  69. package/.docs/raw/networks-vnext/single-task-execution.mdx +131 -0
  70. package/.docs/raw/reference/client-js/agents.mdx +41 -0
  71. package/.docs/raw/reference/deployer/netlify.mdx +22 -68
  72. package/.docs/raw/reference/deployer/vercel.mdx +7 -77
  73. package/.docs/raw/reference/tools/mcp-client.mdx +244 -0
  74. package/.docs/raw/reference/tools/mcp-server.mdx +186 -0
  75. package/.docs/raw/reference/workflows/create-run.mdx +1 -1
  76. package/.docs/raw/reference/workflows/resume.mdx +1 -1
  77. package/.docs/raw/reference/workflows/start.mdx +1 -1
  78. package/.docs/raw/reference/workflows/stream.mdx +1 -1
  79. package/.docs/raw/reference/workflows/watch.mdx +1 -1
  80. package/.docs/raw/reference/workflows/workflow.mdx +6 -2
  81. package/.docs/raw/workflows/control-flow.mdx +42 -1
  82. package/.docs/raw/workflows/overview.mdx +73 -5
  83. package/.docs/raw/workflows/pausing-execution.mdx +1 -1
  84. package/.docs/raw/workflows/suspend-and-resume.mdx +68 -23
  85. package/.docs/raw/workflows/using-with-agents-and-tools.mdx +1 -1
  86. package/package.json +3 -3
@@ -50,21 +50,147 @@
50
50
  ### client.ts
51
51
  ```typescript
52
52
  import { MCPClient } from '@mastra/mcp';
53
+ // import type { ElicitationHandler } from '@mastra/mcp';
54
+ import { createInterface } from 'readline';
55
+
56
+ // Create readline interface for user input
57
+ const readline = createInterface({
58
+ input: process.stdin,
59
+ output: process.stdout,
60
+ });
61
+
62
+ // Helper function to prompt user for input
63
+ function askQuestion(question: string): Promise<string> {
64
+ return new Promise(resolve => {
65
+ readline.question(question, answer => {
66
+ resolve(answer.trim());
67
+ });
68
+ });
69
+ }
70
+
71
+ // Elicitation handler that prompts the user for input
72
+ const elicitationHandler = async request => {
73
+ console.log('\n🔔 Elicitation Request Received:');
74
+ console.log(`Message: ${request.message}`);
75
+ console.log('Requested Schema:');
76
+ console.log(JSON.stringify(request.requestedSchema, null, 2));
77
+
78
+ const schema = request.requestedSchema;
79
+ const properties = schema.properties;
80
+ const required = schema.required || [];
81
+
82
+ console.log('\nPlease provide the following information:');
83
+
84
+ const content: Record<string, unknown> = {};
85
+
86
+ // Collect input for each field
87
+ for (const [fieldName, fieldSchema] of Object.entries(properties)) {
88
+ const field = fieldSchema as {
89
+ type?: string;
90
+ title?: string;
91
+ description?: string;
92
+ format?: string;
93
+ };
94
+
95
+ const isRequired = required.includes(fieldName);
96
+ let prompt = `${field.title || fieldName}`;
97
+
98
+ // Add helpful information to the prompt
99
+ if (field.description) {
100
+ prompt += ` (${field.description})`;
101
+ }
102
+ if (field.format) {
103
+ prompt += ` [format: ${field.format}]`;
104
+ }
105
+ if (isRequired) {
106
+ prompt += ' *required*';
107
+ }
108
+
109
+ prompt += ': ';
110
+
111
+ const answer = await askQuestion(prompt);
112
+
113
+ // Check for cancellation
114
+ if (answer.toLowerCase() === 'cancel' || answer.toLowerCase() === 'c') {
115
+ return { action: 'cancel' as const };
116
+ }
117
+
118
+ // Handle empty responses
119
+ if (answer === '' && isRequired) {
120
+ console.log(`❌ Error: ${fieldName} is required`);
121
+ return { action: 'reject' as const };
122
+ } else if (answer !== '') {
123
+ content[fieldName] = answer;
124
+ }
125
+ }
126
+
127
+ // Show the collected data and ask for confirmation
128
+ console.log('\n✅ Collected data:');
129
+ console.log(JSON.stringify(content, null, 2));
130
+
131
+ const confirmAnswer = await askQuestion('\nSubmit this information? (yes/no/cancel): ');
132
+
133
+ if (confirmAnswer.toLowerCase() === 'yes' || confirmAnswer.toLowerCase() === 'y') {
134
+ return {
135
+ action: 'accept' as const,
136
+ content,
137
+ };
138
+ } else if (confirmAnswer.toLowerCase() === 'cancel' || confirmAnswer.toLowerCase() === 'c') {
139
+ return { action: 'cancel' as const };
140
+ } else {
141
+ return { action: 'reject' as const };
142
+ }
143
+ };
53
144
 
54
145
  async function main() {
55
146
  const mcpClient = new MCPClient({
56
147
  servers: {
57
- myMcpServer: {
58
- url: new URL('http://localhost:4111/api/mcp/myMcpServer/mcp'),
148
+ myMcpServerTwo: {
149
+ url: new URL('http://localhost:4111/api/mcp/myMcpServerTwo/mcp'),
59
150
  },
60
151
  },
61
152
  });
62
153
 
63
- const tools = await mcpClient.getTools();
64
- console.log('Tools:', tools);
154
+ mcpClient.elicitation.onRequest('myMcpServerTwo', elicitationHandler);
155
+
156
+ try {
157
+ console.log('Connecting to MCP server...');
158
+ const tools = await mcpClient.getTools();
159
+ console.log('Available tools:', Object.keys(tools));
160
+
161
+ // Test the elicitation functionality
162
+ console.log('\n🧪 Testing elicitation functionality...');
163
+
164
+ // Find the collectContactInfo tool
165
+ const collectContactInfoTool = tools['myMcpServerTwo_collectContactInfo'];
166
+ if (collectContactInfoTool) {
167
+ console.log('\nCalling collectContactInfo tool...');
168
+
169
+ try {
170
+ const result = await collectContactInfoTool.execute({
171
+ context: {
172
+ reason: 'We need your contact information to send you updates about our service.',
173
+ },
174
+ });
175
+
176
+ console.log('\n📋 Tool Result:');
177
+ console.log(result);
178
+ } catch (error) {
179
+ console.error('❌ Error calling collectContactInfo tool:', error);
180
+ }
181
+ } else {
182
+ console.log('❌ collectContactInfo tool not found');
183
+ console.log('Available tools:', Object.keys(tools));
184
+ }
185
+ } catch (error) {
186
+ console.error('❌ Error:', error);
187
+ } finally {
188
+ readline.close();
189
+ await mcpClient.disconnect();
190
+ }
65
191
  }
66
192
 
67
- main();
193
+ main().catch(console.error);
68
194
 
69
195
  ```
70
196
 
@@ -664,6 +790,57 @@ export const myMcpServerTwo = new MCPServer({
664
790
  return `Hello, ${context.name}! Welcome to the MCP server.`;
665
791
  },
666
792
  }),
793
+ collectContactInfo: createTool({
794
+ id: 'collectContactInfo',
795
+ description: 'Collects user contact information through elicitation.',
796
+ inputSchema: z.object({
797
+ reason: z.string().optional().describe('Optional reason for collecting contact info'),
798
+ }),
799
+ execute: async ({ context }, options) => {
800
+ const { reason } = context;
801
+
802
+ try {
803
+ // Use the session-aware elicitation functionality
804
+ const result = await options.elicitation.sendRequest({
805
+ message: reason
806
+ ? `Please provide your contact information. ${reason}`
807
+ : 'Please provide your contact information',
808
+ requestedSchema: {
809
+ type: 'object',
810
+ properties: {
811
+ name: {
812
+ type: 'string',
813
+ title: 'Full Name',
814
+ description: 'Your full name',
815
+ },
816
+ email: {
817
+ type: 'string',
818
+ title: 'Email Address',
819
+ description: 'Your email address',
820
+ format: 'email',
821
+ },
822
+ phone: {
823
+ type: 'string',
824
+ title: 'Phone Number',
825
+ description: 'Your phone number (optional)',
826
+ },
827
+ },
828
+ required: ['name', 'email'],
829
+ },
830
+ });
831
+
832
+ if (result.action === 'accept') {
833
+ return `Thank you! Contact information collected: ${JSON.stringify(result.content, null, 2)}`;
834
+ } else if (result.action === 'reject') {
835
+ return 'Contact information collection was declined by the user.';
836
+ } else {
837
+ return 'Contact information collection was cancelled by the user.';
838
+ }
839
+ } catch (error) {
840
+ return `Error collecting contact information: ${error}`;
841
+ }
842
+ },
843
+ }),
667
844
  },
668
845
  });
669
846
 
@@ -30,7 +30,7 @@
30
30
  "@types/node": "^20.17.57",
31
31
  "@types/react": "^19.1.8",
32
32
  "@types/react-dom": "^19.1.6",
33
- "eslint": "^8.57.1",
33
+ "eslint": "^9.29.0",
34
34
  "eslint-config-next": "15.3.3",
35
35
  "postcss": "^8.5.3",
36
36
  "tailwindcss": "^3.4.17",
@@ -39,7 +39,7 @@
39
39
  "@types/node": "^20.17.57",
40
40
  "@types/react": "^18.3.23",
41
41
  "@types/react-dom": "^18.3.7",
42
- "eslint": "^8.57.1",
42
+ "eslint": "^9.29.0",
43
43
  "eslint-config-next": "15.3.3",
44
44
  "postcss": "^8.5.3",
45
45
  "tailwindcss": "^3.4.17",
@@ -38,7 +38,7 @@
38
38
  "@types/node": "^20.17.57",
39
39
  "@types/react": "^19.1.8",
40
40
  "@types/react-dom": "^19.1.6",
41
- "eslint": "^8.57.1",
41
+ "eslint": "^9.29.0",
42
42
  "eslint-config-next": "15.3.3",
43
43
  "postcss": "^8.5.3",
44
44
  "tailwindcss": "^3.4.17",
@@ -91,8 +91,8 @@
91
91
  "drizzle-kit": "^0.31.0",
92
92
  "eslint": "^9.29.0",
93
93
  "eslint-config-next": "15.3.3",
94
- "eslint-config-prettier": "^9.1.0",
95
- "eslint-import-resolver-typescript": "^3.10.1",
94
+ "eslint-config-prettier": "^10.1.5",
95
+ "eslint-import-resolver-typescript": "^4.4.3",
96
96
  "eslint-plugin-import": "^2.31.0",
97
97
  "eslint-plugin-tailwindcss": "^3.18.0",
98
98
  "postcss": "^8.5.3",
@@ -41,7 +41,7 @@
41
41
  "@types/react": "^19.1.8",
42
42
  "@types/react-dom": "^19.1.6",
43
43
  "@types/react-syntax-highlighter": "^15.5.13",
44
- "eslint": "^8.57.1",
44
+ "eslint": "^9.29.0",
45
45
  "eslint-config-next": "15.3.3",
46
46
  "postcss": "^8.5.3",
47
47
  "tailwindcss": "^3.4.17",
@@ -75,8 +75,6 @@ Once you have a server you want to use with your agent, import the Mastra `MCPCl
75
75
 
76
76
  ```typescript filename="src/mastra/mcp.ts" {1,7-16}
77
77
  import { MCPClient } from "@mastra/mcp";
78
- import { Agent } from "@mastra/core/agent";
79
- import { openai } from "@ai-sdk/openai";
80
78
 
81
79
  // Configure MCPClient to connect to your server(s)
82
80
  export const mcp = new MCPClient({
@@ -96,7 +94,10 @@ export const mcp = new MCPClient({
96
94
  Then connect your agent to the server tools:
97
95
 
98
96
  ```typescript filename="src/mastra/agents/mcpAgent.ts" {7}
97
+ import { Agent } from "@mastra/core/agent";
98
+ import { openai } from "@ai-sdk/openai";
99
99
  import { mcp } from "../mcp";
100
+
100
101
  // Create an agent and add tools from the MCP client
101
102
  const agent = new Agent({
102
103
  name: "Agent with MCP Tools",
@@ -4,9 +4,14 @@ Let's check that your project has the correct structure. You should have:
4
4
 
5
5
  1. A `src/mastra` directory that contains:
6
6
  - `index.ts` - The main entry point for your Mastra project
7
- - `agents/index.ts` - Where your agents are defined
8
- - `tools/index.ts` - Where your tools are defined
7
+ - `agents/` - Directory containing individual agent files
8
+ - `tools/` - Directory containing individual tool files
9
+ - `workflows/` - Directory containing individual workflow files
9
10
 
10
- If these files exist, you're ready to start building your agent!
11
+ If the CLI created your project, you should see files like:
12
+
13
+ - `agents/weather-agent.ts` - Example weather agent
14
+ - `tools/weather-tool.ts` - Example weather tool
15
+ - `workflows/weather-workflow.ts` - Example weather workflow
11
16
 
12
17
  This structure is important because it follows the Mastra convention for organizing your code. The `index.ts` file is the main entry point for your Mastra project, while the `agents` and `tools` directories contain the definitions for your agents and tools, respectively.
@@ -1,11 +1,13 @@
1
1
  # Creating Your Agent
2
2
 
3
- Let's create a simple agent that will help users analyze financial transaction data. We'll start by modifying the `agents/index.ts` file.
3
+ Let's create a simple agent that will help users analyze financial transaction data. We'll create a new file called `agents/financial-agent.ts`.
4
4
 
5
- First, make sure you have the necessary imports at the top of your file:
5
+ First, create the new agent file at src/mastra/agents/financial-agent.ts
6
+
7
+ Now add the necessary imports at the top of your file:
6
8
 
7
9
  ```typescript
8
- import { Agent } from "@mastra/core";
10
+ import { Agent } from "@mastra/core/agent";
9
11
  import { openai } from "@ai-sdk/openai";
10
12
  // We'll import our tool in a later step
11
13
  ```
@@ -1,18 +1,32 @@
1
1
  # Exporting Your Agent
2
2
 
3
- To make your agent available to the playground, you need to export it through the Mastra class in your `src/mastra/index.ts` file:
3
+ To make your agent available to the playground, you need to export it through the Mastra class in your `src/mastra/index.ts` file.
4
+
5
+ First, import the necessary dependencies and your agent:
4
6
 
5
7
  ```typescript
6
- import { Mastra } from "@mastra/core";
7
- import { financialAgent } from "./agents";
8
+ import { Mastra } from "@mastra/core/mastra";
9
+ import { PinoLogger } from "@mastra/loggers";
10
+ import { LibSQLStore } from "@mastra/libsql";
11
+ import { financialAgent } from "./agents/financial-agent";
8
12
 
9
- export const mastra: Mastra = new Mastra({
13
+ export const mastra = new Mastra({
10
14
  agents: {
11
15
  financialAgent,
12
16
  },
17
+ storage: new LibSQLStore({
18
+ url: ":memory:",
19
+ }),
20
+ logger: new PinoLogger({
21
+ name: 'Mastra',
22
+ level: 'info',
23
+ }),
13
24
  });
14
25
  ```
15
26
 
16
- This creates a new Mastra instance that includes your financial agent, making it available to the playground and any other parts of your application.
27
+ This creates a new Mastra instance that includes:
28
+ - Your financial agent
29
+ - In-memory storage for development
30
+ - A logger for debugging and monitoring
17
31
 
18
- The Mastra class is the main entry point for your Mastra project. It's responsible for registering your agents and making them available to the rest of your application. By adding your agent to the Mastra instance, you're telling Mastra that this agent should be available for use.
32
+ The Mastra class is the main entry point for your Mastra project. It's responsible for registering your agents and configuring the core services like storage and logging.
@@ -1,11 +1,13 @@
1
1
  # Creating the getTransactions Tool
2
2
 
3
- Let's create a tool that fetches transaction data from a Google Sheet. We'll add this to your `tools/index.ts` file.
3
+ Let's create a tool that fetches transaction data from a Google Sheet. We'll create a new file called `tools/get-transactions-tool.ts`.
4
4
 
5
- First, make sure you have the necessary imports:
5
+ First, create the new tool file at src/mastra/tools/get-transactions-tool.ts
6
+
7
+ Now add the necessary imports:
6
8
 
7
9
  ```typescript
8
- import { createTool } from "@mastra/core";
10
+ import { createTool } from "@mastra/core/tools";
9
11
  import { z } from "zod";
10
12
  ```
11
13
 
@@ -1,11 +1,11 @@
1
1
  # Connecting the Tool to Your Agent
2
2
 
3
- Now that we've created our tool, we need to connect it to our agent. Go back to your `agents/index.ts` file and update it:
3
+ Now that we've created our tool, we need to connect it to our agent. Go back to your `agents/financial-agent.ts` file and update it:
4
4
 
5
5
  1. Import the tool:
6
6
 
7
7
  ```typescript
8
- import { getTransactionsTool } from "../tools";
8
+ import { getTransactionsTool } from "../tools/get-transactions-tool";
9
9
  ```
10
10
 
11
11
  2. Add the tool to your agent:
@@ -0,0 +1,44 @@
1
+ # Introduction to Workflows
2
+
3
+ Welcome to the fourth lesson of the Mastra course! In this lesson, you'll learn about Mastra Workflows - a powerful way to orchestrate complex sequences of operations.
4
+
5
+ ## What are Workflows?
6
+
7
+ Workflows in Mastra let you chain together multiple operations in a predictable, type-safe manner. Think of them as a recipe that breaks down complex tasks into smaller, manageable steps.
8
+
9
+ Instead of writing one big function that does everything, workflows let you:
10
+
11
+ - Break complex operations into smaller, reusable steps
12
+ - Define clear inputs and outputs for each step
13
+ - Chain steps together with automatic data validation
14
+ - Handle errors gracefully at each step
15
+
16
+ ## Simple Example
17
+
18
+ Without workflows, you might write:
19
+
20
+ ```typescript
21
+ async function processContent(text: string) {
22
+ // All logic in one function - hard to test and reuse
23
+ const validated = validateText(text);
24
+ const enhanced = enhanceText(validated);
25
+ const summarized = summarizeText(enhanced);
26
+ return summarized;
27
+ }
28
+ ```
29
+
30
+ With workflows, the same logic becomes modular and reusable with tracing built in at every step.
31
+
32
+ ```typescript
33
+ export const contentWorkflow = createWorkflow({...})
34
+ .then(validateStep)
35
+ .then(enhanceStep)
36
+ .then(summarizeStep)
37
+ .commit();
38
+ ```
39
+
40
+ ## What You'll Build
41
+
42
+ In this lesson, you'll create a content processing workflow that validates, enhances, and summarizes text content using multiple connected steps.
43
+
44
+ Let's start by understanding the basic building blocks!
@@ -0,0 +1,53 @@
1
+ # Understanding Steps
2
+
3
+ Steps are the building blocks of workflows. Each step is a self-contained unit that takes some input, processes it, and produces an output.
4
+
5
+ ## What is a Step?
6
+
7
+ A step has three main parts:
8
+
9
+ 1. **Input Schema** - what data it expects to receive
10
+ 2. **Output Schema** - what data it will produce
11
+ 3. **Execute Function** - the logic that transforms input to output
12
+
13
+ ## Step Structure
14
+
15
+ Every step follows this pattern:
16
+
17
+ ```typescript
18
+ const myStep = createStep({
19
+ id: "unique-step-name",
20
+ description: "What this step does",
21
+ inputSchema: z.object({
22
+ // Define expected input structure
23
+ }),
24
+ outputSchema: z.object({
25
+ // Define output structure
26
+ }),
27
+ execute: async ({ inputData }) => {
28
+ // Your logic here
29
+ return {
30
+ // Return data matching output schema
31
+ };
32
+ },
33
+ });
34
+ ```
35
+
36
+ ## Why Use Schemas?
37
+
38
+ Schemas provide several benefits:
39
+
40
+ - **Type Safety**: TypeScript knows exactly what data flows between steps
41
+ - **Runtime Validation**: Invalid data is caught immediately with helpful error messages
42
+ - **Documentation**: Schemas serve as living documentation of your workflow
43
+ - **Debugging**: Clear contracts make it easy to identify issues
44
+
45
+ ## Key Benefits
46
+
47
+ - **Reusable**: Steps can be used in multiple workflows
48
+ - **Testable**: Each step can be tested in isolation
49
+ - **Composable**: Steps can be combined in different ways
50
+ - **Reliable**: Schemas catch data flow issues early
51
+ - **Traceable**: Every step is traced so you can see the flow of data
52
+
53
+ Next, you'll create your first step!
@@ -0,0 +1,57 @@
1
+ # Creating Your First Step
2
+
3
+ Let's create your first workflow step! We'll build a step that validates text content.
4
+
5
+ ## Setting Up
6
+
7
+ First, create a new file for your workflow in the `src/mastra/workflows` directory. Let's name this file `content-workflow.ts`
8
+
9
+ ## Creating a Validation Step
10
+
11
+ Add this code to your workflow file:
12
+
13
+ ```typescript
14
+ import { createStep } from "@mastra/core/workflows";
15
+ import { z } from "zod";
16
+
17
+ const validateContentStep = createStep({
18
+ id: "validate-content",
19
+ description: "Validates incoming text content",
20
+ inputSchema: z.object({
21
+ content: z.string().min(1, "Content cannot be empty"),
22
+ type: z.enum(["article", "blog", "social"]).default("article"),
23
+ }),
24
+ outputSchema: z.object({
25
+ content: z.string(),
26
+ type: z.string(),
27
+ wordCount: z.number(),
28
+ isValid: z.boolean(),
29
+ }),
30
+ execute: async ({ inputData }) => {
31
+ const { content, type } = inputData;
32
+
33
+ const wordCount = content.trim().split(/\s+/).length;
34
+ const isValid = wordCount >= 5; // Minimum 5 words
35
+
36
+ if (!isValid) {
37
+ throw new Error(`Content too short: ${wordCount} words`);
38
+ }
39
+
40
+ return {
41
+ content: content.trim(),
42
+ type,
43
+ wordCount,
44
+ isValid,
45
+ };
46
+ },
47
+ });
48
+ ```
49
+
50
+ ## Understanding the Code
51
+
52
+ - **ID**: Unique identifier for this step
53
+ - **Input Schema**: Expects `content` (string) and optional `type`
54
+ - **Output Schema**: Returns content, type, word count, and validation status
55
+ - **Execute**: Contains the validation logic
56
+
57
+ Your first step is ready! Next, you'll test it to make sure it works correctly.
@@ -0,0 +1,58 @@
1
+ # Creating a Second Step
2
+
3
+ Now let's create a second step that enhances the validated content with metadata.
4
+
5
+ ## The Enhancement Step
6
+
7
+ Add this step to your workflow file:
8
+
9
+ ```typescript
10
+ const enhanceContentStep = createStep({
11
+ id: "enhance-content",
12
+ description: "Adds metadata to validated content",
13
+ inputSchema: z.object({
14
+ content: z.string(),
15
+ type: z.string(),
16
+ wordCount: z.number(),
17
+ isValid: z.boolean(),
18
+ }),
19
+ outputSchema: z.object({
20
+ content: z.string(),
21
+ type: z.string(),
22
+ wordCount: z.number(),
23
+ metadata: z.object({
24
+ readingTime: z.number(),
25
+ difficulty: z.enum(["easy", "medium", "hard"]),
26
+ processedAt: z.string(),
27
+ }),
28
+ }),
29
+ execute: async ({ inputData }) => {
30
+ const { content, type, wordCount } = inputData;
31
+
32
+ // Calculate reading time (200 words per minute)
33
+ const readingTime = Math.ceil(wordCount / 200);
34
+
35
+ // Determine difficulty based on word count
36
+ let difficulty: "easy" | "medium" | "hard" = "easy";
37
+ if (wordCount > 100) difficulty = "medium";
38
+ if (wordCount > 300) difficulty = "hard";
39
+
40
+ return {
41
+ content,
42
+ type,
43
+ wordCount,
44
+ metadata: {
45
+ readingTime,
46
+ difficulty,
47
+ processedAt: new Date().toISOString(),
48
+ },
49
+ };
50
+ },
51
+ });
52
+ ```
53
+
54
+ ## Notice the Input Schema
55
+
56
+ The input schema of this step matches the output schema of the previous step. This is important for chaining steps together!
57
+
58
+ Your second step is ready! Next, you'll learn how to chain these steps together into a complete workflow.
@@ -0,0 +1,56 @@
1
+ # Chaining Steps Together
2
+
3
+ Now you'll learn how to chain your steps together to create a complete workflow.
4
+
5
+ ## Creating the Workflow
6
+
7
+ Add this workflow definition to your file:
8
+
9
+ ```typescript
10
+ import { createWorkflow } from "@mastra/core/workflows";
11
+
12
+ export const contentWorkflow = createWorkflow({
13
+ id: "content-processing-workflow",
14
+ description: "Validates and enhances content",
15
+ inputSchema: z.object({
16
+ content: z.string(),
17
+ type: z.enum(["article", "blog", "social"]).default("article")
18
+ }),
19
+ outputSchema: z.object({
20
+ content: z.string(),
21
+ type: z.string(),
22
+ wordCount: z.number(),
23
+ metadata: z.object({
24
+ readingTime: z.number(),
25
+ difficulty: z.enum(["easy", "medium", "hard"]),
26
+ processedAt: z.string()
27
+ })
28
+ })
29
+ })
30
+ .then(validateContentStep)
31
+ .then(enhanceContentStep)
32
+ .commit();
33
+ ```
34
+
35
+ ## Understanding the Workflow
36
+
37
+ - **Input Schema**: Defines what data the workflow expects
38
+ - **Output Schema**: Defines what the workflow will return
39
+ - **Steps**: Chained using `.then()` in the order they should execute
40
+ - **Commit**: Finalizes the workflow definition
41
+
42
+ ## How Data Flows
43
+
44
+ 1. Workflow receives input matching the input schema
45
+ 2. First step processes input and outputs validated data
46
+ 3. Second step receives the first step's output as its input
47
+ 4. Workflow returns the final step's output
48
+
49
+ ## Schema Validation
50
+
51
+ The workflow automatically validates:
52
+ - Input data matches the workflow's input schema
53
+ - Each step's output matches the next step's input schema
54
+ - Final output matches the workflow's output schema
55
+
56
+ Your workflow is now ready to run! Next, you'll test the complete workflow.