> **Building with AI coding agents?** Install the authstack plugin with one command. This equips your agent with accurate Scalekit implementation patterns.
>
> **Recommended**:
> ```bash
> npx @scalekit-inc/cli setup
> ```
>
> Global:
> ```bash
> npm install -g @scalekit-inc/cli
> scalekit setup
> ```
>
> Supports Claude Code, Cursor, GitHub Copilot, Codex + skills for 40+ agents.
> Skills: integrate-agentkit, implement-saaskit, add-mcp-oauth, implement-sso, implement-scim.
> [Full setup guide](https://docs.scalekit.com/dev-kit/build-with-ai/)

---

# Mastra

Connect a Mastra agent to Scalekit tools using MCP. Mastra's MCP client connects to a Virtual MCP Server URL with a session token.
Connect a Mastra agent to Scalekit tools using MCP. Mastra has native MCP support via `@mastra/mcp`. Pass a Scalekit Virtual MCP Server URL and a session token, and Mastra handles tool discovery automatically.

> note: Why MCP for Mastra
>
> Mastra's tool system uses Zod schemas internally. The MCP path skips manual schema conversion. Mastra discovers tools and their schemas directly from the Scalekit MCP server.

## Install

```sh
npm install @scalekit-sdk/node @mastra/core @mastra/mcp @ai-sdk/openai
```

## Create the Virtual MCP server

Create the server once per agent role, not once per user. The response includes a static `mcp_server_url` that every user and every session reuses.

```python
# Backend (Python): run once, then save the values
from scalekit.actions.models.mcp_config import McpConfigConnectionToolMapping

vmcp_response = scalekit_client.actions.mcp.create_config(
    name="gmail-user-tools",
    connection_tool_mappings=[
        McpConfigConnectionToolMapping(
            connection_name="gmail",
            tools=["gmail_fetch_mails"],
        ),
    ],
)

config_id = vmcp_response.config.id
mcp_server_url = vmcp_response.config.mcp_server_url
```

See [Set up and connect a Virtual MCP server](/agentkit/mcp/configure-mcp-server/) for the full setup, including how to choose which tools to expose.

## Mint a session token for the user

The server URL is static. The **session token** carries the user identity. Mint a fresh token before each agent run and pass it to your Mastra app.

```python
# Backend (Python): run before each agent session
from datetime import timedelta

from scalekit.common.exceptions import (
    ScalekitNotFoundException,
    ScalekitUnauthorizedException,
    ScalekitServerException,
)

try:
    list_response = scalekit_client.actions.mcp.list_configs(filter_name="gmail-user-tools")
    mcp_server_url = list_response.configs[0].mcp_server_url
    config_id = list_response.configs[0].id

    token_response = scalekit_client.actions.mcp.create_session_token(
        mcp_config_id=config_id,
        identifier="user_123",
        expiry=timedelta(hours=1),
    )
    # Return mcp_server_url and token_response.token to the Mastra app for this user only
except ScalekitNotFoundException:
    # The server was deleted or renamed — recreate it, then retry
    raise
except ScalekitUnauthorizedException:
    # Scalekit client credentials are wrong or expired — fix the environment variables
    raise
except ScalekitServerException as e:
    # Unexpected platform error — do not start the agent without a token
    print(e.error_code, e.http_status)
    raise
```

Do not start the agent when minting fails. An agent that runs without a token calls every tool and gets a `401`. See [Error handling](/agentkit/sdks/python/errors/) for the full exception list.

Set `expiry` longer than the expected agent run. `create_session_token` also mints replacements. Call it again whenever you need a new token.

> caution: Do not share one session token across users
>
> The `mcp_server_url` is safe to share, because every user gets the same URL. The session token is different. Each token is scoped to one identifier, and any request carrying that token runs as that user. Mint a token per user on the server, and never put a token in client-side code.

## Build the agent

Pass the static server URL to `MCPClient`, and the user's session token as a bearer header in `requestInit`. Mastra fetches the tool list and schemas automatically:

```typescript

// From your backend for the authenticated user — not a shared process-wide secret
const { mcpServerUrl, mcpToken } = await getMcpSessionForUser(currentUserId);

const mcp = new MCPClient({
  servers: {
    scalekit: {
      url: new URL(mcpServerUrl),
      requestInit: {
        headers: { Authorization: `Bearer ${mcpToken}` },
      },
    },
  },
});

const tools = await mcp.getTools();

const agent = new Agent({
  name: 'gmail_assistant',
  instructions: 'You are a helpful Gmail assistant.',
  model: openai('gpt-4o'),
  tools,
});

const result = await agent.generate('Fetch my last 5 unread emails and summarize them');
console.log(result.text);

await mcp.disconnect();
```


---

## More Scalekit documentation

| Resource | What it contains | When to use it |
|----------|-----------------|----------------|
| [/llms.txt](/llms.txt) | Structured index with routing hints per product area | Start here — find which documentation set covers your topic before loading full content |
| [/llms-full.txt](/llms-full.txt) | Complete documentation for all Scalekit products in one file | Use when you need exhaustive context across multiple products or when the topic spans several areas |
| [sitemap-0.xml](https://docs.scalekit.com/sitemap-0.xml) | Full URL list of every documentation page | Use to discover specific page URLs you can fetch for targeted, page-level answers |
