> ## Documentation Index
> Fetch the complete documentation index at: https://bundleup.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# AI Agent Quickstart

> Let an AI agent act in a user’s connected account through MCP, without the agent ever seeing a token.

In this guide, a model answers “What issues are assigned to me?” using the user’s own **Linear** account. The model calls Linear’s MCP tools through `mcp.bundleup.io`. BundleUp attaches the user’s token, so neither the model nor your code handles it.

```mermaid theme={null}
sequenceDiagram
    participant App as Your backend
    participant LLM as Model provider<br/>(OpenAI / Anthropic)
    participant BM as BundleUp MCP
    participant L as Linear MCP server

    App->>LLM: Prompt + MCP server: mcp.bundleup.io, token: API key.connection ID
    LLM->>BM: tools/list, tools/call
    BM->>BM: Check key, connection, rate limit, token
    BM->>L: Same message, with the user's Linear token
    L-->>BM: Tool results
    BM-->>LLM: Tool results, unchanged
    LLM-->>App: Final answer
```

Your backend tells the model provider to use `mcp.bundleup.io` as an MCP server, with your API key and the user’s connection ID as the credential. The model provider calls BundleUp, BundleUp swaps in the user’s Linear token and forwards to Linear’s MCP server, and the results flow back to the model.

## Prerequisites

* A BundleUp workspace with a **Linear** integration (identifier `linear`), an API key, and a registered redirect URI. Follow steps 1 to 3 of the [Quickstart](/docs/quickstart), choosing Linear instead of GitHub.
* An OpenAI or Anthropic API key.

MCP works for providers that run their own MCP server. Each provider’s page at [bundleup.io/integrations](https://www.bundleup.io/integrations) shows whether it does.

## 1. Connect the user’s account

Run the [authorization flow](/docs/guides/auth/authorization-flow) for the `linear` integration and store the resulting `connection_id` against your user. For a quick test, follow steps 4 and 5 of the [Quickstart](/docs/quickstart) with `integration_id=linear`.

## 2. Check the connection works

Before involving a model, list the tools the connection can see:

```bash theme={null}
curl -s https://mcp.bundleup.io \
  -H "Authorization: Bearer $BUNDLEUP_API_KEY" \
  -H "BU-Connection-Id: conn_abc123" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

You should get Linear’s tool list back. A `400 mcp_not_supported` means the provider has no MCP server; use the [Proxy](/docs/guides/proxy/overview) for it instead.

## 3. Give the connection to a model

OpenAI and Anthropic can call an MCP server themselves. They accept a single credential, so BundleUp accepts the API key and connection ID joined with a dot: `API_KEY.CONNECTION_ID`. The SDK’s `hosted()` builds that for you.

<CodeGroup>
  ```typescript OpenAI theme={null}
  import OpenAI from 'openai';
  import { BundleUp } from '@bundleup/sdk';

  const openai = new OpenAI();
  const bundleup = new BundleUp(process.env.BUNDLEUP_API_KEY);

  // Look this up for the signed-in user
  const { url, token } = bundleup.mcp(user.linearConnectionId).hosted();

  const response = await openai.responses.create({
    model: 'gpt-4o',
    input: 'What issues are assigned to me?',
    tools: [
      {
        type: 'mcp',
        server_label: 'linear',
        server_url: url,
        authorization: token,
        require_approval: 'never',
      },
    ],
  });

  console.log(response.output_text);
  ```

  ```typescript Anthropic theme={null}
  import Anthropic from '@anthropic-ai/sdk';
  import { BundleUp } from '@bundleup/sdk';

  const anthropic = new Anthropic();
  const bundleup = new BundleUp(process.env.BUNDLEUP_API_KEY);

  const { url, token } = bundleup.mcp(user.linearConnectionId).hosted();

  const message = await anthropic.beta.messages.create({
    model: 'claude-opus-5-5',
    max_tokens: 16000,
    betas: ['mcp-client-2025-11-20'],
    mcp_servers: [
      { type: 'url', url, name: 'linear', authorization_token: token },
    ],
    // Every server in mcp_servers needs a matching mcp_toolset entry
    tools: [{ type: 'mcp_toolset', mcp_server_name: 'linear' }],
    messages: [{ role: 'user', content: 'What issues are assigned to me?' }],
  });
  ```

  ```python OpenAI (Python) theme={null}
  from openai import OpenAI
  from bundleup import BundleUp

  openai = OpenAI()
  bundleup = BundleUp(os.environ["BUNDLEUP_API_KEY"])

  hosted = bundleup.mcp(user.linear_connection_id).hosted()

  response = openai.responses.create(
      model="gpt-4o",
      input="What issues are assigned to me?",
      tools=[{
          "type": "mcp",
          "server_label": "linear",
          "server_url": hosted["url"],
          "authorization": hosted["token"],
          "require_approval": "never",
      }],
  )
  print(response.output_text)
  ```
</CodeGroup>

<Warning>
  With model-hosted MCP, your BundleUp API key is sent to the model provider, whose servers make the MCP calls. If that isn’t acceptable, run an MCP client in your own backend instead. See [Using MCP clients](/docs/guides/mcp/clients).
</Warning>

## 4. Serve many users

The only per-user input is the connection ID. Look it up for whoever is chatting, and pass it in. Two users get two different Linear accounts from the same code.

To give one agent several providers for the same user, add one MCP server entry per connection (for example, one for Linear and one for Slack). See [Agents for many users](/docs/guides/mcp/multi-tenant-agents).

## Next steps

* [How Proxy MCP works](/docs/guides/mcp/proxy-mcp): headers, sessions, streaming and errors.
* [Using MCP clients](/docs/guides/mcp/clients): run the MCP client in your own backend, or connect from Claude Code.
* [Choosing scopes](/docs/guides/integrations/scopes): the OAuth scopes you grant decide which tools the agent can use.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.