traia-iatp 0.1.1__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.
Potentially problematic release.
This version of traia-iatp might be problematic. Click here for more details.
- traia_iatp/README.md +368 -0
- traia_iatp/__init__.py +30 -0
- traia_iatp/cli/__init__.py +5 -0
- traia_iatp/cli/main.py +483 -0
- traia_iatp/client/__init__.py +10 -0
- traia_iatp/client/a2a_client.py +274 -0
- traia_iatp/client/crewai_a2a_tools.py +335 -0
- traia_iatp/client/grpc_a2a_tools.py +349 -0
- traia_iatp/client/root_path_a2a_client.py +1 -0
- traia_iatp/core/__init__.py +43 -0
- traia_iatp/core/models.py +161 -0
- traia_iatp/mcp/__init__.py +15 -0
- traia_iatp/mcp/client.py +201 -0
- traia_iatp/mcp/mcp_agent_template.py +422 -0
- traia_iatp/mcp/templates/Dockerfile.j2 +56 -0
- traia_iatp/mcp/templates/README.md.j2 +212 -0
- traia_iatp/mcp/templates/cursor-rules.md.j2 +326 -0
- traia_iatp/mcp/templates/deployment_params.json.j2 +20 -0
- traia_iatp/mcp/templates/docker-compose.yml.j2 +23 -0
- traia_iatp/mcp/templates/dockerignore.j2 +47 -0
- traia_iatp/mcp/templates/gitignore.j2 +77 -0
- traia_iatp/mcp/templates/mcp_health_check.py.j2 +150 -0
- traia_iatp/mcp/templates/pyproject.toml.j2 +26 -0
- traia_iatp/mcp/templates/run_local_docker.sh.j2 +94 -0
- traia_iatp/mcp/templates/server.py.j2 +240 -0
- traia_iatp/mcp/traia_mcp_adapter.py +381 -0
- traia_iatp/preview_diagrams.html +181 -0
- traia_iatp/registry/__init__.py +26 -0
- traia_iatp/registry/atlas_search_indexes.json +280 -0
- traia_iatp/registry/embeddings.py +298 -0
- traia_iatp/registry/iatp_search_api.py +839 -0
- traia_iatp/registry/mongodb_registry.py +771 -0
- traia_iatp/registry/readmes/ATLAS_SEARCH_INDEXES.md +252 -0
- traia_iatp/registry/readmes/ATLAS_SEARCH_SETUP.md +134 -0
- traia_iatp/registry/readmes/AUTHENTICATION_UPDATE.md +124 -0
- traia_iatp/registry/readmes/EMBEDDINGS_SETUP.md +172 -0
- traia_iatp/registry/readmes/IATP_SEARCH_API_GUIDE.md +257 -0
- traia_iatp/registry/readmes/MONGODB_X509_AUTH.md +208 -0
- traia_iatp/registry/readmes/README.md +251 -0
- traia_iatp/registry/readmes/REFACTORING_SUMMARY.md +191 -0
- traia_iatp/server/__init__.py +15 -0
- traia_iatp/server/a2a_server.py +215 -0
- traia_iatp/server/example_template_usage.py +72 -0
- traia_iatp/server/iatp_server_agent_generator.py +237 -0
- traia_iatp/server/iatp_server_template_generator.py +235 -0
- traia_iatp/server/templates/Dockerfile.j2 +49 -0
- traia_iatp/server/templates/README.md +137 -0
- traia_iatp/server/templates/README.md.j2 +425 -0
- traia_iatp/server/templates/__init__.py +1 -0
- traia_iatp/server/templates/__main__.py.j2 +450 -0
- traia_iatp/server/templates/agent.py.j2 +80 -0
- traia_iatp/server/templates/agent_config.json.j2 +22 -0
- traia_iatp/server/templates/agent_executor.py.j2 +264 -0
- traia_iatp/server/templates/docker-compose.yml.j2 +23 -0
- traia_iatp/server/templates/env.example.j2 +67 -0
- traia_iatp/server/templates/gitignore.j2 +78 -0
- traia_iatp/server/templates/grpc_server.py.j2 +218 -0
- traia_iatp/server/templates/pyproject.toml.j2 +76 -0
- traia_iatp/server/templates/run_local_docker.sh.j2 +103 -0
- traia_iatp/server/templates/server.py.j2 +190 -0
- traia_iatp/special_agencies/__init__.py +4 -0
- traia_iatp/special_agencies/registry_search_agency.py +392 -0
- traia_iatp/utils/__init__.py +10 -0
- traia_iatp/utils/docker_utils.py +251 -0
- traia_iatp/utils/general.py +64 -0
- traia_iatp/utils/iatp_utils.py +126 -0
- traia_iatp-0.1.1.dist-info/METADATA +414 -0
- traia_iatp-0.1.1.dist-info/RECORD +72 -0
- traia_iatp-0.1.1.dist-info/WHEEL +5 -0
- traia_iatp-0.1.1.dist-info/entry_points.txt +2 -0
- traia_iatp-0.1.1.dist-info/licenses/LICENSE +21 -0
- traia_iatp-0.1.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
Traia MCP Adapter
|
|
4
|
+
|
|
5
|
+
A custom MCP adapter that extends CrewAI's MCPServerAdapter to support
|
|
6
|
+
passing headers (like Authorization) to streamable-http MCP servers.
|
|
7
|
+
|
|
8
|
+
This adapter transparently handles both authenticated and non-authenticated
|
|
9
|
+
MCP connections by injecting headers when provided.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import logging
|
|
13
|
+
from typing import Dict, Any, List, Optional, Union
|
|
14
|
+
import httpx
|
|
15
|
+
from functools import wraps
|
|
16
|
+
|
|
17
|
+
from crewai_tools import MCPServerAdapter
|
|
18
|
+
from crewai.tools import BaseTool
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class TraiaMCPAdapter(MCPServerAdapter):
|
|
24
|
+
"""
|
|
25
|
+
MCP adapter that supports custom headers for streamable-http transport.
|
|
26
|
+
|
|
27
|
+
This adapter extracts headers from server_params and injects them into
|
|
28
|
+
all HTTP requests made to the MCP server. It works transparently for
|
|
29
|
+
both authenticated and non-authenticated connections.
|
|
30
|
+
|
|
31
|
+
Example:
|
|
32
|
+
```python
|
|
33
|
+
# With authentication headers
|
|
34
|
+
server_params = {
|
|
35
|
+
"url": "https://mcp.example.com/mcp",
|
|
36
|
+
"transport": "streamable-http",
|
|
37
|
+
"headers": {"Authorization": "Bearer YOUR_API_KEY"}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# Without headers (standard connection)
|
|
41
|
+
server_params = {
|
|
42
|
+
"url": "https://mcp.example.com/mcp",
|
|
43
|
+
"transport": "streamable-http"
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
with TraiaMCPAdapter(server_params) as tools:
|
|
47
|
+
# Use tools with or without authentication
|
|
48
|
+
agent = Agent(tools=tools)
|
|
49
|
+
```
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
def __init__(
|
|
53
|
+
self,
|
|
54
|
+
server_params: Union[Dict[str, Any], Any],
|
|
55
|
+
*tool_names: str
|
|
56
|
+
):
|
|
57
|
+
"""
|
|
58
|
+
Initialize the adapter with optional header support.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
server_params: Server configuration. For streamable-http, can include:
|
|
62
|
+
- url: The MCP server URL
|
|
63
|
+
- transport: "streamable-http"
|
|
64
|
+
- headers: Optional dict of headers to include in requests
|
|
65
|
+
*tool_names: Optional tool names to filter
|
|
66
|
+
"""
|
|
67
|
+
# Handle dict params
|
|
68
|
+
if isinstance(server_params, dict):
|
|
69
|
+
# Extract headers if present (don't modify original)
|
|
70
|
+
server_params_copy = server_params.copy()
|
|
71
|
+
self._auth_headers = server_params_copy.pop("headers", {})
|
|
72
|
+
|
|
73
|
+
if self._auth_headers:
|
|
74
|
+
logger.info(f"TraiaMCPAdapter: Headers configured: {list(self._auth_headers.keys())}")
|
|
75
|
+
# Apply monkey patch before parent initialization
|
|
76
|
+
self._apply_httpx_patch()
|
|
77
|
+
|
|
78
|
+
# Pass clean params to parent
|
|
79
|
+
super().__init__(server_params_copy, *tool_names)
|
|
80
|
+
else:
|
|
81
|
+
# Non-dict params, no headers possible
|
|
82
|
+
self._auth_headers = {}
|
|
83
|
+
super().__init__(server_params, *tool_names)
|
|
84
|
+
|
|
85
|
+
def _apply_httpx_patch(self):
|
|
86
|
+
"""Monkey-patch httpx.AsyncClient to inject headers."""
|
|
87
|
+
original_init = httpx.AsyncClient.__init__
|
|
88
|
+
auth_headers = self._auth_headers
|
|
89
|
+
|
|
90
|
+
@wraps(original_init)
|
|
91
|
+
def patched_init(client_self, *args, **kwargs):
|
|
92
|
+
# Get existing headers
|
|
93
|
+
existing_headers = kwargs.get('headers', {})
|
|
94
|
+
if isinstance(existing_headers, dict):
|
|
95
|
+
# Merge our headers
|
|
96
|
+
merged_headers = {**auth_headers, **existing_headers}
|
|
97
|
+
kwargs['headers'] = merged_headers
|
|
98
|
+
logger.debug(f"Injected headers into httpx.AsyncClient: {list(auth_headers.keys())}")
|
|
99
|
+
|
|
100
|
+
# Also ensure headers are preserved on redirects
|
|
101
|
+
if 'follow_redirects' not in kwargs:
|
|
102
|
+
kwargs['follow_redirects'] = True
|
|
103
|
+
|
|
104
|
+
# Call original init
|
|
105
|
+
original_init(client_self, *args, **kwargs)
|
|
106
|
+
|
|
107
|
+
# Apply the patch
|
|
108
|
+
httpx.AsyncClient.__init__ = patched_init
|
|
109
|
+
self._original_httpx_init = original_init
|
|
110
|
+
logger.debug("Applied httpx.AsyncClient monkey patch")
|
|
111
|
+
|
|
112
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
113
|
+
"""Exit context manager and restore original httpx if patched."""
|
|
114
|
+
# Restore original httpx.AsyncClient.__init__ if we patched it
|
|
115
|
+
if hasattr(self, '_original_httpx_init'):
|
|
116
|
+
httpx.AsyncClient.__init__ = self._original_httpx_init
|
|
117
|
+
logger.debug("Restored original httpx.AsyncClient")
|
|
118
|
+
|
|
119
|
+
# Call parent exit
|
|
120
|
+
return super().__exit__(exc_type, exc_val, exc_tb)
|
|
121
|
+
|
|
122
|
+
def __enter__(self) -> List[BaseTool]:
|
|
123
|
+
"""Enter context manager."""
|
|
124
|
+
if self._auth_headers:
|
|
125
|
+
logger.debug(f"TraiaMCPAdapter: Using authenticated connection")
|
|
126
|
+
|
|
127
|
+
return super().__enter__()
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def create_mcp_adapter(
|
|
131
|
+
url: str,
|
|
132
|
+
headers: Optional[Dict[str, str]] = None,
|
|
133
|
+
transport: str = "streamable-http",
|
|
134
|
+
tool_names: Optional[List[str]] = None
|
|
135
|
+
) -> TraiaMCPAdapter:
|
|
136
|
+
"""
|
|
137
|
+
Create a Traia MCP adapter with optional headers.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
url: MCP server URL
|
|
141
|
+
headers: Optional dictionary of headers to include in requests
|
|
142
|
+
transport: Transport type (default: streamable-http)
|
|
143
|
+
tool_names: Optional list of tool names to filter
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
TraiaMCPAdapter configured with or without headers
|
|
147
|
+
|
|
148
|
+
Example:
|
|
149
|
+
```python
|
|
150
|
+
# With headers
|
|
151
|
+
adapter = create_mcp_adapter(
|
|
152
|
+
url="https://news-mcp.example.com/mcp",
|
|
153
|
+
headers={"Authorization": "Bearer YOUR_API_KEY"}
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
# Without headers
|
|
157
|
+
adapter = create_mcp_adapter(
|
|
158
|
+
url="https://news-mcp.example.com/mcp"
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
with adapter as tools:
|
|
162
|
+
agent = Agent(tools=tools)
|
|
163
|
+
```
|
|
164
|
+
"""
|
|
165
|
+
server_params = {
|
|
166
|
+
"url": url,
|
|
167
|
+
"transport": transport
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if headers:
|
|
171
|
+
server_params["headers"] = headers
|
|
172
|
+
|
|
173
|
+
if tool_names:
|
|
174
|
+
return TraiaMCPAdapter(server_params, *tool_names)
|
|
175
|
+
else:
|
|
176
|
+
return TraiaMCPAdapter(server_params)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def create_mcp_adapter_with_auth(
|
|
180
|
+
url: str,
|
|
181
|
+
api_key: str,
|
|
182
|
+
auth_header: str = "Authorization",
|
|
183
|
+
auth_prefix: str = "Bearer",
|
|
184
|
+
transport: str = "streamable-http",
|
|
185
|
+
tool_names: Optional[List[str]] = None
|
|
186
|
+
) -> TraiaMCPAdapter:
|
|
187
|
+
"""
|
|
188
|
+
Create a Traia MCP adapter with authentication.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
url: MCP server URL
|
|
192
|
+
api_key: API key for authentication
|
|
193
|
+
auth_header: Header name for auth (default: Authorization)
|
|
194
|
+
auth_prefix: Auth scheme prefix (default: Bearer)
|
|
195
|
+
transport: Transport type (default: streamable-http)
|
|
196
|
+
tool_names: Optional list of tool names to filter
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
TraiaMCPAdapter configured with auth headers
|
|
200
|
+
|
|
201
|
+
Example:
|
|
202
|
+
```python
|
|
203
|
+
adapter = create_mcp_adapter_with_auth(
|
|
204
|
+
url="https://news-mcp.example.com/mcp",
|
|
205
|
+
api_key="your-api-key"
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
with adapter as tools:
|
|
209
|
+
# Tools will include Authorization header in all requests
|
|
210
|
+
agent = Agent(tools=tools)
|
|
211
|
+
```
|
|
212
|
+
"""
|
|
213
|
+
headers = {}
|
|
214
|
+
if auth_prefix:
|
|
215
|
+
headers[auth_header] = f"{auth_prefix} {api_key}"
|
|
216
|
+
else:
|
|
217
|
+
headers[auth_header] = api_key
|
|
218
|
+
|
|
219
|
+
return create_mcp_adapter(url, headers, transport, tool_names)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
# Backwards compatibility aliases
|
|
223
|
+
HeaderMCPAdapter = TraiaMCPAdapter
|
|
224
|
+
create_mcp_adapter_with_headers = create_mcp_adapter
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
# Usage examples
|
|
228
|
+
USAGE_GUIDE = """
|
|
229
|
+
TraiaMCPAdapter Usage Guide
|
|
230
|
+
==========================
|
|
231
|
+
|
|
232
|
+
The TraiaMCPAdapter seamlessly handles both authenticated and non-authenticated
|
|
233
|
+
MCP connections. It extracts headers from server_params and injects them into
|
|
234
|
+
all HTTP requests when using streamable-http transport.
|
|
235
|
+
|
|
236
|
+
Basic Usage
|
|
237
|
+
-----------
|
|
238
|
+
```python
|
|
239
|
+
from iatp.mcp import TraiaMCPAdapter
|
|
240
|
+
|
|
241
|
+
# Standard connection (no authentication)
|
|
242
|
+
server_params = {
|
|
243
|
+
"url": "http://localhost:8000/mcp",
|
|
244
|
+
"transport": "streamable-http"
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
# Authenticated connection
|
|
248
|
+
server_params = {
|
|
249
|
+
"url": "http://localhost:8000/mcp",
|
|
250
|
+
"transport": "streamable-http",
|
|
251
|
+
"headers": {
|
|
252
|
+
"Authorization": "Bearer YOUR_API_KEY"
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
# Use the same way regardless of authentication
|
|
257
|
+
with TraiaMCPAdapter(server_params) as tools:
|
|
258
|
+
agent = Agent(
|
|
259
|
+
role="My Agent",
|
|
260
|
+
tools=tools
|
|
261
|
+
)
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Using Helper Functions
|
|
265
|
+
----------------------
|
|
266
|
+
```python
|
|
267
|
+
from iatp.mcp import create_mcp_adapter_with_auth
|
|
268
|
+
|
|
269
|
+
# Create authenticated adapter
|
|
270
|
+
adapter = create_mcp_adapter_with_auth(
|
|
271
|
+
url="http://localhost:8000/mcp",
|
|
272
|
+
api_key="your-api-key"
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
with adapter as tools:
|
|
276
|
+
# Use authenticated tools
|
|
277
|
+
pass
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Multiple Headers
|
|
281
|
+
----------------
|
|
282
|
+
```python
|
|
283
|
+
adapter = create_mcp_adapter(
|
|
284
|
+
url="http://localhost:8000/mcp",
|
|
285
|
+
headers={
|
|
286
|
+
"Authorization": "Bearer YOUR_API_KEY",
|
|
287
|
+
"X-API-Version": "v1",
|
|
288
|
+
"X-Client-ID": "my-client"
|
|
289
|
+
}
|
|
290
|
+
)
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
With Tool Filtering
|
|
294
|
+
-------------------
|
|
295
|
+
```python
|
|
296
|
+
adapter = create_mcp_adapter_with_auth(
|
|
297
|
+
url="http://localhost:8000/mcp",
|
|
298
|
+
api_key="your-api-key",
|
|
299
|
+
tool_names=["search_news", "get_api_info"]
|
|
300
|
+
)
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Server-Side Authentication
|
|
304
|
+
--------------------------
|
|
305
|
+
For MCP servers that require authentication, implement FastMCP middleware:
|
|
306
|
+
|
|
307
|
+
```python
|
|
308
|
+
from fastmcp import FastMCP, Context
|
|
309
|
+
from fastmcp.server.middleware import Middleware, MiddlewareContext
|
|
310
|
+
from fastmcp.server.dependencies import get_http_request, get_context
|
|
311
|
+
from starlette.requests import Request
|
|
312
|
+
|
|
313
|
+
class AuthMiddleware(Middleware):
|
|
314
|
+
async def on_request(self, context: MiddlewareContext, call_next):
|
|
315
|
+
try:
|
|
316
|
+
# Access the raw HTTP request
|
|
317
|
+
request: Request = get_http_request()
|
|
318
|
+
|
|
319
|
+
# Extract bearer token from Authorization header
|
|
320
|
+
auth = request.headers.get("Authorization", "")
|
|
321
|
+
token = auth[7:].strip() if auth.lower().startswith("bearer ") else None
|
|
322
|
+
|
|
323
|
+
if not token:
|
|
324
|
+
# Check X-API-KEY header as alternative
|
|
325
|
+
token = request.headers.get("X-API-KEY", "")
|
|
326
|
+
|
|
327
|
+
if token:
|
|
328
|
+
# Store the API key in the context state
|
|
329
|
+
if hasattr(context, 'state'):
|
|
330
|
+
context.state.api_key = token
|
|
331
|
+
else:
|
|
332
|
+
# Try to store it in the request state as fallback
|
|
333
|
+
request.state.api_key = token
|
|
334
|
+
except Exception as e:
|
|
335
|
+
logger.debug(f"Could not extract API key from request: {e}")
|
|
336
|
+
|
|
337
|
+
return await call_next(context)
|
|
338
|
+
|
|
339
|
+
mcp = FastMCP("My Server", middleware=[AuthMiddleware()])
|
|
340
|
+
|
|
341
|
+
def get_session_api_key(context: Context) -> Optional[str]:
|
|
342
|
+
'''Get the API key for the current session.'''
|
|
343
|
+
try:
|
|
344
|
+
# Try to get the API key from the context state
|
|
345
|
+
if hasattr(context, 'state') and hasattr(context.state, 'api_key'):
|
|
346
|
+
return context.state.api_key
|
|
347
|
+
|
|
348
|
+
# Fallback: try to get it from the current HTTP request
|
|
349
|
+
try:
|
|
350
|
+
request: Request = get_http_request()
|
|
351
|
+
if hasattr(request.state, 'api_key'):
|
|
352
|
+
return request.state.api_key
|
|
353
|
+
except Exception:
|
|
354
|
+
pass
|
|
355
|
+
|
|
356
|
+
# If we're in a tool context, try to get the context using the dependency
|
|
357
|
+
try:
|
|
358
|
+
ctx = get_context()
|
|
359
|
+
if hasattr(ctx, 'state') and hasattr(ctx.state, 'api_key'):
|
|
360
|
+
return ctx.state.api_key
|
|
361
|
+
except Exception:
|
|
362
|
+
pass
|
|
363
|
+
except Exception as e:
|
|
364
|
+
logger.debug(f"Could not retrieve API key from context: {e}")
|
|
365
|
+
|
|
366
|
+
return None
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
Note: Headers are only applicable for streamable-http transport.
|
|
370
|
+
For stdio or SSE transports, authentication must be handled differently.
|
|
371
|
+
"""
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
__all__ = [
|
|
375
|
+
'TraiaMCPAdapter',
|
|
376
|
+
'HeaderMCPAdapter', # Alias for backward compatibility
|
|
377
|
+
'create_mcp_adapter',
|
|
378
|
+
'create_mcp_adapter_with_auth',
|
|
379
|
+
'create_mcp_adapter_with_headers', # Alias
|
|
380
|
+
'USAGE_GUIDE'
|
|
381
|
+
]
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>IATP Mermaid Diagrams Preview</title>
|
|
7
|
+
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
|
|
8
|
+
<style>
|
|
9
|
+
body {
|
|
10
|
+
font-family: Arial, sans-serif;
|
|
11
|
+
max-width: 1200px;
|
|
12
|
+
margin: 0 auto;
|
|
13
|
+
padding: 20px;
|
|
14
|
+
background-color: #f5f5f5;
|
|
15
|
+
}
|
|
16
|
+
h1, h2 {
|
|
17
|
+
color: #333;
|
|
18
|
+
}
|
|
19
|
+
.diagram-container {
|
|
20
|
+
background-color: white;
|
|
21
|
+
border: 1px solid #ddd;
|
|
22
|
+
border-radius: 8px;
|
|
23
|
+
padding: 20px;
|
|
24
|
+
margin-bottom: 30px;
|
|
25
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
26
|
+
}
|
|
27
|
+
.mermaid {
|
|
28
|
+
text-align: center;
|
|
29
|
+
}
|
|
30
|
+
</style>
|
|
31
|
+
</head>
|
|
32
|
+
<body>
|
|
33
|
+
<h1>IATP (Inter-Agent Transfer Protocol) Diagrams</h1>
|
|
34
|
+
|
|
35
|
+
<div class="diagram-container">
|
|
36
|
+
<h2>Standard Request-Response Flow</h2>
|
|
37
|
+
<div class="mermaid">
|
|
38
|
+
sequenceDiagram
|
|
39
|
+
participant CrewAI as CrewAI Agent
|
|
40
|
+
participant Client as A2A Client
|
|
41
|
+
participant Server as A2A Server
|
|
42
|
+
participant MCP as MCP Server
|
|
43
|
+
|
|
44
|
+
CrewAI->>Client: Execute request
|
|
45
|
+
Client->>Client: Ensure HTTP/2 connection
|
|
46
|
+
Client->>Server: Send message (JSON-RPC)
|
|
47
|
+
Server->>Server: Process request
|
|
48
|
+
Server->>MCP: Execute MCP tools
|
|
49
|
+
MCP-->>Server: Return results
|
|
50
|
+
Server-->>Client: Send response/task
|
|
51
|
+
|
|
52
|
+
alt Task-based response
|
|
53
|
+
loop Poll for completion
|
|
54
|
+
Client->>Server: Get task status
|
|
55
|
+
Server-->>Client: Task state
|
|
56
|
+
end
|
|
57
|
+
Client->>Server: Get final result
|
|
58
|
+
Server-->>Client: Task messages/artifacts
|
|
59
|
+
else Direct response
|
|
60
|
+
Note over Client: Extract message content
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
Client-->>CrewAI: Return formatted result
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<div class="diagram-container">
|
|
68
|
+
<h2>SSE Streaming Flow</h2>
|
|
69
|
+
<div class="mermaid">
|
|
70
|
+
sequenceDiagram
|
|
71
|
+
participant CrewAI as CrewAI Agent
|
|
72
|
+
participant Client as A2A Client
|
|
73
|
+
participant Server as A2A Server (HTTP/2)
|
|
74
|
+
participant MCP as MCP Server
|
|
75
|
+
|
|
76
|
+
CrewAI->>Client: Stream request
|
|
77
|
+
Client->>Client: Check streaming support
|
|
78
|
+
Client->>Server: POST /a2a/stream (SSE)
|
|
79
|
+
Server->>Server: Initialize SSE stream
|
|
80
|
+
Server->>Client: stream_start event
|
|
81
|
+
|
|
82
|
+
loop Streaming chunks
|
|
83
|
+
Server->>MCP: Get data chunk
|
|
84
|
+
MCP-->>Server: Data
|
|
85
|
+
Server->>Client: stream_chunk event
|
|
86
|
+
Client->>CrewAI: Yield chunk
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
Server->>Client: stream_complete event
|
|
90
|
+
Client->>Client: Close stream
|
|
91
|
+
Client-->>CrewAI: Complete
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
<div class="diagram-container">
|
|
96
|
+
<h2>Client Decision Flow</h2>
|
|
97
|
+
<div class="mermaid">
|
|
98
|
+
graph TD
|
|
99
|
+
subgraph "CrewAI Agent Request"
|
|
100
|
+
A[Agent calls tool._run<br/>with request]
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
subgraph "A2ATool Decision Logic"
|
|
104
|
+
B{Check context}
|
|
105
|
+
C[_execute_with_retry]
|
|
106
|
+
D{streaming=True<br/>AND<br/>supports_streaming?}
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
subgraph "Standard Mode"
|
|
110
|
+
E[_execute_standard]
|
|
111
|
+
F[Send JSON-RPC message]
|
|
112
|
+
G{Response type?}
|
|
113
|
+
H[Direct Message<br/>Extract text parts]
|
|
114
|
+
I[Task Response<br/>Poll with _wait_for_task_completion]
|
|
115
|
+
J[_get_task_status<br/>Loop until complete]
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
subgraph "Streaming Mode"
|
|
119
|
+
K[_execute_streaming]
|
|
120
|
+
L[Open SSE connection<br/>via _stream_sse]
|
|
121
|
+
M[Collect all chunks]
|
|
122
|
+
N[Return combined result]
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
subgraph "Async Iterator Mode"
|
|
126
|
+
O[stream method called]
|
|
127
|
+
P[Force streaming=True]
|
|
128
|
+
Q[_stream_sse context manager]
|
|
129
|
+
R[Yield chunks individually]
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
A --> B
|
|
133
|
+
B --> C
|
|
134
|
+
C --> D
|
|
135
|
+
D -->|No| E
|
|
136
|
+
D -->|Yes| K
|
|
137
|
+
|
|
138
|
+
E --> F
|
|
139
|
+
F --> G
|
|
140
|
+
G -->|Message| H
|
|
141
|
+
G -->|Task| I
|
|
142
|
+
I --> J
|
|
143
|
+
J -->|Loop| I
|
|
144
|
+
|
|
145
|
+
K --> L
|
|
146
|
+
L --> M
|
|
147
|
+
M --> N
|
|
148
|
+
|
|
149
|
+
O --> P
|
|
150
|
+
P --> Q
|
|
151
|
+
Q --> R
|
|
152
|
+
|
|
153
|
+
H --> S[Return result]
|
|
154
|
+
J --> S
|
|
155
|
+
N --> S
|
|
156
|
+
R --> T[Async iteration]
|
|
157
|
+
|
|
158
|
+
style A fill:#e1f5fe
|
|
159
|
+
style S fill:#c8e6c9
|
|
160
|
+
style T fill:#c8e6c9
|
|
161
|
+
style D fill:#fff3cd
|
|
162
|
+
style G fill:#fff3cd
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
|
|
166
|
+
<script>
|
|
167
|
+
mermaid.initialize({
|
|
168
|
+
startOnLoad: true,
|
|
169
|
+
theme: 'default',
|
|
170
|
+
themeVariables: {
|
|
171
|
+
primaryColor: '#f5f5f5',
|
|
172
|
+
primaryTextColor: '#333',
|
|
173
|
+
primaryBorderColor: '#7C0000',
|
|
174
|
+
lineColor: '#5D5D5D',
|
|
175
|
+
secondaryColor: '#006100',
|
|
176
|
+
tertiaryColor: '#fff'
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
</script>
|
|
180
|
+
</body>
|
|
181
|
+
</html>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""IATP registry module for managing utility agents and MCP servers."""
|
|
2
|
+
|
|
3
|
+
from .mongodb_registry import UtilityAgentRegistry, MCPServerRegistry
|
|
4
|
+
from .iatp_search_api import (
|
|
5
|
+
find_utility_agent,
|
|
6
|
+
list_utility_agents,
|
|
7
|
+
search_utility_agents,
|
|
8
|
+
find_mcp_server,
|
|
9
|
+
list_mcp_servers,
|
|
10
|
+
search_mcp_servers,
|
|
11
|
+
get_mcp_server
|
|
12
|
+
)
|
|
13
|
+
from .embeddings import get_embedding_service
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"UtilityAgentRegistry",
|
|
17
|
+
"MCPServerRegistry",
|
|
18
|
+
"find_utility_agent",
|
|
19
|
+
"list_utility_agents",
|
|
20
|
+
"search_utility_agents",
|
|
21
|
+
"find_mcp_server",
|
|
22
|
+
"list_mcp_servers",
|
|
23
|
+
"search_mcp_servers",
|
|
24
|
+
"get_mcp_server",
|
|
25
|
+
"get_embedding_service",
|
|
26
|
+
]
|