Anthropic SDK

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.

Prerequisites

Installation

Python

Terminal window
pip install anthropic mcp

TypeScript

Terminal window
npm install @anthropic-ai/sdk @modelcontextprotocol/sdk

Connecting to Toolcog

Toolcog exposes an MCP server at https://mcp.toolcog.com. Connect to it as an SSE transport.

Python Example

import anthropic
from mcp import ClientSession
from 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"
}]
)

TypeScript Example

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

Using Toolcog’s Tools

Once connected, Claude has access to three API meta-tools:

ToolPurpose
find_apiDiscover operations by intent
learn_apiGet TypeScript types for operations
call_apiExecute operations

Tool Execution Loop

When Claude wants to use a tool, you need to execute it via the MCP session:

# Handle tool use in Claude's response
for 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
}]}
]
)

Handling Authentication

When Toolcog needs authorization (for your Toolcog account or downstream services), the tool result includes an authorization URL. Your agent should:

  1. Detect the authorization requirement in the response
  2. Present the URL to the user
  3. Wait for authorization to complete
  4. Retry the operation
result = await session.call_tool("call_api", {
"operation": "github/repos.issues.create",
"arguments": {...}
})
# Check if authorization is needed
if "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", {...})

Complete Agent Example

import anthropic
from mcp import ClientSession
from 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 agent
import asyncio
result = asyncio.run(run_agent("Create a GitHub issue for a bug in the login flow"))
print(result)

Catalogs

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

Best Practices

  1. Handle tool loops — Claude may call multiple tools in sequence. Keep looping until stop_reason == "end_turn".

  2. Manage context — Keep the full conversation history for multi-turn interactions.

  3. Handle errors gracefully — Tool calls can fail. Check for error responses and let Claude retry or adjust.

  4. Respect rate limits — Both Anthropic and Toolcog have rate limits. Implement backoff strategies.

Next Steps