Skip to content
Scalekit Docs
Talk to an Engineer Dashboard

Vercel AI SDK

Build a Vercel AI SDK agent that reads Gmail as the user with AgentKit: wrap Scalekit tools with tool() and jsonSchema(), or connect to a Virtual MCP server.

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().

  • Create a Gmail connection in AgentKit > Connections. The samples use the connection name gmail, so change it if yours differs. See Set up a connection.
  • Have the .env file from the Quickstart, and add your OpenAI API key as OPENAI_API_KEY to it.
  • The samples load .env with import 'dotenv/config'.
Terminal window
npm install @scalekit-sdk/node ai@7 @ai-sdk/openai@4 dotenv

For Node.js, save the code in a .mts file, such as agent.mts, and run it with npx tsx agent.mts. The .mts extension makes the file an ES module, so it can use top-level await.

import 'dotenv/config';
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!,
);
import { createInterface } from 'node:readline/promises';
import { ConnectorStatus } from '@scalekit-sdk/node';
// Connect the user's Gmail account, and wait until it's ACTIVE before calling tools
const connectionName = 'gmail';
const identifier = 'user_123'; // your app's unique user ID
let { connectedAccount } = await scalekit.actions.getOrCreateConnectedAccount({
connectionName,
identifier,
});
if (connectedAccount?.status !== ConnectorStatus.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 !== ConnectorStatus.ACTIVE) {
throw new Error(`Gmail is not ACTIVE (status ${connectedAccount?.status}). Authorize it and run again.`);
}

See Authorize a user for production auth handling.

Fetch the tools scoped to this user, wrap each one with the AI SDK’s tool() helper, then let generateText run the tool-calling loop. Use built-in tools explains the scoped tool list, paging past 100 tools, and how to read data when the app returns an error.

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, // up to 100 tools per page; page with nextPageToken for more
});
// Tool definitions are typed as generic JSON, so read each field explicitly
const 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);

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.

Terminal window
npm install @ai-sdk/mcp@2

Mint the session token on your backend for each agent session with scalekit.actions.mcp.createSessionToken, as shown in Mint session tokens, and pass it 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 server
const 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 Create a Virtual MCP server to create the server, and Mint session tokens to check the user’s connections and mint a token.

API reference

The endpoints this page's code calls, with every field and the SDK method for each: