Appearance
Connect a private MCP server with OAuth
Host MCP OAuth lets the machine running your agent authorize a remote MCP server without putting tokens in your source or workspace.
Use a private MCP tool locally
Declare the server and authorize it once in the browser.
ts
// bot/mcp-connections/inventory.ts
import { defineConnection } from "@grok/agent-sdk/connections";
export default defineConnection({
url: "https://mcp.example.com/inventory",
oauth: true,
advertiseTools: true,
});bash
agent-sdk mcp oauth inventoryThe filename is the connection name. If you change the server URL, run mcp oauth again.
Connect on first use
Without a prior mcp oauth, the first call to the server pauses the turn, and the playground shows Connect. Finish the browser flow, and the call retries in the running process.
A turn waits for Connect only when a person can click it:
- A playground or HTTP chat turn.
- A Slack message, when the channel shows Connect through
slackChannel({ toolApprovals: true })orbuildToolApprovalEventsinevents.
The wait stops after 10 minutes or when the turn is interrupted. Schedules, reminders, webhooks, evals, and Slack channels without Connect don't wait. A required connection fails the call with Reconnect <connection>, and an optional one is skipped, even in the playground. Authorize those ahead of time with mcp oauth.
Keep privileged tools behind a wrapper
The model never sees a connection under bot/host-connections/. A server tool reaches it through ctx.host.mcp and exposes one narrow operation.
ts
// bot/host-connections/inventory.ts
import { defineConnection } from "@grok/agent-sdk/connections";
export default defineConnection({
url: "https://mcp.example.com/inventory",
oauth: true,
tools: ["lookup_stock"],
});ts
// bot/tools/get_stock.ts
import { defineTool } from "@grok/agent-sdk/tools";
import { z } from "zod";
export default defineTool({
description: "Read stock for one approved region.",
inputSchema: z.object({
sku: z.string(),
region: z.enum(["us-east", "us-west"]),
}),
async execute(input, ctx) {
const result = await ctx.host.mcp.callTool(
"inventory",
"lookup_stock",
input
);
return {
ok: result.isError !== true,
stock: result.structuredContent ?? null,
};
},
});Use an OAuth server from a hosted agent
Tokens from mcp oauth stay on the machine that authorized them. For a Cursor-hosted agent, add the server under MCP in the Cursor dashboard, reach it through a cursorAccount: true connection, and connect it from Deployed Agents. Anyone who can use the agent can use that connection, so narrow its servers list.
Choose where credentials live
| Connection | Credentials live in | Use it when |
|---|---|---|
cursorAccount: true | Cursor's backend | You connected the server in the Cursor dashboard |
url with oauth: true | The serve host | The serve host should own access |
url with headers | Your secrets | The server takes an API key or bearer token |
Host OAuth can't share a connection with per-session auth, which gives each caller its own downstream identity.
Related
- Follow the
bdk-mcp-authskill, then runagent-sdk mcp oauth <connection>. - MCP connections