Native Tools vs MCP
Native tools give your LLM tool schemas as function definitions. Composio formats them for your specific framework (OpenAI, Anthropic, Vercel AI, etc.) through provider packages.
MCP exposes tools through the Model Context Protocol. Any MCP-compatible client can connect to a Composio MCP server URL. No provider packages needed.
| Native tools | MCP | |
|---|---|---|
| Setup | Provider package for your framework | SDK or just a URL |
| Intercepting tool calls | Yes, you can log, retry, or require approval before each call | Limited, depends on what the MCP client supports |
| Context window | You control what's loaded | Client loads all tools the server exposes |
| Latency | SDK calls Composio API directly | MCP protocol adds overhead for tool list discovery and each execution |
With native tools, you choose exactly which schemas enter your LLM's context. With MCP, the client pulls the full tool list from the server. A 5-server setup can consume ~55K tokens before the conversation starts. If you're working with many tools, native tools give you more control over that cost.
Native tools
from composio import Composio
from composio_openai import OpenAIProvider
composio = Composio(provider=OpenAIProvider())
session = composio.create(user_id="user_123")
tools = session.tools()
# Returns meta tools (COMPOSIO_SEARCH_TOOLS, COMPOSIO_MANAGE_CONNECTIONS, etc.)
# Agent discovers and executes tools at runtimeimport { Composio } from '@composio/core';
import { OpenAIProvider } from '@composio/openai';
const composio = new Composio({
apiKey: process.env.COMPOSIO_API_KEY,
provider: new OpenAIProvider(),
});
const session = await composio.create("user_123");
const tools = await session.tools();
// Returns meta tools (COMPOSIO_SEARCH_TOOLS, COMPOSIO_MANAGE_CONNECTIONS, etc.)MCP
from composio import Composio
composio = Composio()
session = composio.create(user_id="user_123")
mcp_url = session.mcp.url
mcp_headers = session.mcp.headersimport { Composio } from '@composio/core';
const composio = new Composio();
const session = await composio.create("user_123");
const mcpUrl = session.mcp.url;
const mcpHeaders = session.mcp.headers;Then pass session.mcp.url and session.mcp.headers to your framework:
from agents import Agent, HostedMCPTool
agent = Agent(
name="Assistant",
tools=[
HostedMCPTool(
tool_config={
"type": "mcp",
"server_label": "composio",
"server_url": session.mcp.url,
"headers": session.mcp.headers,
"require_approval": "never",
}
)
],
)from claude_agent_sdk import ClaudeAgentOptions
options = ClaudeAgentOptions(
mcp_servers={
"composio": {
"type": "http",
"url": session.mcp.url,
"headers": session.mcp.headers,
}
},
)import { Composio } from "@composio/core";
import { createMCPClient } from "@ai-sdk/mcp";
const composio = new Composio();
const { mcp } = await composio.create("user_123");
const client = await createMCPClient({
transport: {
type: "http",
url: mcp.url,
headers: mcp.headers,
},
});
const tools = await client.tools();See the quickstart for full working examples.