> **Building with AI coding agents?** If you're using an AI coding agent, install the official Scalekit plugin. It gives your agent full awareness of the Scalekit API — reducing hallucinations and enabling faster, more accurate code generation.
>
> - **Claude Code**: `/plugin marketplace add scalekit-inc/claude-code-authstack` then `/plugin install <auth-type>@scalekit-auth-stack`
> - **GitHub Copilot CLI**: `copilot plugin marketplace add scalekit-inc/github-copilot-authstack` then `copilot plugin install <auth-type>@scalekit-auth-stack`
> - **Codex**: run the bash installer, restart, then open Plugin Directory and enable `<auth-type>`
> - **Skills CLI** (Windsurf, Cline, 40+ agents): `npx skills add scalekit-inc/skills --list` then `--skill <skill-name>`
>
> `<auth-type>` / `<skill-name>`: `agent-auth`, `full-stack-auth`, `mcp-auth`, `modular-sso`, `modular-scim` — [Full setup guide](https://docs.scalekit.com/dev-kit/build-with-ai/)

---

# Give your agent tool access via MCP

When your agent needs to act on behalf of a user — reading their email, creating calendar events — each user must authenticate to each service separately. Managing those credentials in your agent adds complexity and security risk.

Scalekit solves this with per-user MCP servers. You define which tools and connections a server exposes, and Scalekit gives you a unique, pre-authenticated URL for each user. Hand that URL to your agent — it calls tools through MCP, Scalekit handles the auth. MCP servers only support Streamable HTTP transport.
**Testing only — not for production:** This feature is in beta and intended for testing purposes only. Do not use it in production environments.

## How it works

Two objects are central to this model:

| Object | What it is | Created |
|---|---|---|
| **MCP config** | A reusable template that defines which connections and tools are exposed | Once, by your app |
| **MCP instance** | A per-user instantiation of a config, with its own URL | Once per user |

Your app creates a config once, then calls `ensure_instance` whenever a new user needs access. Scalekit generates a unique URL for that user. When the agent calls tools through that URL, Scalekit routes each call using the user's pre-authorized credentials.

![Architecture diagram showing how Scalekit MCP works: app creates a config, Scalekit creates per-user instances with unique URLs, users authorize OAuth connections, and the agent connects via MCP URL](@/assets/docs/agent-auth/mcp/mcp-tool-access-architecture.png)

## Prerequisites

Before you start, make sure you have:

- **Scalekit API credentials** — Go to **Dashboard → Settings** and copy your `environment_url`, `client_id` and `client_secret`
- **Gmail and Google Calendar connections configured in Scalekit:**
  - **Gmail**: **Dashboard → Connections** (Agent Auth) → Create Connection → Gmail → set `Connection Name = MY_GMAIL` → Save
  - **Google Calendar**: **Dashboard → Connections** (Agent Auth) → Create Connection → Google Calendar → set `Connection Name = MY_CALENDAR` → Save

1. ## Install the SDK and initialize the client

   Install the Scalekit Python SDK:

   <p>
     ```sh showLineNumbers=false frame="none"
     pip install scalekit-sdk-python python-dotenv>=1.0.1
     ```
   </p>

   Initialize the client using your environment credentials:

   <p>
     ```python showLineNumbers=false frame="none"
     import os
     import scalekit.client
     from scalekit.actions.models.mcp_config import McpConfigConnectionToolMapping

     scalekit_client = scalekit.client.ScalekitClient(
         client_id=os.getenv("SCALEKIT_CLIENT_ID"),
         client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"),
         env_url=os.getenv("SCALEKIT_ENV_URL"),
     )
     my_mcp = scalekit_client.actions.mcp
     ```
   </p>

2. ## Create an MCP config

   An MCP config is a reusable template. It declares which connections and tools your server exposes. Create it once — not once per user.

   <p>
     ```python showLineNumbers=false frame="none"
     cfg_response = my_mcp.create_config(
         name="reminder-manager",
         description="Summarizes latest email and creates a reminder event",
         connection_tool_mappings=[
             McpConfigConnectionToolMapping(
                 connection_name="MY_GMAIL",
                 tools=["gmail_fetch_mails"],
             ),
             McpConfigConnectionToolMapping(
                 connection_name="MY_CALENDAR",
                 tools=["googlecalendar_create_event"],
             ),
         ],
     )
     config_name = cfg_response.config.name
     ```
   </p>

3. ## Get a per-user MCP URL

   Call `ensure_instance` to get a unique MCP URL for a specific user. If an instance already exists for that user, Scalekit returns it — so it's safe to call on every login.

   <p>
     ```python showLineNumbers=false frame="none"
     inst_response = my_mcp.ensure_instance(
         config_name=config_name,
         user_identifier="john-doe",
     )
     mcp_url = inst_response.instance.url
     print("MCP URL:", mcp_url)
     ```
   </p>

   Before the agent can use this URL, the user must authorize each connection. Retrieve the auth links and surface them to the user:

   <p>
     ```python showLineNumbers=false frame="none"
     auth_state_response = my_mcp.get_instance_auth_state(
         instance_id=inst_response.instance.id,
         include_auth_links=True,
     )
     for conn in getattr(auth_state_response, "connections", []):
         print("Connection:", conn.connection_name,
               "| Status:", conn.connected_account_status,
               "| Auth link:", conn.authentication_link)
     ```
   </p>
**Complete authentication:** Open the printed links in your browser and complete authentication for each connection.

     In production, surface these links to users via your app UI, email, or a Slack message. Poll `get_instance_auth_state` (without `include_auth_links`) to check when a user has completed authorization before passing the URL to your agent.

   At this point you have a per-user MCP URL. You can pass it to any spec-compliant MCP client — MCP Inspector, Claude Desktop, or an agent framework. The next step shows an example using LangChain.

4. ## Connect an agent (LangChain example)

   Install the LangChain dependencies:

   <p>
     ```sh showLineNumbers=false frame="none"
     pip install langgraph>=0.6.5 langchain-mcp-adapters>=0.1.9 openai>=1.53.0
     ```
   </p>

   Set your OpenAI API key:

   <p>
     ```sh showLineNumbers=false frame="none"
     export OPENAI_API_KEY=your-openai-api-key
     ```
   </p>

   Pass the MCP URL to a LangChain agent. The agent discovers available tools automatically — no additional auth configuration required:

   <p>
     ```python showLineNumbers=false frame="none"
     import asyncio
     from langgraph.prebuilt import create_react_agent
     from langchain_mcp_adapters.client import MultiServerMCPClient

     async def run_agent(mcp_url: str):
         client = MultiServerMCPClient(
             {
                 "reminder_demo": {
                     "transport": "streamable_http",
                     "url": mcp_url,
                 },
             }
         )
         tools = await client.get_tools()
         agent = create_react_agent("openai:gpt-4.1", tools)
         response = await agent.ainvoke({
             "messages": "Get my latest email and create a calendar reminder in the next 15 minutes."
         })
         print(response)

     asyncio.run(run_agent(mcp_url))
     ```
   </p>
**MCP client compatibility:** This MCP server works with MCP Inspector, Claude Desktop, and any spec-compliant MCP client. ChatGPT's beta connector may not work correctly — it is still in beta and does not fully implement the MCP specification.
Full working code for all steps above is on <a href="https://github.com/scalekit-inc/python-connect-demos/tree/main/mcp" target="_blank" rel="noopener">GitHub</a>.

## Next steps

[LangChain integration](/agent-auth/frameworks/langchain)
  [Google ADK integration](/agent-auth/frameworks/google-adk)
  [Manage connections](/agent-auth/connections)

---

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