Vercel AI SDK
Build a Vercel AI SDK agent with Scalekit-authenticated tools using the tool() helper and jsonSchema() adapter.
Build an agent using the Vercel AI SDK that reads a user’s Gmail inbox. Wrap each Scalekit tool with tool() from the ai package, and pass its JSON Schema to the model with jsonSchema().
Install
Section titled “Install”npm install @scalekit-sdk/node ai@7 @ai-sdk/openai@4Initialize
Section titled “Initialize”import { ScalekitClient } from '@scalekit-sdk/node';
const scalekit = new ScalekitClient( process.env.SCALEKIT_ENVIRONMENT_URL!, process.env.SCALEKIT_CLIENT_ID!, process.env.SCALEKIT_CLIENT_SECRET!,);Connect the user to Gmail
Section titled “Connect the user to Gmail”import { createInterface } from 'node:readline/promises';
// Connect the user's Gmail account, and wait until it's ACTIVE before calling toolsconst connectionName = 'gmail';const identifier = 'user_123'; // your app's unique user IDconst ACTIVE = 1; // ConnectorStatus.ACTIVE
let { connectedAccount } = await scalekit.actions.getOrCreateConnectedAccount({ connectionName, identifier,});if (connectedAccount?.status !== ACTIVE) { const { link } = await scalekit.actions.getAuthorizationLink({ connectionName, identifier }); console.log('Authorize Gmail:', link); const rl = createInterface({ input: process.stdin, output: process.stdout }); await rl.question('Press Enter after authorizing...'); rl.close(); // Fetch the account again to pick up the new status ({ connectedAccount } = await scalekit.actions.getOrCreateConnectedAccount({ connectionName, identifier, }));}
if (connectedAccount?.status !== ACTIVE) { throw new Error(`Gmail is not ACTIVE (status ${connectedAccount?.status}). Authorize it and run again.`);}See Authorize a user for production auth handling.
Run the agent
Section titled “Run the agent”import { generateText, jsonSchema, stepCountIs, tool } from 'ai';import { openai } from '@ai-sdk/openai';
const { tools: scopedTools } = await scalekit.tools.listScopedTools('user_123', { filter: { connectionNames: ['gmail'] }, pageSize: 100, // fetch beyond the default page so no connector tools are missed});
// Tool definitions are typed as generic JSON, so read each field explicitlyconst definitions = scopedTools.flatMap((t) => (t.tool?.definition ? [t.tool.definition] : []));
const tools = Object.fromEntries( definitions.map((definition) => { const name = String(definition.name); const schema = definition.input_schema ?? { type: 'object', properties: {} }; return [ name, tool({ description: String(definition.description ?? ''), inputSchema: jsonSchema<Record<string, unknown>>(schema as Parameters<typeof jsonSchema>[0]), execute: async (args) => { const result = await scalekit.actions.executeTool({ toolName: name, identifier: 'user_123', connector: 'gmail', toolInput: args, }); return result.data; }, }), ]; }),);
const { text } = await generateText({ model: openai('gpt-4o'), tools, stopWhen: stepCountIs(5), prompt: 'Fetch my last 5 unread emails and summarize them',});console.log(text);Use MCP instead
Section titled “Use MCP instead”The Vercel AI SDK connects to MCP servers with createMCPClient from @ai-sdk/mcp. Pass the Virtual MCP Server URL and a session token, and the client loads the server’s tools for you.
npm install @ai-sdk/mcp@2Mint the session token on your backend for each agent session. The Node.js SDK doesn’t create session tokens yet, so use the Python SDK as shown in Connect an agent, and pass the token to this code.
import { createMCPClient } from '@ai-sdk/mcp';import { generateText, stepCountIs } from 'ai';import { openai } from '@ai-sdk/openai';
const mcpUrl = process.env.SCALEKIT_MCP_SERVER_URL!; // mcp_server_url from your Virtual MCP Serverconst mcpToken = process.env.SCALEKIT_MCP_SESSION_TOKEN!; // minted on your backend for this user
const mcpClient = await createMCPClient({ transport: { type: 'http', url: mcpUrl, headers: { Authorization: `Bearer ${mcpToken}` }, },});
const tools = await mcpClient.tools();
const { text } = await generateText({ model: openai('gpt-4o'), tools, stopWhen: stepCountIs(5), prompt: 'Fetch my last 5 unread emails and summarize them',});await mcpClient.close();console.log(text);See Set up and connect to create the server and check that the user’s connections are active before you mint a token.