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.

Files changed (72) hide show
  1. traia_iatp/README.md +368 -0
  2. traia_iatp/__init__.py +30 -0
  3. traia_iatp/cli/__init__.py +5 -0
  4. traia_iatp/cli/main.py +483 -0
  5. traia_iatp/client/__init__.py +10 -0
  6. traia_iatp/client/a2a_client.py +274 -0
  7. traia_iatp/client/crewai_a2a_tools.py +335 -0
  8. traia_iatp/client/grpc_a2a_tools.py +349 -0
  9. traia_iatp/client/root_path_a2a_client.py +1 -0
  10. traia_iatp/core/__init__.py +43 -0
  11. traia_iatp/core/models.py +161 -0
  12. traia_iatp/mcp/__init__.py +15 -0
  13. traia_iatp/mcp/client.py +201 -0
  14. traia_iatp/mcp/mcp_agent_template.py +422 -0
  15. traia_iatp/mcp/templates/Dockerfile.j2 +56 -0
  16. traia_iatp/mcp/templates/README.md.j2 +212 -0
  17. traia_iatp/mcp/templates/cursor-rules.md.j2 +326 -0
  18. traia_iatp/mcp/templates/deployment_params.json.j2 +20 -0
  19. traia_iatp/mcp/templates/docker-compose.yml.j2 +23 -0
  20. traia_iatp/mcp/templates/dockerignore.j2 +47 -0
  21. traia_iatp/mcp/templates/gitignore.j2 +77 -0
  22. traia_iatp/mcp/templates/mcp_health_check.py.j2 +150 -0
  23. traia_iatp/mcp/templates/pyproject.toml.j2 +26 -0
  24. traia_iatp/mcp/templates/run_local_docker.sh.j2 +94 -0
  25. traia_iatp/mcp/templates/server.py.j2 +240 -0
  26. traia_iatp/mcp/traia_mcp_adapter.py +381 -0
  27. traia_iatp/preview_diagrams.html +181 -0
  28. traia_iatp/registry/__init__.py +26 -0
  29. traia_iatp/registry/atlas_search_indexes.json +280 -0
  30. traia_iatp/registry/embeddings.py +298 -0
  31. traia_iatp/registry/iatp_search_api.py +839 -0
  32. traia_iatp/registry/mongodb_registry.py +771 -0
  33. traia_iatp/registry/readmes/ATLAS_SEARCH_INDEXES.md +252 -0
  34. traia_iatp/registry/readmes/ATLAS_SEARCH_SETUP.md +134 -0
  35. traia_iatp/registry/readmes/AUTHENTICATION_UPDATE.md +124 -0
  36. traia_iatp/registry/readmes/EMBEDDINGS_SETUP.md +172 -0
  37. traia_iatp/registry/readmes/IATP_SEARCH_API_GUIDE.md +257 -0
  38. traia_iatp/registry/readmes/MONGODB_X509_AUTH.md +208 -0
  39. traia_iatp/registry/readmes/README.md +251 -0
  40. traia_iatp/registry/readmes/REFACTORING_SUMMARY.md +191 -0
  41. traia_iatp/server/__init__.py +15 -0
  42. traia_iatp/server/a2a_server.py +215 -0
  43. traia_iatp/server/example_template_usage.py +72 -0
  44. traia_iatp/server/iatp_server_agent_generator.py +237 -0
  45. traia_iatp/server/iatp_server_template_generator.py +235 -0
  46. traia_iatp/server/templates/Dockerfile.j2 +49 -0
  47. traia_iatp/server/templates/README.md +137 -0
  48. traia_iatp/server/templates/README.md.j2 +425 -0
  49. traia_iatp/server/templates/__init__.py +1 -0
  50. traia_iatp/server/templates/__main__.py.j2 +450 -0
  51. traia_iatp/server/templates/agent.py.j2 +80 -0
  52. traia_iatp/server/templates/agent_config.json.j2 +22 -0
  53. traia_iatp/server/templates/agent_executor.py.j2 +264 -0
  54. traia_iatp/server/templates/docker-compose.yml.j2 +23 -0
  55. traia_iatp/server/templates/env.example.j2 +67 -0
  56. traia_iatp/server/templates/gitignore.j2 +78 -0
  57. traia_iatp/server/templates/grpc_server.py.j2 +218 -0
  58. traia_iatp/server/templates/pyproject.toml.j2 +76 -0
  59. traia_iatp/server/templates/run_local_docker.sh.j2 +103 -0
  60. traia_iatp/server/templates/server.py.j2 +190 -0
  61. traia_iatp/special_agencies/__init__.py +4 -0
  62. traia_iatp/special_agencies/registry_search_agency.py +392 -0
  63. traia_iatp/utils/__init__.py +10 -0
  64. traia_iatp/utils/docker_utils.py +251 -0
  65. traia_iatp/utils/general.py +64 -0
  66. traia_iatp/utils/iatp_utils.py +126 -0
  67. traia_iatp-0.1.1.dist-info/METADATA +414 -0
  68. traia_iatp-0.1.1.dist-info/RECORD +72 -0
  69. traia_iatp-0.1.1.dist-info/WHEEL +5 -0
  70. traia_iatp-0.1.1.dist-info/entry_points.txt +2 -0
  71. traia_iatp-0.1.1.dist-info/licenses/LICENSE +21 -0
  72. traia_iatp-0.1.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,76 @@
1
+ [project]
2
+ name = "{{ package_name }}"
3
+ version = "{{ agent_version }}"
4
+ description = "{{ agent_description }}"
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ dependencies = [
8
+ "crewai>=0.130.0",
9
+ "crewai-tools[mcp]>=0.47.1",
10
+ "a2a-sdk>=0.2.6",
11
+ "fastmcp>=2.8.1",
12
+ "hypercorn>=0.17.3", # HTTP/2 support via h2 dependency
13
+ "httpx[http2]>=0.28.1", # HTTP/2 support with http2 extra
14
+ "starlette>=0.46.2", # For SSE streaming support
15
+ "sse-starlette>=2.3.6", # Server-Sent Events support
16
+ "pydantic>=2.11.0",
17
+ "python-dotenv>=1.1.0",
18
+ "pymongo>=4.13.0", # Required for MCP registry
19
+ "traia-iatp", # Core IATP functionality - always use latest version
20
+ {% for dep in additional_dependencies %}
21
+ "{{ dep }}",
22
+ {% endfor %}
23
+ ]
24
+
25
+ [project.optional-dependencies]
26
+ grpc = [
27
+ "grpcio>=1.73.0",
28
+ "grpcio-tools>=1.71.0",
29
+ "grpcio-reflection>=1.71.0",
30
+ ]
31
+
32
+ [tool.uv]
33
+ dev-dependencies = [
34
+ "pytest>=7.0.0",
35
+ "pytest-asyncio>=0.21.0",
36
+ "black>=23.0.0",
37
+ "ruff>=0.1.0",
38
+ "mypy>=1.0.0",
39
+ ]
40
+
41
+ [build-system]
42
+ requires = ["setuptools>=64", "wheel"]
43
+ build-backend = "setuptools.build_meta"
44
+
45
+ [tool.black]
46
+ line-length = 100
47
+ target-version = ['py312']
48
+ include = '\.pyi?$'
49
+
50
+ [tool.ruff]
51
+ line-length = 100
52
+ target-version = "py312"
53
+ select = [
54
+ "E", # pycodestyle errors
55
+ "W", # pycodestyle warnings
56
+ "F", # pyflakes
57
+ "I", # isort
58
+ "B", # flake8-bugbear
59
+ "C4", # flake8-comprehensions
60
+ "UP", # pyupgrade
61
+ ]
62
+ ignore = [
63
+ "E501", # line too long
64
+ "B008", # do not perform function calls in argument defaults
65
+ "C901", # too complex
66
+ ]
67
+
68
+ [tool.ruff.isort]
69
+ known-first-party = ["{{ package_name }}"]
70
+
71
+ [tool.mypy]
72
+ python_version = "3.12"
73
+ warn_return_any = true
74
+ warn_unused_configs = true
75
+ disallow_untyped_defs = true
76
+ ignore_missing_imports = true
@@ -0,0 +1,103 @@
1
+ #!/bin/bash
2
+
3
+ # Script to build and run the {{ agent_name }} locally in Docker
4
+
5
+ set -e # Exit on error
6
+
7
+ # Color codes for output
8
+ GREEN='\033[0;32m'
9
+ BLUE='\033[0;34m'
10
+ YELLOW='\033[1;33m'
11
+ RED='\033[0;31m'
12
+ NC='\033[0m' # No Color
13
+
14
+ # Load environment variables from .env if it exists
15
+ if [ -f .env ]; then
16
+ echo -e "${BLUE}📋 Loading environment variables from .env file...${NC}"
17
+ set -a # Export all variables
18
+ source .env
19
+ set +a # Stop exporting
20
+ else
21
+ echo -e "${YELLOW}⚠️ No .env file found. Using defaults.${NC}"
22
+ echo -e "${YELLOW} Copy .env.example to .env and configure as needed.${NC}"
23
+ fi
24
+
25
+ # Configuration with defaults
26
+ IMAGE_NAME="{{ agent_id }}"
27
+ CONTAINER_NAME="{{ agent_id }}-local"
28
+ HOST_PORT=${PORT:-8000}
29
+ CONTAINER_PORT=${PORT:-8000}
30
+
31
+ echo -e "${BLUE}🚀 Building and running {{ agent_name }}...${NC}"
32
+ echo -e "${BLUE} Using port: ${HOST_PORT}${NC}"
33
+ echo
34
+
35
+ # Check if Docker is installed
36
+ if ! command -v docker &> /dev/null; then
37
+ echo -e "${RED}❌ Docker is not installed. Please install Docker first.${NC}"
38
+ exit 1
39
+ fi
40
+
41
+ # Stop and remove existing container if it exists
42
+ if docker ps -a | grep -q $CONTAINER_NAME; then
43
+ echo -e "${YELLOW}🛑 Stopping existing container...${NC}"
44
+ docker stop $CONTAINER_NAME >/dev/null 2>&1 || true
45
+ docker rm $CONTAINER_NAME >/dev/null 2>&1 || true
46
+ fi
47
+
48
+ # Build the Docker image
49
+ echo -e "${BLUE}🔨 Building Docker image...${NC}"
50
+ docker build -t $IMAGE_NAME .
51
+
52
+ # Run the container
53
+ echo -e "${BLUE}🏃 Starting container...${NC}"
54
+ docker run -d \
55
+ --name $CONTAINER_NAME \
56
+ -p $HOST_PORT:$CONTAINER_PORT \
57
+ --env-file .env \
58
+ -e DEBUG_PROTOCOL=${DEBUG_PROTOCOL:-false} \
59
+ $IMAGE_NAME
60
+
61
+ # Wait for the server to start
62
+ echo -e "${YELLOW}⏳ Waiting for server to start...${NC}"
63
+ sleep 3
64
+
65
+ # Check if container is running
66
+ if ! docker ps | grep -q $CONTAINER_NAME; then
67
+ echo -e "${RED}❌ Container failed to start. Checking logs:${NC}"
68
+ docker logs $CONTAINER_NAME
69
+ exit 1
70
+ fi
71
+
72
+ # Get container info
73
+ CONTAINER_ID=$(docker ps -q -f name=$CONTAINER_NAME)
74
+
75
+ # Output connection information
76
+ echo
77
+ echo -e "${GREEN}✅ {{ agent_name }} is running!${NC}"
78
+ echo
79
+ echo -e "${BLUE}📍 Connection Information:${NC}"
80
+ echo -e " A2A Endpoint: ${GREEN}http://localhost:${HOST_PORT}/a2a${NC}"
81
+ echo -e " Agent Info: ${GREEN}http://localhost:${HOST_PORT}/.well-known/agent.json${NC}"
82
+ echo -e " Container Name: ${GREEN}${CONTAINER_NAME}${NC}"
83
+ echo -e " Container ID: ${GREEN}${CONTAINER_ID:0:12}${NC}"
84
+ echo
85
+ echo -e "${BLUE}📝 Useful commands:${NC}"
86
+ echo -e " View logs: ${YELLOW}docker logs -f ${CONTAINER_NAME}${NC}"
87
+ echo -e " Stop server: ${YELLOW}docker stop ${CONTAINER_NAME}${NC}"
88
+ echo -e " Remove container: ${YELLOW}docker rm ${CONTAINER_NAME}${NC}"
89
+ echo -e " Shell access: ${YELLOW}docker exec -it ${CONTAINER_NAME} /bin/bash${NC}"
90
+ echo
91
+
92
+ # Check if the server is responding
93
+ echo -e "${YELLOW}🔍 Checking server health...${NC}"
94
+ if curl -s -o /dev/null -w "%{http_code}" "http://localhost:${HOST_PORT}/.well-known/agent.json" | grep -q "200"; then
95
+ echo -e "${GREEN}✅ Server is healthy!${NC}"
96
+
97
+ # Get and display agency info
98
+ echo
99
+ echo -e "${BLUE}📋 Agency Information:${NC}"
100
+ curl -s "http://localhost:${HOST_PORT}/.well-known/agent.json" | python -m json.tool || echo "Could not fetch agency info"
101
+ else
102
+ echo -e "${YELLOW}⚠️ Server may still be starting up. Check logs with: docker logs -f ${CONTAINER_NAME}${NC}"
103
+ fi
@@ -0,0 +1,190 @@
1
+ """
2
+ {{ agent_name }} - A2A Server Implementation
3
+
4
+ Auto-generated utility agent that exposes {{ mcp_server_name }} via A2A protocol.
5
+ This is a simplified all-in-one implementation.
6
+ """
7
+
8
+ import asyncio
9
+ import json
10
+ import logging
11
+ import os
12
+ from typing import Dict, Any, Optional
13
+ from a2a.server.apps import A2AStarletteApplication
14
+ from a2a.server.agent_execution import AgentExecutor, RequestContext
15
+ from a2a.server.events.event_queue import EventQueue
16
+ from a2a.server.tasks import InMemoryTaskStore
17
+ from a2a.server.request_handlers import DefaultRequestHandler
18
+ from a2a.types import AgentCard, AgentSkill, AgentCapabilities
19
+ from a2a.utils import new_agent_text_message
20
+ import uvicorn
21
+ from crewai import Task
22
+
23
+ # Import the MCP agent builder and run function
24
+ from traia_iatp.mcp import MCPServerConfig, MCPAgentBuilder, run_with_mcp_tools, MCPServerInfo
25
+
26
+ logging.basicConfig(level=logging.INFO)
27
+ logger = logging.getLogger(__name__)
28
+
29
+ # Load agent configuration
30
+ with open("agent_config.json", "r") as f:
31
+ config = json.load(f)
32
+
33
+ # Create MCP configuration
34
+ mcp_config = MCPServerConfig(
35
+ name=config["mcp_server"]["name"],
36
+ url=config["mcp_server"]["url"],
37
+ description=config["mcp_server"]["description"],
38
+ server_type=config["mcp_server"].get("server_type", "streamable-http"),
39
+ capabilities=config["mcp_server"].get("capabilities", []),
40
+ metadata=config["mcp_server"].get("metadata", {})
41
+ )
42
+
43
+ # Create MCP server info for use with run_with_mcp_tools
44
+ mcp_server_info = MCPServerInfo(
45
+ id="", # Not needed for direct usage
46
+ name=mcp_config.name,
47
+ url=mcp_config.url,
48
+ description=mcp_config.description,
49
+ server_type=mcp_config.server_type,
50
+ capabilities=mcp_config.capabilities,
51
+ metadata=mcp_config.metadata,
52
+ tags=mcp_config.metadata.get("tags", [])
53
+ )
54
+
55
+ # Get MCP server API key if required
56
+ {% if requires_api_key %}
57
+ # Check for API keys required by the MCP server
58
+ MCP_API_KEY = None
59
+ {% for api_key_name in api_keys %}
60
+ if not MCP_API_KEY and os.getenv("{{ api_key_name }}"):
61
+ MCP_API_KEY = os.getenv("{{ api_key_name }}")
62
+ logger.info(f"Using API key from {{ api_key_name }} environment variable")
63
+ {% endfor %}
64
+
65
+ if not MCP_API_KEY:
66
+ logger.warning("No API key found for MCP server authentication.")
67
+ logger.warning("The MCP server requires one of these environment variables to be set:")
68
+ {% for api_key_name in api_keys %}
69
+ logger.warning(" - {{ api_key_name }}")
70
+ {% endfor %}
71
+ {% else %}
72
+ MCP_API_KEY = None
73
+ {% endif %}
74
+
75
+
76
+ class {{ class_name }}AgentExecutor(AgentExecutor):
77
+ """Agent executor for {{ agency_name }}."""
78
+
79
+ def __init__(self):
80
+ self.mcp_config = mcp_config
81
+ self.mcp_server_info = mcp_server_info
82
+
83
+ async def execute(self, context: RequestContext, event_queue: EventQueue) -> None:
84
+ """Process a request using the {{ agency_name }} capabilities."""
85
+ try:
86
+ # Get the user's request from context
87
+ request_text = context.get_user_input()
88
+ if not request_text:
89
+ await event_queue.enqueue_event(
90
+ new_agent_text_message("No user message provided")
91
+ )
92
+ return
93
+
94
+ # Get additional context if provided
95
+ task_context = {}
96
+ if hasattr(context, 'metadata'):
97
+ task_context = context.metadata or {}
98
+
99
+ # Create an agent for this request
100
+ agent = MCPAgentBuilder.create_agent(
101
+ role=f"{config['name']} Specialist",
102
+ goal=f"Process the request using {self.mcp_config.name} capabilities",
103
+ backstory=f"You are an expert at using {self.mcp_config.name}. {self.mcp_config.description}"
104
+ )
105
+
106
+ # Create a task
107
+ task = Task(
108
+ description=request_text,
109
+ expected_output="The processed result based on the request",
110
+ agent=agent
111
+ )
112
+
113
+ # Run with MCP tools
114
+ result = run_with_mcp_tools(
115
+ tasks=[task],
116
+ mcp_server=self.mcp_server_info,
117
+ inputs=task_context,
118
+ skip_health_check=True, # Skip for production usage
119
+ api_key=MCP_API_KEY # Pass the API key if available
120
+ )
121
+
122
+ # Send the result as agent message
123
+ await event_queue.enqueue_event(
124
+ new_agent_text_message(str(result))
125
+ )
126
+
127
+ except Exception as e:
128
+ logger.error(f"Error processing request: {e}")
129
+ await event_queue.enqueue_event(
130
+ new_agent_text_message(f"Error processing request: {str(e)}")
131
+ )
132
+
133
+
134
+ def create_app():
135
+ """Create the A2A application."""
136
+ # Create agent skill
137
+ skill = AgentSkill(
138
+ id="process_request",
139
+ name=f"Process request using {config['name']}",
140
+ description=config["description"],
141
+ examples=config.get("a2a_config", {}).get("skill_examples", [
142
+ "Help me with this request",
143
+ "Process this data"
144
+ ])
145
+ )
146
+
147
+ # Create capabilities
148
+ capabilities = AgentCapabilities(
149
+ streaming=False,
150
+ pushNotifications=False,
151
+ stateTransitionHistory=False
152
+ )
153
+
154
+ # Create agent card
155
+ agent_card = AgentCard(
156
+ name=config["agency_id"],
157
+ description=config["description"],
158
+ url=f"http://0.0.0.0:{os.environ.get('PORT', 8000)}",
159
+ version=config["version"],
160
+ capabilities=capabilities,
161
+ skills=[skill]
162
+ )
163
+
164
+ # Create executor
165
+ executor = {{ class_name }}AgentExecutor()
166
+
167
+ # Create task store and request handler
168
+ task_store = InMemoryTaskStore()
169
+ request_handler = DefaultRequestHandler(
170
+ agent_executor=executor,
171
+ task_store=task_store
172
+ )
173
+
174
+ # Create the A2A application
175
+ app = A2AStarletteApplication(
176
+ agent_card=agent_card,
177
+ http_handler=request_handler
178
+ )
179
+
180
+ return app
181
+
182
+
183
+ if __name__ == "__main__":
184
+ # Get port from environment variable (for Cloud Run compatibility)
185
+ port = int(os.environ.get("PORT", 8000))
186
+ logger.info(f"Starting {config['name']} on port {port}")
187
+
188
+ # Create and run the app
189
+ app = create_app()
190
+ uvicorn.run(app.build(), host="0.0.0.0", port=port)
@@ -0,0 +1,4 @@
1
+ """Special pre-built agencies for common IATP use cases."""
2
+
3
+ # Module for special agencies - currently empty
4
+ __all__ = []