Guides
Production Next.js App
Recommended integrate-sdk setup for multi-integration AI apps (drizzleAdapter, code mode, caching)
This guide summarizes patterns proven in production apps using integrate-sdk with Next.js App Router, session-based auth, and Vercel AI SDK.
Server setup
// lib/integrate.ts
import {
createMCPServer,
createIntegrationBundle,
createMemoryToolDiscoveryCache,
createToolDiscoveryCacheInvalidator,
} from "integrate-sdk/server";
import { drizzleAdapter } from "integrate-sdk/adapters/drizzle";
import { db } from "@/database";
import { providerToken, trigger } from "@/database/schema";
const toolDiscoveryCache = createMemoryToolDiscoveryCache();
export const { client: serverClient } = createMCPServer({
apiKey: process.env.INTEGRATE_API_KEY!,
apiBaseUrl: process.env.APP_URL,
codeMode: { publicUrl: process.env.INTEGRATE_URL ?? process.env.APP_URL },
integrations: createIntegrationBundle({ include: ["github", "gmail", "slack"] }),
enabledProviders: ["github", "gmail", "slack"],
database: drizzleAdapter(db, {
provider: "pg",
schema: { providerToken, trigger },
hooks: {
onTokenChange: ({ userId }) => {
void toolDiscoveryCache.invalidate(userId);
},
},
}),
getSessionContext: async (req) => {
const session = await auth.api.getSession({ headers: req.headers });
return session?.user?.id ? { userId: session.user.id } : undefined;
},
triggers: {
onComplete: handleTriggerCompletion,
getCallbackUrl: () => process.env.APP_URL!,
},
});Route handler
// app/api/integrate/[...all]/route.ts
import { serverClient } from "@/lib/integrate";
import { toNextJsHandler } from "integrate-sdk/server";
export const maxDuration = 300;
export const { POST, GET } = toNextJsHandler(serverClient);Tool name normalization runs inside the SDK handler. No app-level POST wrapper is required.
AI chat tools
import { getVercelAITools } from "integrate-sdk/server";
import { serverClient } from "@/lib/integrate";
const tools = await getVercelAITools(serverClient, {
context: { userId: session.user.id },
connectedOnly: true,
mode: "code",
cache: { cache: toolDiscoveryCache, ttlMs: 300_000 },
});See Performance and MCP Tool Scoping.
Browser OAuth UI
"use client";
import { client } from "integrate-sdk";
import { useIntegrateAuth } from "integrate-sdk/react";
function ConnectGitHub() {
const { isAuthorized, authorize, isLoading } = useIntegrateAuth(client, "github");
return (
<button disabled={isLoading || isAuthorized} onClick={() => void authorize()}>
{isAuthorized ? "Connected" : "Connect GitHub"}
</button>
);
}Disconnect multi-account tokens with disconnectAccount(provider, email, { userId }) on the server.
Internal service auth
Background jobs that call MCP tools without a user session should pass explicit context:
await serverClient.callTool("gmail_list_messages", { maxResults: 5 }, {
context: { userId: actorUserId },
});Protect internal routes with shared secrets validated in getSessionContext.
Related guides
- Native Automations: hybrid scheduling
- Code Mode
- Triggers