traia-iatp 0.1.2__py3-none-any.whl → 0.1.67__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- traia_iatp/__init__.py +105 -8
- traia_iatp/cli/main.py +85 -1
- traia_iatp/client/__init__.py +28 -3
- traia_iatp/client/crewai_a2a_tools.py +32 -12
- traia_iatp/client/d402_a2a_client.py +348 -0
- traia_iatp/contracts/__init__.py +11 -0
- traia_iatp/contracts/data/abis/contract-abis-localhost.json +4091 -0
- traia_iatp/contracts/data/abis/contract-abis-sepolia.json +4890 -0
- traia_iatp/contracts/data/addresses/contract-addresses.json +17 -0
- traia_iatp/contracts/data/addresses/contract-proxies.json +12 -0
- traia_iatp/contracts/iatp_contracts_config.py +263 -0
- traia_iatp/contracts/wallet_creator.py +369 -0
- traia_iatp/core/models.py +17 -3
- traia_iatp/d402/MIDDLEWARE_ARCHITECTURE.md +205 -0
- traia_iatp/d402/PRICE_BUILDER_USAGE.md +249 -0
- traia_iatp/d402/README.md +489 -0
- traia_iatp/d402/__init__.py +54 -0
- traia_iatp/d402/asgi_wrapper.py +469 -0
- traia_iatp/d402/chains.py +102 -0
- traia_iatp/d402/client.py +150 -0
- traia_iatp/d402/clients/__init__.py +7 -0
- traia_iatp/d402/clients/base.py +218 -0
- traia_iatp/d402/clients/httpx.py +266 -0
- traia_iatp/d402/common.py +114 -0
- traia_iatp/d402/encoding.py +28 -0
- traia_iatp/d402/examples/client_example.py +197 -0
- traia_iatp/d402/examples/server_example.py +171 -0
- traia_iatp/d402/facilitator.py +481 -0
- traia_iatp/d402/mcp_middleware.py +296 -0
- traia_iatp/d402/models.py +116 -0
- traia_iatp/d402/networks.py +98 -0
- traia_iatp/d402/path.py +43 -0
- traia_iatp/d402/payment_introspection.py +126 -0
- traia_iatp/d402/payment_signing.py +183 -0
- traia_iatp/d402/price_builder.py +164 -0
- traia_iatp/d402/servers/__init__.py +61 -0
- traia_iatp/d402/servers/base.py +139 -0
- traia_iatp/d402/servers/example_general_server.py +140 -0
- traia_iatp/d402/servers/fastapi.py +253 -0
- traia_iatp/d402/servers/mcp.py +304 -0
- traia_iatp/d402/servers/starlette.py +878 -0
- traia_iatp/d402/starlette_middleware.py +529 -0
- traia_iatp/d402/types.py +300 -0
- traia_iatp/mcp/D402_MCP_ADAPTER_FLOW.md +357 -0
- traia_iatp/mcp/__init__.py +3 -0
- traia_iatp/mcp/d402_mcp_tool_adapter.py +526 -0
- traia_iatp/mcp/mcp_agent_template.py +78 -13
- traia_iatp/mcp/templates/Dockerfile.j2 +27 -4
- traia_iatp/mcp/templates/README.md.j2 +104 -8
- traia_iatp/mcp/templates/cursor-rules.md.j2 +194 -0
- traia_iatp/mcp/templates/deployment_params.json.j2 +1 -2
- traia_iatp/mcp/templates/docker-compose.yml.j2 +13 -3
- traia_iatp/mcp/templates/env.example.j2 +60 -0
- traia_iatp/mcp/templates/mcp_health_check.py.j2 +2 -2
- traia_iatp/mcp/templates/pyproject.toml.j2 +11 -5
- traia_iatp/mcp/templates/pyrightconfig.json.j2 +22 -0
- traia_iatp/mcp/templates/run_local_docker.sh.j2 +320 -10
- traia_iatp/mcp/templates/server.py.j2 +174 -197
- traia_iatp/mcp/traia_mcp_adapter.py +182 -20
- traia_iatp/registry/__init__.py +47 -12
- traia_iatp/registry/atlas_search_indexes.json +108 -54
- traia_iatp/registry/iatp_search_api.py +169 -39
- traia_iatp/registry/mongodb_registry.py +241 -69
- traia_iatp/registry/readmes/EMBEDDINGS_SETUP.md +1 -1
- traia_iatp/registry/readmes/IATP_SEARCH_API_GUIDE.md +8 -8
- traia_iatp/registry/readmes/MONGODB_X509_AUTH.md +1 -1
- traia_iatp/registry/readmes/README.md +3 -3
- traia_iatp/registry/readmes/REFACTORING_SUMMARY.md +6 -6
- traia_iatp/scripts/__init__.py +2 -0
- traia_iatp/scripts/create_wallet.py +244 -0
- traia_iatp/server/a2a_server.py +22 -7
- traia_iatp/server/iatp_server_template_generator.py +23 -0
- traia_iatp/server/templates/.dockerignore.j2 +48 -0
- traia_iatp/server/templates/Dockerfile.j2 +23 -1
- traia_iatp/server/templates/README.md +2 -2
- traia_iatp/server/templates/README.md.j2 +5 -5
- traia_iatp/server/templates/__main__.py.j2 +374 -66
- traia_iatp/server/templates/agent.py.j2 +12 -11
- traia_iatp/server/templates/agent_config.json.j2 +3 -3
- traia_iatp/server/templates/agent_executor.py.j2 +45 -27
- traia_iatp/server/templates/env.example.j2 +32 -4
- traia_iatp/server/templates/gitignore.j2 +7 -0
- traia_iatp/server/templates/pyproject.toml.j2 +13 -12
- traia_iatp/server/templates/run_local_docker.sh.j2 +143 -11
- traia_iatp/server/templates/server.py.j2 +197 -10
- traia_iatp/special_agencies/registry_search_agency.py +1 -1
- traia_iatp/utils/iatp_utils.py +6 -6
- traia_iatp-0.1.67.dist-info/METADATA +320 -0
- traia_iatp-0.1.67.dist-info/RECORD +117 -0
- traia_iatp-0.1.2.dist-info/METADATA +0 -414
- traia_iatp-0.1.2.dist-info/RECORD +0 -72
- {traia_iatp-0.1.2.dist-info → traia_iatp-0.1.67.dist-info}/WHEEL +0 -0
- {traia_iatp-0.1.2.dist-info → traia_iatp-0.1.67.dist-info}/entry_points.txt +0 -0
- {traia_iatp-0.1.2.dist-info → traia_iatp-0.1.67.dist-info}/licenses/LICENSE +0 -0
- {traia_iatp-0.1.2.dist-info → traia_iatp-0.1.67.dist-info}/top_level.txt +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
{{ agent_name }} - A2A Server Implementation
|
|
3
3
|
|
|
4
4
|
Auto-generated utility agent that exposes {{ mcp_server_name }} via A2A protocol.
|
|
5
|
-
This is a simplified all-in-one implementation.
|
|
5
|
+
This is a simplified all-in-one implementation with MCP connection verification.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
import asyncio
|
|
@@ -10,6 +10,7 @@ import json
|
|
|
10
10
|
import logging
|
|
11
11
|
import os
|
|
12
12
|
from typing import Dict, Any, Optional
|
|
13
|
+
from datetime import datetime, timedelta
|
|
13
14
|
from a2a.server.apps import A2AStarletteApplication
|
|
14
15
|
from a2a.server.agent_execution import AgentExecutor, RequestContext
|
|
15
16
|
from a2a.server.events.event_queue import EventQueue
|
|
@@ -19,10 +20,16 @@ from a2a.types import AgentCard, AgentSkill, AgentCapabilities
|
|
|
19
20
|
from a2a.utils import new_agent_text_message
|
|
20
21
|
import uvicorn
|
|
21
22
|
from crewai import Task
|
|
23
|
+
from fastapi import Request
|
|
24
|
+
import httpx
|
|
22
25
|
|
|
23
26
|
# Import the MCP agent builder and run function
|
|
24
27
|
from traia_iatp.mcp import MCPServerConfig, MCPAgentBuilder, run_with_mcp_tools, MCPServerInfo
|
|
25
28
|
|
|
29
|
+
# Import D402 payment support - using Starlette middleware
|
|
30
|
+
from traia_iatp.d402.starlette_middleware import D402PaymentMiddleware
|
|
31
|
+
from traia_iatp.d402.types import TokenAmount, TokenAsset, EIP712Domain, D402Config
|
|
32
|
+
|
|
26
33
|
logging.basicConfig(level=logging.INFO)
|
|
27
34
|
logger = logging.getLogger(__name__)
|
|
28
35
|
|
|
@@ -72,13 +79,175 @@ if not MCP_API_KEY:
|
|
|
72
79
|
MCP_API_KEY = None
|
|
73
80
|
{% endif %}
|
|
74
81
|
|
|
82
|
+
# D402 Configuration (if enabled)
|
|
83
|
+
d402_enabled = os.getenv("D402_ENABLED", "false").lower() == "true"
|
|
84
|
+
d402_config = None
|
|
85
|
+
|
|
86
|
+
if d402_enabled:
|
|
87
|
+
logger.info("D402 payments enabled")
|
|
88
|
+
|
|
89
|
+
contract_address = os.getenv("UTILITY_AGENT_CONTRACT_ADDRESS")
|
|
90
|
+
token_address = os.getenv("D402_TOKEN_ADDRESS")
|
|
91
|
+
token_decimals = int(os.getenv("D402_TOKEN_DECIMALS", "6"))
|
|
92
|
+
network = os.getenv("D402_NETWORK", "sepolia")
|
|
93
|
+
facilitator_url = os.getenv("D402_FACILITATOR_URL", "http://localhost:8080")
|
|
94
|
+
operator_key = os.getenv("UTILITY_AGENT_OPERATOR_PRIVATE_KEY")
|
|
95
|
+
testing_mode = os.getenv("D402_TESTING_MODE", "false").lower() == "true"
|
|
96
|
+
|
|
97
|
+
if not contract_address:
|
|
98
|
+
logger.error("D402 enabled but UTILITY_AGENT_CONTRACT_ADDRESS not set!")
|
|
99
|
+
d402_enabled = False
|
|
100
|
+
elif not token_address:
|
|
101
|
+
logger.error("D402 enabled but D402_TOKEN_ADDRESS not set!")
|
|
102
|
+
d402_enabled = False
|
|
103
|
+
else:
|
|
104
|
+
# Calculate token amount from USD price
|
|
105
|
+
# Example: $0.01 USD with 6 decimals = 10000 (0.01 * 10^6)
|
|
106
|
+
usd_price = float(os.getenv("D402_PRICE_USD", "0.01"))
|
|
107
|
+
token_amount = str(int(usd_price * (10 ** token_decimals)))
|
|
108
|
+
|
|
109
|
+
d402_config = D402Config(
|
|
110
|
+
enabled=True,
|
|
111
|
+
pay_to_address=contract_address,
|
|
112
|
+
default_price=TokenAmount(
|
|
113
|
+
amount=token_amount,
|
|
114
|
+
asset=TokenAsset(
|
|
115
|
+
address=token_address,
|
|
116
|
+
decimals=token_decimals,
|
|
117
|
+
network=network,
|
|
118
|
+
eip712=EIP712Domain(
|
|
119
|
+
name="IATPWallet",
|
|
120
|
+
version="1"
|
|
121
|
+
)
|
|
122
|
+
)
|
|
123
|
+
),
|
|
124
|
+
facilitator_url=facilitator_url,
|
|
125
|
+
operator_private_key=operator_key,
|
|
126
|
+
testing_mode=testing_mode,
|
|
127
|
+
service_description=config["description"],
|
|
128
|
+
protected_paths=["*"] # Protect all A2A endpoints except .well-known
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
logger.info("="*60)
|
|
132
|
+
logger.info("💳 D402 Payment Configuration:")
|
|
133
|
+
logger.info(f" Price: ${usd_price} USD")
|
|
134
|
+
logger.info(f" Token: {token_address}")
|
|
135
|
+
logger.info(f" Network: {network}")
|
|
136
|
+
logger.info(f" Recipient: {contract_address}")
|
|
137
|
+
logger.info(f" Facilitator: {facilitator_url}")
|
|
138
|
+
logger.info(f" Testing Mode: {testing_mode}")
|
|
139
|
+
logger.info("="*60)
|
|
140
|
+
|
|
75
141
|
|
|
76
142
|
class {{ class_name }}AgentExecutor(AgentExecutor):
|
|
77
|
-
"""Agent executor for {{ agency_name }}."""
|
|
143
|
+
"""Agent executor for {{ agency_name }} with MCP connection verification."""
|
|
78
144
|
|
|
79
145
|
def __init__(self):
|
|
80
146
|
self.mcp_config = mcp_config
|
|
81
147
|
self.mcp_server_info = mcp_server_info
|
|
148
|
+
self.mcp_connection_verified = False
|
|
149
|
+
self.mcp_last_check_time = None
|
|
150
|
+
self.mcp_connection_error = None
|
|
151
|
+
self.mcp_available_tools = []
|
|
152
|
+
|
|
153
|
+
async def verify_mcp_connection(self) -> bool:
|
|
154
|
+
"""
|
|
155
|
+
Verify MCP server connection by:
|
|
156
|
+
1. Fetching server info/tools
|
|
157
|
+
2. Testing a basic connection
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
bool: True if connection is healthy, False otherwise
|
|
161
|
+
"""
|
|
162
|
+
try:
|
|
163
|
+
logger.info("🔍 Verifying MCP server connection...")
|
|
164
|
+
logger.info(f" MCP URL: {self.mcp_config.url}")
|
|
165
|
+
|
|
166
|
+
async with httpx.AsyncClient(timeout=30.0) as client:
|
|
167
|
+
# Try to connect to MCP server
|
|
168
|
+
try:
|
|
169
|
+
# For HTTP MCP servers, try the health endpoint or root
|
|
170
|
+
health_url = f"{self.mcp_config.url}/health"
|
|
171
|
+
response = await client.get(health_url)
|
|
172
|
+
|
|
173
|
+
if response.status_code == 200:
|
|
174
|
+
logger.info(f"✅ MCP server health check passed")
|
|
175
|
+
else:
|
|
176
|
+
logger.warning(f"⚠️ MCP server returned status {response.status_code}")
|
|
177
|
+
except Exception as health_error:
|
|
178
|
+
logger.debug(f"Health endpoint not available: {health_error}")
|
|
179
|
+
# Try a basic connection instead
|
|
180
|
+
try:
|
|
181
|
+
response = await client.get(self.mcp_config.url)
|
|
182
|
+
logger.info(f"✅ MCP server is reachable")
|
|
183
|
+
except Exception as conn_error:
|
|
184
|
+
self.mcp_connection_error = f"Cannot connect to MCP server: {conn_error}"
|
|
185
|
+
logger.error(f"❌ {self.mcp_connection_error}")
|
|
186
|
+
return False
|
|
187
|
+
|
|
188
|
+
# Try to initialize MCP adapter to get tools
|
|
189
|
+
try:
|
|
190
|
+
from traia_iatp.mcp.traia_mcp_adapter import TraiaMCPAdapter
|
|
191
|
+
|
|
192
|
+
adapter = TraiaMCPAdapter(
|
|
193
|
+
server_url=self.mcp_config.url,
|
|
194
|
+
server_type=self.mcp_config.server_type,
|
|
195
|
+
api_key=MCP_API_KEY
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
# Get available tools
|
|
199
|
+
tools = await adapter.list_tools()
|
|
200
|
+
self.mcp_available_tools = [tool.name for tool in tools]
|
|
201
|
+
|
|
202
|
+
logger.info(f"✅ MCP connection verified successfully")
|
|
203
|
+
logger.info(f" Available tools: {len(self.mcp_available_tools)}")
|
|
204
|
+
if self.mcp_available_tools:
|
|
205
|
+
logger.info(f" Tools: {', '.join(self.mcp_available_tools[:5])}")
|
|
206
|
+
if len(self.mcp_available_tools) > 5:
|
|
207
|
+
logger.info(f" ... and {len(self.mcp_available_tools) - 5} more")
|
|
208
|
+
|
|
209
|
+
# Close the adapter
|
|
210
|
+
await adapter.close()
|
|
211
|
+
|
|
212
|
+
except Exception as adapter_error:
|
|
213
|
+
self.mcp_connection_error = f"MCP adapter initialization failed: {adapter_error}"
|
|
214
|
+
logger.error(f"❌ {self.mcp_connection_error}")
|
|
215
|
+
return False
|
|
216
|
+
|
|
217
|
+
# Connection successful
|
|
218
|
+
self.mcp_connection_verified = True
|
|
219
|
+
self.mcp_last_check_time = datetime.now()
|
|
220
|
+
self.mcp_connection_error = None
|
|
221
|
+
|
|
222
|
+
return True
|
|
223
|
+
|
|
224
|
+
except Exception as e:
|
|
225
|
+
self.mcp_connection_error = f"MCP verification error: {e}"
|
|
226
|
+
logger.error(f"❌ {self.mcp_connection_error}")
|
|
227
|
+
import traceback
|
|
228
|
+
logger.debug(traceback.format_exc())
|
|
229
|
+
return False
|
|
230
|
+
|
|
231
|
+
async def check_mcp_health(self) -> bool:
|
|
232
|
+
"""
|
|
233
|
+
Check if MCP connection is healthy.
|
|
234
|
+
Re-verifies if more than 10 minutes have passed since last check.
|
|
235
|
+
|
|
236
|
+
Returns:
|
|
237
|
+
bool: True if MCP connection is healthy, False otherwise
|
|
238
|
+
"""
|
|
239
|
+
# If never checked, verify now
|
|
240
|
+
if not self.mcp_connection_verified or self.mcp_last_check_time is None:
|
|
241
|
+
return await self.verify_mcp_connection()
|
|
242
|
+
|
|
243
|
+
# Check if more than 10 minutes have passed
|
|
244
|
+
time_since_check = datetime.now() - self.mcp_last_check_time
|
|
245
|
+
if time_since_check > timedelta(minutes=10):
|
|
246
|
+
logger.info("🔄 10+ minutes since last MCP check, re-verifying...")
|
|
247
|
+
return await self.verify_mcp_connection()
|
|
248
|
+
|
|
249
|
+
# Still within 10 minute window, use cached status
|
|
250
|
+
return self.mcp_connection_verified
|
|
82
251
|
|
|
83
252
|
async def execute(self, context: RequestContext, event_queue: EventQueue) -> None:
|
|
84
253
|
"""Process a request using the {{ agency_name }} capabilities."""
|
|
@@ -152,14 +321,17 @@ def create_app():
|
|
|
152
321
|
)
|
|
153
322
|
|
|
154
323
|
# Create agent card
|
|
155
|
-
|
|
156
|
-
name
|
|
157
|
-
description
|
|
158
|
-
url
|
|
159
|
-
version
|
|
160
|
-
capabilities
|
|
161
|
-
skills
|
|
162
|
-
|
|
324
|
+
agent_card_dict = {
|
|
325
|
+
"name": config["agency_id"],
|
|
326
|
+
"description": config["description"],
|
|
327
|
+
"url": f"http://0.0.0.0:{os.environ.get('PORT', 8000)}",
|
|
328
|
+
"version": config["version"],
|
|
329
|
+
"capabilities": capabilities.model_dump(),
|
|
330
|
+
"skills": [skill.model_dump()]
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
# Create agent card from dict
|
|
334
|
+
agent_card = AgentCard(**agent_card_dict)
|
|
163
335
|
|
|
164
336
|
# Create executor
|
|
165
337
|
executor = {{ class_name }}AgentExecutor()
|
|
@@ -177,6 +349,21 @@ def create_app():
|
|
|
177
349
|
http_handler=request_handler
|
|
178
350
|
)
|
|
179
351
|
|
|
352
|
+
# Add D402 middleware if enabled (using Starlette middleware)
|
|
353
|
+
if d402_enabled and d402_config:
|
|
354
|
+
logger.info("💳 Adding D402 payment middleware to A2A application")
|
|
355
|
+
|
|
356
|
+
# Get the underlying Starlette app from A2AStarletteApplication
|
|
357
|
+
starlette_app = app.app if hasattr(app, 'app') else app
|
|
358
|
+
|
|
359
|
+
# Add D402PaymentMiddleware
|
|
360
|
+
starlette_app.add_middleware(
|
|
361
|
+
D402PaymentMiddleware,
|
|
362
|
+
config=d402_config
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
logger.info("✅ D402 middleware configured")
|
|
366
|
+
|
|
180
367
|
return app
|
|
181
368
|
|
|
182
369
|
|
|
@@ -357,7 +357,7 @@ python -m uvicorn server:app --host 0.0.0.0 --port 8000
|
|
|
357
357
|
## Usage Example
|
|
358
358
|
|
|
359
359
|
```python
|
|
360
|
-
from
|
|
360
|
+
from traia_iatp import create_utility_agency_tools
|
|
361
361
|
|
|
362
362
|
# This agency will be discoverable like any other
|
|
363
363
|
tools = create_utility_agency_tools(
|
traia_iatp/utils/iatp_utils.py
CHANGED
|
@@ -4,7 +4,7 @@ import logging
|
|
|
4
4
|
from typing import Dict, Any, Optional, List
|
|
5
5
|
import httpx
|
|
6
6
|
|
|
7
|
-
from
|
|
7
|
+
from ..core.models import AgentCard, AgentSkill, AgentCapabilities, IATPEndpoints
|
|
8
8
|
|
|
9
9
|
logger = logging.getLogger(__name__)
|
|
10
10
|
|
|
@@ -93,12 +93,12 @@ def create_iatp_endpoints(base_url: str, supports_streaming: bool = False) -> IA
|
|
|
93
93
|
"""Create IATP endpoints configuration from base URL.
|
|
94
94
|
|
|
95
95
|
The A2A protocol defines specific endpoints:
|
|
96
|
-
- JSON-RPC endpoint at
|
|
96
|
+
- JSON-RPC endpoint at /a2a
|
|
97
97
|
- Agent card at /.well-known/agent.json
|
|
98
98
|
- SSE endpoints at /a2a/tasks/* (if streaming is supported)
|
|
99
99
|
|
|
100
|
-
Note:
|
|
101
|
-
|
|
100
|
+
Note: Updated to use /a2a as the main JSON-RPC endpoint for consistency
|
|
101
|
+
with D402 payment tracking and endpoint management.
|
|
102
102
|
|
|
103
103
|
Args:
|
|
104
104
|
base_url: Base URL of the service (e.g., "http://localhost:8000" or "https://service.run.app")
|
|
@@ -112,14 +112,14 @@ def create_iatp_endpoints(base_url: str, supports_streaming: bool = False) -> IA
|
|
|
112
112
|
|
|
113
113
|
endpoints = IATPEndpoints(
|
|
114
114
|
base_url=base_url,
|
|
115
|
-
iatp_endpoint=base_url, # A2A JSON-RPC endpoint is at
|
|
115
|
+
iatp_endpoint=f"{base_url}/a2a", # A2A JSON-RPC endpoint is at /a2a
|
|
116
116
|
health_endpoint=None, # Not part of A2A protocol
|
|
117
117
|
info_endpoint=None, # Not part of A2A protocol
|
|
118
118
|
agent_card_endpoint=f"{base_url}/.well-known/agent.json"
|
|
119
119
|
)
|
|
120
120
|
|
|
121
121
|
if supports_streaming:
|
|
122
|
-
endpoints.streaming_endpoint
|
|
122
|
+
endpoints.streaming_endpoint=f"{base_url}/a2a", # Same /a2a endpoint, different output_mode
|
|
123
123
|
endpoints.subscribe_endpoint = f"{base_url}/a2a/tasks/subscribe"
|
|
124
124
|
endpoints.resubscribe_endpoint = f"{base_url}/a2a/tasks/resubscribe"
|
|
125
125
|
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: traia-iatp
|
|
3
|
+
Version: 0.1.67
|
|
4
|
+
Summary: Inter-Agent Transfer Protocol (IATP) - Enable AI Agents to utilize other AI Agents as tools
|
|
5
|
+
Project-URL: Documentation, https://docs.d402.net
|
|
6
|
+
Project-URL: Source, https://github.com/Traia-IO/IATP
|
|
7
|
+
Keywords: crewai,iatp,agent-to-agent,a2a,mcp,web3,cryptocurrency,tools
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Python: >=3.12
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: a2a-sdk>=0.3.19
|
|
14
|
+
Requires-Dist: aiohttp>=3.12.13
|
|
15
|
+
Requires-Dist: anyio>=4.0.0
|
|
16
|
+
Requires-Dist: crewai>=0.203.1
|
|
17
|
+
Requires-Dist: crewai-tools[mcp]>=0.76.0
|
|
18
|
+
Requires-Dist: docker>=7.1.0
|
|
19
|
+
Requires-Dist: fastapi>=0.119.0
|
|
20
|
+
Requires-Dist: httpx[http2]>=0.28.1
|
|
21
|
+
Requires-Dist: jinja2>=3.1.6
|
|
22
|
+
Requires-Dist: mcp>=1.1.2
|
|
23
|
+
Requires-Dist: nest-asyncio>=1.6.0
|
|
24
|
+
Requires-Dist: openai>=1.109.1
|
|
25
|
+
Requires-Dist: pydantic>=2.12.2
|
|
26
|
+
Requires-Dist: pymongo[aws]>=4.13.0
|
|
27
|
+
Requires-Dist: python-dotenv>=1.1.1
|
|
28
|
+
Requires-Dist: pytz>=2025.2
|
|
29
|
+
Requires-Dist: requests>=2.32.5
|
|
30
|
+
Requires-Dist: rich>=14.2.0
|
|
31
|
+
Requires-Dist: starlette>=0.45.0
|
|
32
|
+
Requires-Dist: tomli>=2.0.0
|
|
33
|
+
Requires-Dist: typer>=0.19.2
|
|
34
|
+
Requires-Dist: uvicorn>=0.37.0
|
|
35
|
+
Requires-Dist: agentops>=0.4.21
|
|
36
|
+
Requires-Dist: dnspython==2.6.1
|
|
37
|
+
Requires-Dist: eth-account>=0.11.0
|
|
38
|
+
Requires-Dist: web3>=6.15.0
|
|
39
|
+
Provides-Extra: dev
|
|
40
|
+
Requires-Dist: pytest>=8.4.2; extra == "dev"
|
|
41
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
42
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
43
|
+
Requires-Dist: flake8>=6.0.0; extra == "dev"
|
|
44
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
45
|
+
Requires-Dist: pre-commit>=3.0.0; extra == "dev"
|
|
46
|
+
Provides-Extra: publish
|
|
47
|
+
Requires-Dist: wheel; extra == "publish"
|
|
48
|
+
Requires-Dist: twine; extra == "publish"
|
|
49
|
+
Requires-Dist: build; extra == "publish"
|
|
50
|
+
Dynamic: license-file
|
|
51
|
+
|
|
52
|
+
# IATP-D402: Inter-Agent Transfer Protocol with Payment Support
|
|
53
|
+
|
|
54
|
+
[](https://badge.fury.io/py/traia-iatp)
|
|
55
|
+
[](https://www.python.org/downloads/)
|
|
56
|
+
[](https://opensource.org/licenses/MIT)
|
|
57
|
+
[](https://docs.d402.net)
|
|
58
|
+
|
|
59
|
+
**IATP-D402** enables AI agents and APIs to charge for their services using the D402 payment protocol (HTTP 402 Payment Required). Build payment-enabled:
|
|
60
|
+
- 🌐 APIs and web servers
|
|
61
|
+
- 🔧 MCP (Model Context Protocol) servers
|
|
62
|
+
- 🤖 A2A utility agents
|
|
63
|
+
- 🤝 CrewAI tools and agents
|
|
64
|
+
|
|
65
|
+
## 🚀 Quick Start
|
|
66
|
+
|
|
67
|
+
### Installation
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pip install traia-iatp
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Add D402 to Your FastAPI Server (5 lines)
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
from fastapi import FastAPI
|
|
77
|
+
from traia_iatp.d402.servers.fastapi import D402FastAPIMiddleware
|
|
78
|
+
from traia_iatp.d402.price_builder import D402PriceBuilder
|
|
79
|
+
|
|
80
|
+
app = FastAPI()
|
|
81
|
+
|
|
82
|
+
# Add D402 (5 lines)
|
|
83
|
+
price_builder = D402PriceBuilder(network="sepolia")
|
|
84
|
+
d402 = D402FastAPIMiddleware(server_address="0x...", facilitator_url="https://test-facilitator.d402.net")
|
|
85
|
+
price = price_builder.create_price(0.01) # $0.01 USD
|
|
86
|
+
d402.register_endpoint("/api/analyze", price_wei=price.amount, token_address=price.asset.address, network="sepolia", description="Analysis")
|
|
87
|
+
d402.add_to_app(app)
|
|
88
|
+
|
|
89
|
+
# Your endpoint (unchanged!)
|
|
90
|
+
@app.post("/api/analyze")
|
|
91
|
+
async def analyze(request: Request):
|
|
92
|
+
return {"result": "done"}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Call D402-Protected Servers (2 lines)
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
from traia_iatp.d402.clients.httpx import d402HttpxClient
|
|
99
|
+
from eth_account import Account
|
|
100
|
+
|
|
101
|
+
async with d402HttpxClient(
|
|
102
|
+
operator_account=Account.from_key("0x..."),
|
|
103
|
+
wallet_address="0x...",
|
|
104
|
+
max_value=100000,
|
|
105
|
+
base_url="http://localhost:8000"
|
|
106
|
+
) as client:
|
|
107
|
+
# Payment automatic!
|
|
108
|
+
response = await client.post("/api/analyze", json={"text": "test"})
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## 📚 Documentation
|
|
112
|
+
|
|
113
|
+
**Full documentation**: [docs.d402.net](https://docs.d402.net)
|
|
114
|
+
|
|
115
|
+
### Quick Links
|
|
116
|
+
|
|
117
|
+
- **[Complete Examples](docs/examples/overview.md)** - Step-by-step integration examples (0-6)
|
|
118
|
+
- **[Server Integration](docs/d402-servers/overview.md)** - Add D402 to existing servers
|
|
119
|
+
- **[Client Integration](docs/d402-clients/overview.md)** - Call D402-protected APIs
|
|
120
|
+
- **[MCP Servers](docs/mcp-servers/overview.md)** - Build payment-enabled MCP servers
|
|
121
|
+
- **[Utility Agents](docs/utility-agents/overview.md)** - Build A2A utility agents
|
|
122
|
+
- **[CrewAI Integration](docs/crewai-integration/overview.md)** - Use D402 tools in CrewAI
|
|
123
|
+
|
|
124
|
+
### Complete Integration Examples
|
|
125
|
+
|
|
126
|
+
The [examples section](docs/examples/overview.md) provides complete, working code for:
|
|
127
|
+
|
|
128
|
+
0. **[Wallet Creation & Funding](docs/examples/0-wallet-creation-funding.md)** - Setup wallets, get testnet USDC
|
|
129
|
+
1. **[Existing Server → D402](docs/examples/1-server-to-d402.md)** - Add payments to your API (before/after)
|
|
130
|
+
2. **[Calling D402 Servers](docs/examples/2-calling-d402-servers.md)** - Build payment-enabled client
|
|
131
|
+
3. **[API → MCP Server](docs/examples/3-api-to-mcp-server.md)** - Convert REST to MCP tools
|
|
132
|
+
4. **[CrewAI + MCP](docs/examples/4-crewai-using-mcp.md)** - Use MCP server in crews
|
|
133
|
+
5. **[MCP → Utility Agent](docs/examples/5-mcp-to-utility-agent.md)** - Wrap MCP as A2A agent
|
|
134
|
+
6. **[CrewAI + Utility Agent](docs/examples/6-crewai-using-utility-agent.md)** - Use agents in crews
|
|
135
|
+
|
|
136
|
+
## 🌟 Key Features
|
|
137
|
+
|
|
138
|
+
### D402 Payment Protocol
|
|
139
|
+
- ✅ **HTTP 402 Payment Required** - Standard payment protocol
|
|
140
|
+
- ✅ **EIP-712 Signatures** - Secure payment authorization
|
|
141
|
+
- ✅ **On-Chain Settlement** - Smart contract-based settlements
|
|
142
|
+
- ✅ **Hosted Facilitators** - No infrastructure setup required
|
|
143
|
+
|
|
144
|
+
### Server Integration
|
|
145
|
+
- ✅ **FastAPI** - `D402FastAPIMiddleware`
|
|
146
|
+
- ✅ **Starlette** - `D402PaymentMiddleware`
|
|
147
|
+
- ✅ **Any ASGI Framework** - `D402ASGIWrapper` (Flask, Django, Quart, etc.)
|
|
148
|
+
- ✅ **5-line integration** - Minimal code changes
|
|
149
|
+
|
|
150
|
+
### Client Integration
|
|
151
|
+
- ✅ **HTTPX (Async)** - `d402HttpxClient` with automatic payment
|
|
152
|
+
- ✅ **Requests (Sync)** - Wrapper for synchronous apps
|
|
153
|
+
- ✅ **2-line integration** - Just make requests normally
|
|
154
|
+
|
|
155
|
+
### MCP & A2A
|
|
156
|
+
- ✅ **MCP Servers** - Payment-enabled tool servers
|
|
157
|
+
- ✅ **Utility Agents** - A2A protocol with D402
|
|
158
|
+
- ✅ **CrewAI Integration** - A2AToolkit for paid tools
|
|
159
|
+
- ✅ **Template Generation** - Auto-generate server code
|
|
160
|
+
|
|
161
|
+
## 🔧 What's in the Package
|
|
162
|
+
|
|
163
|
+
### Core Components (IN pip package)
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
src/traia_iatp/
|
|
167
|
+
├── d402/ # D402 payment protocol
|
|
168
|
+
│ ├── servers/ # Server middleware (FastAPI, Starlette, MCP)
|
|
169
|
+
│ ├── clients/ # Client libraries (HTTPX, base client)
|
|
170
|
+
│ ├── asgi_wrapper.py # Universal ASGI wrapper
|
|
171
|
+
│ ├── price_builder.py # USD-based pricing
|
|
172
|
+
│ └── facilitator.py # Facilitator client
|
|
173
|
+
│
|
|
174
|
+
├── mcp/ # MCP server templates & tools
|
|
175
|
+
├── server/ # Utility agent templates
|
|
176
|
+
├── client/ # A2A client & CrewAI tools
|
|
177
|
+
├── contracts/ # Smart contract integration
|
|
178
|
+
└── registry/ # Agent discovery & search
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Examples (NOT in pip package)
|
|
182
|
+
|
|
183
|
+
```
|
|
184
|
+
examples/ # Integration examples
|
|
185
|
+
├── servers/ # FastAPI, Starlette, ASGI examples
|
|
186
|
+
└── clients/ # HTTPX, Requests examples
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Documentation (NOT in pip package)
|
|
190
|
+
|
|
191
|
+
```
|
|
192
|
+
docs/ # GitBook documentation
|
|
193
|
+
├── getting-started/ # Installation, quick start
|
|
194
|
+
├── examples/ # Complete integration examples (0-6)
|
|
195
|
+
├── wallet-setup/ # Wallet creation & CLI
|
|
196
|
+
├── d402-servers/ # Server integration guides
|
|
197
|
+
├── d402-clients/ # Client integration guides
|
|
198
|
+
├── mcp-servers/ # MCP server guides
|
|
199
|
+
├── utility-agents/ # Utility agent guides
|
|
200
|
+
└── crewai-integration/ # CrewAI guides
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## 🏗 Architecture
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
┌────────────────────────────────────────────────────────────┐
|
|
207
|
+
│ Your Application │
|
|
208
|
+
│ (API / MCP Server / Utility Agent / CrewAI Crew) │
|
|
209
|
+
└────────────────────────────────────────────────────────────┘
|
|
210
|
+
│
|
|
211
|
+
▼
|
|
212
|
+
┌────────────────────────────────────────────────────────────┐
|
|
213
|
+
│ IATP-D402 Framework │
|
|
214
|
+
│ • Server Middleware • Client Libraries • Templates │
|
|
215
|
+
└────────────────────────────────────────────────────────────┘
|
|
216
|
+
│
|
|
217
|
+
▼
|
|
218
|
+
┌────────────────────────────────────────────────────────────┐
|
|
219
|
+
│ D402 Payment Protocol │
|
|
220
|
+
│ • HTTP 402 • EIP-712 Signing • Facilitator Service │
|
|
221
|
+
└────────────────────────────────────────────────────────────┘
|
|
222
|
+
│
|
|
223
|
+
▼
|
|
224
|
+
┌────────────────────────────────────────────────────────────┐
|
|
225
|
+
│ Smart Contracts (On-Chain) │
|
|
226
|
+
│ • IATPWallet • Settlement • Tokens │
|
|
227
|
+
└────────────────────────────────────────────────────────────┘
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## 🌐 Facilitators (No Setup Required)
|
|
231
|
+
|
|
232
|
+
**You don't need to run your own facilitator!**
|
|
233
|
+
|
|
234
|
+
- **All Testnets**: `https://test-facilitator.d402.net` (currently: Sepolia)
|
|
235
|
+
- **All Mainnets**: `https://facilitator.d402.net` (currently: Arbitrum)
|
|
236
|
+
|
|
237
|
+
See [Facilitator URLs](docs/getting-started/facilitators.md) for details.
|
|
238
|
+
|
|
239
|
+
## 🔐 Wallet Creation
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
# Create IATP wallet (owner creates their own wallet)
|
|
243
|
+
traia-iatp create-iatp-wallet \
|
|
244
|
+
--owner-key 0x... \
|
|
245
|
+
--create-operator \
|
|
246
|
+
--wallet-name "My Server" \
|
|
247
|
+
--wallet-type MCP_SERVER \
|
|
248
|
+
--network sepolia
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
See [Creating Wallets](docs/wallet-setup/creating-wallets.md) for complete guide.
|
|
252
|
+
|
|
253
|
+
## 📦 Use Cases
|
|
254
|
+
|
|
255
|
+
### 1. Monetize Your API
|
|
256
|
+
|
|
257
|
+
```python
|
|
258
|
+
# Add payment to any endpoint
|
|
259
|
+
d402.register_endpoint("/api/analyze", price_usd=0.01)
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### 2. Build Payment-Enabled MCP Servers
|
|
263
|
+
|
|
264
|
+
```python
|
|
265
|
+
@mcp.tool()
|
|
266
|
+
@require_payment_for_tool(price=price_builder.create_price(0.01))
|
|
267
|
+
def analyze(text: str) -> dict:
|
|
268
|
+
return analyze_sentiment(text)
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### 3. Use Paid Tools in CrewAI
|
|
272
|
+
|
|
273
|
+
```python
|
|
274
|
+
toolkit = A2AToolkit.create_from_endpoint(
|
|
275
|
+
endpoint="http://localhost:9001",
|
|
276
|
+
payment_private_key="0x...",
|
|
277
|
+
wallet_address="0x...",
|
|
278
|
+
max_payment_usd=1.0
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
agent = Agent(role="Analyst", tools=toolkit.tools)
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## 🛠 CLI Commands
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
# Create IATP wallet
|
|
288
|
+
traia-iatp create-iatp-wallet --owner-key 0x... --create-operator
|
|
289
|
+
|
|
290
|
+
# Create utility agency from MCP server
|
|
291
|
+
traia-iatp create-agency --name "My Agent" --mcp-name "Trading MCP"
|
|
292
|
+
|
|
293
|
+
# List available agencies
|
|
294
|
+
traia-iatp list-agencies
|
|
295
|
+
|
|
296
|
+
# Search for tools
|
|
297
|
+
traia-iatp find-tools --query "sentiment analysis"
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## 🔗 Links
|
|
301
|
+
|
|
302
|
+
- **Documentation**: [docs.d402.net](https://docs.d402.net)
|
|
303
|
+
- **PyPI**: [pypi.org/project/traia-iatp](https://pypi.org/project/traia-iatp)
|
|
304
|
+
- **GitHub**: [github.com/Traia-IO/IATP](https://github.com/Traia-IO/IATP)
|
|
305
|
+
- **Examples**: [docs/examples/](docs/examples/overview.md)
|
|
306
|
+
|
|
307
|
+
## 📄 License
|
|
308
|
+
|
|
309
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
310
|
+
|
|
311
|
+
## 🤝 Support
|
|
312
|
+
|
|
313
|
+
- 📖 **Documentation**: [docs.d402.net](https://docs.d402.net)
|
|
314
|
+
- 🐛 **Issues**: [GitHub Issues](https://github.com/Traia-IO/IATP/issues)
|
|
315
|
+
- 💬 **Website**: [traia.io](https://traia.io)
|
|
316
|
+
- 📧 **Email**: support@traia.io
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
**Made with ❤️ by the Traia Team**
|