> ## Documentation Index
> Fetch the complete documentation index at: https://vendo-mintlify-54d109e7.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# From outside agents

> Turn your app into an MCP server that Claude, ChatGPT, Cursor and your own backend drive as one of your users.

`vendo init` turns your app into an MCP server. Your own agent connects to it —
from this codebase or from your backend — and acts as the user who is signed in,
under the same guard, approvals and audit trail as the rest of your product.
Claude, ChatGPT and Cursor connect to the same door.

<Steps>
  <Step title="Run init">
    <CodeGroup>
      ```bash npm theme={null}
      npm install @vendoai/vendo
      npx vendo init
      ```

      ```bash pnpm theme={null}
      pnpm add @vendoai/vendo
      pnpm exec vendo init
      ```
    </CodeGroup>

    Answer the first question with **From outside agents over MCP**, then give init
    the origin your dev server prints. With a Vendo Cloud key — yours, or the one
    init's browser login mints in a click — there is nothing else to decide: dev
    runs on this machine, and your deployment uses the Cloud broker automatically.

    Init writes the door — `mcp: true` — into `lib/vendo.ts`, adds the discovery
    route beside your wire route, and fills `.vendo/` with your tool catalog, policy
    and brand.
  </Step>

  <Step title="Wire your agent">
    `vendo.agentTools` opens the door for one conversation. Pass the incoming
    request and the agent acts as whoever is signed in; pass one of your own user
    ids and it acts as them headlessly, from a cron or a queue worker.
    `vendo.tokenFor` takes the same two arguments, for a client you would rather
    hold yourself.

    ```ts app/api/agent/route.ts theme={null}
    import Anthropic from "@anthropic-ai/sdk";
    import { vendo } from "@/lib/vendo";

    const anthropic = new Anthropic();

    export async function POST(request: Request) {
      const { task } = await request.json();
      const door = await vendo.agentTools(request);
      const messages: Anthropic.MessageParam[] = [{ role: "user", content: task }];

      while (true) {
        const reply = await anthropic.messages.create({
          model: "claude-sonnet-4-6",
          max_tokens: 4096,
          tools: door.tools,
          messages,
        });
        messages.push({ role: "assistant", content: reply.content });

        const results = await door.results(reply);
        if (results.length === 0) return Response.json({ reply, embeds: door.embeds });
        messages.push({ role: "user", content: results });
      }
    }
    ```

    An empty `results` is how the loop knows the model is done. Ship `door.embeds`
    to the page and render each one:

    ```tsx app/chat.tsx theme={null}
    import { VendoToolResult } from "@vendoai/vendo/react";

    // wherever you render the assistant's turn:
    embeds.map((embed, index) => <VendoToolResult key={index} output={embed} />)
    ```

    Nothing to wrap: the embed finds the wire at `/api/vendo` and rides your host
    session cookie.
  </Step>

  <Step title="Approvals">
    Ask your agent to write something — pay someone, cancel something — and the call
    parks: a tool nobody has graded needs a person, so the guard asks. The approval
    card is one of the embeds, so it renders in your chat. Approve it there, ask
    again, and the call runs.

    Grade the catalog with `vendo sync --ai` and the asking stops for everything but
    the destructive tools.
  </Step>
</Steps>

## When you deploy

Two variables on your platform, and the same code:

```bash theme={null}
VENDO_BASE_URL=https://app.example.com
VENDO_API_KEY=vnd_…
```

`VENDO_BASE_URL` is the public https origin your app answers on — every
discovery URL derives from it. `VENDO_API_KEY` is the key init already put in
`.env.local`.

<svg viewBox="0 0 760 172" role="img" aria-label="Dev on this machine and your deployment run the same code; only where the keys live differs" style={{ width: "100%", height: "auto", margin: "1.5rem 0" }}>
  <g fill="none" stroke="currentColor" strokeOpacity="0.2">
    <rect x="1" y="1" width="300" height="56" rx="11" />

    <rect x="459" y="1" width="300" height="56" rx="11" />

    <rect x="230" y="114" width="300" height="56" rx="11" />
  </g>

  <g fill="none" stroke="#6c3bff" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
    <path d="M151 61v29h229v20" />

    <path d="M609 61v29H380" />
  </g>

  <g fill="#6c3bff">
    <path d="M376 106l4 8 4-8z" />
  </g>

  <g fill="currentColor" fontSize="13.5" fontWeight="600" textAnchor="middle">
    <text x="151" y="26">Dev — this machine</text>
    <text x="609" y="26">Your deployment</text>
    <text x="380" y="139">The same code</text>
  </g>

  <g fill="currentColor" fillOpacity="0.55" fontSize="11.5" textAnchor="middle">
    <text x="151" y="45">init wrote .env.local</text>
    <text x="609" y="45">VENDO\_BASE\_URL · VENDO\_API\_KEY</text>

    <text x="380" y="158">
      {"createVendo({ mcp: true })"}
    </text>
  </g>
</svg>

## Claude, ChatGPT and Cursor

Your users' setup page ships with the door. Open it in a browser:

```
http://localhost:3000/api/vendo/mcp/connect
```

It carries the copy-paste config for each client, and they sign in with your
app's own login. For Claude Code, the plugin is two lines:

```
/plugin marketplace add runvendo/vendo
/plugin install vendo@vendo
```

## Where to go next

<CardGroup cols={3}>
  <Card title="How the door works" href="/outside-agents/how-the-door-works">
    Who is calling, how a call reaches your host tools, and what comes back.

    `mcp + oauth + actAs`
  </Card>

  <Card title="Your own agent" href="/outside-agents/your-own-agent">
    The whole loop: one door per conversation, approvals, long calls.

    `agentTools`
  </Card>

  <Card title="Service keys & broker" href="/outside-agents/service-keys-and-broker">
    Where the key lives, the audit's `svc:` attribution, and rotation.

    `svc:<hash8>`
  </Card>
</CardGroup>
