diff --git a/app/en/get-started/agent-frameworks/_meta.tsx b/app/en/get-started/agent-frameworks/_meta.tsx
index 3ebbaae3a..6ececb277 100644
--- a/app/en/get-started/agent-frameworks/_meta.tsx
+++ b/app/en/get-started/agent-frameworks/_meta.tsx
@@ -23,7 +23,7 @@ export const meta: MetaRecord = {
title: "OpenAI Agents",
},
vercelai: {
- title: "Vercel AI",
+ title: "Vercel AI SDK",
},
};
diff --git a/app/en/get-started/agent-frameworks/mastra/_meta.tsx b/app/en/get-started/agent-frameworks/mastra/_meta.tsx
deleted file mode 100644
index 9c7bbf1eb..000000000
--- a/app/en/get-started/agent-frameworks/mastra/_meta.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import type { MetaRecord } from "nextra";
-
-const meta: MetaRecord = {
- "*": {
- theme: {
- breadcrumb: true,
- toc: true,
- copyPage: true,
- },
- },
- overview: {
- title: "Overview",
- },
- "use-arcade-tools": {
- title: "Using Arcade tools",
- },
- "user-auth-interrupts": {
- title: "Managing user authorization",
- },
-};
-
-export default meta;
diff --git a/app/en/get-started/agent-frameworks/mastra/overview/page.mdx b/app/en/get-started/agent-frameworks/mastra/overview/page.mdx
deleted file mode 100644
index 53dd45c2a..000000000
--- a/app/en/get-started/agent-frameworks/mastra/overview/page.mdx
+++ /dev/null
@@ -1,33 +0,0 @@
----
-title: "Integrating Arcade with Mastra"
-description: "Leverage Arcade's tool ecosystem within your Mastra applications."
----
-
-import { Callout } from "nextra/components";
-
-## Overview: Arcade Tools in Mastra
-
-[Mastra](https://mastra.ai/docs) is an open-source TypeScript agent framework that provides essential primitives for building AI applications. Integrate Arcade's extensive tool ecosystem to enhance your Mastra agents and enable them to interact seamlessly with numerous third-party services.
-
-This integration enables you to:
-
-- **Access a wide range of tools:** Use Arcade's [pre-built tools](/resources/integrations) for GitHub, Google Workspace, Slack, and more directly within your Mastra agent.
-- **Simplify tool management:** Let Arcade handle the complexities of tool discovery, execution, and authentication.
-- **Build sophisticated agents:** Combine Mastra's agent framework (including memory, workflows, and RAG) with Arcade's powerful tool capabilities.
-
-### How it Works
-
-The integration works through three key mechanisms:
-
-1. **Tool Discovery:** Access available tools through a unified API (`arcade.tools.list`).
-2. **Schema Conversion:** Transform Arcade's tool definitions into Mastra-compatible Zod schemas with the `toZodToolSet` utility, enabling seamless integration between the two frameworks without manual schema mapping.
-3. **Execution Delegation:** Seamlessly route tool calls from your Mastra agent through Arcade's API, which handles all the complexities of third-party service authentication and execution.
-
-
- Before starting, obtain an [Arcade API key](/get-started/setup/api-keys).
-
-
-### Next Steps
-
-- Learn how to [use Arcade tools](/get-started/agent-frameworks/mastra/use-arcade-tools) in a Mastra agent
-- Implement [user authentication handling](/get-started/agent-frameworks/mastra/user-auth-interrupts) for tools in multi-user applications
diff --git a/app/en/get-started/agent-frameworks/mastra/page.mdx b/app/en/get-started/agent-frameworks/mastra/page.mdx
new file mode 100644
index 000000000..0decca491
--- /dev/null
+++ b/app/en/get-started/agent-frameworks/mastra/page.mdx
@@ -0,0 +1,972 @@
+---
+title: "Build an AI Agent and Workflow with Arcade and Mastra"
+description: "Create a TypeScript agent that uses Arcade tools to access Gmail and Slack"
+---
+
+import { Steps, Tabs, Callout } from "nextra/components";
+
+[Mastra](https://mastra.ai/docs) is an open-source, TypeScript agent framework for building AI applications. It provides agents with memory, tool calling, workflows, and RAG capabilities. This guide uses **Mastra v1.x**.
+
+In this guide, you'll build an agent lets you read emails, send messages, and interact with Gmail and Slack using Arcade's MCP tools in a conversational interface with built-in authentication. You will also build a workflow that summarizes emails and sends them to Slack.
+
+
+
+
+A Mastra agent and workflow that integrates Arcade tools for Gmail and Slack.
+
+
+
+
+
+-
+- [Node.js 18+](https://nodejs.org/)
+- An [OpenAI API key](https://platform.openai.com/api-keys) (or another supported model provider)
+
+
+
+
+
+- How to retrieve Arcade tools and convert them to Mastra format
+- How to create an agent with tool calling capabilities
+- How to create a workflow with multiple steps
+- How to handle Arcade's authorization flow in your application
+- How to test your agent and workflow with Mastra Studio
+
+
+
+
+## Mastra concepts
+
+Before diving into the code, here are the key Mastra concepts you'll use:
+
+- [Mastra Studio](https://mastra.ai/docs/getting-started/studio): An interactive development environment for building and testing agents locally.
+- [Zod schemas](https://zod.dev): Mastra uses Zod for type-safe tool definitions.
+- [Memory](https://mastra.ai/docs/memory/overview): Persists conversation history across sessions using storage backends like LibSQL.
+- [Processors](https://mastra.ai/docs/memory/processors): Transform messages before they reach the LLM. This tutorial uses:
+ - `ToolCallFilter`: Removes tool calls and results from memory to prevent large API responses from bloating context.
+ - `TokenLimiterProcessor`: Limits input tokens to stay within model context limits.
+
+## Build an agent
+
+
+
+### Create a new Mastra project
+
+```bash
+npx create-mastra@latest arcade-agent
+```
+
+Select your preferred model provider when prompted (we recommend OpenAI). Enter your API key when asked.
+
+Then navigate to the project directory and install the Arcade client:
+
+
+
+
+
+```bash
+cd arcade-agent
+npm install @arcadeai/arcadejs @ai-sdk/openai zod@3
+```
+
+
+
+
+
+```bash
+cd arcade-agent
+pnpm add @arcadeai/arcadejs @ai-sdk/openai zod@3
+```
+
+
+
+
+
+```bash
+cd arcade-agent
+yarn add @arcadeai/arcadejs @ai-sdk/openai zod@3
+```
+
+
+
+
+
+
+These commands explicitly install `zod@3` because the Arcade SDK's `toZodToolSet` currently requires Zod 3.x. Zod 4 has a different internal API that isn't yet supported.
+
+
+### Set up environment variables
+
+Add your Arcade API key to **.env**:
+
+```env filename=".env"
+ARCADE_API_KEY={arcade_api_key}
+ARCADE_USER_ID={arcade_user_id}
+```
+
+The `ARCADE_USER_ID` is your app's internal identifier for the user (often the email you signed up with, a UUID, etc.). Arcade uses this to track authorizations per user.
+
+### Create the tool configuration
+
+Create **src/mastra/tools/arcade.ts** to handle Arcade tool fetching and conversion.
+
+
+ **Handling large tool outputs:** Tools like `Gmail.ListEmails` can return 200KB+ of email content. When the agent passes this data back to the LLM in the agentic loop, it may exceed token limits, resulting in rate limit errors. The code below includes output truncation to prevent this.
+
+
+```ts filename="src/mastra/tools/arcade.ts"
+import { Arcade } from "@arcadeai/arcadejs";
+import {
+ toZodToolSet,
+ executeOrAuthorizeZodTool,
+} from "@arcadeai/arcadejs/lib";
+
+const config = {
+ // Get all tools from these MCP servers
+ mcpServers: ["Slack"],
+ // Add specific individual tools
+ individualTools: ["Gmail_ListEmails", "Gmail_SendEmail", "Gmail_WhoAmI"],
+};
+
+// Maximum characters for any string field in tool output
+// Keeps responses small while preserving structure (subjects, senders, snippets)
+const MAX_STRING_CHARS = 300;
+
+/**
+ * Recursively truncates all large strings in objects/arrays.
+ * This prevents token overflow when tool results pass back to the LLM.
+ */
+function truncateDeep(obj: unknown): unknown {
+ if (obj === null || obj === undefined) return obj;
+
+ if (typeof obj === "string") {
+ if (obj.length > MAX_STRING_CHARS) {
+ return obj.slice(0, MAX_STRING_CHARS) + "...";
+ }
+ return obj;
+ }
+
+ if (Array.isArray(obj)) {
+ return obj.map(truncateDeep);
+ }
+
+ if (typeof obj === "object") {
+ const result: Record = {};
+ for (const [key, value] of Object.entries(obj as Record)) {
+ result[key] = truncateDeep(value);
+ }
+ return result;
+ }
+
+ return obj;
+}
+
+export async function getArcadeTools(userId: string) {
+ const arcade = new Arcade();
+
+ // Fetch tools from MCP servers
+ const mcpTools = await Promise.all(
+ config.mcpServers.map(async (server) => {
+ const response = await arcade.tools.list({ toolkit: server });
+ return response.items;
+ })
+ );
+
+ // Fetch individual tools
+ const individualTools = await Promise.all(
+ config.individualTools.map((toolName) => arcade.tools.get(toolName))
+ );
+
+ // Combine all tools
+ const allTools = [...mcpTools.flat(), ...individualTools];
+
+ // Convert to Zod format for Mastra compatibility
+ const zodTools = toZodToolSet({
+ tools: allTools,
+ client: arcade,
+ userId,
+ executeFactory: executeOrAuthorizeZodTool,
+ });
+
+ // Wrap tools with truncation and add 'id' property for Mastra Studio
+ type ToolType = (typeof zodTools)[string] & { id: string };
+ const mastraTools: Record = {};
+
+ for (const [toolName, tool] of Object.entries(zodTools)) {
+ const originalExecute = tool.execute;
+ mastraTools[toolName] = {
+ ...tool,
+ id: toolName,
+ execute: async (input: unknown) => {
+ const result = await originalExecute(input);
+ return truncateDeep(result) as Awaited>;
+ },
+ } as ToolType;
+ }
+
+ return mastraTools;
+}
+```
+
+#### What this code does
+
+##### Tool fetching
+
+- `mcpServers`: Fetches *all* tools from an MCP server. Use this when you want everything a service offers (for example, `"Slack"` gives you `Slack_SendMessage`, `Slack_ListChannels`, `Slack_ListUsers`, etc.)
+- `individualTools`: Fetches specific tools by name. Use this to cherry-pick only what you need (for example, `"Gmail_ListEmails"` without `Gmail_DeleteEmail` or other tools you don't want exposed)
+
+You might select your tools individually for a few reasons:
+
+* **Security** You may not want to expose all the tools a service offers, for instance `Gmail_DeleteEmail` is not necessary and could even be dangerous to expose to an agent designed to summarize emails.
+* **Cost** Each tool's schema consumes tokens. Loading all Gmail tools (~20 tools) uses more tokens than loading just the 3 you need. This matters for rate limits and cost.
+
+
+ Browse the [complete MCP server catalog](/resources/integrations) to see available servers and their tools.
+
+
+##### Arcade SDK functions
+
+- `arcade.tools.list({ toolkit })`: Fetches all tools from an MCP server
+- `arcade.tools.get(toolName)`: Fetches a single tool by its full name
+- `toZodToolSet`: Converts Arcade tools to [Zod](https://zod.dev) schemas that Mastra requires
+- `executeOrAuthorizeZodTool`: Handles tool execution and returns authorization URLs when needed
+
+### Output handling
+
+- `truncateDeep`: Recursively limits all strings to 300 characters to prevent token overflow when tool results are passed back to the LLM
+
+### Create the agent
+
+Create **src/mastra/agents/arcade.ts**:
+
+```ts filename="src/mastra/agents/arcade.ts"
+import { Agent } from "@mastra/core/agent";
+import { TokenLimiterProcessor, ToolCallFilter } from "@mastra/core/processors";
+import { Memory } from "@mastra/memory";
+import { LibSQLStore } from "@mastra/libsql";
+import { openai } from "@ai-sdk/openai";
+import { getArcadeTools } from "../tools/arcade";
+
+const userId = process.env.ARCADE_USER_ID || "default-user";
+
+// Fetch Arcade tools at startup
+const arcadeTools = await getArcadeTools(userId);
+
+// Configure memory with conversation history
+const memory = new Memory({
+ storage: new LibSQLStore({
+ id: "arcade-agent-memory",
+ url: "file:memory.db",
+ }),
+ options: {
+ lastMessages: 10,
+ },
+});
+
+export const arcadeAgent = new Agent({
+ id: "arcade-agent",
+ name: "arcadeAgent",
+ instructions: `You are a helpful assistant that can access Gmail and Slack.
+Always use the available tools to fulfill user requests.
+
+For Gmail:
+- Use Gmail_ListEmails to fetch recent emails
+- Use Gmail_SendEmail to send emails
+- Use Gmail_WhoAmI to get the user's email address
+- To find sent emails, use the query parameter with "in:sent"
+- To find received emails, use "in:inbox" or no query
+- When composing emails, use plain text (no markdown)
+
+For Slack:
+- Use Slack_SendMessage to send messages to channels or users
+- Use Slack_ListChannels to see available channels
+
+After completing any action, always confirm what you did with specific details.
+
+IMPORTANT: When a tool returns an authorization response with a URL, tell the user to visit that URL to grant access. After they authorize, they can retry their request.`,
+ model: openai("gpt-4o"),
+ tools: arcadeTools,
+ memory,
+ // Filter out tool results from memory (they can be large) and limit tokens
+ inputProcessors: [new ToolCallFilter(), new TokenLimiterProcessor({ limit: 50000 })],
+});
+```
+
+### Register the agent
+
+Replace the contents of **src/mastra/index.ts** with the following to register your agent:
+
+```ts filename="src/mastra/index.ts"
+import { Mastra } from "@mastra/core";
+import { arcadeAgent } from "./agents/arcade";
+
+export const mastra = new Mastra({
+ agents: {
+ arcadeAgent,
+ },
+});
+```
+
+### Test with Mastra Studio
+
+Start the development server:
+
+
+
+
+
+```bash
+npm run dev
+```
+
+
+
+
+
+```bash
+pnpm dev
+```
+
+
+
+
+
+```bash
+yarn dev
+```
+
+
+
+
+
+Open [http://localhost:4111](http://localhost:4111) to access Mastra Studio. Select **arcadeAgent** from the list and try prompts like:
+
+- "Summarize my last 3 emails"
+- "Send a Slack DM to myself saying hello"
+- "What's my Gmail address?"
+
+On first use, the agent will return an authorization URL. Visit the URL to connect your Gmail or Slack account, then retry your request. Arcade remembers this authorization for future requests.
+
+
+
+
+
+## Build a workflow
+
+Agents are great for open-ended conversations, but sometimes you want a **deterministic process** that runs the same way every time. Mastra workflows let you chain steps together, with each step's output feeding into the next.
+
+This workflow does the following:
+1. Fetches emails from Gmail
+2. Summarizes them with an LLM
+3. Sends the digest as a direct message to the user on Slack
+
+This also demonstrates how workflows:
+* handle **large data** the full email content stays internal to the workflow, and only the compact summary gets sent to Slack.
+* handle **authorization errors**
+* **pass auth URLs** through multiple workflow steps
+
+
+
+### Create the workflow
+
+Create **src/mastra/workflows/email-digest.ts**:
+
+```ts filename="src/mastra/workflows/email-digest.ts"
+import { createStep, createWorkflow } from "@mastra/core/workflows";
+import { z } from "zod";
+import { Arcade } from "@arcadeai/arcadejs";
+
+const defaultUserId = process.env.ARCADE_USER_ID || "default-user";
+
+// Step 1: Fetch emails from Gmail
+const fetchEmails = createStep({
+ id: "fetch-emails",
+ inputSchema: z.object({
+ userId: z.string().optional(),
+ maxEmails: z.number().optional(),
+ }),
+ outputSchema: z.object({
+ emails: z.array(z.object({
+ subject: z.string(),
+ from: z.string(),
+ snippet: z.string(),
+ })),
+ userId: z.string(),
+ authRequired: z.boolean().optional(),
+ authUrl: z.string().optional(),
+ }),
+ execute: async ({ inputData }) => {
+ const arcade = new Arcade();
+ const userId = inputData?.userId || defaultUserId;
+
+ try {
+ const result = await arcade.tools.execute({
+ tool_name: "Gmail_ListEmails",
+ user_id: userId,
+ input: { n_emails: inputData!.maxEmails ?? 5 },
+ });
+
+ const response = result as { output?: { value?: { emails?: any[] } } };
+ const emails = (response.output?.value?.emails || []).map((e: any) => ({
+ subject: String(e.subject || "(No subject)"),
+ from: String(e.sender || e.from || "Unknown"),
+ snippet: String(e.snippet || "").slice(0, 200),
+ }));
+
+ return { emails, userId };
+ } catch (error: any) {
+ // Handle authorization required error
+ if (error.status === 403 || error.message?.includes("authorization")) {
+ const authResponse = await arcade.auth.start({
+ user_id: userId,
+ provider: "google",
+ scopes: ["https://www.googleapis.com/auth/gmail.readonly"],
+ });
+ return {
+ emails: [],
+ userId,
+ authRequired: true,
+ authUrl: authResponse.url,
+ };
+ }
+ throw error;
+ }
+ },
+});
+
+// Step 2: Summarize with LLM
+const summarizeEmails = createStep({
+ id: "summarize-emails",
+ inputSchema: z.object({
+ emails: z.array(z.object({
+ subject: z.string(),
+ from: z.string(),
+ snippet: z.string(),
+ })),
+ userId: z.string(),
+ authRequired: z.boolean().optional(),
+ authUrl: z.string().optional(),
+ }),
+ outputSchema: z.object({
+ summary: z.string(),
+ userId: z.string(),
+ authRequired: z.boolean().optional(),
+ authUrl: z.string().optional(),
+ }),
+ execute: async ({ inputData, mastra }) => {
+ const { emails, userId, authRequired, authUrl } = inputData!;
+
+ // Pass through auth requirement
+ if (authRequired) {
+ return { summary: "", userId, authRequired, authUrl };
+ }
+
+ if (emails.length === 0) {
+ return { summary: "No new emails.", userId };
+ }
+
+ const agent = mastra?.getAgent("arcadeAgent");
+ const emailList = emails.map((e, i) =>
+ `${i + 1}. From: ${e.from}\n Subject: ${e.subject}\n Preview: ${e.snippet}`
+ ).join("\n\n");
+
+ const response = await agent!.generate(
+ `Summarize these emails in 2-3 bullet points:\n\n${emailList}`
+ );
+
+ return { summary: response.text, userId };
+ },
+});
+
+// Step 3: Send DM to Slack user
+const sendToSlack = createStep({
+ id: "send-to-slack",
+ inputSchema: z.object({
+ summary: z.string(),
+ userId: z.string(),
+ authRequired: z.boolean().optional(),
+ authUrl: z.string().optional(),
+ }),
+ outputSchema: z.object({
+ success: z.boolean(),
+ message: z.string(),
+ authUrl: z.string().optional(),
+ }),
+ execute: async ({ inputData }) => {
+ const { summary, userId, authRequired, authUrl } = inputData!;
+
+ // Return auth URL if authorization is needed
+ if (authRequired) {
+ return {
+ success: false,
+ message: `Authorization required. Please visit this URL to grant access: ${authUrl}`,
+ authUrl,
+ };
+ }
+
+ const arcade = new Arcade();
+
+ try {
+ // Get the user's Slack identity
+ const whoAmI = await arcade.tools.execute({
+ tool_name: "Slack_WhoAmI",
+ user_id: userId,
+ input: {},
+ });
+
+ const slackUserId = (whoAmI as any)?.output?.value?.user_id;
+
+ // Send DM to the user
+ await arcade.tools.execute({
+ tool_name: "Slack_SendMessage",
+ user_id: userId,
+ input: {
+ message: `📬 *Email Digest*\n\n${summary}`,
+ user_ids: [slackUserId],
+ },
+ });
+
+ return { success: true, message: "Digest sent as DM" };
+ } catch (error: any) {
+ // Handle Slack authorization required
+ if (error.status === 403 || error.message?.includes("authorization")) {
+ const slackAuth = await arcade.auth.start({
+ user_id: userId,
+ provider: "slack",
+ scopes: ["chat:write", "users:read"],
+ });
+ return {
+ success: false,
+ message: `Slack authorization required. Please visit: ${slackAuth.url}`,
+ authUrl: slackAuth.url,
+ };
+ }
+ throw error;
+ }
+ },
+});
+
+// Chain the steps together
+const emailDigestWorkflow = createWorkflow({
+ id: "email-digest",
+ inputSchema: z.object({
+ userId: z.string().default(defaultUserId),
+ maxEmails: z.number().default(5),
+ }),
+ outputSchema: z.object({
+ success: z.boolean(),
+ message: z.string(),
+ authUrl: z.string().optional(),
+ }),
+})
+ .then(fetchEmails)
+ .then(summarizeEmails)
+ .then(sendToSlack);
+
+emailDigestWorkflow.commit();
+
+export { emailDigestWorkflow };
+```
+
+### Register the workflow
+
+Update **src/mastra/index.ts**:
+
+```ts filename="src/mastra/index.ts"
+import { Mastra } from "@mastra/core";
+import { arcadeAgent } from "./agents/arcade";
+import { emailDigestWorkflow } from "./workflows/email-digest";
+
+export const mastra = new Mastra({
+ agents: {
+ arcadeAgent,
+ },
+ workflows: {
+ emailDigestWorkflow,
+ },
+});
+```
+
+### Test the workflow
+
+1. Restart the dev server and open Mastra Studio. In the sidebar, open **Workflows**. Select **email-digest**.
+2. In the right sidebar, select "run" to run the workflow.
+3. If authorization is required, the workflow returns an auth URL. Visit the URL, complete authorization, then run the workflow again.
+4. Check your Slack DMs for the digest.
+
+
+
+
+
+## Key takeaways
+
+- **Arcade tools work seamlessly with Mastra**: Use `toZodToolSet` to convert Arcade tools to the Zod schema format Mastra expects.
+- **Agent vs Workflow**: The agent handles open-ended requests ("help me with my emails"). The workflow handles repeatable processes ("every morning, summarize and send to Slack"). Use both together for powerful automation.
+- **Truncate large outputs**: Tools like Gmail can return 200KB+ of data. Wrap tool execution with truncation to prevent token overflow in the agentic loop.
+- **Authorization is automatic**: The `executeOrAuthorizeZodTool` factory handles auth flows. When a tool needs authorization, it returns a URL for the user to visit.
+- **Workflows need explicit auth handling**: Unlike agents, workflows don't have built-in auth handling. Catch 403 errors, call `arcade.auth.start()`, and pass the auth URL through your workflow steps.
+
+## Next steps
+
+- **Add more tools**: Browse the [tool catalog](/resources/integrations) and add tools for GitHub, Notion, Linear, and more.
+- **Schedule your workflow**: Use a cron job or [Mastra's scheduling](https://mastra.ai/docs/workflows/scheduling) to run your email digest every morning.
+- **Deploy to production**: Follow Mastra's [deployment guides](https://mastra.ai/docs/deployment/overview) to deploy your agent and workflows.
+
+
+ **Building a multi-user app?** This tutorial uses a single `ARCADE_USER_ID` for simplicity. For production apps where each user needs their own OAuth tokens, see [Secure auth for production](/guides/user-facing-agents/secure-auth-production) to learn how to dynamically pass user IDs and handle per-user authorization.
+
+
+## Complete code
+
+
+**src/mastra/tools/arcade.ts** (full file)
+
+```ts filename="src/mastra/tools/arcade.ts"
+import { Arcade } from "@arcadeai/arcadejs";
+import {
+ toZodToolSet,
+ executeOrAuthorizeZodTool,
+} from "@arcadeai/arcadejs/lib";
+
+const config = {
+ mcpServers: ["Slack"],
+ individualTools: ["Gmail_ListEmails", "Gmail_SendEmail", "Gmail_WhoAmI"],
+};
+
+const MAX_STRING_CHARS = 300;
+
+function truncateDeep(obj: unknown): unknown {
+ if (obj === null || obj === undefined) return obj;
+
+ if (typeof obj === "string") {
+ if (obj.length > MAX_STRING_CHARS) {
+ return obj.slice(0, MAX_STRING_CHARS) + "...";
+ }
+ return obj;
+ }
+
+ if (Array.isArray(obj)) {
+ return obj.map(truncateDeep);
+ }
+
+ if (typeof obj === "object") {
+ const result: Record = {};
+ for (const [key, value] of Object.entries(obj as Record)) {
+ result[key] = truncateDeep(value);
+ }
+ return result;
+ }
+
+ return obj;
+}
+
+export async function getArcadeTools(userId: string) {
+ const arcade = new Arcade();
+
+ const mcpTools = await Promise.all(
+ config.mcpServers.map(async (server) => {
+ const response = await arcade.tools.list({ toolkit: server });
+ return response.items;
+ })
+ );
+
+ const individualTools = await Promise.all(
+ config.individualTools.map((toolName) => arcade.tools.get(toolName))
+ );
+
+ const allTools = [...mcpTools.flat(), ...individualTools];
+
+ const zodTools = toZodToolSet({
+ tools: allTools,
+ client: arcade,
+ userId,
+ executeFactory: executeOrAuthorizeZodTool,
+ });
+
+ type ToolType = (typeof zodTools)[string] & { id: string };
+ const mastraTools: Record = {};
+
+ for (const [toolName, tool] of Object.entries(zodTools)) {
+ const originalExecute = tool.execute;
+ mastraTools[toolName] = {
+ ...tool,
+ id: toolName,
+ execute: async (input: unknown) => {
+ const result = await originalExecute(input);
+ return truncateDeep(result) as Awaited>;
+ },
+ } as ToolType;
+ }
+
+ return mastraTools;
+}
+```
+
+
+
+
+**src/mastra/agents/arcade.ts** (full file)
+
+```ts filename="src/mastra/agents/arcade.ts"
+import { Agent } from "@mastra/core/agent";
+import { TokenLimiterProcessor, ToolCallFilter } from "@mastra/core/processors";
+import { Memory } from "@mastra/memory";
+import { LibSQLStore } from "@mastra/libsql";
+import { openai } from "@ai-sdk/openai";
+import { getArcadeTools } from "../tools/arcade";
+
+const userId = process.env.ARCADE_USER_ID || "default-user";
+const arcadeTools = await getArcadeTools(userId);
+
+const memory = new Memory({
+ storage: new LibSQLStore({
+ id: "arcade-agent-memory",
+ url: "file:memory.db",
+ }),
+ options: {
+ lastMessages: 10,
+ },
+});
+
+export const arcadeAgent = new Agent({
+ id: "arcade-agent",
+ name: "arcadeAgent",
+ instructions: `You are a helpful assistant that can access Gmail and Slack.
+Always use the available tools to fulfill user requests.
+
+For Gmail:
+- Use Gmail_ListEmails to fetch recent emails
+- Use Gmail_SendEmail to send emails
+- Use Gmail_WhoAmI to get the user's email address
+- To find sent emails, use the query parameter with "in:sent"
+- To find received emails, use "in:inbox" or no query
+- When composing emails, use plain text (no markdown)
+
+For Slack:
+- Use Slack_SendMessage to send messages to channels or users
+- Use Slack_ListChannels to see available channels
+
+After completing any action, always confirm what you did with specific details.
+
+IMPORTANT: When a tool returns an authorization response with a URL, tell the user to visit that URL to grant access. After they authorize, they can retry their request.`,
+ model: openai("gpt-4o"),
+ tools: arcadeTools,
+ memory,
+ // Filter out tool results from memory (they can be large) and limit tokens
+ inputProcessors: [new ToolCallFilter(), new TokenLimiterProcessor({ limit: 50000 })],
+});
+```
+
+
+
+
+**src/mastra/index.ts** (full file)
+
+```ts filename="src/mastra/index.ts"
+import { Mastra } from "@mastra/core";
+import { arcadeAgent } from "./agents/arcade";
+import { emailDigestWorkflow } from "./workflows/email-digest";
+
+export const mastra = new Mastra({
+ agents: {
+ arcadeAgent,
+ },
+ workflows: {
+ emailDigestWorkflow,
+ },
+});
+```
+
+
+
+
+**src/mastra/workflows/email-digest.ts** (full file)
+
+```ts filename="src/mastra/workflows/email-digest.ts"
+import { createStep, createWorkflow } from "@mastra/core/workflows";
+import { z } from "zod";
+import { Arcade } from "@arcadeai/arcadejs";
+
+const defaultUserId = process.env.ARCADE_USER_ID || "default-user";
+
+const fetchEmails = createStep({
+ id: "fetch-emails",
+ inputSchema: z.object({
+ userId: z.string().optional(),
+ maxEmails: z.number().optional(),
+ }),
+ outputSchema: z.object({
+ emails: z.array(z.object({
+ subject: z.string(),
+ from: z.string(),
+ snippet: z.string(),
+ })),
+ userId: z.string(),
+ authRequired: z.boolean().optional(),
+ authUrl: z.string().optional(),
+ }),
+ execute: async ({ inputData }) => {
+ const arcade = new Arcade();
+ const userId = inputData?.userId || defaultUserId;
+
+ try {
+ const result = await arcade.tools.execute({
+ tool_name: "Gmail_ListEmails",
+ user_id: userId,
+ input: { n_emails: inputData!.maxEmails ?? 5 },
+ });
+
+ const response = result as { output?: { value?: { emails?: any[] } } };
+ const emails = (response.output?.value?.emails || []).map((e: any) => ({
+ subject: String(e.subject || "(No subject)"),
+ from: String(e.sender || e.from || "Unknown"),
+ snippet: String(e.snippet || "").slice(0, 200),
+ }));
+
+ return { emails, userId };
+ } catch (error: any) {
+ if (error.status === 403 || error.message?.includes("authorization")) {
+ const authResponse = await arcade.auth.start({
+ user_id: userId,
+ provider: "google",
+ scopes: ["https://www.googleapis.com/auth/gmail.readonly"],
+ });
+ return {
+ emails: [],
+ userId,
+ authRequired: true,
+ authUrl: authResponse.url,
+ };
+ }
+ throw error;
+ }
+ },
+});
+
+const summarizeEmails = createStep({
+ id: "summarize-emails",
+ inputSchema: z.object({
+ emails: z.array(z.object({
+ subject: z.string(),
+ from: z.string(),
+ snippet: z.string(),
+ })),
+ userId: z.string(),
+ authRequired: z.boolean().optional(),
+ authUrl: z.string().optional(),
+ }),
+ outputSchema: z.object({
+ summary: z.string(),
+ userId: z.string(),
+ authRequired: z.boolean().optional(),
+ authUrl: z.string().optional(),
+ }),
+ execute: async ({ inputData, mastra }) => {
+ const { emails, userId, authRequired, authUrl } = inputData!;
+
+ if (authRequired) {
+ return { summary: "", userId, authRequired, authUrl };
+ }
+
+ if (emails.length === 0) {
+ return { summary: "No new emails.", userId };
+ }
+
+ const agent = mastra?.getAgent("arcadeAgent");
+ const emailList = emails.map((e, i) =>
+ `${i + 1}. From: ${e.from}\n Subject: ${e.subject}\n Preview: ${e.snippet}`
+ ).join("\n\n");
+
+ const response = await agent!.generate(
+ `Summarize these emails in 2-3 bullet points:\n\n${emailList}`
+ );
+
+ return { summary: response.text, userId };
+ },
+});
+
+const sendToSlack = createStep({
+ id: "send-to-slack",
+ inputSchema: z.object({
+ summary: z.string(),
+ userId: z.string(),
+ authRequired: z.boolean().optional(),
+ authUrl: z.string().optional(),
+ }),
+ outputSchema: z.object({
+ success: z.boolean(),
+ message: z.string(),
+ authUrl: z.string().optional(),
+ }),
+ execute: async ({ inputData }) => {
+ const { summary, userId, authRequired, authUrl } = inputData!;
+
+ if (authRequired) {
+ return {
+ success: false,
+ message: `Authorization required. Please visit this URL to grant access: ${authUrl}`,
+ authUrl,
+ };
+ }
+
+ const arcade = new Arcade();
+
+ try {
+ const whoAmI = await arcade.tools.execute({
+ tool_name: "Slack_WhoAmI",
+ user_id: userId,
+ input: {},
+ });
+
+ const slackUserId = (whoAmI as any)?.output?.value?.user_id;
+
+ await arcade.tools.execute({
+ tool_name: "Slack_SendMessage",
+ user_id: userId,
+ input: {
+ message: `📬 *Email Digest*\n\n${summary}`,
+ user_ids: [slackUserId],
+ },
+ });
+
+ return { success: true, message: "Digest sent as DM" };
+ } catch (error: any) {
+ if (error.status === 403 || error.message?.includes("authorization")) {
+ const slackAuth = await arcade.auth.start({
+ user_id: userId,
+ provider: "slack",
+ scopes: ["chat:write", "users:read"],
+ });
+ return {
+ success: false,
+ message: `Slack authorization required. Please visit: ${slackAuth.url}`,
+ authUrl: slackAuth.url,
+ };
+ }
+ throw error;
+ }
+ },
+});
+
+const emailDigestWorkflow = createWorkflow({
+ id: "email-digest",
+ inputSchema: z.object({
+ userId: z.string().default(defaultUserId),
+ maxEmails: z.number().default(5),
+ }),
+ outputSchema: z.object({
+ success: z.boolean(),
+ message: z.string(),
+ authUrl: z.string().optional(),
+ }),
+})
+ .then(fetchEmails)
+ .then(summarizeEmails)
+ .then(sendToSlack);
+
+emailDigestWorkflow.commit();
+
+export { emailDigestWorkflow };
+```
+
+
diff --git a/app/en/get-started/agent-frameworks/mastra/use-arcade-tools/page.mdx b/app/en/get-started/agent-frameworks/mastra/use-arcade-tools/page.mdx
deleted file mode 100644
index ff85034af..000000000
--- a/app/en/get-started/agent-frameworks/mastra/use-arcade-tools/page.mdx
+++ /dev/null
@@ -1,161 +0,0 @@
----
-title: "Using Arcade tools with Mastra"
-description: "Integrate Arcade tools into your Mastra applications for basic use cases."
----
-
-import { Steps, Tabs, Callout } from "nextra/components";
-
-This guide shows you how to integrate and use Arcade tools within a Mastra agent. For the complete working example, check out our [GitHub repository](https://github.com/ArcadeAI/arcade-ai/tree/main/examples/mastra).
-
-
-
-### Prerequisites
-
-- [Obtain an Arcade API key](/get-started/setup/api-keys)
-- Basic familiarity with TypeScript and Mastra concepts
-
-### Create a Mastra project
-
-Start by creating a new Mastra project using the official CLI:
-
-```bash
-# Create a new Mastra project
-npx create-mastra@latest my-arcade-agent
-
-# Navigate to the project
-cd my-arcade-agent
-```
-
-For more details on setting up a Mastra project, refer to the [Mastra documentation](https://mastra.ai/docs/getting-started/installation).
-
-### Install Arcade client
-
-Install the Arcade client:
-
-
-
-
-
-```bash
-pnpm add @arcadeai/arcadejs
-```
-
-
-
-
-
-```bash
-npm install @arcadeai/arcadejs
-```
-
-
-
-
-
-```bash
-yarn install @arcadeai/arcadejs
-```
-
-
-
-
-
-### Configure API keys
-
-Set up your environment with the required API keys:
-
-```typescript
-// Set your API keys in your environment variables or .env file
-process.env.ARCADE_API_KEY = "your_arcade_api_key";
-process.env.ANTHROPIC_API_KEY = "your_anthropic_api_key"; // or another supported model provider
-```
-
-### Convert Arcade tools to Mastra tools
-
-Arcade offers methods to convert tools into Zod schemas, which is essential since Mastra defines tools using Zod. The `toZodToolSet` method is particularly useful, as it simplifies this integration and makes it easier to use Arcade's tools with Mastra. Learn more about Arcade's Zod integration options [here](/guides/tool-calling/custom-apps/get-tool-definitions#get-zod-tool-definitions).
-
-```ts
-import { Arcade } from "@arcadeai/arcadejs";
-import {
- executeOrAuthorizeZodTool,
- toZodToolSet,
-} from "@arcadeai/arcadejs/lib";
-
-// Initialize Arcade
-const arcade = new Arcade();
-
-// Get Gmail MCP Server
-// MCP Server names can be found in the Arcade dashboard via Tools > view > MCP Server or via the CLI `arcade workers list`
-const gmailToolkit = await arcade.tools.list({ toolkit: "Gmail", limit: 30 });
-
-// Get Gmail tools
-export const gmailTools = toZodToolSet({
- tools: gmailToolkit.items,
- client: arcade,
- userId: "", // Your app's internal ID for the user (an email, UUID, etc). It's used internally to identify your user in Arcade
- executeFactory: executeOrAuthorizeZodTool, // Checks if tool is authorized and executes it, or returns authorization URL if needed
-});
-
-```
-
-### Create and configure your Mastra agent
-
-Now create a Mastra agent that uses Arcade tools:
-
-```typescript
-import { Agent } from "@mastra/core/agent";
-import { anthropic } from "@ai-sdk/anthropic";
-
-// Create the Mastra agent with Arcade tools
-export const gmailAgent = new Agent({
- name: "gmailAgent",
- instructions: `You are a Gmail assistant that helps users manage their inbox.
-
-When helping users:
-- Always verify their intent before performing actions
-- Keep responses clear and concise
-- Confirm important actions before executing them
-- Respect user privacy and data security
-
-Use the gmailTools to interact with various Gmail services and perform related tasks.`,
- model: anthropic("claude-3-7-sonnet-20250219"),
- tools: gmailTools,
-});
-```
-
-### Interact with your agent
-
-You can interact with your agent in two main ways:
-
-**1. Using the Mastra Development Playground:**
-
-Start the Mastra development server:
-
-```bash
-npm run dev
-```
-
-This will launch a local development playground, typically accessible at `http://localhost:4111`. Open this URL in your browser, select the `gmailAgent` from the list of available agents, and start chatting with it directly in the UI.
-
-**2. Programmatically:**
-
-Alternatively, you can interact with the agent directly in your code:
-
-```typescript
-// Generate a response from the agent
-const response = await gmailAgent.generate(
- "Read my last email and summarize it in a few sentences",
-);
-console.log(response.text);
-
-// Or stream the response for a more interactive experience
-const stream = await gmailAgent.stream("Send an email to dev@arcade.dev with the subject 'Hello from Mastra'");
-
-for await (const chunk of stream.textStream) {
- process.stdout.write(chunk);
-}
-```
-
-
-
-When running your agent for the first time with tools that require user consent (like Google or Github), the agent will return an authorization reponse (for example, `{ authorization_required: true, url: '...', message: '...' }`). Your agent's instructions should guide it to present this URL to the user. After the user visits this URL and grants permissions, the tool can be used successfully. See the [Managing user authorization](/get-started/agent-frameworks/mastra/user-auth-interrupts) guide for more details on handling authentication flows.
diff --git a/app/en/get-started/agent-frameworks/mastra/user-auth-interrupts/page.mdx b/app/en/get-started/agent-frameworks/mastra/user-auth-interrupts/page.mdx
deleted file mode 100644
index eea1f31dc..000000000
--- a/app/en/get-started/agent-frameworks/mastra/user-auth-interrupts/page.mdx
+++ /dev/null
@@ -1,153 +0,0 @@
----
-title: "Managing user authorization"
-description: "Handle user-specific authorization for Arcade tools in Mastra applications."
----
-
-import { Callout } from "nextra/components";
-
-## Dynamic Tool Loading with Toolsets
-
-Mastra lets you dynamically provide tools to an agent at runtime using toolsets. This approach is essential when integrating Arcade tools in web applications where each user needs their own authentication flow.
-
-### Per-User Tool Authentication in Web Applications
-
-In web applications serving multiple users, implement user-specific authentication flows with these steps:
-
-First, set up your Mastra configuration and agents in separate files:
-
-```typescript
-// @/mastra/index.ts
-import { Mastra } from "@mastra/core";
-import { githubAgent } from "./agents/githubAgent";
-
-// Initialize Mastra
-export const mastra = new Mastra({
- agents: {
- githubAgent,
- },
-});
-```
-
-```typescript
-// @/mastra/agents/githubAgent.ts
-import { Agent } from "@mastra/core/agent";
-import { anthropic } from "@ai-sdk/anthropic";
-
-// Create the agent without tools - we'll add them at runtime
-export const githubAgent = new Agent({
- name: "githubAgent",
- instructions: `You are a GitHub Agent that helps with repository management.
-
- You can help with tasks like:
- - Listing repositories
- - Creating and managing issues
- - Viewing pull requests
- - Managing repository settings
-
- If a tool requires authorization, you will receive an authorization URL.
- When that happens, clearly present this URL to the user and ask them to visit it to grant permissions.`,
- model: anthropic("claude-3-7-sonnet-20250219"),
- // No tools defined here - will be provided dynamically at runtime
-});
-```
-
-Then, create an API endpoint that provides tools dynamically:
-
-```typescript
-// app/api/chat/route.ts
-import { NextRequest, NextResponse } from "next/server";
-import { mastra } from "@/mastra";
-import { Arcade } from "@arcadeai/arcadejs";
-import { getUserSession } from "@/lib/auth"; // Your authentication handling
-import { toZodToolSet } from "@arcadeai/arcadejs/lib";
-import { executeOrAuthorizeZodTool } from "@arcadeai/arcadejs/lib";
-
-export async function POST(req: NextRequest) {
- // Extract request data
- const { messages, threadId } = await req.json();
-
- // Authenticate the user
- const session = await getUserSession(req);
- if (!session) {
- return NextResponse.json({ message: "Unauthorized" }, { status: 401 });
- }
-
- try {
- // Get the agent from Mastra
- const githubAgent = mastra.getAgent("githubAgent");
-
- const arcade = new Arcade();
- const githubToolkit = await arcade.tools.list({ toolkit: "github", limit: 30 });
-
- // Fetch user-specific Arcade tools for GitHub
- const arcadeTools = toZodToolSet({
- tools: githubToolkit.items,
- client: arcade,
- userId: session.user.email,
- executeFactory: executeOrAuthorizeZodTool,
- });
-
- // Stream the response with dynamically provided tools
- const response = await githubAgent.stream(messages, {
- threadId, // Optional: For maintaining conversation context
- resourceId: session.user.id, // Optional: For associating memory with user
- toolChoice: "auto",
- toolsets: {
- arcade: arcadeTools, // Provide tools in a named toolset
- },
- });
-
- // Return streaming response
- return response.toDataStreamResponse();
- } catch (error) {
- console.error("Error processing GitHub request:", error);
- return NextResponse.json(
- { message: "Failed to process request" },
- { status: 500 },
- );
- }
-}
-```
-
-This approach provides several benefits:
-
-- Each user gets their own separate authentication flow with Arcade tools
-- A single agent instance works with multiple user-specific toolsets
-
-The toolsets parameter provides tools only for the current request without modifying the agent's base configuration. This makes it ideal for multi-user applications where each user needs their own secure OAuth flow with Arcade.
-
-## Handling Tool Authorization
-
-When a tool requires user authorization, the agent receives a response with:
-
-```typescript
-{
- authorization_required: true,
- url: "https://auth.arcade.com/...",
- message: "Forward this url to the user for authorization"
-}
-```
-
-Your agent should recognize this pattern and present the URL to the user. To create a better user experience:
-
-- Display the authorization URL as a clickable link in your UI
-- Explain which service needs authorization and why
-- Provide a way for users to retry their request after authorization
-
-## Tips for Selecting Tools
-
-- **Focus on relevance**: Choose tools that directly support your agent's specific purpose
-- **Consider performance**: Some tools may have higher latency than others
-- **Handle errors gracefully**: Implement robust error handling for third-party service failures
-- **Create clear user flows**: Design intuitive authorization experiences
-
-## Next Steps
-
-After integrating Arcade tools into your Mastra agent, you can:
-
-- Add [memory capabilities](https://mastra.ai/docs/agents/agent-memory) to maintain context between interactions
-- Implement [structured workflows](https://mastra.ai/docs/workflows/overview) for complex multi-step operations
-- Enhance your agent with [RAG capabilities](https://mastra.ai/docs/rag/overview) for domain-specific knowledge
-- Set up [logging and tracing](https://mastra.ai/docs/observability/logging) to monitor performance
-
-For more detailed information on Mastra's capabilities, visit the [Mastra documentation](https://mastra.ai/docs).
diff --git a/app/globals.css b/app/globals.css
index fa510d573..830563d51 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -97,3 +97,17 @@ nav > div:has(.nextra-search) {
.guide-overview ul ul {
margin-top: 0;
}
+
+/* Only number h3 (###) in Steps component, not smaller nested headings */
+.nextra-steps h4,
+.nextra-steps h5,
+.nextra-steps h6 {
+ counter-increment: none !important;
+}
+
+.nextra-steps h4::before,
+.nextra-steps h5::before,
+.nextra-steps h6::before {
+ content: none !important;
+ display: none !important;
+}
diff --git a/next.config.ts b/next.config.ts
index 85cc05316..224ff8afe 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -44,6 +44,24 @@ const nextConfig: NextConfig = withLlmsTxt({
"/:locale/get-started/agent-frameworks/langchain/use-arcade-with-langchain",
permanent: true,
},
+ // Mastra tutorial consolidation
+ {
+ source: "/:locale/get-started/agent-frameworks/mastra/overview",
+ destination: "/:locale/get-started/agent-frameworks/mastra",
+ permanent: true,
+ },
+ {
+ source:
+ "/:locale/get-started/agent-frameworks/mastra/use-arcade-tools",
+ destination: "/:locale/get-started/agent-frameworks/mastra",
+ permanent: true,
+ },
+ {
+ source:
+ "/:locale/get-started/agent-frameworks/mastra/user-auth-interrupts",
+ destination: "/:locale/get-started/agent-frameworks/mastra",
+ permanent: true,
+ },
// Moved from guides to get-started
{
source:
@@ -86,8 +104,7 @@ const nextConfig: NextConfig = withLlmsTxt({
},
{
source: "/:locale/home/mastra/user-auth-interrupts",
- destination:
- "/:locale/get-started/agent-frameworks/mastra/user-auth-interrupts",
+ destination: "/:locale/get-started/agent-frameworks/mastra",
permanent: true,
},
{
@@ -312,8 +329,7 @@ const nextConfig: NextConfig = withLlmsTxt({
},
{
source: "/:locale/home/mastra/use-arcade-tools",
- destination:
- "/:locale/get-started/agent-frameworks/mastra/use-arcade-tools",
+ destination: "/:locale/get-started/agent-frameworks/mastra",
permanent: true,
},
{
@@ -495,8 +511,7 @@ const nextConfig: NextConfig = withLlmsTxt({
},
{
source: "/:locale/guides/agent-frameworks/mastra/typescript",
- destination:
- "/:locale/get-started/agent-frameworks/mastra/use-arcade-tools",
+ destination: "/:locale/get-started/agent-frameworks/mastra",
permanent: true,
},
{
@@ -519,8 +534,7 @@ const nextConfig: NextConfig = withLlmsTxt({
// Old resource paths
{
source: "/:locale/resources/mastra/user-auth-interrupts",
- destination:
- "/:locale/get-started/agent-frameworks/mastra/user-auth-interrupts",
+ destination: "/:locale/get-started/agent-frameworks/mastra",
permanent: true,
},
{
diff --git a/public/images/screenshots/mastra-studio-agent-interaction.png b/public/images/screenshots/mastra-studio-agent-interaction.png
new file mode 100644
index 000000000..1984dc563
Binary files /dev/null and b/public/images/screenshots/mastra-studio-agent-interaction.png differ
diff --git a/public/images/screenshots/mastra-studio-workflow-run.png b/public/images/screenshots/mastra-studio-workflow-run.png
new file mode 100644
index 000000000..5d0d15dc9
Binary files /dev/null and b/public/images/screenshots/mastra-studio-workflow-run.png differ
diff --git a/public/llms.txt b/public/llms.txt
index e533e985c..34a4829f5 100644
--- a/public/llms.txt
+++ b/public/llms.txt
@@ -1,4 +1,4 @@
-
+
# Arcade
@@ -103,7 +103,6 @@ Arcade delivers three core capabilities: Deploy agents even your security team w
- [Connect Arcade to your LLM](https://docs.arcade.dev/en/get-started/agent-frameworks/setup-arcade-with-your-llm-python.md): This documentation page provides a step-by-step guide for integrating Arcade with a Large Language Model (LLM) using Python. It outlines the necessary prerequisites, including API keys and package installations, and teaches users how to create a harness that facilitates communication between the
- [Connect to MCP Clients](https://docs.arcade.dev/en/get-started/mcp-clients.md): This documentation page provides guidance on connecting MCP servers to various MCP-compatible clients and development environments, enabling users to enhance their agent workflows.
- [Contact Us](https://docs.arcade.dev/en/resources/contact-us.md): This documentation page provides users with information on how to connect with the Arcade team for support through various channels. It aims to facilitate communication and assistance for users and their agents.
-- [Create a new Mastra project](https://docs.arcade.dev/en/get-started/agent-frameworks/mastra/use-arcade-tools.md): This documentation page provides a comprehensive guide for users to create a new Mastra project and integrate Arcade tools into their applications. It covers prerequisites, project setup, installation of the Arcade client, configuration of API keys, and interaction methods with the Mastra agent
- [Create an evaluation suite](https://docs.arcade.dev/en/guides/create-tools/evaluate-tools/create-evaluation-suite.md): This documentation page provides a comprehensive guide on creating an evaluation suite to test AI models' tool usage through Arcade. Users will learn how to set up prerequisites, define evaluation files and suites, run evaluations, and interpret results, ensuring accurate tool selection and parameter
- [Create an MCP tool with secrets](https://docs.arcade.dev/en/guides/create-tools/tool-basics/create-tool-secrets.md): This documentation page guides users on how to create custom MCP tools that securely handle sensitive information, or "secrets," using the Arcade platform. It covers the process of reading secrets from various sources, such as environment variables and the Arcade Dashboard, and provides
- [Create via Dashboard](https://docs.arcade.dev/en/guides/mcp-gateways/create-via-dashboard.md): This documentation page guides users through the process of creating and configuring MCP Gateways using the Arcade dashboard, providing detailed instructions on selecting tools, setting authentication modes, and customizing gateway settings. It also outlines prerequisites for creating a gateway and offers post-creation steps
@@ -193,10 +192,9 @@ Arcade delivers three core capabilities: Deploy agents even your security team w
- [OutlookMail Reference](https://docs.arcade.dev/en/resources/integrations/productivity/outlook-mail/reference.md): The OutlookMail Reference documentation provides a comprehensive list of enumerations, folder names, email filter properties, and filter operators used in the OutlookMail MCP Server. It helps users understand and utilize these elements effectively when working with OutlookMail tools. This reference is
- [page](https://docs.arcade.dev/en/resources/examples.md): This documentation page showcases a collection of example applications that utilize Arcade's tools and MCP servers, providing users with practical implementations and templates for various workflows and agent functionalities. Users can explore detailed descriptions and links to GitHub repositories for each app, enabling them to
- [page](https://docs.arcade.dev/en/resources/integrations.md): This documentation page provides a comprehensive registry of all MCP Servers within the Arcade ecosystem, helping users to easily identify and access the available servers.
+- [page](https://docs.arcade.dev/en/get-started/agent-frameworks/mastra.md): This documentation page guides users in building a TypeScript AI agent and workflow using the Mastra framework and Arcade tools to interact with Gmail and Slack. Users will learn how to create an agent capable of reading emails, sending messages, and summarizing content,
- [page](https://docs.arcade.dev/en/get-started/agent-frameworks/crewai/use-arcade-tools.md): This documentation page provides a comprehensive guide on integrating Arcade tools into CrewAI applications, detailing the necessary prerequisites, setup, and configuration steps. Users will learn how to manage tool authorization and effectively utilize these tools within their CrewAI agent teams. Additionally, it
- [page](https://docs.arcade.dev/en/get-started/agent-frameworks/langchain/auth-langchain-tools.md): This documentation page provides a step-by-step guide on how to authorize existing LangChain tools, such as the `GmailToolkit`, using the Arcade platform. It outlines the prerequisites, installation of necessary packages, and detailed instructions for the authorization process in both
-- [page](https://docs.arcade.dev/en/get-started/agent-frameworks/mastra/overview.md): This documentation page provides guidance on integrating Arcade's tool ecosystem with Mastra applications, enabling users to enhance their Mastra agents with access to a variety of pre-built tools and simplified tool management. It outlines the key mechanisms for integration, including tool discovery,
-- [page](https://docs.arcade.dev/en/get-started/agent-frameworks/mastra/user-auth-interrupts.md): This documentation page provides guidance on managing user-specific authorization for Arcade tools within Mastra applications, focusing on dynamic tool loading and per-user authentication flows. It outlines the necessary steps to configure agents, create API endpoints, and handle tool authorization effectively, ensuring a
- [page](https://docs.arcade.dev/en/resources/integrations/productivity/dropbox/reference.md): This documentation page defines the various item categories used in Dropbox, including types such as image, document, PDF, spreadsheet, presentation, audio, video, folder, and paper. It helps users understand the classification of files within the Dropbox system.
- [PagerDuty](https://docs.arcade.dev/en/resources/integrations/customer-support/pagerduty.md): This documentation page provides guidance on using the PagerDuty MCP Server, which enables agents to access and manage incidents, on-call information, services, and teams through read-only API tools. It includes details on OAuth configuration, available tools with descriptions, and code
- [PagerdutyApi](https://docs.arcade.dev/en/resources/integrations/development/pagerduty-api.md): The PagerDutyApi documentation provides a comprehensive overview of tools that enable users to manage incidents, services, and integrations within the PagerDuty platform using the API. It outlines various functionalities, such as assigning tags, retrieving metrics, and managing add-ons, allowing