> **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.
> Features: full-stack-auth, agent-auth, mcp-auth, modular-sso, modular-scim.
> [Full setup guide](https://docs.scalekit.com/dev-kit/build-with-ai/)

---

# CrewAI

Build a CrewAI agent with Scalekit-authenticated Gmail tools via MCP. CrewAI's MCPServerAdapter connects to a Scalekit MCP URL for automatic tool discovery.
Build a CrewAI agent that reads a user's Gmail inbox. Scalekit handles OAuth, token storage, and exposes tools over MCP. CrewAI's `MCPServerAdapter` discovers the tools automatically — no manual schema conversion needed.

Full code on GitHub

## Install

```sh
pip install crewai crewai-tools scalekit-sdk-python python-dotenv
```

## Initialize

```python

from scalekit import ScalekitClient
from dotenv import find_dotenv, load_dotenv

load_dotenv(find_dotenv())

scalekit_client = ScalekitClient(
    env_url=os.environ["SCALEKIT_ENV_URL"],
    client_id=os.environ["SCALEKIT_CLIENT_ID"],
    client_secret=os.environ["SCALEKIT_CLIENT_SECRET"],
)
actions = scalekit_client.actions
```

## Connect the user to Gmail

```python
response = actions.get_or_create_connected_account(
    connection_name="gmail",
    identifier="user_123",
)
if response.connected_account.status != "ACTIVE":
    link = actions.get_authorization_link(connection_name="gmail", identifier="user_123")
    print("Authorize Gmail:", link.link)
    input("Press Enter after authorizing...")
```

See [Authorize a user](/agentkit/tools/authorize/) for production auth handling.

## Build and run the agent

Get the Virtual MCP Server URL and mint a session token, then pass both to `MCPServerAdapter`. CrewAI discovers all available Gmail tools from the MCP server:

```python
from crewai import Agent, Crew, LLM, Task
from crewai_tools import MCPServerAdapter
from datetime import timedelta

# Retrieve config_id by listing Virtual MCP Servers filtered by name
list_response = actions.mcp.list_configs(filter_name="gmail-user-tools")
mcp_server_url = list_response.configs[0].mcp_server_url
mcp_id = list_response.configs[0].id

token_response = actions.mcp.create_session_token(
    mcp_config_id=mcp_id,
    identifier="user_123",
    expiry=timedelta(hours=1),
)

with MCPServerAdapter({
    "url": mcp_server_url,
    "headers": {"Authorization": f"Bearer {token_response.token}"},
    "transport": "streamable-http",
}) as tools:
    agent = Agent(
        role="Email Assistant",
        goal="Fetch and summarize the user's unread emails",
        backstory="You are a helpful assistant with access to the user's Gmail inbox.",
        tools=tools,
        llm=LLM(
            model=os.getenv("LLM_MODEL", "gpt-4o"),
            base_url=os.getenv("OPENAI_BASE_URL"),
            api_key=os.getenv("OPENAI_API_KEY"),
        ),
        verbose=True,
    )

    task = Task(
        description="Fetch the last 5 unread emails and provide a brief summary of each.",
        expected_output="A list of 5 unread emails with subject, sender, and a one-sentence summary.",
        agent=agent,
    )

    result = Crew(agents=[agent], tasks=[task]).kickoff()
    print(result)
```

> note: Nullable schema fields
>
> Some Scalekit tool schemas include nullable types (`{"type": ["string", "null"]}`) that CrewAI's schema converter doesn't handle out of the box. If you see a `TypeError` during tool parsing, apply the [schema patch](https://github.com/scalekit-developers/crewai-scalekit-example/blob/main/agent.py#L28-L43) at the top of your script.

## Multi-agent crew

CrewAI's real strength is multi-agent orchestration. For a full example that splits email triage across three specialized agents (scanner, prioritizer, drafter), see the [CrewAI email triage cookbook](/cookbooks/crewai-agentkit-email-triage/).

## Get the MCP server URL

The code above reads `mcp_server_url` from a Virtual MCP Server config. Create a config in the Scalekit Dashboard under **AgentKit → MCP Configs**. See [Virtual MCP Servers](/agentkit/mcp/overview/) for setup details.


---

## 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 |
