# How to integrate Cloudinary MCP with Vercel AI SDK v6

```json
{
  "title": "How to integrate Cloudinary MCP with Vercel AI SDK v6",
  "toolkit": "Cloudinary",
  "toolkit_slug": "cloudinary",
  "framework": "Vercel AI SDK",
  "framework_slug": "ai-sdk",
  "url": "https://composio.dev/toolkits/cloudinary/framework/ai-sdk",
  "markdown_url": "https://composio.dev/toolkits/cloudinary/framework/ai-sdk.md",
  "updated_at": "2026-05-12T10:06:47.963Z"
}
```

## Introduction

This guide walks you through connecting Cloudinary to Vercel AI SDK v6 using the Composio tool router. By the end, you'll have a working Cloudinary agent that can create a new folder for event photos, delete derived assets with ids [123,456], set up upload preset with watermarking through natural language commands.
This guide will help you understand how to give your Vercel AI SDK agent real control over a Cloudinary account through Composio's Cloudinary MCP server.
Before we dive in, let's take a quick look at the key ideas and tools involved.

## Also integrate Cloudinary with

- [OpenAI Agents SDK](https://composio.dev/toolkits/cloudinary/framework/open-ai-agents-sdk)
- [Claude Agent SDK](https://composio.dev/toolkits/cloudinary/framework/claude-agents-sdk)
- [Claude Code](https://composio.dev/toolkits/cloudinary/framework/claude-code)
- [Claude Cowork](https://composio.dev/toolkits/cloudinary/framework/claude-cowork)
- [Codex](https://composio.dev/toolkits/cloudinary/framework/codex)
- [OpenClaw](https://composio.dev/toolkits/cloudinary/framework/openclaw)
- [Hermes](https://composio.dev/toolkits/cloudinary/framework/hermes-agent)
- [CLI](https://composio.dev/toolkits/cloudinary/framework/cli)
- [Google ADK](https://composio.dev/toolkits/cloudinary/framework/google-adk)
- [LangChain](https://composio.dev/toolkits/cloudinary/framework/langchain)
- [Mastra AI](https://composio.dev/toolkits/cloudinary/framework/mastra-ai)
- [LlamaIndex](https://composio.dev/toolkits/cloudinary/framework/llama-index)
- [CrewAI](https://composio.dev/toolkits/cloudinary/framework/crew-ai)

## TL;DR

Here's what you'll learn:
- How to set up and configure a Vercel AI SDK agent with Cloudinary integration
- Using Composio's Tool Router to dynamically load and access Cloudinary 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 Cloudinary MCP server, and what's possible with it?

The Cloudinary MCP server is an implementation of the Model Context Protocol that connects your AI agent and assistants like Claude, Cursor, etc directly to your Cloudinary account. It provides structured and secure access to your digital asset management system, so your agent can perform actions like organizing folders, creating metadata fields, managing upload presets, and handling asset deletion on your behalf.
- Automated folder and asset organization: Easily instruct your agent to create new asset folders or remove empty ones, keeping your Cloudinary library tidy and structured.
- Metadata management: Let your agent create custom metadata fields or delete obsolete ones, extending and refining your asset tagging and search capabilities.
- Preset and upload mapping creation: Have your agent set up upload presets with specific options or define dynamic folder mappings, automating consistent upload processes across your assets.
- Resource and derived asset cleanup: Direct your agent to permanently delete assets by ID or remove unnecessary derived resources, ensuring your storage stays efficient and clutter-free.
- Datasource entry management: Ask your agent to inactivate or delete specific datasource entries from metadata fields, keeping your metadata schema accurate and up to date.

## Supported Tools

| Tool slug | Name | Description |
|---|---|---|
| `CLOUDINARY_ACTIVATE_LIVE_STREAM` | Activate Live Stream | Tool to manually activate a Cloudinary live stream. Use when you need to start a live stream that is in an inactive state. |
| `CLOUDINARY_CREATE_ASSET_RELATIONS_BY_ASSET_ID` | Create Asset Relations by Asset ID | Tool to add related assets by asset ID. Use when you need to create relationships between assets in Cloudinary. Can relate up to 10 assets at once to a source asset. |
| `CLOUDINARY_CREATE_ASSET_RELATIONS_BY_PUBLIC_ID` | Create Asset Relations by Public ID | Tool to create relations between assets by public ID. Use when you need to link related assets together (e.g., linking subtitles to videos, or associating images with each other). Each request can relate up to 10 assets to the primary asset. |
| `CLOUDINARY_CREATE_FOLDER` | Create Folder | Tool to create a new asset folder. Use when you need to organize assets into nested directories. Use after confirming the folder path does not already exist. |
| `CLOUDINARY_CREATE_IMAGE_FROM_TEXT` | Create Image from Text | Tool to create an image from text using Cloudinary's text generation API. Use when you need to generate custom text images with specific styling options. The generated image can be customized with font, color, alignment, and other visual properties. |
| `CLOUDINARY_CREATE_LIVE_STREAM` | Create Live Stream | Tool to create a new live stream in Cloudinary. Use when you need to set up a new live streaming session. The created stream will provide connection details (URI and stream key) for pushing live content. |
| `CLOUDINARY_CREATE_LIVE_STREAM_OUTPUT` | Create Live Stream Output | Tool to create a new live stream output configuration. Use when you need to add an output destination to an existing live stream, such as simulcasting to YouTube, Facebook, or creating an archive. |
| `CLOUDINARY_CREATE_METADATA_FIELD` | Create Metadata Field | Tool to create a new metadata field definition. Use when extending your metadata schema with new fields. |
| `CLOUDINARY_CREATE_METADATA_RULE` | Create Metadata Rule | Tool to create a new conditional metadata rule. Use when you need to automatically populate metadata fields based on conditions. The rule applies a value to a target metadata field when a condition on another metadata field is met. |
| `CLOUDINARY_CREATE_MULTI_RESOURCE` | Create Multi-Resource Animation | Tool to create an animated image, video, or PDF from a set of images. Use when you need to combine multiple images into an animated format. Provide either a tag (to combine all images with that tag) or a list of URLs. |
| `CLOUDINARY_CREATE_SLIDESHOW` | Create Slideshow | Tool to create an auto-generated video slideshow from existing Cloudinary assets. Use when you need to compile multiple images or videos into a single video with transitions. The slideshow is created asynchronously; check status field or use notification_url for completion updates. |
| `CLOUDINARY_CREATE_STREAMING_PROFILE` | Create Streaming Profile | Tool to create a new adaptive streaming profile in your Cloudinary account. Use when you need to define custom video quality settings for adaptive bitrate streaming. The profile will contain multiple representations at different resolutions and bitrates. |
| `CLOUDINARY_CREATE_TRANSFORMATION` | Create Transformation | Tool to create a new named transformation by assigning a custom name to a set of transformation parameters. Use when you need to save and reuse a transformation configuration with a memorable name. |
| `CLOUDINARY_CREATE_TRIGGER` | Create Trigger | Tool to create a new webhook trigger for a specified event type. Use after configuring your webhook endpoint and choosing the event type. Example: "Create a trigger for uploads to https://example.com/hooks/cloudinary" |
| `CLOUDINARY_CREATE_UPLOAD_MAPPING` | Create Upload Mapping | Tool to create a new upload mapping folder and URL template. Use when you need to dynamically map external URL prefixes to a Cloudinary asset folder before uploading files. |
| `CLOUDINARY_CREATE_UPLOAD_PRESET` | Create Upload Preset | Tool to create a new upload preset. Use when defining centralized upload options (tags, formats, transformations, etc.) before asset uploads. |
| `CLOUDINARY_DELETE_ASSET_RELATIONS_BY_ASSET_ID` | Delete Asset Relations by Asset ID | Tool to delete asset relations by asset ID. Use when you need to unrelate a specific asset from other assets. |
| `CLOUDINARY_DELETE_ASSET_RELATIONS_BY_PUBLIC_ID` | Delete Asset Relations by Public ID | Tool to delete asset relations by public ID. Use when you need to unrelate assets from a specific asset. |
| `CLOUDINARY_DELETE_DERIVED_RESOURCES` | Delete Derived Resources | Tool to delete derived assets. Use when you need to remove specific derived assets by their IDs. Example: "Delete derived assets with IDs [id1, id2]". |
| `CLOUDINARY_DELETE_ENTRIES_IN_METADATA_FIELD_DATASOURCE` | Delete Metadata Field Datasource Entries | Tool to delete datasource entries for a specified metadata field. Use when you need to soft-delete (inactivate) specific entries in a field's datasource. Example prompt: "Delete entries ['color1','color2'] from metadata field 'color_id'" |
| `CLOUDINARY_DELETE_FOLDER` | Delete Folder | Tool to delete an empty asset folder. Use when the folder is confirmed empty and you need to remove it. |
| `CLOUDINARY_DELETE_LIVE_STREAM` | Delete Live Stream | Tool to delete a live stream from Cloudinary. Use when you need to permanently remove a live stream that is no longer needed. |
| `CLOUDINARY_DELETE_LIVE_STREAM_OUTPUT` | Delete Live Stream Output | Tool to delete a live stream output from Cloudinary. Use when you need to remove a specific output configuration from a live stream. |
| `CLOUDINARY_DELETE_METADATA_FIELD` | Delete Metadata Field | Tool to delete a metadata field by external ID. Use when you need to remove a metadata field that is no longer required. |
| `CLOUDINARY_DELETE_METADATA_RULE` | Delete Metadata Rule | Tool to delete a conditional metadata rule by its ID. Use when you need to remove a metadata rule that is no longer required. |
| `CLOUDINARY_DELETE_RESOURCES_BY_ASSET_ID` | Delete Resources by Asset ID | Tool to delete resources by asset IDs. Use when you need to permanently remove specific resources by their immutable asset IDs; irreversible. |
| `CLOUDINARY_DELETE_RESOURCES_BY_PUBLIC_ID` | Delete Resources by Public ID | Tool to delete Cloudinary resources by public ID, prefix, or all resources. Use when you need to permanently remove specific assets by their public IDs, or bulk delete by prefix pattern. Deletion is irreversible. |
| `CLOUDINARY_DELETE_RESOURCES_BY_TAGS` | Delete Resources by Tags | Tool to delete Cloudinary assets by tag. Use when you need to remove all assets associated with a given tag. |
| `CLOUDINARY_DELETE_STREAMING_PROFILE` | Delete Streaming Profile | Tool to delete a custom streaming profile or revert a built-in profile to original settings. Use when you need to remove a custom profile that is no longer needed. |
| `CLOUDINARY_DELETE_TRANSFORMATION2` | Delete Transformation (v2) | Tool to delete a named transformation from your Cloudinary account. Use when you need to remove a transformation that is no longer required. |
| `CLOUDINARY_DELETE_TRIGGER` | Delete Trigger | Tool to delete a trigger (webhook notification). Use when you need to remove a trigger by its ID after confirming the correct ID. |
| `CLOUDINARY_DELETE_UPLOAD_MAPPING` | Delete Upload Mapping | Tool to delete a folder upload mapping. Use when you need to remove an existing upload mapping configuration. |
| `CLOUDINARY_DELETE_UPLOAD_PRESET` | Delete Upload Preset | Tool to delete an upload preset from the account. Use when you need to remove an upload preset that is no longer needed. |
| `CLOUDINARY_DESTROY_ASSET` | Destroy Asset | Tool to permanently destroy a Cloudinary asset/resource by public ID. Use when you need to permanently delete a specific asset. This operation is irreversible and removes the asset from Cloudinary storage. |
| `CLOUDINARY_DESTROY_ASSET_BY_ID` | Destroy Asset by ID | Tool to delete an asset by its immutable asset ID. Use when you need to permanently remove a specific asset using its asset ID; operation is irreversible. |
| `CLOUDINARY_EXPLICIT_RESOURCE` | Explicit Resource Update | Tool to update an existing asset and/or eagerly generate derived transformations using Cloudinary's Explicit API. Use when you need to pre-generate transformations, update metadata, move assets to new folders, or modify tags on already-uploaded resources. |
| `CLOUDINARY_EXPLODE_RESOURCE` | Explode Multi-Page Resource | Tool to create derived images from multi-page files (PDF, PSD, TIFF, animated GIF) by exploding them into separate images. Use when you need to extract individual pages or frames from a multi-page resource. The operation is asynchronous and returns a batch_id for tracking. |
| `CLOUDINARY_GENERATE_ARCHIVE` | Generate Archive | Tool to create an archive (ZIP or TGZ file) containing a set of assets from your Cloudinary environment. Use when you need to download multiple assets as a single archive file. Supports filtering by tags, public IDs, or prefixes. The archive is created asynchronously if async=true; use notification_url to receive completion notifications. |
| `CLOUDINARY_GET_ADAPTIVE_STREAMING_PROFILES` | Get Adaptive Streaming Profiles | Tool to list adaptive streaming profiles. Use when retrieving built-in and custom adaptive streaming profiles for delivering video via HLS or DASH. |
| `CLOUDINARY_GET_ANALYSIS_TASK_STATUS` | Get Analysis Task Status | Tool to get the status of an analysis task. Use when you need to check the progress or completion status of a previously submitted analysis task. |
| `CLOUDINARY_GET_CONFIG` | Get product environment config details | Tool to get product environment config details. Use when you need to fetch or verify environment configuration such as folder_mode. Config values like folder_mode constrain uploads, folder creation, and preset creation — check this config before those operations to avoid mode conflicts. |
| `CLOUDINARY_GET_LIVE_STREAM` | Get Live Stream | Tool to get details of a single live stream by ID. Use when you need to retrieve configuration, status, and metadata of an existing live stream. |
| `CLOUDINARY_GET_LIVE_STREAM_OUTPUT` | Get Live Stream Output | Tool to get details of a single live stream output. Use when you need information about a specific output configuration for a live stream. |
| `CLOUDINARY_GET_LIVE_STREAM_OUTPUTS` | Get Live Stream Outputs | Tool to get a list of live stream outputs. Use when you need to retrieve all outputs configured for a specific live stream in Cloudinary. |
| `CLOUDINARY_GET_LIVE_STREAMS` | Get Live Streams | Tool to get a list of live streams from Cloudinary. Use when you need to retrieve all configured live streams for your account. |
| `CLOUDINARY_GET_METADATA_FIELD_BY_ID` | Get Metadata Field By ID | Tool to get a single metadata field definition by external ID. Use after creating or updating a metadata field to fetch its full definition. Example: "Get metadata field definition for external ID 'color_id'." |
| `CLOUDINARY_GET_RESOURCE_BY_ASSET_ID` | Get Resource by Asset ID | Get Resource by Asset ID |
| `CLOUDINARY_GET_RESOURCE_BY_PUBLIC_ID` | Get Resource by Public ID | Tool to get details of a single resource by public ID. All three of resource_type, type, and public_id must exactly match the stored asset's values; a mismatch in any one causes lookup failure even if the asset exists under a different combination. Returns full asset, derived, and related info. |
| `CLOUDINARY_GET_RESOURCES_BY_ASSET_FOLDER` | Get Resources by Asset Folder | Tool to list assets stored directly in a specified folder. Use when you need to view assets in a specific folder without including subfolder contents. |
| `CLOUDINARY_GET_RESOURCES_BY_CONTEXT` | Get Resources by Context | Tool to retrieve assets with a specified contextual metadata key/value. Use when filtering resources by context metadata. Empty `resources` array indicates no matches, not an error. Enable `context`, `metadata`, `tags`, or `moderations` only when needed; use `fields` to limit payload size. |
| `CLOUDINARY_GET_RESOURCES_IN_MODERATION` | Get Resources in Moderation | Tool to retrieve assets in a moderation queue by status. Use after moderation to process pending or reviewed assets. |
| `CLOUDINARY_GET_ROOT_FOLDERS` | Get Root Folders | Tool to list all root folders in the product environment. Use when you need to retrieve top-level asset folders. |
| `CLOUDINARY_GET_STREAMING_PROFILE_DETAILS` | Get Streaming Profile Details | Tool to get details of a single streaming profile by name. Use when you need to inspect an existing profile's configuration before making changes. Example: "Get details of streaming profile 'hd'." |
| `CLOUDINARY_GET_TAGS` | Get Resource Tags | Tool to list all tags used for a specified resource type. Use when you need to retrieve or page through the tags assigned to your assets. |
| `CLOUDINARY_GET_TRANSFORMATION` | Get Transformation | Tool to retrieve details of a specific transformation. Use when you need to get information about a named transformation or transformation string, including its parameters, derived resources, and usage status. |
| `CLOUDINARY_GET_TRANSFORMATIONS` | Get Transformations | Tool to list all transformations (named and unnamed). Use when you need to retrieve transformation definitions or paginate through transformation records. |
| `CLOUDINARY_GET_TRIGGERS` | List Webhook Triggers | Tool to list all webhook triggers for event types in your environment. Use when you need to retrieve or filter existing triggers by type. |
| `CLOUDINARY_GET_UPLOAD_MAPPING_DETAILS` | Get Upload Mapping Details | Tool to retrieve details of a single upload mapping by folder. Use when you need the URL prefix template associated with a specific mapping folder. |
| `CLOUDINARY_GET_UPLOAD_MAPPINGS` | Get Upload Mappings | Tool to list all upload mappings. Use when you need to retrieve and paginate through upload mapping configurations. For details of a specific mapping, use CLOUDINARY_GET_UPLOAD_MAPPING_DETAILS. |
| `CLOUDINARY_GET_UPLOAD_PRESET` | Get Upload Preset | Tool to retrieve details of a single upload preset by name. Use when you need to inspect an existing preset's configuration. |
| `CLOUDINARY_GET_USAGE` | Get Usage | Tool to get product environment usage details. Use when you need to monitor your Cloudinary account storage, bandwidth, requests, and other usage limits. Exceeding these limits can silently block uploads and other operations; check usage when operations fail unexpectedly to rule out cap exhaustion. |
| `CLOUDINARY_GET_VIDEO_VIEWS` | Get Video Views | Tool to get video analytics views from Cloudinary. Use when you need to retrieve video viewing statistics including watch time, viewer location, and device information. |
| `CLOUDINARY_IDLE_LIVE_STREAM` | Idle Live Stream | Tool to manually idle a Cloudinary live stream. Use when you need to put an active live stream into idle state without stopping it completely. |
| `CLOUDINARY_LIST_IMAGES` | List Images | Tool to list image assets from Cloudinary. Use when you need to retrieve a list of image resources, with optional filtering by prefix, tags, or public IDs. Supports pagination for large result sets. |
| `CLOUDINARY_LIST_METADATA_FIELDS` | List Metadata Fields | Tool to list all structured metadata fields defined in your Cloudinary product environment. Use to retrieve metadata schema definitions, optionally filtered by external IDs. |
| `CLOUDINARY_LIST_METADATA_RULES` | List Metadata Rules | Tool to retrieve all conditional metadata rules defined in your Cloudinary account. Use when you need to list or audit metadata rules that automatically apply values to assets based on conditions. |
| `CLOUDINARY_LIST_RAW_FILES` | List Raw Files | Tool to list raw assets from Cloudinary. Use when you need to retrieve raw files with optional filtering by prefix, tags, or public IDs. |
| `CLOUDINARY_LIST_RESOURCES_BY_ASSET_IDS` | List Resources by Asset IDs | Tool to retrieve multiple resources by their asset IDs. Use when you need to fetch details for multiple specific assets (up to 100) by their immutable asset IDs. |
| `CLOUDINARY_LIST_RESOURCES_BY_EXTERNAL_IDS` | List Resources by External IDs | Tool to retrieve resources by their external IDs. Use when you need to fetch multiple resources using external identifiers assigned during upload. |
| `CLOUDINARY_LIST_RESOURCES_BY_TAG` | List Resources by Tag | Tool to list resources (assets) with a specified tag. Use when you need to retrieve assets filtered by tag value. |
| `CLOUDINARY_LIST_RESOURCES_BY_TYPE` | List Resources by Type | Tool to retrieve resources (assets) by resource type and storage type. Use when you need to list all assets of a specific type (image, video, raw) and storage method (upload, private, etc.). |
| `CLOUDINARY_LIST_RESOURCE_TYPES` | List Resource Types | Tool to list all available resource types in your Cloudinary product environment. Use when you need to discover which resource types are available. |
| `CLOUDINARY_LIST_UPLOAD_PRESETS` | List Upload Presets | Tool to list all upload presets configured in the account. Use when you need to retrieve and paginate through upload preset configurations. For creating a new upload preset, use CLOUDINARY_CREATE_UPLOAD_PRESET. |
| `CLOUDINARY_LIST_VIDEOS` | List Video Assets | Tool to list video assets from Cloudinary. Use when you need to retrieve video assets with optional filtering by prefix, public IDs, tags, or timestamps. |
| `CLOUDINARY_MANAGE_CONTEXT` | Manage Context Metadata | Tool to add or remove contextual metadata on Cloudinary assets. Use when you need to manage custom context key-value pairs on existing assets. |
| `CLOUDINARY_ORDER_METADATA_FIELD_DATASOURCE` | Order Metadata Field Datasource | Tool to update ordering of a metadata field datasource. Use when you need to reorder enum or set values for a metadata field datasource before updating assets. |
| `CLOUDINARY_PING_CLOUDINARY_SERVERS` | Ping Cloudinary Servers | Tool to ping Cloudinary servers. Use when testing API reachability and authentication. |
| `CLOUDINARY_PUBLISH_RESOURCES` | Publish Resources | Tool to publish Cloudinary assets by public IDs, prefix, or tag. Use when you need to make authenticated or private assets publicly accessible. |
| `CLOUDINARY_RENAME_RESOURCE` | Rename or Move Resource Public ID | Tool to rename an asset's public ID using Cloudinary's rename endpoint. Use when reorganizing resources by changing public_id without re-uploading. Note: renaming changes URLs; optionally invalidate CDN caches. |
| `CLOUDINARY_REORDER_METADATA_FIELD` | Reorder Metadata Field | Tool to change the position of a specific metadata field. Use when you need to reorder a single metadata field to a specific position in the list. |
| `CLOUDINARY_REORDER_METADATA_FIELDS` | Reorder Metadata Fields | Tool to reorder all metadata fields in the product environment. Use when you need to change the display order of metadata fields based on label, creation date, or external ID. |
| `CLOUDINARY_RESTORE_ENTRIES_IN_METADATA_FIELD_DATASOURCE` | Restore Metadata Field Datasource Entries | Tool to restore previously deleted datasource entries for a metadata field. Use after deleting entries to reactivate soft-deleted datasource entries. |
| `CLOUDINARY_RESTORE_RESOURCES` | Restore Deleted Resources | Tool to restore deleted Cloudinary resources by public IDs. Use when you need to recover previously deleted assets that have backups available. Only works if backups were enabled when the resources were deleted. |
| `CLOUDINARY_RESTORE_RESOURCES_BY_ASSET_IDS` | Restore Resources by Asset IDs | Tool to restore backed up assets by asset IDs. Use when you need to restore previously backed up resources from their immutable asset IDs. The API processes each asset ID independently; some may succeed while others fail. |
| `CLOUDINARY_SEARCH_ASSETS` | Search Assets | Tool to search and filter assets using powerful query expressions. Use when you need to find specific assets by resource type, tags, metadata, or other attributes with sorting and pagination support. |
| `CLOUDINARY_SEARCH_DATASOURCE_IN_METADATA_FIELD` | Search Datasource in Metadata Field | Tool to search datasource values in a metadata field. Use when looking for specific values in enum or set metadata fields. |
| `CLOUDINARY_SEARCH_FOLDERS` | Search Folders | Tool to search asset folders with filtering, sorting, and pagination. Use when you need to locate specific folders by name, path, or creation date. |
| `CLOUDINARY_SEARCH_METADATA_FIELD_DATASOURCE` | Search All Metadata Field Datasources | Tool to search across all metadata field datasources. Use when you need to find values across multiple metadata fields without knowing the specific field ID. |
| `CLOUDINARY_SEARCH_VISUAL_ASSETS` | Visual Search Assets | Tool to find images in your asset library based on visual similarity or content. Use when searching for visually similar images using an image URL, an existing asset, or a text description. |
| `CLOUDINARY_SHOW_FOLDER` | Show Folder | Tool to list sub-folders within a specified folder. Use when you need to explore folder hierarchy or list nested folders. |
| `CLOUDINARY_UPDATE_ASSET_METADATA` | Update Asset Metadata | Tool to populate or update metadata field values on one or more Cloudinary assets. Use when you need to set structured metadata on existing assets using their public IDs. |
| `CLOUDINARY_UPDATE_FOLDER` | Update Folder | Tool to rename or move an existing asset folder. Use when you need to change the folder's name or location. |
| `CLOUDINARY_UPDATE_LIVE_STREAM` | Update Live Stream | Tool to update a live stream's configuration in Cloudinary. Use when you need to modify the name, idle timeout, or maximum runtime of an existing live stream. |
| `CLOUDINARY_UPDATE_LIVE_STREAM_OUTPUT` | Update Live Stream Output | Tool to modify an existing live stream output configuration. Use when you need to update the name, URI, stream key, or other settings of a live stream output. Note: Default HLS and archive outputs cannot be updated; only custom simulcast outputs can be modified. |
| `CLOUDINARY_UPDATE_METADATA_FIELD` | Update Metadata Field | Tool to update a metadata field definition by external ID. Use when modifying an existing schema field (e.g., changing label or validation) without redefining all properties. |
| `CLOUDINARY_UPDATE_METADATA_FIELD_DATASOURCE` | Update Metadata Field Datasource | Tool to update the datasource (allowed values) for a metadata field. Use when replacing or modifying the predefined list of values for enum or set type metadata fields. |
| `CLOUDINARY_UPDATE_METADATA_RULE` | Update Metadata Rule | Tool to update an existing conditional metadata rule. Use when you need to modify the name, condition, result, state, or position of a metadata rule. |
| `CLOUDINARY_UPDATE_RESOURCE_BY_ASSET_ID` | Update Resource by Asset ID | Tool to update asset properties by asset ID in Cloudinary. Use when you need to modify tags, metadata, display name, or other asset properties using the immutable asset ID. |
| `CLOUDINARY_UPDATE_RESOURCE_BY_PUBLIC_ID` | Update Resource by Public ID | Tool to update asset properties by public ID in Cloudinary. Use when you need to modify tags, metadata, display name, or other asset properties without re-uploading. |
| `CLOUDINARY_UPDATE_RESOURCE_TAGS` | Update Resource Tags | Tool to add, remove, replace, or remove all tags for one or more Cloudinary assets. Use when you need to manage tags on existing assets without re-uploading them. Constraint: Maximum 1000 total operations (public_ids * tags <= 1000). |
| `CLOUDINARY_UPDATE_STREAMING_PROFILE` | Update Streaming Profile | Tool to modify an existing adaptive streaming profile's configuration. Use when you need to update video quality settings for an existing profile. The updated profile will contain the new representations and display name specified in the request. |
| `CLOUDINARY_UPDATE_TRANSFORMATION2` | Update Transformation (v2) | Tool to update the definition of an existing named transformation. Use when you need to modify transformation parameters or strict mode settings for a transformation. |
| `CLOUDINARY_UPDATE_TRIGGER` | Update Trigger | Tool to update the callback URL of an existing webhook trigger. Use when you need to change the notification endpoint for a trigger by its ID. |
| `CLOUDINARY_UPDATE_UPLOAD_MAPPING` | Update Upload Mapping | Tool to update an existing upload mapping by changing its remote URL template. Use when you need to modify the URL prefix for an existing folder mapping. |
| `CLOUDINARY_UPDATE_UPLOAD_PRESET` | Update Upload Preset | Tool to update an existing upload preset's configuration settings. Use when modifying preset options like tags, transformations, or analysis features. |
| `CLOUDINARY_UPLOAD_ASSET` | Upload Asset | Tool to upload media assets (images, videos, raw files) to Cloudinary. Use when you need to upload files from local storage or remote URLs. Supports both synchronous and asynchronous uploads with various transformation and analysis options. |
| `CLOUDINARY_UPLOAD_CHUNK` | Upload File Chunk | Tool to upload a single chunk of a large file to Cloudinary. Use when implementing chunked upload for large files. All chunks of the same file must use the same x_unique_upload_id. The final chunk triggers processing and returns the complete upload response. |
| `CLOUDINARY_UPLOAD_FILE_AUTO_DETECT` | Upload File (Auto Detect) | Tool to upload files with automatic resource type detection. Use when uploading images, videos, or raw files without specifying the type. Cloudinary automatically detects whether the file is an image, video, or raw file based on its content. |

## Supported Triggers

None listed.

## Creating MCP Server - Stand-alone vs Composio SDK

The Cloudinary MCP server is an implementation of the Model Context Protocol that connects your AI agent to Cloudinary. It provides structured and secure access so your agent can perform Cloudinary operations on your behalf through a secure, permission-based interface.
With Composio's managed implementation, you don't have to create your own developer app. For production, if you're building an end product, we recommend using your own credentials. The managed server helps you prototype fast and go from 0-1 faster.

## Step-by-step Guide

### 1. Prerequisites

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

### 1. Getting API Keys for OpenAI and Composio

OpenAI API Key
- Go to the [OpenAI dashboard](https://platform.openai.com/settings/organization/api-keys) 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](https://dashboard.composio.dev?utm_source=toolkits&utm_medium=framework_docs).
- Navigate to your API settings and generate a new API key.
- Store this key securely as you'll need it for authentication.

### 2. Install required dependencies

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
```bash
npm install @ai-sdk/openai @ai-sdk/mcp @composio/core ai dotenv
```

### 3. Set up environment variables

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
```bash
OPENAI_API_KEY=your_openai_api_key_here
COMPOSIO_API_KEY=your_composio_api_key_here
COMPOSIO_USER_ID=your_user_id_here
```

### 4. Import required modules and validate environment

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
```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,
});
```

### 5. Create Tool Router session and initialize MCP client

What's happening:
- We're creating a Tool Router session that gives your agent access to Cloudinary 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 Cloudinary-related tools through the MCP protocol
```typescript
async function main() {
  // Create a tool router session for the user
  const session = await composio.create(composioUserID!, {
    toolkits: ["cloudinary"],
  });

  const mcpUrl = session.mcp.url;
```

### 6. Connect to MCP server and retrieve 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 Cloudinary tools that the agent can use
```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();
```

### 7. Initialize conversation and CLI interface

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
```typescript
let messages: ModelMessage[] = [];

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

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

rl.prompt();
```

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

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 Cloudinary 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
```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);
});
```

## Complete Code

```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: ["cloudinary"],
  });

  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 cloudinary, 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 Cloudinary 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.

## How to build Cloudinary MCP Agent with another framework

- [OpenAI Agents SDK](https://composio.dev/toolkits/cloudinary/framework/open-ai-agents-sdk)
- [Claude Agent SDK](https://composio.dev/toolkits/cloudinary/framework/claude-agents-sdk)
- [Claude Code](https://composio.dev/toolkits/cloudinary/framework/claude-code)
- [Claude Cowork](https://composio.dev/toolkits/cloudinary/framework/claude-cowork)
- [Codex](https://composio.dev/toolkits/cloudinary/framework/codex)
- [OpenClaw](https://composio.dev/toolkits/cloudinary/framework/openclaw)
- [Hermes](https://composio.dev/toolkits/cloudinary/framework/hermes-agent)
- [CLI](https://composio.dev/toolkits/cloudinary/framework/cli)
- [Google ADK](https://composio.dev/toolkits/cloudinary/framework/google-adk)
- [LangChain](https://composio.dev/toolkits/cloudinary/framework/langchain)
- [Mastra AI](https://composio.dev/toolkits/cloudinary/framework/mastra-ai)
- [LlamaIndex](https://composio.dev/toolkits/cloudinary/framework/llama-index)
- [CrewAI](https://composio.dev/toolkits/cloudinary/framework/crew-ai)

## Related Toolkits

- [Figma](https://composio.dev/toolkits/figma) - Figma is a collaborative interface design tool for teams and individuals. It streamlines design workflows with real-time collaboration and easy sharing.
- [Abyssale](https://composio.dev/toolkits/abyssale) - Abyssale is a creative automation platform for generating images, videos, GIFs, PDFs, and HTML5 content programmatically. It streamlines and scales visual content production for marketing, design, and operations teams.
- [Alttext ai](https://composio.dev/toolkits/alttext_ai) - AltText.ai is a service that generates alt text for images automatically. It helps boost accessibility and SEO for your visual content.
- [Bannerbear](https://composio.dev/toolkits/bannerbear) - Bannerbear is an API-driven platform for generating images and videos automatically at scale. It helps businesses create custom graphics, social visuals, and marketing assets using powerful templates.
- [Canva](https://composio.dev/toolkits/canva) - Canva is a drag-and-drop design suite for creating professional graphics, presentations, and marketing materials. It makes it easy for anyone to design with beautiful templates and a vast library of elements.
- [Claid ai](https://composio.dev/toolkits/claid_ai) - Claid.ai delivers AI-driven image editing APIs for tasks like background removal, upscaling, and color correction. It helps automate and enhance image workflows with powerful, developer-friendly tools.
- [Cults](https://composio.dev/toolkits/cults) - Cults is a digital marketplace for 3D printing models, connecting designers and makers. It lets creators share, sell, and discover a huge variety of printable designs easily.
- [DeepImage](https://composio.dev/toolkits/deepimage) - DeepImage is an AI-powered image enhancer and upscaler. Get higher-quality images with just a few clicks.
- [Dreamstudio](https://composio.dev/toolkits/dreamstudio) - DreamStudio is Stability AI’s platform for generating and editing images with AI. It lets you easily turn ideas into stunning visuals, fast.
- [Dynapictures](https://composio.dev/toolkits/dynapictures) - Dynapictures is a cloud-based platform for generating personalized images at scale. Instantly create hundreds of custom visuals using your data sources, like Google Sheets.
- [Fal.ai](https://composio.dev/toolkits/fal_ai) - Fal.ai is a generative media platform offering 600+ AI models for images, video, voice, and audio. Developers use Fal.ai for fast, scalable access to cutting-edge generative AI tools.
- [Gamma](https://composio.dev/toolkits/gamma) - Gamma is an AI-powered platform for making beautiful, interactive presentations and documents. It lets anyone create and share engaging decks with minimal effort.
- [Html to image](https://composio.dev/toolkits/html_to_image) - Html to image converts HTML and CSS into images or captures web page screenshots. Instantly generate visuals from code or web content—no manual screenshots needed.
- [Imagior](https://composio.dev/toolkits/imagior) - Imagior is an AI-powered image generation platform that lets you create and customize images using dynamic templates and APIs. Perfect for businesses and creators needing fast, scalable visuals without design hassle.
- [Imejis io](https://composio.dev/toolkits/imejis_io) - Imejis io is an API-based image generation platform with powerful customization and template support. It lets you create and modify images in seconds, no manual design work required.
- [Imgix](https://composio.dev/toolkits/imgix) - Imgix is a real-time image processing and delivery service for developers. It helps you optimize, transform, and deliver images efficiently at any scale.
- [Kraken io](https://composio.dev/toolkits/kraken_io) - Kraken.io is an image optimization and compression platform. It helps you shrink image file sizes while keeping visual quality intact.
- [Logo dev](https://composio.dev/toolkits/logo_dev) - Logo.dev is an API and database for high-resolution company logos and brand metadata. Instantly fetch official logos from any domain without scraping or manual searching.
- [Miro](https://composio.dev/toolkits/miro) - Miro is a collaborative online whiteboard platform for teams to brainstorm, design, and manage projects visually. It streamlines teamwork by enabling real-time idea sharing, diagramming, and workflow planning in a single space.
- [Mural](https://composio.dev/toolkits/mural) - Mural is a digital whiteboard platform for distributed visual collaboration. It helps teams brainstorm, map ideas, and diagram together in real time.

## Frequently Asked Questions

### What are the differences in Tool Router MCP and Cloudinary MCP?

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

### Can I use Tool Router MCP with Vercel AI SDK v6?

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 Cloudinary tools.

### Can I manage the permissions and scopes for Cloudinary while using Tool Router?

Yes, absolutely. You can configure which Cloudinary 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.

### How safe is my data with Composio Tool Router?

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 Cloudinary data and credentials are handled as safely as possible.

---
[See all toolkits](https://composio.dev/toolkits) · [Composio docs](https://docs.composio.dev/llms.txt)
