How to integrate Apify MCP with Vercel AI SDK v6

This guide walks you through connecting Apify to Vercel AI SDK v6 using the Composio tool router. By the end, you'll have a working Apify agent that can create a new dataset for scraped results, fetch items from a specific apify dataset, get details of your latest apify actor through natural language commands. This guide will help you understand how to give your Vercel AI SDK agent real control over a Apify account through Composio's Apify MCP server. Before we dive in, let's take a quick look at the key ideas and tools involved.

Apify logoApify
Api Key

Apify is a cloud platform for building, deploying, and managing web scraping and automation tools called Actors. It lets you automate data extraction and workflow tasks at scale—no infrastructure headaches.

112 Tools

Introduction

This guide walks you through connecting Apify to Vercel AI SDK v6 using the Composio tool router. By the end, you'll have a working Apify agent that can create a new dataset for scraped results, fetch items from a specific apify dataset, get details of your latest apify actor through natural language commands.

This guide will help you understand how to give your Vercel AI SDK agent real control over a Apify account through Composio's Apify MCP server.

Before we dive in, let's take a quick look at the key ideas and tools involved.

Also integrate Apify with

TL;DR

Here's what you'll learn:
  • How to set up and configure a Vercel AI SDK agent with Apify integration
  • Using Composio's Tool Router to dynamically load and access Apify tools
  • Creating an MCP client connection using HTTP transport
  • Building an interactive CLI chat interface with conversation history management
  • Handling tool calls and results within the Vercel AI SDK framework

What is Vercel AI SDK?

The Vercel AI SDK is a TypeScript library for building AI-powered applications. It provides tools for creating agents that can use external services and maintain conversation state.

Key features include:

  • streamText: Core function for streaming responses with real-time tool support
  • MCP Client: Built-in support for Model Context Protocol via @ai-sdk/mcp
  • Step Counting: Control multi-step tool execution with stopWhen: stepCountIs()
  • OpenAI Provider: Native integration with OpenAI models

What is the Apify MCP server, and what's possible with it?

The Apify MCP server is an implementation of the Model Context Protocol that connects your AI agent and assistants like Claude, Cursor, etc directly to your Apify account. It provides structured and secure access to your web scraping and automation workflows, so your agent can create actors, manage datasets, fetch scraped data, schedule tasks, and maintain webhooks on your behalf.

  • Automated Actor Creation and Management: Easily instruct your agent to programmatically create, configure, or delete Apify actors for custom web automation or scraping jobs.
  • Dataset Handling and Data Retrieval: Let your agent spin up new datasets, organize scraped results, and pull items from datasets for downstream analysis or reporting.
  • Task Scheduling and Automation: Have your agent create and manage recurring actor tasks, making it simple to automate data extraction or browser automation at set intervals.
  • Webhook Integration and Event Handling: Direct your agent to set up or remove webhooks for actor tasks, enabling real-time notifications or downstream integrations when a task completes or fails.
  • Actor and Build Metadata Access: Empower your agent to fetch detailed metadata about actors, including build information and configuration details, for monitoring or troubleshooting purposes.

What is the Composio tool router, and how does it fit here?

What is Composio SDK?

Composio's Composio SDK helps agents find the right tools for a task at runtime. You can plug in multiple toolkits (like Gmail, HubSpot, and GitHub), and the agent will identify the relevant app and action to complete multi-step workflows. This can reduce token usage and improve the reliability of tool calls. Read more here: Getting started with Composio SDK

The tool router generates a secure MCP URL that your agents can access to perform actions.

How the Composio SDK works

The Composio SDK follows a three-phase workflow:

  1. Discovery: Searches for tools matching your task and returns relevant toolkits with their details.
  2. Authentication: Checks for active connections. If missing, creates an auth config and returns a connection URL via Auth Link.
  3. Execution: Executes the action using the authenticated connection.

Step-by-step Guide

Step by step09 STEPS
1

Prerequisites

Before you begin, make sure you have:
  • Node.js and npm installed
  • A Composio account with API key
  • An OpenAI API key
2

Getting API Keys for OpenAI and Composio

OpenAI API Key
  • Go to the OpenAI dashboard and create an API key. You'll need credits to use the models, or you can connect to another model provider.
  • Keep the API key safe.
Composio API Key
  • Log in to the Composio dashboard.
  • Navigate to your API settings and generate a new API key.
  • Store this key securely as you'll need it for authentication.
3

Install required dependencies

bash
npm install @ai-sdk/openai @ai-sdk/mcp @composio/core ai dotenv

First, install the necessary packages for your project.

What you're installing:

  • @ai-sdk/openai: Vercel AI SDK's OpenAI provider
  • @ai-sdk/mcp: MCP client for Vercel AI SDK
  • @composio/core: Composio SDK for tool integration
  • ai: Core Vercel AI SDK
  • dotenv: Environment variable management
4

Set up environment variables

bash
OPENAI_API_KEY=your_openai_api_key_here
COMPOSIO_API_KEY=your_composio_api_key_here
COMPOSIO_USER_ID=your_user_id_here

Create a .env file in your project root.

What's needed:

  • OPENAI_API_KEY: Your OpenAI API key for GPT model access
  • COMPOSIO_API_KEY: Your Composio API key for tool access
  • COMPOSIO_USER_ID: A unique identifier for the user session
5

Import required modules and validate environment

typescript
import "dotenv/config";
import { openai } from "@ai-sdk/openai";
import { Composio } from "@composio/core";
import * as readline from "readline";
import { streamText, type ModelMessage, stepCountIs } from "ai";
import { createMCPClient } from "@ai-sdk/mcp";

const composioAPIKey = process.env.COMPOSIO_API_KEY;
const composioUserID = process.env.COMPOSIO_USER_ID;

if (!process.env.OPENAI_API_KEY) throw new Error("OPENAI_API_KEY is not set");
if (!composioAPIKey) throw new Error("COMPOSIO_API_KEY is not set");
if (!composioUserID) throw new Error("COMPOSIO_USER_ID is not set");

const composio = new Composio({
  apiKey: composioAPIKey,
});
What's happening:
  • We're importing all necessary libraries including Vercel AI SDK's OpenAI provider and Composio
  • The dotenv/config import automatically loads environment variables
  • The MCP client import enables connection to Composio's tool server
6

Create Tool Router session and initialize MCP client

typescript
async function main() {
  // Create a tool router session for the user
  const session = await composio.create(composioUserID!, {
    toolkits: ["apify"],
  });

  const mcpUrl = session.mcp.url;
What's happening:
  • We're creating a Tool Router session that gives your agent access to Apify tools
  • The create method takes the user ID and specifies which toolkits should be available
  • The returned mcp object contains the URL and authentication headers needed to connect to the MCP server
  • This session provides access to all Apify-related tools through the MCP protocol
7

Connect to MCP server and retrieve tools

typescript
const mcpClient = await createMCPClient({
  transport: {
    type: "http",
    url: mcpUrl,
    headers: session.mcp.headers, // Authentication headers for the Composio MCP server
  },
});

const tools = await mcpClient.tools();
What's happening:
  • We're creating an MCP client that connects to our Composio Tool Router session via HTTP
  • The mcp.url provides the endpoint, and mcp.headers contains authentication credentials
  • The type: "http" is important - Composio requires HTTP transport
  • tools() retrieves all available Apify tools that the agent can use
8

Initialize conversation and CLI interface

typescript
let messages: ModelMessage[] = [];

console.log("Chat started! Type 'exit' or 'quit' to end the conversation.\n");
console.log(
  "Ask any questions related to apify, like summarize my last 5 emails, send an email, etc... :)))\n",
);

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  prompt: "> ",
});

rl.prompt();
What's happening:
  • We initialize an empty messages array to maintain conversation history
  • A readline interface is created to accept user input from the command line
  • Instructions are displayed to guide the user on how to interact with the agent
9

Handle user input and stream responses with real-time tool feedback

typescript
rl.on("line", async (userInput: string) => {
  const trimmedInput = userInput.trim();

  if (["exit", "quit", "bye"].includes(trimmedInput.toLowerCase())) {
    console.log("\nGoodbye!");
    rl.close();
    process.exit(0);
  }

  if (!trimmedInput) {
    rl.prompt();
    return;
  }

  messages.push({ role: "user", content: trimmedInput });
  console.log("\nAgent is thinking...\n");

  try {
    const stream = streamText({
      model: openai("gpt-5"),
      messages,
      tools,
      toolChoice: "auto",
      stopWhen: stepCountIs(10),
      onStepFinish: (step) => {
        for (const toolCall of step.toolCalls) {
          console.log(`[Using tool: ${toolCall.toolName}]`);
          }
          if (step.toolCalls.length > 0) {
            console.log(""); // Add space after tool calls
          }
        },
      });

      for await (const chunk of stream.textStream) {
        process.stdout.write(chunk);
      }

      console.log("\n\n---\n");

      // Get final result for message history
      const response = await stream.response;
      if (response?.messages?.length) {
        messages.push(...response.messages);
      }
    } catch (error) {
      console.error("\nAn error occurred while talking to the agent:");
      console.error(error);
      console.log(
        "\nYou can try again or restart the app if it keeps happening.\n",
      );
    } finally {
      rl.prompt();
    }
  });

  rl.on("close", async () => {
    await mcpClient.close();
    console.log("\n👋 Session ended.");
    process.exit(0);
  });
}

main().catch((err) => {
  console.error("Fatal error:", err);
  process.exit(1);
});
What's happening:
  • We use streamText instead of generateText to stream responses in real-time
  • toolChoice: "auto" allows the model to decide when to use Apify tools
  • stopWhen: stepCountIs(10) allows up to 10 steps for complex multi-tool operations
  • onStepFinish callback displays which tools are being used in real-time
  • We iterate through the text stream to create a typewriter effect as the agent responds
  • The complete response is added to conversation history to maintain context
  • Errors are caught and displayed with helpful retry suggestions

Complete Code

Here's the complete code to get you started with Apify and Vercel AI SDK:

typescript
import "dotenv/config";
import { openai } from "@ai-sdk/openai";
import { Composio } from "@composio/core";
import * as readline from "readline";
import { streamText, type ModelMessage, stepCountIs } from "ai";
import { createMCPClient } from "@ai-sdk/mcp";

const composioAPIKey = process.env.COMPOSIO_API_KEY;
const composioUserID = process.env.COMPOSIO_USER_ID;

if (!process.env.OPENAI_API_KEY) throw new Error("OPENAI_API_KEY is not set");
if (!composioAPIKey) throw new Error("COMPOSIO_API_KEY is not set");
if (!composioUserID) throw new Error("COMPOSIO_USER_ID is not set");

const composio = new Composio({
  apiKey: composioAPIKey,
});

async function main() {
  // Create a tool router session for the user
  const session = await composio.create(composioUserID!, {
    toolkits: ["apify"],
  });

  const mcpUrl = session.mcp.url;

  const mcpClient = await createMCPClient({
    transport: {
      type: "http",
      url: mcpUrl,
      headers: session.mcp.headers, // Authentication headers for the Composio MCP server
    },
  });

  const tools = await mcpClient.tools();

  let messages: ModelMessage[] = [];

  console.log("Chat started! Type 'exit' or 'quit' to end the conversation.\n");
  console.log(
    "Ask any questions related to apify, like summarize my last 5 emails, send an email, etc... :)))\n",
  );

  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
    prompt: "> ",
  });

  rl.prompt();

  rl.on("line", async (userInput: string) => {
    const trimmedInput = userInput.trim();

    if (["exit", "quit", "bye"].includes(trimmedInput.toLowerCase())) {
      console.log("\nGoodbye!");
      rl.close();
      process.exit(0);
    }

    if (!trimmedInput) {
      rl.prompt();
      return;
    }

    messages.push({ role: "user", content: trimmedInput });
    console.log("\nAgent is thinking...\n");

    try {
      const stream = streamText({
        model: openai("gpt-5"),
        messages,
        tools,
        toolChoice: "auto",
        stopWhen: stepCountIs(10),
        onStepFinish: (step) => {
          for (const toolCall of step.toolCalls) {
            console.log(`[Using tool: ${toolCall.toolName}]`);
          }
          if (step.toolCalls.length > 0) {
            console.log(""); // Add space after tool calls
          }
        },
      });

      for await (const chunk of stream.textStream) {
        process.stdout.write(chunk);
      }

      console.log("\n\n---\n");

      // Get final result for message history
      const response = await stream.response;
      if (response?.messages?.length) {
        messages.push(...response.messages);
      }
    } catch (error) {
      console.error("\nAn error occurred while talking to the agent:");
      console.error(error);
      console.log(
        "\nYou can try again or restart the app if it keeps happening.\n",
      );
    } finally {
      rl.prompt();
    }
  });

  rl.on("close", async () => {
    await mcpClient.close();
    console.log("\n👋 Session ended.");
    process.exit(0);
  });
}

main().catch((err) => {
  console.error("Fatal error:", err);
  process.exit(1);
});

Conclusion

You've successfully built a Apify agent using the Vercel AI SDK with streaming capabilities! This implementation provides a powerful foundation for building AI applications with natural language interfaces and real-time feedback.

Key features of this implementation:

  • Real-time streaming responses for a better user experience with typewriter effect
  • Live tool execution feedback showing which tools are being used as the agent works
  • Dynamic tool loading through Composio's Tool Router with secure authentication
  • Multi-step tool execution with configurable step limits (up to 10 steps)
  • Comprehensive error handling for robust agent execution
  • Conversation history maintenance for context-aware responses

You can extend this further by adding custom error handling, implementing specific business logic, or integrating additional Composio toolkits to create multi-app workflows.
TOOLS

Supported Tools

Every Apify action and event your agent gets out of the box.

Build Actor

Tool to build an Actor with specified configuration.

Abort Actor Build

Tool to abort an Actor build that is starting or running.

Delete Actor Build

Tool to delete an Actor build permanently.

Get Actor Build

Tool to get detailed information about a specific Actor build.

Get Actor Build Log

Tool to retrieve the log file for a specific Actor build.

Get user builds list

Tool to get a paginated list of all builds for a user.

Abort Actor Run

Tool to abort a running or starting Actor run.

Delete Actor Run

Tool to delete a finished Actor run.

Get Actor Run

Tool to get details about a specific Actor run.

Update Actor Run Status Message

Tool to update the status message of an Actor run.

Delete Actor Task

Tool to delete an Actor task permanently.

Get Actor Task

Tool to get complete details about an Actor task.

Update Actor Task

Tool to update Actor task settings using JSON payload.

Get last actor task run

Tool to get the most recent run of a specific Actor task.

Run Task Sync (GET)

Tool to run a specific task synchronously and return its output.

Run Task Sync & Get Dataset Items

Tool to run an actor task synchronously and retrieve its dataset items.

Run Task Sync with Input Override & Get Dataset Items

Tool to run an actor task synchronously with input overrides and retrieve its dataset items.

Run Task Sync (POST)

Tool to run an Actor task synchronously with input override and return its output.

Update Actor

Tool to update Actor settings using JSON payload.

Get last actor run

Tool to get the most recent run of a specific Actor.

Run Actor Sync without Input (GET)

Tool to run a specific Actor synchronously without input and return its output.

Run Actor Sync & Get Dataset Items

Tool to run Actor synchronously and get dataset items.

Get list of Actors

Tool to get the list of all Actors that the user created or used.

Delete Actor Version

Tool to delete a specific version of an Actor's source code.

Delete Actor Version Environment Variable

Tool to delete an environment variable from a specific Actor version.

Get Actor Version Environment Variable

Tool to get environment variable details for a specific Actor version.

Update Actor Version Environment Variable

Tool to update environment variable for a specific Actor version using JSON payload.

Get list of Actor version environment variables

Tool to get the list of environment variables for a specific Actor version.

Create Actor Version Environment Variable

Tool to create an environment variable for a specific Actor version.

Get Actor version

Tool to get details about a specific version of an Actor.

Update Actor Version

Tool to update an Actor version's configuration and source code.

Get list of Actor versions

Tool to get the list of versions of a specific Actor.

Create Actor Version

Tool to create a new version of an Actor.

Get list of Actor webhooks

Tool to get a list of webhooks for a specific Actor.

Create Actor

Tool to create a new Actor with specified configuration.

Create Dataset

Tool to create a new dataset.

Create Actor Task

Tool to create a new Actor task with specified settings.

Create Task Webhook

Tool to create a webhook for an Actor task.

Delete Dataset

Tool to delete a dataset permanently.

Get Dataset

Tool to retrieve dataset metadata by dataset ID.

Update Dataset

Tool to update a dataset's name via JSON payload.

Get list of datasets

Tool to get list of datasets for a user.

Get Dataset Statistics

Tool to get dataset field statistics by dataset ID.

Delete Actor

Tool to delete an Actor permanently.

Delete Webhook

Tool to delete a webhook by its ID.

Get Actor Details

Tool to get details of a specific Actor.

Get Actor Last Run Dataset Items

Tool to get dataset items from the last run of an Actor.

Get all webhooks

Tool to get a list of all webhooks created by the user.

Get dataset items

Tool to retrieve items from a dataset.

Get Default Build

Tool to get the default build for an Actor.

Get Key-Value Record

Tool to retrieve a record from a key-value store.

Get list of builds

Tool to get a list of builds for a specific Actor.

Get list of runs

Tool to get a list of runs for a specific Actor.

Get list of task runs

Tool to get a list of runs for a specific Actor task.

Get list of tasks

Tool to fetch a paginated list of tasks belonging to the authenticated user.

Get list of task webhooks

Tool to get a list of webhooks for a specific Actor task.

Get log

Tool to retrieve logs for a specific Actor run or build.

Get OpenAPI Definition

Tool to get the OpenAPI definition for a specific Actor build.

Get Run Dataset Items

Tool to get dataset items from a specific Actor run.

Get Task Input

Tool to retrieve the input configuration of a specific task.

Get Task Last Run Dataset Items

Tool to get dataset items from the last run of an Actor task.

Delete Key-Value Store

Tool to delete a key-value store permanently.

Get Key-Value Store

Tool to retrieve key-value store metadata by store ID.

Get Key-Value Store Keys

Tool to retrieve a list of keys from a key-value store.

Delete Key-Value Store Record

Tool to delete a record from a key-value store.

Check Key-Value Store Record Exists

Tool to check if a record exists in a key-value store.

Get list of key-value stores

Tool to get the list of key-value stores owned by the user.

Create Key-Value Store

Tool to create a new key-value store or retrieve an existing one by name.

List User Actor Runs

Tool to get a paginated list of all Actor runs for the authenticated user.

Delete Request Queue

Tool to delete a request queue permanently.

Get Request Queue

Tool to retrieve request queue metadata by queue ID.

Get Request Queue Head

Tool to retrieve first requests from the queue for inspection.

Get Head and Lock Queue Requests

Tool to get and lock head requests from the queue.

Update Request Queue

Tool to update request queue name using JSON payload.

Delete Request from Queue

Tool to delete a specific request from a request queue.

Get Request from Queue

Tool to retrieve a specific request from a request queue by its ID.

Delete Request Lock

Tool to delete a request lock from a request queue.

Prolong Request Lock

Tool to prolong request lock in a request queue.

Update Request in Queue

Tool to update a request in a request queue.

Batch Delete Requests from Queue

Tool to batch-delete up to 25 requests from a queue.

Batch Add Requests to Queue

Tool to batch-add up to 25 requests to a request queue.

List Request Queue Requests

Tool to list requests in a request queue with pagination support.

Add Request to Queue

Tool to add a request to the queue.

Unlock Queue Requests

Tool to unlock requests in a request queue that are currently locked by the client.

Get list of request queues

Tool to get list of request queues for a user.

Create Request Queue

Tool to create a new request queue or retrieve an existing one by name.

Run Actor Asynchronously

Tool to run a specific Actor asynchronously.

Run Actor Sync

Tool to run a specific Actor synchronously with input and return its output record.

Run Actor Sync & Get Dataset Items

Tool to run an Actor synchronously and retrieve its dataset items.

Run Task Asynchronously

Tool to run a specific Actor task asynchronously.

Delete Schedule

Tool to delete a schedule by its ID.

Get Schedule

Tool to get schedule details by ID.

Get Schedule Log

Tool to get schedule log by ID.

Update Schedule

Tool to update an existing schedule with new settings.

Get list of schedules

Tool to get list of schedules created by the user.

Create Schedule

Tool to create a new schedule with specified settings.

Store Data in Dataset

Tool to store data items in a dataset.

Store Data in Key-Value Store

Tool to create or update a record in a key-value store.

Get list of Actors in Store

Tool to get list of public Actors from Apify Store.

Update Key-Value Store

Tool to update a key-value store's properties.

Update Task Input

Tool to update the input configuration of a specific Actor task.

Get Public User Data

Tool to get public user data.

Get Current User Account Data

Tool to get private user account information.

Get Account Limits

Tool to get a complete summary of account limits and usage.

Update Account Limits

Tool to update account limits manageable on the Limits page.

Get Monthly Usage

Tool to get monthly usage summary with daily breakdown.

Get list of webhook dispatches

Tool to get list of webhook dispatches for the user.

Get Webhook Dispatch

Tool to get webhook dispatch object with all details.

Get webhook

Tool to get webhook object with all details.

Update Webhook

Tool to update webhook using JSON payload.

Test Webhook

Tool to test a webhook by creating a test dispatch with a dummy payload.

Get webhook dispatches

Tool to get list of webhook dispatches for a specific webhook.

FAQ

Frequently asked questions

With a standalone Apify MCP server, the agents and LLMs can only access a fixed set of Apify tools tied to that server. However, with the Composio Tool Router, agents can dynamically load tools from Apify and many other apps based on the task at hand, all through a single MCP endpoint.

Yes, you can. Vercel AI SDK v6 fully supports MCP integration. You get structured tool calling, message history handling, and model orchestration while Tool Router takes care of discovering and serving the right Apify tools.

Yes, absolutely. You can configure which Apify scopes and actions are allowed when connecting your account to Composio. You can also bring your own OAuth credentials or API configuration so you keep full control over what the agent can do.

All sensitive data such as tokens, keys, and configuration is fully encrypted at rest and in transit. Composio is SOC 2 Type 2 compliant and follows strict security practices so your Apify data and credentials are handled as safely as possible.

Start with Apify.It takes 30 seconds.

Managed auth, hosted MCP servers, and every Apify tool your agent needs.Free to start.

Start building
Apify MCP Integration with Vercel AI SDK | Composio