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

---

# Generate user MCP URLs

Once you have an MCP config, call `ensure_instance` to get a unique MCP URL for a specific user. Scalekit generates a URL that encodes the user's identity and authorized connections. The agent connecting to it gets exactly the tools that user is allowed to call.

## Get a per-user MCP URL

`ensure_instance` is idempotent: if an instance already exists for this user and config, Scalekit returns it. Call it on every login without side effects.

```python
inst_response = actions.mcp.ensure_instance(
    config_name=config_name,     # from cfg_response.config.name
    user_identifier="user_123",  # your app's unique user ID
)
mcp_url = inst_response.instance.url
print("MCP URL:", mcp_url)
```
**Keep the URL server-side:** The MCP URL is pre-authenticated. Treat it like a credential. Never expose it to the browser or include it in client-side code.

## Check auth state

Before handing the URL to your agent, verify that the user has authorized all connections the config requires. Call `get_instance_auth_state` with `include_auth_links=True` to retrieve auth status and authorization links for any pending connections:

```python
auth_state_response = actions.mcp.get_instance_auth_state(
    instance_id=inst_response.instance.id,
    include_auth_links=True,
)
for conn in auth_state_response.connections:
    print("Connection:", conn.connection_name)
    print("Status:    ", conn.connected_account_status)
    print("Auth link: ", conn.authentication_link)
```

Surface the auth links to the user (via your app UI, email, or a Slack message) for any connection that isn't `ACTIVE`.

## Poll until all connections are authorized

Before passing the URL to your agent, poll `get_instance_auth_state` (without `include_auth_links`) until all connections are `ACTIVE`:

```python
import time

def wait_for_auth(instance_id: str, poll_interval: int = 5):
    while True:
        state = actions.mcp.get_instance_auth_state(instance_id=instance_id)
        if all(c.connected_account_status == "ACTIVE" for c in state.connections):
            print("All connections authorized; MCP URL is ready.")
            return
        pending = [c.connection_name for c in state.connections if c.connected_account_status != "ACTIVE"]
        print(f"Waiting for: {pending}")
        time.sleep(poll_interval)

wait_for_auth(inst_response.instance.id)
```

Once all connections are `ACTIVE`, pass `mcp_url` to your agent. See [Connect an MCP client](/agentkit/mcp/connect-mcp-client/) for the next step.

---

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