Search

Search the documentation

Protobox

Embed Protobox in Your Product

Give each of your end-users a scoped, revocable MCP endpoint — mint sessions server-side, let their agents connect their own accounts.

You run a product whose users bring their own AI agents (Claude Desktop, Claude Code, custom MCP clients). Protobox lets you hand each user a personal MCP endpoint that is scoped to a toolset you choose and to that user's own connected accounts — without you building any OAuth, token storage, or MCP plumbing.

Concepts

ConceptWhat it is
WorkspaceYours. Holds your API key, toolsets, and billing.
ToolsetThe set of integration actions your users' agents may reach.
SessionOne end-user's scoped MCP credential: { userId, toolsetSlug } → a URL + bearer token.
ConnectionThat user's own account login (their GitLab, their Gmail) — connected by them, stored and refreshed by Protobox.

1. Mint a session server-side

Mint one session per logged-in user, from your backend only:

import { ProtoboxSDK } from '@protoboxai/sdk';

const protobox = new ProtoboxSDK({ apiKey: process.env.PROTOBOX_API_KEY! });

const session = await protobox.sessions.create({
  userId: 'user_123',        // YOUR user id — the session is hard-bound to it
  toolsetSlug: 'support',    // optional: restrict to one toolset
});
// session.mcpUrl → https://<your-ws>.protobox.app/mcp/s/<sessionId>
// session.token  → shown ONCE. Store it encrypted server-side; it cannot be
//                  retrieved again (only a hash is stored).

Hand the user's agent the URL plus the token as a bearer header.

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "yourproduct-tools": {
      "command": "npx",
      "args": [
        "mcp-remote", "https://<your-ws>.protobox.app/mcp/s/<sessionId>",
        "--header", "Authorization: Bearer <session-token>"
      ]
    }
  }
}

Claude Code:

claude mcp add --transport http yourproduct-tools \
  https://<your-ws>.protobox.app/mcp/s/<sessionId> \
  --header "Authorization: Bearer <session-token>"

Any MCP client (Streamable HTTP):

import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';

const transport = new StreamableHTTPClientTransport(new URL(session.mcpUrl), {
  requestInit: { headers: { Authorization: `Bearer ${session.token}` } },
});
const client = new Client({ name: 'yourproduct', version: '1.0.0' }, { capabilities: {} });
await client.connect(transport);

The session exposes exactly three meta-toolssearch_actions, get_action_schema, execute_action — never your workspace's admin tools. The toolset scopes which integration actions those meta-tools may reach.

2. The auth_required contract

When the agent calls execute_action for an integration the user hasn't connected yet, the tool call succeeds and returns a structured payload instead of a result:

{
  "status": "auth_required",
  "integration": "gitlab",
  "message": "Connect gitlab to use this action.",
  "connectUrl": "https://app.protobox.ai/connect/gitlab?method=managed&userId=user_123"
}

The connectUrl is a hosted connect page already carrying the session's bound user id — the agent (or your UI) surfaces the link, the user consents and logs into their own account, and the agent simply retries the action. Nothing to build on your side beyond showing the link.

3. Lifecycle & safety

  • Token shown once. Only a hash is stored; get/list never return it. Lost token → revoke and mint a new session.

  • Revoke on sign-out/offboarding:

    const sessions = await protobox.sessions.list({ search: 'user_123' });
    await Promise.all(sessions.map((s) => protobox.sessions.revoke(s.id)));

    A revoked session's MCP endpoint immediately returns 401.

  • Observability: every search/execute/connection event is logged for 90 days — protobox.sessions.listEvents(id) returns { items, nextCursor } (newest first; pass nextCursor back as cursor to page). protobox.sessions.get(id) includes an aggregate summary.

  • Impersonation is ignored by design. The caller identity is hard-bound to the session's userId at mint time; identity headers sent by the agent are discarded. One user's session can never read another user's connections.

4. Security notes

  • Treat session tokens as per-user secrets: mint server-side only, store encrypted, never log them, never ship them in frontend bundles.
  • Your workspace API key stays on your backend — it can mint/revoke ALL sessions; the session token can only act as its one user.
  • Scope sessions with a toolsetSlug — least privilege for what the agent can even discover, not just execute.

Worked example

A complete ~100-line Express backend implementing this page (login stub → mint → agent config → revoke) lives in the repo: examples/partner-embed.

On this page