Added waitForConnections (TypeScript) / wait_for_connections (Python) property to manage connections configuration. This allows tool router sessions to wait for users to complete authentication before proceeding to the next step.
Function to transform tool schemas before they're exposed to consumers.
This allows customizing input/output parameters, descriptions, and other metadata.
Function to intercept and modify meta tool execution parameters before the tool is executed.
This allows customizing the request based on session-specific needs.
Function to intercept and modify meta tool execution responses after the tool has executed.
This allows transforming the response or implementing custom session-specific handling.
Added getRawToolRouterMetaTools (TypeScript) / get_raw_tool_router_meta_tools (Python) method in the Tools class for fetching meta tools directly from a tool router session.
Fetches the meta tools for a tool router session.
This method fetches the meta tools from the Composio API and transforms them to the expected format.
It provides access to the underlying meta tool data without provider-specific wrapping.
@paramsessionId The session id to get the meta tools for@paramoptions Optional configuration for tool retrieval@paramoptions.modifySchema - Function to transform the tool schema@returnsThe list of meta tools@example```typescript
const metaTools = await composio.tools.getRawToolRouterMetaTools('session_123');
console.log(metaTools);
```
This change will not break your integration if you are using latest toolkit versions or fetching tools dynamically. The SDK automatically resolves the correct tool names.
If you're referencing any affected tool enums by their old names, update to the new shortened names.
Optional API Key Enforcement for MCP Servers
We've introduced a new project-level security setting that allows you to require API key authentication for all MCP server requests. This opt-in feature gives you fine-grained control over who can access your MCP endpoints.
Opt-in today, default soon: This feature is currently opt-in. Starting March 1, 2026, it will be enabled by default for new organizations. We recommend enabling it now to prepare your integrations.
A new "Require API Key for MCP" toggle is now available in your Project Settings. When enabled, all requests to your MCP servers must include a valid Composio API key in the request headers.
Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
@paramvalue A JavaScript value, usually an object or array, to be converted.@paramreplacer A function that transforms the results.@paramspace Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.@throws{TypeError} If a circular reference or a BigInt value is found.
The `console` module provides a simple debugging console that is similar to the
JavaScript console mechanism provided by web browsers.
The module exports two specific components:
* A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream.
* A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstdout) and
[`process.stderr`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module.
_**Warning**_: The global console object's methods are neither consistently
synchronous like the browser APIs they resemble, nor are they consistently
asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v24.x/api/process.html#a-note-on-process-io) for
more information.
Example using the global `console`:
```js
console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
```
Example using the `Console` class:
```js
const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
```
Prints to `stdout` with newline. Multiple arguments can be passed, with the
first used as the primary message and all additional used as substitution
values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html)
(the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args)).
```js
const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout
```
See [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args) for more information.
Tool execution errors now return a standardized response format across all failure types. Previously, the data field was empty on errors—now it always includes status_code and message, matching the structure of successful responses.
{ "data": {}, "successfull": false, "error": "404 Client Error: Not Found for url: ...",}
New error response:
{ "data": { "http_error": "404 Client Error: Not Found for url: ...", "status_code": 404, "message": "Resource not found: The requested item does not exist" }, "successfull": false, "error": "Resource not found: The requested item does not exist",}
For these toolkits, we recommend using alternative auth schemes (for example, OAUTH2, API_KEY, or other toolkit-supported schemes) instead of BEARER_TOKEN.
To upload a file via the proxy, use the binary_body field in your request payload. This supports two approaches: specifying either a URL pointing to the file or providing the base64-encoded content directly.
When the proxied request returns a binary response (for example, a PDF or image), the proxy automatically uploads the file to temporary storage, and you receive a signed URL in the binary_data field. This enables you to download large files securely.
{ "data": {}, "binary_data": { "url": "url to the file", "content_type": "content type of the file", "size": "size of the file", "expires_at": "expires at of the file" }, "status": "status code of the response", "headers": "headers of the response"}
We'd love your feedback on the new proxy execute capabilities. If anything feels unclear or you have suggestions for improvement, please reach out.
Webhook Payload V3 - Lookahead Announcement
We're introducing Webhook Payload V3 - a redesigned webhook structure that follows industry standards and provides better developer experience. This update affects how you receive trigger events via webhooks and Pusher.
Metadata Separation: Composio-specific fields (connection IDs, trigger IDs, user IDs) are now in a dedicated metadata object
Clean Data: The data field now contains only the actual trigger payload without infrastructure metadata
Standardized Type Field: The type field now follows a consistent format (composio.trigger.message) instead of trigger-specific names like gmail_new_gmail_message
Trigger Slug in Metadata: The trigger slug (e.g., GMAIL_NEW_GMAIL_MESSAGE) is now available in metadata.trigger_slug for easy identification
Standards Compliance: Follows Standard Webhooks specification for better interoperability
Consistent Structure: Same payload structure for both webhooks and Pusher channels
This release includes significant authentication and configuration improvements across 16+ toolkits. The changes standardize Base URL handling, modernize authentication methods, and fix various endpoint configurations to improve reliability and flexibility.
Toolkit
Change Type
Description
Make
Breaking
Removed Region field, replaced with Base URL
Linear
Improvement
Base URL is no longer configurable
Kibana
Improvement
Removed default value for Base URL
Insightly
Fix
Added default value for Pod field
HelloBar
Deprecated
Deprecated bearer authentication
Gong
Fix
Added default value for Base URL
FormSite
Deprecated
Deprecated bearer auth, added API key authentication
DataScope
Fix
Fixed Get Current User Endpoint
D2L Brightspace
Fix
Updated Get Current User Endpoint
ClickUp
Fix
Changed Base URL field type
Bubble
Breaking
Fixed Base URL field, removed Subdomain
Brilliant Directories
Fix
Implemented dynamic Base URL for user endpoint
Braintree
Improvement
Updated to production defaults with dynamic endpoints
Auth0
Improvement
Replaced hardcoded endpoint with dynamic tenant Base URL
Linear Toolkit - Base URL is no longer a configurable field. The toolkit now uses a fixed endpoint, simplifying the authentication process.
Kibana Toolkit - Removed the default value for Base URL, allowing for more flexible deployment configurations. Users can now specify custom Kibana instances without overriding defaults.
Gong Toolkit - Added a sensible default value for Base URL to simplify initial setup. New users can connect without manually configuring the endpoint.
Insightly Toolkit - Added default value for the Pod field to streamline configuration. Reduces setup complexity for standard deployments.
ClickUp Toolkit - Fixed the Base URL field type for proper validation and handling. Ensures consistent URL formatting across all operations.
Brilliant Directories Toolkit - Implemented dynamic Base URL resolution for the Get Current User Endpoint. Automatically adapts to different deployment environments.
Braintree Toolkit - Updated configuration to use production defaults. Implemented dynamic endpoint resolution for better environment handling. Improved reliability for production deployments.
Auth0 Toolkit - Replaced hardcoded endpoints with dynamic tenant-based URL resolution. Supports multi-tenant deployments without manual configuration. Automatically constructs the correct endpoint based on the tenant configuration.
DataScope Toolkit - Fixed the Get Current User Endpoint to use the correct API path. Resolves authentication verification issues.
D2L Brightspace Toolkit - Updated the Get Current User Endpoint to match the latest API specifications. Ensures proper user identification and session validation.
These toolkits had incorrect or outdated authentication configurations that needed fixing. We verified that active usage for these toolkits is practically zero before proceeding with these changes.
Impact: Existing connections will stop working. You'll need to create new auth configs and ask affected users to reconnect.
Replaced region-based configuration with full base URL input. Users now provide the complete Make instance URL (e.g., https://us2.make.com or https://us1.make.celonis.com) instead of just a region code.
Updated from region-based to full base URL configuration. Fixed field descriptions and metadata. Updated categories to AI/Productivity/Communication and added proper documentation links.
Simplified authentication by removing deprecated Project ID field. Added conditional mapping for region codes to API subdomains (AU→f1db6c, EU→d7b62b, US→bcbe5a). Region field now defaults to US.
Added new OAuth2 authentication scheme with comprehensive scopes for contacts, companies, audiences, scoops, news, and intent data. Deprecated the old JWT-based Basic authentication. Password field now properly marked as secret.
No Action Required: Old JWT auth continues to function. New connections will use OAuth2.
Fixed region mapping logic for data residency. Added proper conditional evaluation to map regions to correct API hosts (EU, India, or Standard). Region field is now optional and defaults to Standard server. Service account secret now properly marked as secret.
No Action Required: Existing connections continue to work without changes.
Changed base_url field type from auth_config_field to connection_field for both OAuth and API Key schemes. Updated base action logic to respect user-provided base URLs, enabling support for self-hosted Supabase instances.
No Action Required: Existing connections continue to work. Self-hosted instances now supported.
We're deprecating 15 toolkits that currently have no supported actions. These toolkits will be reactivated once we add functional actions to them, ensuring you only see integrations that are ready to use.
We're deprecating 60 toolkits that currently have no supported actions. These toolkits will be reactivated once we add functional actions to them, ensuring you only see integrations that are ready to use.
The is_local_toolkit field in toolkit API responses is now deprecated. This field was originally intended to indicate whether a toolkit was local to a specific project, but it is no longer meaningful as no toolkits use this classification.
Affected Endpoints:
GET /api/v3/toolkits - List toolkits
GET /api/v3/toolkits/{slug} - Get single toolkit
GET /api/v3/toolkits/multi - Get multiple toolkits
The field will continue to be returned in API responses for backward compatibility, but it will always return false. It is marked as deprecated: true in the OpenAPI specification.
The field will continue to be present in responses but will always return false. You can safely ignore this field or remove any logic that depends on it.
Before:
constconst toolkit: anytoolkit = awaitcomposio.toolkits.get('github');if (const toolkit: anytoolkit.is_local_toolkit) { // This condition will never be truehandleLocalToolkit(const toolkit: anytoolkit);}
The Composio SDKs achieved a significant milestone with Tool Router moving from experimental to stable production status in December 2025. The Tool Router is now a fully supported feature that enables creating isolated MCP sessions with scoped toolkit access across both Python 0.10.1 and TypeScript 0.3.0.
Native Tool Execution: Both SDKs now support direct tool execution through Tool Router sessions. The TypeScript implementation emphasizes improved type safety and error handling, while Python developers benefit from better integration with provider-wrapped tools.
Webhook Security: A new verification method was introduced. The system now provides secure webhook endpoint validation and signature verification for incoming webhooks, enhancing protection for trigger-based workflows.
Framework Compatibility: The stable Tool Router integrates with multiple AI platforms including OpenAI, Anthropic, LangChain, LlamaIndex, CrewAI, and Vercel AI SDK.
The TypeScript SDK resolved significant CommonJS compatibility issues by switching bundlers. This addresses a common developer pain point, particularly for Node.js projects not using ES modules.
The Python SDK extended LangChain provider support to version 1, while simultaneously fixing a critical KeyError occurring when SUPABASE_BETA_RUN_SQL_QUERY is used with Agents.
Users upgrading from experimental APIs should note the simplified approach—the Tool Router API now operates directly rather than through experimental namespaces, with comprehensive migration documentation provided.
Removal of label query parameter from connected accounts API
The label query parameter has been removed from the GET /api/v3/connected_accounts endpoint.
The label query parameter is no longer supported when listing connected accounts. This parameter was previously accepted but had no functional behavior since label ingestion was removed in an earlier update.
None - This is a cleanup change. The label query parameter was not performing any filtering since the underlying label ingestion functionality was already removed. If your code was passing this parameter, it was being silently ignored.
We've updated many toolkits so their outputs are now strongly typed objects instead of a generic response_data blob, meaning tools like Outlook, HubSpot, Notion, etc. now return well-shaped, documented fields you can rely on directly in your code and agents. These improvements apply to the latest toolkit versions—see our toolkit versioning docs for how versions are managed.
Breaking Change for latest Version
If you're using the latest version and your code post-processes the old response_data structure, you'll need to update your code to work with the new flattened, typed response schemas.
Breaking change for consumers on the latest version who post-process the old nested response_data shape: outputs are now flattened and explicitly typed.
New and modified fields include richer descriptions and examples; some legacy placeholders were removed.
Re-fetch schemas for your tool/version to see the typed definitions. Use the toolkit view in platform.composio.dev for authoritative field details.
Transition to Self-Managed Credentials for Select Applications
This is a non-breaking change. Your existing integrations will continue to work as expected. This change only affects new integrations with the applications listed below.
To continue using these applications with Composio:
Create Developer Accounts: Register for developer accounts on the platforms you need
Generate API Credentials: Create OAuth apps following each platform's documentation
Configure in Composio: Add your credentials to Composio using custom auth configs
Test Your Integration: Test your integration with the new credentials
All other Composio applications continue to work with Composio-managed credentials. This change only affects the 12 applications listed above.
Connected Account Expiration for Incomplete Connections
We're implementing automatic expiration for connected accounts that remain in incomplete states, helping maintain a cleaner and more efficient authentication system.
Connected accounts in Initializing and Initiated states will now automatically expire after 10 minutes. This applies to connection attempts that were started but never completed.
Better Resource Management: Automatically cleans up incomplete connection attempts
Improved System Hygiene: Prevents accumulation of stale, unused connection records
Enhanced User Experience: Reduces clutter from abandoned authentication flows
This is a non-breaking change. Your existing integrations and completed connections will continue to work as expected. This change only affects connection attempts that are never completed.
Starting December 15th, 2025, all new Composio projects must include the x-api-key header when making requests to MCP URLs. This header authenticates your application and ensures secure communication with the Composio platform.
For existing projects: We value backward compatibility and understand the need for a smooth transition. Your existing MCP URLs will continue to work without the x-api-key header until April 15th, 2026.
Important: After April 15th, 2026, all MCP URL requests without the x-api-key header will be rejected. Please ensure you update your applications before this date to avoid service disruption.
Note: If you're already passing the x-api-key header in your MCP requests, no action is required—you're all set!
If you have any questions about this security enhancement or need assistance with migration, please reach out to our support team or check our MCP documentation.
Added toolkit version support to trigger operations (create and getType) in both Python and TypeScript SDKs. This allows users to explicitly specify which toolkit version to use when creating trigger instances and retrieving trigger type information, ensuring consistent behavior across different toolkit versions.
Trigger operations now respect the global toolkitVersions configuration set during Composio initialization, providing better control over which trigger versions are used in your applications.
toolkitVersions: { github: stringgithub: '10082025_01' }});// Get trigger type for specific versionconstconst triggerType: anytriggerType = awaitconst composio: anycomposio.triggers.getType('GITHUB_COMMIT_EVENT');// Returns trigger type for version '10082025_01'
# Pythoncomposio = Composio( api_key="your-api-key", toolkit_versions={"github": "10082025_01"})# Get trigger type for specific versiontrigger_type = composio.triggers.get_type("GITHUB_COMMIT_EVENT")# Returns trigger type for version '10082025_01'
We're introducing improved security requirements for Model Context Protocol (MCP) URLs to ensure better isolation between user connections and prevent unauthorized access.
For existing projects: We understand the importance of backward compatibility. While we've sent email notifications to project owners about upgrading their MCP URLs, your existing integrations will continue to work until January 15th, 2026.
Important: After January 15th, 2026, MCP URLs without user_id or connected_account_id query parameters will no longer be supported. Please ensure you update your MCP URLs before this date to avoid service disruption.
Note: If your MCP URLs already include either user_id or connected_account_id query parameters, no action is required—you can safely ignore this notice.
If you have any questions about this security enhancement or need assistance with migration, please reach out to our support team or check our MCP documentation.
Adds Version Checks for Tool Execution and Improved Execution Speed in TS SDK
Added version validation for manual tool execution to prevent unexpected behavior when using latest toolkit versions. This ensures users explicitly specify toolkit versions when executing tools manually, while allowing flexibility through a skip flag.
This release also eliminates a lot of redundant API calls made to check connected account during tool execution, effectively increasing the performance of tool execution.
Manual tool execution without version specification now throws an error. Users must either:
Pass explicit version parameter
Configure toolkit versions in SDK initialization
Set environment variable COMPOSIO_TOOLKIT_VERSION_<TOOLKIT_SLUG>
Use dangerously_skip_version_check=True flag
MCP (Model Control Protocol) & Experimental ToolRouter
Composio now introduces comprehensive MCP (Model Control Protocol) support and an experimental ToolRouter for creating isolated, scoped sessions with advanced toolkit management. These features enable seamless integration with modern AI frameworks and provide powerful session-based tool routing capabilities.
Creates a new instance of the Composio SDK.
The constructor initializes the SDK with the provided configuration options,
sets up the API client, and initializes all core models (tools, toolkits, etc.).
@paramconfig - Configuration options for the Composio SDK@paramconfig.apiKey - The API key for authenticating with the Composio API@paramconfig.baseURL - The base URL for the Composio API (defaults to production URL)@paramconfig.allowTracking - Whether to allow anonymous usage analytics@paramconfig.provider - The provider to use for this Composio instance (defaults to OpenAIProvider)@example```typescript
// Initialize with default configuration
const composio = new Composio();
// Initialize with custom API key and base URL
const composio = new Composio({
apiKey: 'your-api-key',
baseURL: 'https://api.composio.dev'
});
// Initialize with custom provider
const composio = new Composio({
apiKey: 'your-api-key',
provider: new CustomProvider()
});
```
Composio({apiKey?: string | null | undefined
The API key for the Composio API.
@example'sk-1234567890'
apiKey: var process: NodeJS.Processprocess.NodeJS.Process.env: NodeJS.ProcessEnv
The `process.env` property returns an object containing the user environment.
See [`environ(7)`](http://man7.org/linux/man-pages/man7/environ.7.html).
An example of this object looks like:
```js
{
TERM: 'xterm-256color',
SHELL: '/usr/local/bin/bash',
USER: 'maciej',
PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin',
PWD: '/Users/maciej',
EDITOR: 'vim',
SHLVL: '1',
HOME: '/Users/maciej',
LOGNAME: 'maciej',
_: '/usr/local/bin/node'
}
```
It is possible to modify this object, but such modifications will not be
reflected outside the Node.js process, or (unless explicitly requested)
to other `Worker` threads.
In other words, the following example would not work:
```bash
node -e 'process.env.foo = "bar"' && echo $foo
```
While the following will:
```js
import { env } from 'node:process';
env.foo = 'bar';
console.log(env.foo);
```
Assigning a property on `process.env` will implicitly convert the value
to a string. **This behavior is deprecated.** Future versions of Node.js may
throw an error when the value is not a string, number, or boolean.
```js
import { env } from 'node:process';
env.test = null;
console.log(env.test);
// => 'null'
env.test = undefined;
console.log(env.test);
// => 'undefined'
```
Use `delete` to delete a property from `process.env`.
```js
import { env } from 'node:process';
env.TEST = 1;
delete env.TEST;
console.log(env.TEST);
// => undefined
```
On Windows operating systems, environment variables are case-insensitive.
```js
import { env } from 'node:process';
env.TEST = 1;
console.log(env.test);
// => 1
```
Unless explicitly specified when creating a `Worker` instance,
each `Worker` thread has its own copy of `process.env`, based on its
parent thread's `process.env`, or whatever was specified as the `env` option
to the `Worker` constructor. Changes to `process.env` will not be visible
across `Worker` threads, and only the main thread can make changes that
are visible to the operating system or to native add-ons. On Windows, a copy of `process.env` on a `Worker` instance operates in a case-sensitive manner
unlike the main thread.
@paramparams - Parameters for creating the MCP configuration@paramparams.authConfig - Array of auth configurations with id and allowed tools@paramparams.options - Configuration options@paramparams.options.name - Unique name for the MCP configuration@paramparams.options.manuallyManageConnections - Whether to use chat-based authentication or manually connect accounts@returnsCreated server details with instance getter@example```typescript
const server = await composio.mcpConfig.create("personal-mcp-server", {
toolkits: ["github", "slack"],
allowedTools: ["GMAIL_FETCH_EMAILS", "SLACK_SEND_MESSAGE"],
manuallyManageConnections: false
}
});
const server = await composio.mcpConfig.create("personal-mcp-server", {
toolkits: [{ toolkit: "gmail", authConfigId: "ac_243434343" }],
allowedTools: ["GMAIL_FETCH_EMAILS"],
manuallyManageConnections: false
}
});
```
Get server URLs for an existing MCP server.
The response is wrapped according to the provider's specifications.
@example```typescript
import { Composio } from "@composio/code";
const composio = new Composio();
const mcp = await composio.experimental.mcp.generate("default", "<mcp_config_id>");
```@paramuserId external user id from your database for whom you want the server for@parammcpConfigId config id of the MCPConfig for which you want to create a server for@paramoptions additional options@paramoptions.isChatAuth Authenticate the users via chat when they use the MCP Server
The `console` module provides a simple debugging console that is similar to the
JavaScript console mechanism provided by web browsers.
The module exports two specific components:
* A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream.
* A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstdout) and
[`process.stderr`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module.
_**Warning**_: The global console object's methods are neither consistently
synchronous like the browser APIs they resemble, nor are they consistently
asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v24.x/api/process.html#a-note-on-process-io) for
more information.
Example using the global `console`:
```js
console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
```
Example using the `Console` class:
```js
const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
```
Prints to `stdout` with newline. Multiple arguments can be passed, with the
first used as the primary message and all additional used as substitution
values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html)
(the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args)).
```js
const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout
```
See [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args) for more information.
// Vercel AI Integrationimport { class SSEClientTransport
Client transport for SSE: this will connect to a server using Server-Sent Events for receiving
messages and make separate POST requests for sending messages.
@deprecatedSSEClientTransport is deprecated. Prefer to use StreamableHTTPClientTransport where possible instead. Note that because some servers are still using SSE, clients may need to support both transports during the migration period.
Client transport for SSE: this will connect to a server using Server-Sent Events for receiving
messages and make separate POST requests for sending messages.
@deprecatedSSEClientTransport is deprecated. Prefer to use StreamableHTTPClientTransport where possible instead. Note that because some servers are still using SSE, clients may need to support both transports during the migration period.
The `console` module provides a simple debugging console that is similar to the
JavaScript console mechanism provided by web browsers.
The module exports two specific components:
* A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream.
* A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstdout) and
[`process.stderr`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module.
_**Warning**_: The global console object's methods are neither consistently
synchronous like the browser APIs they resemble, nor are they consistently
asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v24.x/api/process.html#a-note-on-process-io) for
more information.
Example using the global `console`:
```js
console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
```
Example using the `Console` class:
```js
const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
```
Prints to `stdout` with newline. Multiple arguments can be passed, with the
first used as the primary message and all additional used as substitution
values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html)
(the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args)).
```js
const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout
```
See [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args) for more information.
The `console` module provides a simple debugging console that is similar to the
JavaScript console mechanism provided by web browsers.
The module exports two specific components:
* A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream.
* A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstdout) and
[`process.stderr`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module.
_**Warning**_: The global console object's methods are neither consistently
synchronous like the browser APIs they resemble, nor are they consistently
asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v24.x/api/process.html#a-note-on-process-io) for
more information.
Example using the global `console`:
```js
console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
```
Example using the `Console` class:
```js
const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
```
Prints to `stdout` with newline. Multiple arguments can be passed, with the
first used as the primary message and all additional used as substitution
values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html)
(the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args)).
```js
const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout
```
See [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args) for more information.
Tool Filtering: Specify allowed tools across all toolkits
User Instance Generation: Generate user-specific MCP server instances
Basic Usage:
from composio import Composiocomposio = Composio()# Create MCP server with toolkit configurationsserver = composio.mcp.create( 'personal-mcp-server', toolkits=[ { 'toolkit': 'github', 'auth_config_id': 'ac_xyz', }, { 'toolkit': 'slack', 'auth_config_id': 'ac_abc', }, ], allowed_tools=['GITHUB_CREATE_ISSUE', 'SLACK_SEND_MESSAGE'], manually_manage_connections=False)# Generate server instance for a usermcp_instance = server.generate('user_12345')print(f"MCP URL: {mcp_instance['url']}")
Simple Toolkit Usage:
# Using simple toolkit namesserver = composio.mcp.create( 'simple-mcp-server', toolkits=['composio_search', 'text_to_pdf'], allowed_tools=['COMPOSIO_SEARCH_DUCK_DUCK_GO_SEARCH', 'TEXT_TO_PDF_CONVERT_TEXT_TO_PDF'])# All tools from toolkits (default behavior)server = composio.mcp.create( 'all-tools-server', toolkits=['composio_search', 'text_to_pdf'] # allowed_tools=None means all tools from these toolkits)
Creates a new instance of the Composio SDK.
The constructor initializes the SDK with the provided configuration options,
sets up the API client, and initializes all core models (tools, toolkits, etc.).
@paramconfig - Configuration options for the Composio SDK@paramconfig.apiKey - The API key for authenticating with the Composio API@paramconfig.baseURL - The base URL for the Composio API (defaults to production URL)@paramconfig.allowTracking - Whether to allow anonymous usage analytics@paramconfig.provider - The provider to use for this Composio instance (defaults to OpenAIProvider)@example```typescript
// Initialize with default configuration
const composio = new Composio();
// Initialize with custom API key and base URL
const composio = new Composio({
apiKey: 'your-api-key',
baseURL: 'https://api.composio.dev'
});
// Initialize with custom provider
const composio = new Composio({
apiKey: 'your-api-key',
provider: new CustomProvider()
});
```
Composio();// Old MCP server creationconstconst legacyMCP: anylegacyMCP = awaitconst composio: Composio<OpenAIProvider>composio.deprecated.mcp.createServer({name: stringname: 'my-server',toolkits: string[]toolkits: ['github', 'gmail'],});// Direct URL usageconstconst mcpUrl: anymcpUrl =const legacyMCP: anylegacyMCP.url;
Creates a new instance of the Composio SDK.
The constructor initializes the SDK with the provided configuration options,
sets up the API client, and initializes all core models (tools, toolkits, etc.).
@paramconfig - Configuration options for the Composio SDK@paramconfig.apiKey - The API key for authenticating with the Composio API@paramconfig.baseURL - The base URL for the Composio API (defaults to production URL)@paramconfig.allowTracking - Whether to allow anonymous usage analytics@paramconfig.provider - The provider to use for this Composio instance (defaults to OpenAIProvider)@example```typescript
// Initialize with default configuration
const composio = new Composio();
// Initialize with custom API key and base URL
const composio = new Composio({
apiKey: 'your-api-key',
baseURL: 'https://api.composio.dev'
});
// Initialize with custom provider
const composio = new Composio({
apiKey: 'your-api-key',
provider: new CustomProvider()
});
```
Composio({apiKey?: string | null | undefined
The API key for the Composio API.
@example'sk-1234567890'
apiKey: var process: NodeJS.Processprocess.NodeJS.Process.env: NodeJS.ProcessEnv
The `process.env` property returns an object containing the user environment.
See [`environ(7)`](http://man7.org/linux/man-pages/man7/environ.7.html).
An example of this object looks like:
```js
{
TERM: 'xterm-256color',
SHELL: '/usr/local/bin/bash',
USER: 'maciej',
PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin',
PWD: '/Users/maciej',
EDITOR: 'vim',
SHLVL: '1',
HOME: '/Users/maciej',
LOGNAME: 'maciej',
_: '/usr/local/bin/node'
}
```
It is possible to modify this object, but such modifications will not be
reflected outside the Node.js process, or (unless explicitly requested)
to other `Worker` threads.
In other words, the following example would not work:
```bash
node -e 'process.env.foo = "bar"' && echo $foo
```
While the following will:
```js
import { env } from 'node:process';
env.foo = 'bar';
console.log(env.foo);
```
Assigning a property on `process.env` will implicitly convert the value
to a string. **This behavior is deprecated.** Future versions of Node.js may
throw an error when the value is not a string, number, or boolean.
```js
import { env } from 'node:process';
env.test = null;
console.log(env.test);
// => 'null'
env.test = undefined;
console.log(env.test);
// => 'undefined'
```
Use `delete` to delete a property from `process.env`.
```js
import { env } from 'node:process';
env.TEST = 1;
delete env.TEST;
console.log(env.TEST);
// => undefined
```
On Windows operating systems, environment variables are case-insensitive.
```js
import { env } from 'node:process';
env.TEST = 1;
console.log(env.test);
// => 1
```
Unless explicitly specified when creating a `Worker` instance,
each `Worker` thread has its own copy of `process.env`, based on its
parent thread's `process.env`, or whatever was specified as the `env` option
to the `Worker` constructor. Changes to `process.env` will not be visible
across `Worker` threads, and only the main thread can make changes that
are visible to the operating system or to native add-ons. On Windows, a copy of `process.env` on a `Worker` instance operates in a case-sensitive manner
unlike the main thread.
@paramparams - Parameters for creating the MCP configuration@paramparams.authConfig - Array of auth configurations with id and allowed tools@paramparams.options - Configuration options@paramparams.options.name - Unique name for the MCP configuration@paramparams.options.manuallyManageConnections - Whether to use chat-based authentication or manually connect accounts@returnsCreated server details with instance getter@example```typescript
const server = await composio.mcpConfig.create("personal-mcp-server", {
toolkits: ["github", "slack"],
allowedTools: ["GMAIL_FETCH_EMAILS", "SLACK_SEND_MESSAGE"],
manuallyManageConnections: false
}
});
const server = await composio.mcpConfig.create("personal-mcp-server", {
toolkits: [{ toolkit: "gmail", authConfigId: "ac_243434343" }],
allowedTools: ["GMAIL_FETCH_EMAILS"],
manuallyManageConnections: false
}
});
```
Get server URLs for an existing MCP server.
The response is wrapped according to the provider's specifications.
@example```typescript
import { Composio } from "@composio/code";
const composio = new Composio();
const mcp = await composio.experimental.mcp.generate("default", "<mcp_config_id>");
```@paramuserId external user id from your database for whom you want the server for@parammcpConfigId config id of the MCPConfig for which you want to create a server for@paramoptions additional options@paramoptions.isChatAuth Authenticate the users via chat when they use the MCP Server
Phase 1: New MCP API available alongside legacy implementation
Phase 2: Legacy MCP accessible via deprecated.mcp namespace
Phase 3: Full deprecation (timeline to be announced)
Recommendation: Start new projects with the new MCP API and gradually migrate existing implementations to benefit from enhanced features and better framework integration.
Both MCP and ToolRouter features are designed to complement existing Composio functionality:
// Can be used alongside regular tool managementconstconst regularTools: anyregularTools = awaitcomposio.tools.get({ toolkits: string[]toolkits: ['github'] });constconst mcpSession: anymcpSession = awaitcomposio.experimental.toolRouter.createSession(userId, {toolkits: string[]toolkits: ['gmail', 'slack']});// Both approaches can coexist and serve different purposes
The experimental ToolRouter API provides a preview of advanced session management capabilities, while the MCP API offers production-ready Model Control Protocol support for modern AI frameworks.
ToolRouter Functionality: Fixed ToolRouter tests that were failing due to missing tool_router attribute in HttpClient
Dependency Update: Updated composio-client dependency from version 1.9.1 to 1.10.0+ to include ToolRouter functionality
Version Compatibility: Resolved compatibility issues between ToolRouter implementation and client library
Details:
ToolRouter functionality was briefly broken in versions 0.8.15 to 0.8.18 due to a dependency version mismatch. The composio-client library version 1.9.1 did not include the tool_router attribute, causing all ToolRouter integration tests to fail with AttributeError: 'HttpClient' object has no attribute 'tool_router'.
This has been fixed in version 0.8.19 by:
Updating the composio-client dependency to version 1.10.0+
Ensuring all ToolRouter functionality is now available
All ToolRouter integration tests now pass successfully
Previous Issue:
# This would fail in versions 0.8.15-0.8.18session = composio.experimental.tool_router.create_session(user_id='test')# AttributeError: 'HttpClient' object has no attribute 'tool_router'
Fixed in 0.8.19:
# This now works correctlysession = composio.experimental.tool_router.create_session(user_id='test')# Returns: {'session_id': '...', 'url': '...'}
Field Documentation: Improved field documentation and help text for better developer experience
Details:
Previously, when developers were setting up auth configurations for toolkits, many fields lacked proper descriptions, making it difficult to understand what information was required. This fix ensures all auth config fields now include:
Clear, descriptive field labels
Helpful placeholder text where appropriate
Detailed explanations of field requirements
This improvement affects all toolkits and makes the authentication setup process more intuitive and error-free.
Toolkit Versioning in SDKs
Composio Toolkit Versioning provides granular control over tool versions across all your integrations. Instead of always using the latest version of tools, developers can now specify exact toolkit versions, ensuring consistent behavior and controlled updates in production environments.
Toolkit Versioning Support: New toolkit_versions parameter for controlling tool versions
Added toolkit_versions parameter to Composio class initialization
Support for global version setting (e.g., 'latest')
Support for per-toolkit version mapping (e.g., {'github': '20250902_00', 'slack': '20250902_00'})
Environment variable support with COMPOSIO_TOOLKIT_VERSION_<TOOLKIT_NAME> pattern
New toolkit_version.py utility module for version resolution logic
Examples:
# Global version for all toolkits, only `latest` is supportedcomposio = Composio(toolkit_versions='latest')# Per-toolkit version mappingcomposio = Composio(toolkit_versions={ 'github': '20250902_00', 'slack': '20250902_00', 'gmail': '20250901_01'})# Using environment variables# Set COMPOSIO_TOOLKIT_VERSION_GITHUB=20250902_00composio = Composio() # Automatically picks up env vars# Get tools with specific versionstools = composio.tools.get('default', {'toolkits': ['github']})
New toolkitVersions parameter in Composio class constructor
Support for global version string or per-toolkit version mapping
Environment variable parsing with getToolkitVersionsFromEnv() utility
Enhanced getRawComposioToolBySlug() method for version-specific tool retrieval
Version-aware tool filtering and search capabilities
Examples:
// Global version for all toolkitsconstconst composio: anycomposio = newComposio({toolkitVersions: stringtoolkitVersions: '20250902_00'});// Per-toolkit version mappingconstconst composio: anycomposio = newComposio({
Toolkit versions follow the format: YYYYMMDD_NN (e.g., 20250902_00) or use 'latest' for the most recent version only supported at global scope and not individual toolkit level.
# Set specific versions for different toolkitsexport COMPOSIO_TOOLKIT_VERSION_GITHUB=20250902_00export COMPOSIO_TOOLKIT_VERSION_SLACK=20250902_00export COMPOSIO_TOOLKIT_VERSION_GMAIL=20250901_01
This feature is fully backward compatible. Existing code will continue to work without changes, using the latest versions by default. To enable versioning, simply add the toolkit_versions parameter during SDK initialization.
Package Updates: Bumped all Python provider packages to v0.8.10
Documentation: Enhanced API documentation with versioning examples
Testing: Added comprehensive test coverage (400+ new test cases) for versioning functionality
Examples: New versioning examples demonstrating practical usage patterns
Introducing Composio Auth Links
Composio Auth Links provide a hosted authentication solution that eliminates the need for developers to build custom authentication forms. Instead of manually rendering OAuth consent screens, API key input forms, or custom authentication fields, developers can simply redirect users to a Composio-hosted URL that handles the entire authentication process automatically.
Composio Connect Link Support: New link() method for creating external authentication links
Added link() method to ConnectedAccounts class for generating user authentication links
Support for callback URL redirection after authentication
Enhanced user experience with external link-based authentication flow
No manual form rendering required - Composio handles all authentication UI
Examples:
# Basic usage - create a connection requestconnection_request = composio.connected_accounts.link('user_123', 'auth_config_123')redirect_url = connection_request.redirect_urlprint(f"Visit: {redirect_url} to authenticate your account")# Wait for the connection to be establishedconnected_account = connection_request.wait_for_connection()# With callback URLconnection_request = composio.connected_accounts.link( 'user_123', 'auth_config_123', callback_url='<https://your-app.com/callback>')
The `console` module provides a simple debugging console that is similar to the
JavaScript console mechanism provided by web browsers.
The module exports two specific components:
* A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream.
* A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstdout) and
[`process.stderr`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module.
_**Warning**_: The global console object's methods are neither consistently
synchronous like the browser APIs they resemble, nor are they consistently
asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v24.x/api/process.html#a-note-on-process-io) for
more information.
Example using the global `console`:
```js
console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
```
Example using the `Console` class:
```js
const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
```
Prints to `stdout` with newline. Multiple arguments can be passed, with the
first used as the primary message and all additional used as substitution
values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html)
(the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args)).
```js
const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout
```
See [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
log(`Visit: ${const redirectUrl: anyredirectUrl} to authenticate your account`);// Wait for the connection to be establishedconstconst connectedAccount: anyconnectedAccount = awaitconst connectionRequest: anyconnectionRequest.waitForConnection();// With callback URLconstconst connectionRequest: anyconnectionRequest = awaitcomposio.connectedAccounts.link('user_123', 'auth_config_123', {callbackUrl: stringcallbackUrl: '<https://your-app.com/callback>'});
You can customise the app logo and name showed in the authentication page via the dashboard. Head over your project via platform.composio.dev and choose Settings → Auth Links to upload a new logo and change the name.
This feature replaces manual authentication form development with a simple redirect-based approach, significantly reducing integration time and complexity while providing a better user experience. Auth links are drop in replacement for composio.connectedAccounts.initate, you can safely swap this to composio.connectedAccounts.link