Official Python SDK for the Context Protocol - Discover and execute AI tools programmatically
Project description
ctxprotocol
The Universal Adapter for AI Agents.
Connect your AI to the real world without managing API keys, hosting servers, or reading documentation.
Context Protocol is pip for AI capabilities. Just as you install packages to add functionality to your code, use the Context SDK to give your Agent instant access to thousands of live data sources and actions—from DeFi and Gas Oracles to Weather and Search.
💰 $10,000 Developer Grant Program
We're funding the initial supply of MCP Tools for the Context Marketplace. Become a Data Broker.
- 🛠️ Build: Create an MCP Server using this SDK (Solana data, Trading tools, Scrapers, etc.)
- 📦 List: Publish it to the Context Registry
- 💵 Earn: Get a $250–$1,000 Grant + earn USDC every time an agent queries your tool
👉 View Open Bounties & Apply Here
Why use Context?
- 🔌 One Interface, Everything: Stop integrating APIs one by one. Use a single SDK to access any tool in the marketplace.
- 🧠 Zero-Ops: We're a gateway to the best MCP tools. Just send the JSON and get the result.
- ⚡️ Agentic Discovery: Your Agent can search the marketplace at runtime to find tools it didn't know it needed.
- 💸 Pay-Per-Response: The $500/year subscription? Now $0.01/response. No monthly fees, just results.
Who Is This SDK For?
| Role | What You Use |
|---|---|
| AI Agent Developer | ctxprotocol — Query marketplace, execute tools, handle payments |
| Tool Contributor (Data Broker) | mcp + ctxprotocol — Standard MCP server + security middleware |
Installation
pip install ctxprotocol
Or with optional FastAPI support:
pip install ctxprotocol[fastapi]
Prerequisites
Before using the API, complete setup at ctxprotocol.com:
- Sign in — Creates your embedded wallet
- Enable Auto Pay — Approve USDC spending for tool payments
- Fund wallet — Add USDC for tool execution fees
- Generate API key — In Settings page
Quick Start
import asyncio
from ctxprotocol import ContextClient
async def main():
async with ContextClient(api_key="sk_live_...") as client:
# Discover tools
tools = await client.discovery.search("gas prices")
# Execute a tool
result = await client.tools.execute(
tool_id=tools[0].id,
tool_name=tools[0].mcp_tools[0].name,
args={"chainId": 1},
)
print(result.result)
asyncio.run(main())
Configuration
Client Options
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
api_key |
str |
Yes | — | Your Context Protocol API key |
base_url |
str |
No | https://ctxprotocol.com |
API base URL (for development) |
# Production
client = ContextClient(api_key=os.environ["CONTEXT_API_KEY"])
# Local development
client = ContextClient(
api_key="sk_test_...",
base_url="http://localhost:3000",
)
API Reference
Discovery
client.discovery.search(query, limit?)
Search for tools matching a query string.
tools = await client.discovery.search("ethereum gas", limit=10)
client.discovery.get_featured(limit?)
Get featured/popular tools.
featured = await client.discovery.get_featured(limit=5)
Tools
client.tools.execute(tool_id, tool_name, args?)
Execute a tool method.
result = await client.tools.execute(
tool_id="uuid-of-tool",
tool_name="get_gas_prices",
args={"chainId": 1},
)
Types
from ctxprotocol import (
# Auth utilities for tool contributors
verify_context_request,
is_protected_mcp_method,
is_open_mcp_method,
# Client types
ContextClientOptions,
Tool,
McpTool,
ExecuteOptions,
ExecutionResult,
ContextErrorCode,
# Auth types (for MCP server contributors)
VerifyRequestOptions,
# Context types (for MCP server contributors receiving injected data)
ContextRequirementType,
HyperliquidContext,
PolymarketContext,
WalletContext,
UserContext,
)
Error Handling
The SDK raises ContextError with specific error codes:
from ctxprotocol import ContextClient, ContextError
try:
result = await client.tools.execute(...)
except ContextError as e:
match e.code:
case "no_wallet":
# User needs to set up wallet
print(f"Setup required: {e.help_url}")
case "insufficient_allowance":
# User needs to enable Auto Pay
print(f"Enable Auto Pay: {e.help_url}")
case "payment_failed":
# Insufficient USDC balance
pass
case "execution_failed":
# Tool execution error
pass
Error Codes
| Code | Description | Handling |
|---|---|---|
unauthorized |
Invalid API key | Check configuration |
no_wallet |
Wallet not set up | Direct user to help_url |
insufficient_allowance |
Auto Pay not enabled | Direct user to help_url |
payment_failed |
USDC payment failed | Check balance |
execution_failed |
Tool error | Retry with different args |
🔒 Securing Your Tool (MCP Contributors)
If you're building an MCP server (tool contributor), verify incoming requests:
Quick Implementation with FastAPI
from fastapi import FastAPI, Request, Depends, HTTPException
from ctxprotocol import create_context_middleware, ContextError
app = FastAPI()
verify_context = create_context_middleware(audience="https://your-tool.com/mcp")
@app.post("/mcp")
async def handle_mcp(request: Request, context: dict = Depends(verify_context)):
# context contains verified JWT payload (on protected methods)
# None for open methods like tools/list
body = await request.json()
# Handle MCP request...
Manual Verification
from ctxprotocol import verify_context_request, is_protected_mcp_method, ContextError
# Check if a method requires auth
if is_protected_mcp_method(body["method"]):
try:
payload = await verify_context_request(
authorization_header=request.headers.get("authorization"),
audience="https://your-tool.com/mcp", # optional
)
# payload contains verified JWT claims
except ContextError as e:
# Handle authentication error
raise HTTPException(status_code=401, detail="Unauthorized")
MCP Security Model
The SDK implements a selective authentication model — discovery is open, execution is protected:
| MCP Method | Auth Required | Why |
|---|---|---|
initialize |
❌ No | Session setup |
tools/list |
❌ No | Discovery - agents need to see your schemas |
resources/list |
❌ No | Discovery |
prompts/list |
❌ No | Discovery |
tools/call |
✅ Yes | Execution - costs money, runs your code |
What this means in practice:
- ✅
https://your-mcp.com/mcp+initialize→ Works without auth - ✅
https://your-mcp.com/mcp+tools/list→ Works without auth - ❌
https://your-mcp.com/mcp+tools/call→ Requires Context Protocol JWT
This matches standard API patterns (OpenAPI schemas are public, GraphQL introspection is open).
Execution Timeout & Product Design
⚠️ Important: MCP tool execution has a ~60 second timeout (enforced at the platform/client level, not by MCP itself). This is intentional—it encourages building pre-computed insight products rather than raw data access.
Best practice: Run heavy queries offline (via cron jobs), store results in your database, and serve instant results via MCP. This is how Bloomberg, Nansen, and Arkham work.
# ❌ BAD: Raw access (timeout-prone, no moat)
{"name": "run_sql", "description": "Run any SQL against blockchain data"}
# ✅ GOOD: Pre-computed product (instant, defensible)
{"name": "get_smart_money_wallets", "description": "Top 100 wallets that timed market tops"}
See the full documentation for detailed guidance.
Context Injection (Personalized Tools)
For tools that analyze user data, Context automatically injects user context:
from ctxprotocol import CONTEXT_REQUIREMENTS_KEY, HyperliquidContext
# Define tool with context requirements
TOOLS = [{
"name": "analyze_my_positions",
"description": "Analyze your positions with personalized insights",
"_meta": {
"contextRequirements": ["hyperliquid"],
},
"inputSchema": {
"type": "object",
"properties": {
"portfolio": {
"type": "object",
"description": "Portfolio context (injected by platform)",
},
},
"required": ["portfolio"],
},
}]
# Your handler receives typed context
async def handle_analyze_positions(portfolio: HyperliquidContext):
positions = portfolio.perp_positions
account = portfolio.account_summary
# ... analyze and return insights
Links
- Context Protocol — Main website
- Documentation
- GitHub — This SDK
- TypeScript SDK — For Node.js
- PyPI Package
Requirements
- Python 3.10+
- httpx
- pydantic
- pyjwt[crypto]
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ctxprotocol-0.6.0.tar.gz.
File metadata
- Download URL: ctxprotocol-0.6.0.tar.gz
- Upload date:
- Size: 30.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fceb273181e8b469fc3e74b743652b1b8ff0a5af7580d5e8488093dbda0ce0bf
|
|
| MD5 |
948b8d1e76d3587c2c770c394c063dd4
|
|
| BLAKE2b-256 |
786964748aecffd00625645b66b707d0f40bb6a2af8ba23866f86f4435492d8a
|
File details
Details for the file ctxprotocol-0.6.0-py3-none-any.whl.
File metadata
- Download URL: ctxprotocol-0.6.0-py3-none-any.whl
- Upload date:
- Size: 28.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
664a636b572ffe029b3ad1ed84d9f157cba0da16d3d4eb522be8c462f539b96d
|
|
| MD5 |
7e4b5d2528a52dd6da8f2d1978c5853d
|
|
| BLAKE2b-256 |
794a6a2b26cbe224888d589759ca933a0e7742acae8cdc59741d0e5324f2cdf0
|