Build agents with Claude that can discover and execute API operations using Toolcog. The Anthropic SDK supports MCP (Model Context Protocol), making Toolcog integration straightforward.
pip install anthropic mcpnpm install @anthropic-ai/sdk @modelcontextprotocol/sdkToolcog exposes an MCP server at https://mcp.toolcog.com. Connect to it as an SSE transport.
import anthropicfrom mcp import ClientSessionfrom mcp.client.sse import sse_client
async def main(): # Connect to Toolcog MCP server async with sse_client("https://mcp.toolcog.com") as (read, write): async with ClientSession(read, write) as session: await session.initialize()
# List available tools tools = await session.list_tools() print(f"Available tools: {[t.name for t in tools.tools]}")
# Create Anthropic client client = anthropic.Anthropic()
# Use Claude with Toolcog tools response = client.messages.create( model="claude-sonnet-4-20250514", max_tokens=1024, tools=[{ "name": tool.name, "description": tool.description, "input_schema": tool.inputSchema } for tool in tools.tools], messages=[{ "role": "user", "content": "Find GitHub operations for creating issues" }] )import Anthropic from "@anthropic-ai/sdk";import { Client } from "@modelcontextprotocol/sdk/client/index.js";import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
async function main() { // Connect to Toolcog MCP server const transport = new SSEClientTransport(new URL("https://mcp.toolcog.com")); const client = new Client({ name: "my-agent", version: "1.0.0" }); await client.connect(transport);
// List available tools const { tools } = await client.listTools(); console.log( "Available tools:", tools.map((t) => t.name), );
// Create Anthropic client const anthropic = new Anthropic();
// Use Claude with Toolcog tools const response = await anthropic.messages.create({ model: "claude-sonnet-4-20250514", max_tokens: 1024, tools: tools.map((tool) => ({ name: tool.name, description: tool.description, input_schema: tool.inputSchema, })), messages: [ { role: "user", content: "Find GitHub operations for creating issues", }, ], });}Once connected, Claude has access to three API meta-tools:
| Tool | Purpose |
|---|---|
find_api | Discover operations by intent |
learn_api | Get TypeScript types for operations |
call_api | Execute operations |
When Claude wants to use a tool, you need to execute it via the MCP session:
# Handle tool use in Claude's responsefor content in response.content: if content.type == "tool_use": # Execute the tool via MCP result = await session.call_tool( content.name, content.input )
# Continue conversation with tool result response = client.messages.create( model="claude-sonnet-4-20250514", max_tokens=1024, tools=tools, messages=[ {"role": "user", "content": "Find GitHub operations for creating issues"}, {"role": "assistant", "content": response.content}, {"role": "user", "content": [{ "type": "tool_result", "tool_use_id": content.id, "content": result.content }]} ] )When Toolcog needs authorization (for your Toolcog account or downstream services), the tool result includes an authorization URL. Your agent should:
result = await session.call_tool("call_api", { "operation": "github/repos.issues.create", "arguments": {...}})
# Check if authorization is neededif "authorization_url" in result.content: print(f"Please authorize: {result.content['authorization_url']}") input("Press Enter after authorizing...") # Retry the operation result = await session.call_tool("call_api", {...})import anthropicfrom mcp import ClientSessionfrom mcp.client.sse import sse_client
async def run_agent(user_request: str): async with sse_client("https://mcp.toolcog.com") as (read, write): async with ClientSession(read, write) as session: await session.initialize()
tools = await session.list_tools() client = anthropic.Anthropic()
messages = [{"role": "user", "content": user_request}] tool_defs = [{ "name": t.name, "description": t.description, "input_schema": t.inputSchema } for t in tools.tools]
while True: response = client.messages.create( model="claude-sonnet-4-20250514", max_tokens=4096, tools=tool_defs, messages=messages )
# Check if we're done if response.stop_reason == "end_turn": # Extract final text response for content in response.content: if hasattr(content, "text"): return content.text break
# Process tool calls messages.append({"role": "assistant", "content": response.content})
tool_results = [] for content in response.content: if content.type == "tool_use": result = await session.call_tool(content.name, content.input) tool_results.append({ "type": "tool_result", "tool_use_id": content.id, "content": str(result.content) })
messages.append({"role": "user", "content": tool_results})
# Run the agentimport asyncioresult = asyncio.run(run_agent("Create a GitHub issue for a bug in the login flow"))print(result)To use a specific catalog, append the catalog path to the URL:
async with sse_client("https://mcp.toolcog.com/mycompany/internal-apis") as (read, write): # Tools are scoped to the internal-apis catalog ...Handle tool loops — Claude may call multiple tools in sequence. Keep looping until stop_reason == "end_turn".
Manage context — Keep the full conversation history for multi-turn interactions.
Handle errors gracefully — Tool calls can fail. Check for error responses and let Claude retry or adjust.
Respect rate limits — Both Anthropic and Toolcog have rate limits. Implement backoff strategies.