Using with MCP clients

Every Tool Router session provides a unique MCP server URL. This URL exposes the exact session you created - with the specific user, toolkits, and auth configs you configured. Any MCP client that supports HTTP transport can connect using just the URL and your API key.

Jump to examples for:

Claude Agent SDK

Installation

$pip install composio claude-agent-sdk

Usage

Create a Tool Router session and execute tasks with Claude:

  • Set your COMPOSIO_API_KEY environment variable with your API key from Settings.
  • Set your ANTHROPIC_API_KEY environment variable with your Anthropic API key.
1import asyncio
2import os
3from dotenv import load_dotenv
4from claude_agent_sdk.client import ClaudeSDKClient
5from claude_agent_sdk.types import ClaudeAgentOptions, AssistantMessage, TextBlock, ToolUseBlock
6from composio import Composio
7
8load_dotenv()
9
10# Initialize Composio and create a Tool Router session
11composio = Composio(api_key=os.environ["COMPOSIO_API_KEY"])
12user_id = "user_123" # Your user's unique identifier
13session = composio.create(user_id=user_id)
14
15# Configure Claude with Composio MCP server
16options = ClaudeAgentOptions(
17 system_prompt=("You are a helpful assistant with access to external tools. "
18 "Always use the available tools to complete user requests."),
19 mcp_servers={
20 "composio": {
21 "type": "http",
22 "url": session.mcp.url,
23 "headers": {"x-api-key": os.environ["COMPOSIO_API_KEY"]},
24 }
25 },
26 permission_mode="bypassPermissions",
27)
28
29
30async def main():
31 print("Starting Claude agent with Composio Tool Router...\n")
32
33 async with ClaudeSDKClient(options) as client:
34 # Initial task
35 query = ("Fetch all open issues from the composio GitHub repository "
36 "and create a Google Sheet with issue number, title, labels, and author")
37
38 print(f"Task: {query}\n")
39 print("Claude: ", end="")
40
41 await client.query(query)
42 async for msg in client.receive_response():
43 if isinstance(msg, AssistantMessage):
44 for block in msg.content:
45 if isinstance(block, ToolUseBlock):
46 print(f"\n[🔧 Using tool: {block.name}]")
47 elif isinstance(block, TextBlock):
48 print(block.text, end="")
49 print("\n")
50
51 # If authentication is needed, Claude will provide a link
52 # You can paste it back or type 'quit' to exit
53 user_input = input("\nYou (confirm connection or new task or quit): ").strip()
54
55 if user_input.lower() not in ("quit", "exit") and user_input:
56 await client.query(user_input)
57 print("\nClaude: ", end="")
58 async for msg in client.receive_response():
59 if isinstance(msg, AssistantMessage):
60 for block in msg.content:
61 if isinstance(block, TextBlock):
62 print(block.text, end="")
63 print()
64
65
66if __name__ == "__main__":
67 asyncio.run(main())

OpenAI Agents SDK

Installation

$pip install composio openai-agents

Usage

Create a Tool Router session and execute tasks with OpenAI agents:

  • Set your COMPOSIO_API_KEY environment variable with your API key from Settings.
  • Set your OPENAI_API_KEY environment variable with your OpenAI API key.
1import os
2from dotenv import load_dotenv
3from composio import Composio
4from agents import Agent, Runner, HostedMCPTool, ModelSettings
5
6# Load environment variables from .env file
7load_dotenv()
8
9composio_api_key = os.environ["COMPOSIO_API_KEY"]
10user_id = "user_123" # Your user's unique identifier
11
12print("Starting OpenAI agent with Composio...\n")
13
14# Initialize Composio and create a Tool Router session
15composio = Composio(api_key=composio_api_key)
16session = composio.create(user_id=user_id)
17
18# Configure OpenAI agent with Composio MCP server
19agent = Agent(
20 name="AI Assistant",
21 instructions=(
22 "You are a helpful assistant with access to external tools. "
23 "Always use the available tools to complete user requests instead of just explaining how to do them."
24 ),
25 model="gpt-5.1",
26 model_settings=ModelSettings(
27 reasoning={"effort": "low"},
28 ),
29 tools=[
30 HostedMCPTool(
31 tool_config={
32 "type": "mcp",
33 "server_label": "composio",
34 "server_url": session.mcp.url,
35 "require_approval": "never",
36 "headers": {"x-api-key": composio_api_key},
37 }
38 )
39 ],
40)
41
42# Optional: Pre-authorize tools before use (otherwise you'll get a link during execution)
43# connection_request = session.authorize("github")
44# print(connection_request.redirect_url)
45# connected_account = connection_request.wait_for_connection(timeout=60000)
46# print(f"Connected: {connected_account.id}")
47
48print("Running the OpenAI agent to fetch GitHub issues...\n")
49
50# Execute a task that requires GitHub access
51result = Runner.run_sync(
52 starting_agent=agent,
53 input=("Fetch all the open GitHub issues on the composio repository "
54 "and group them by bugs/features/docs.")
55)
56print(f"Result: {result.final_output}")

Vercel AI SDK

Installation

$npm install @composio/core ai @ai-sdk/anthropic @ai-sdk/mcp

Usage

Use Tool Router with Vercel AI SDK’s generateText for single completions:

  • Set your COMPOSIO_API_KEY environment variable with your API key from Settings.
  • Set your ANTHROPIC_API_KEY environment variable with your Anthropic API key.
TypeScript
1import "dotenv/config"; // Load environment variables from .env file
2import { anthropic } from "@ai-sdk/anthropic";
3import { experimental_createMCPClient as createMCPClient } from "@ai-sdk/mcp";
4import { Composio } from "@composio/core";
5import { stepCountIs, streamText } from "ai";
6const composioApiKey = process.env.COMPOSIO_API_KEY;
7const userId = "user-1234"; // Your user's unique identifier
8
9const composio = new Composio({ apiKey: composioApiKey });
10
11const { mcp } = await composio.create(userId);
12console.log(`Tool Router session created: ${mcp.url}`);
13
14const client = await createMCPClient({
15 transport: {
16 type: "http",
17 url: mcp.url,
18 headers: {
19 "x-api-key": composioApiKey,
20 },
21 },
22});
23
24const tools = await client.tools();
25
26const stream = await streamText({
27 system: "You are a helpful personal assistant. You should use composio MCP tools to take action.",
28 model: anthropic("claude-sonnet-4-5"),
29 prompt: "Summarize all the emails in my Gmail inbox today",
30 stopWhen: stepCountIs(10),
31 onStepFinish: (step) => {
32 if (step.toolCalls.length > 0) {
33 for (const toolCall of step.toolCalls) {
34 console.log(`Executed ${toolCall.toolName}`);
35 }
36 }
37 },
38 tools,
39});
40
41for await (const textPart of stream.textStream) {
42 process.stdout.write(textPart);
43}