agentops-cockpit 0.3.0__py3-none-any.whl → 0.4.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.
- agent_ops_cockpit/ops/mcp_hub.py +62 -17
- agent_ops_cockpit/ops/swarm.py +71 -0
- {agentops_cockpit-0.3.0.dist-info → agentops_cockpit-0.4.1.dist-info}/METADATA +27 -6
- {agentops_cockpit-0.3.0.dist-info → agentops_cockpit-0.4.1.dist-info}/RECORD +7 -6
- {agentops_cockpit-0.3.0.dist-info → agentops_cockpit-0.4.1.dist-info}/WHEEL +0 -0
- {agentops_cockpit-0.3.0.dist-info → agentops_cockpit-0.4.1.dist-info}/entry_points.txt +0 -0
- {agentops_cockpit-0.3.0.dist-info → agentops_cockpit-0.4.1.dist-info}/licenses/LICENSE +0 -0
agent_ops_cockpit/ops/mcp_hub.py
CHANGED
|
@@ -1,35 +1,80 @@
|
|
|
1
|
-
from typing import List, Dict, Any
|
|
1
|
+
from typing import List, Dict, Any, Optional
|
|
2
2
|
import asyncio
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
from mcp import ClientSession, StdioServerParameters
|
|
6
|
+
from mcp.client.stdio import stdio_client
|
|
3
7
|
|
|
4
8
|
class MCPHub:
|
|
5
9
|
"""
|
|
6
10
|
Model Context Protocol (MCP) Hub.
|
|
7
|
-
|
|
11
|
+
Provides a unified interface for tool discovery and execution across
|
|
12
|
+
multiple MCP servers (Google Search, SQL, internal tools).
|
|
8
13
|
"""
|
|
9
14
|
|
|
10
15
|
def __init__(self):
|
|
16
|
+
self.servers: Dict[str, StdioServerParameters] = {}
|
|
11
17
|
self.registry = {
|
|
12
|
-
"search": {"type": "mcp", "provider": "google-search", "
|
|
13
|
-
"db": {"type": "mcp", "provider": "alloydb
|
|
14
|
-
"legacy_crm": {"type": "
|
|
18
|
+
"search": {"type": "mcp", "provider": "google-search", "server": "google-search-mcp"},
|
|
19
|
+
"db": {"type": "mcp", "provider": "alloydb", "server": "postgres-mcp"},
|
|
20
|
+
"legacy_crm": {"type": "rest", "provider": "internal", "status": "deprecated"}
|
|
15
21
|
}
|
|
16
22
|
|
|
17
|
-
|
|
23
|
+
def register_server(self, name: str, command: str, args: List[str] = None):
|
|
24
|
+
"""Registers a local MCP server."""
|
|
25
|
+
self.servers[name] = StdioServerParameters(
|
|
26
|
+
command=command,
|
|
27
|
+
args=args or [],
|
|
28
|
+
env=os.environ.copy()
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
async def execute_tool(self, tool_name: str, arguments: Dict[str, Any]):
|
|
18
32
|
"""
|
|
19
|
-
Executes a tool
|
|
20
|
-
Logs metrics for the Flight Recorder.
|
|
33
|
+
Executes a tool call using the Model Context Protocol.
|
|
21
34
|
"""
|
|
22
35
|
if tool_name not in self.registry:
|
|
23
|
-
raise ValueError(f"Tool {tool_name} not found in MCP
|
|
24
|
-
|
|
36
|
+
raise ValueError(f"Tool {tool_name} not found in MCP registry.")
|
|
37
|
+
|
|
25
38
|
config = self.registry[tool_name]
|
|
26
39
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
40
|
+
# If it's a legacy tool, handle it separately
|
|
41
|
+
if config["type"] == "rest":
|
|
42
|
+
print(f"⚠️ Executing legacy REST tool: {tool_name}")
|
|
43
|
+
return await self._mock_legacy_exec(tool_name, arguments)
|
|
44
|
+
|
|
45
|
+
server_name = config.get("server")
|
|
46
|
+
if not server_name or server_name not in self.servers:
|
|
47
|
+
# Fallback to mock for demo/unconfigured environments
|
|
48
|
+
print(f"ℹ️ MCP Server '{server_name}' not configured. Running in simulated mode.")
|
|
49
|
+
return await self._mock_mcp_exec(tool_name, arguments)
|
|
50
|
+
|
|
51
|
+
# Real MCP Protocol Execution
|
|
52
|
+
async with stdio_client(self.servers[server_name]) as (read, write):
|
|
53
|
+
async with ClientSession(read, write) as session:
|
|
54
|
+
await session.initialize()
|
|
55
|
+
result = await session.call_tool(tool_name, arguments)
|
|
56
|
+
return {
|
|
57
|
+
"result": result.content,
|
|
58
|
+
"protocol": "mcp-v1",
|
|
59
|
+
"server": server_name
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async def _mock_mcp_exec(self, tool_name: str, args: Dict[str, Any]):
|
|
63
|
+
await asyncio.sleep(0.2)
|
|
64
|
+
return {
|
|
65
|
+
"result": f"Simulated MCP response for {tool_name}",
|
|
66
|
+
"protocol": "mcp-virtual",
|
|
67
|
+
"assurance": 0.95
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async def _mock_legacy_exec(self, tool_name: str, args: Dict[str, Any]):
|
|
71
|
+
await asyncio.sleep(0.5)
|
|
72
|
+
return {
|
|
73
|
+
"result": f"Legacy response for {tool_name}",
|
|
74
|
+
"protocol": "rest-legacy",
|
|
75
|
+
"warning": "MIGRATE_TO_MCP"
|
|
76
|
+
}
|
|
34
77
|
|
|
35
78
|
global_mcp_hub = MCPHub()
|
|
79
|
+
# Example registration (commented out as it requires local binaries)
|
|
80
|
+
# global_mcp_hub.register_server("google-search-mcp", "npx", ["-y", "@modelcontextprotocol/server-google-search"])
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from typing import List, Dict, Any, Optional
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from rich.console import Console
|
|
5
|
+
from rich.panel import Panel
|
|
6
|
+
|
|
7
|
+
console = Console()
|
|
8
|
+
|
|
9
|
+
@dataclass
|
|
10
|
+
class SwarmMessage:
|
|
11
|
+
sender: str
|
|
12
|
+
recipient: str
|
|
13
|
+
content: str
|
|
14
|
+
evidence_packet: Optional[Dict[str, Any]] = None
|
|
15
|
+
|
|
16
|
+
class MultiAgentOrchestrator:
|
|
17
|
+
"""
|
|
18
|
+
Standardizes Swarm/Coordinator patterns using the A2A spec.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self):
|
|
22
|
+
self.agents: Dict[str, Any] = {}
|
|
23
|
+
self.history: List[SwarmMessage] = []
|
|
24
|
+
|
|
25
|
+
def register_agent(self, name: str, agent_func):
|
|
26
|
+
self.agents[name] = agent_func
|
|
27
|
+
console.print(f"🤖 Agent [bold cyan]{name}[/bold cyan] registered in swarm.")
|
|
28
|
+
|
|
29
|
+
async def dispatch(self, sender: str, recipient: str, message: str):
|
|
30
|
+
"""Dispatches a message with an A2A Reasoning Evidence Packet."""
|
|
31
|
+
console.print(f"\n📡 [dim]A2A Transmission:[/dim] [bold]{sender}[/bold] -> [bold]{recipient}[/bold]")
|
|
32
|
+
|
|
33
|
+
# Simulated Evidence Packet for Governance
|
|
34
|
+
evidence = {
|
|
35
|
+
"assurance_score": 0.99,
|
|
36
|
+
"origin_vpc": "secure-engine-zone",
|
|
37
|
+
"pii_scrubbed": True
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
swarm_msg = SwarmMessage(sender, recipient, message, evidence)
|
|
41
|
+
self.history.append(swarm_msg)
|
|
42
|
+
|
|
43
|
+
if recipient in self.agents:
|
|
44
|
+
response = await self.agents[recipient](message, evidence)
|
|
45
|
+
return response
|
|
46
|
+
else:
|
|
47
|
+
return {"error": f"Agent {recipient} not found."}
|
|
48
|
+
|
|
49
|
+
def get_swarm_report(self):
|
|
50
|
+
console.print(Panel.fit("🐝 [bold]Swarm Orchestration Trace[/bold]", border_style="yellow"))
|
|
51
|
+
for msg in self.history:
|
|
52
|
+
console.print(f"[blue]{msg.sender}[/blue] -> [green]{msg.recipient}[/green]: {msg.content}")
|
|
53
|
+
|
|
54
|
+
def run_swarm_demo():
|
|
55
|
+
orchestrator = MultiAgentOrchestrator()
|
|
56
|
+
|
|
57
|
+
async def researcher(query, evidence):
|
|
58
|
+
return f"Research results for {query} (Evidence verified: {evidence['assurance_score']})"
|
|
59
|
+
|
|
60
|
+
async def writer(query, evidence):
|
|
61
|
+
return f"Professional summary of {query}"
|
|
62
|
+
|
|
63
|
+
orchestrator.register_agent("Researcher", researcher)
|
|
64
|
+
orchestrator.register_agent("Writer", writer)
|
|
65
|
+
|
|
66
|
+
loop = asyncio.get_event_loop()
|
|
67
|
+
loop.run_until_complete(orchestrator.dispatch("Orchestrator", "Researcher", "Analyze market trends"))
|
|
68
|
+
orchestrator.get_swarm_report()
|
|
69
|
+
|
|
70
|
+
if __name__ == "__main__":
|
|
71
|
+
run_swarm_demo()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentops-cockpit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: Production-grade Agent Operations (AgentOps) Platform
|
|
5
5
|
Project-URL: Homepage, https://github.com/enriquekalven/agent-ops-cockpit
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/enriquekalven/agent-ops-cockpit/issues
|
|
@@ -11,6 +11,7 @@ Classifier: Operating System :: OS Independent
|
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
12
|
Requires-Python: >=3.10
|
|
13
13
|
Requires-Dist: gitpython>=3.1.0
|
|
14
|
+
Requires-Dist: mcp>=0.1.0
|
|
14
15
|
Requires-Dist: rich>=13.0.0
|
|
15
16
|
Requires-Dist: typer>=0.9.0
|
|
16
17
|
Description-Content-Type: text/markdown
|
|
@@ -18,10 +19,22 @@ Description-Content-Type: text/markdown
|
|
|
18
19
|
# 🕹️ AgentOps Cockpit
|
|
19
20
|
|
|
20
21
|
<div align="center">
|
|
22
|
+
<img src="https://raw.githubusercontent.com/enriquekalven/agent-cockpit/main/public/og-image.png" alt="AgentOps Cockpit Social Preview" width="100%" />
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<div align="center">
|
|
26
|
+
<br />
|
|
27
|
+
<a href="https://agent-cockpit.web.app" target="_blank"><strong>🌐 Official Website & Live Demo</strong></a>
|
|
28
|
+
<br /><br />
|
|
29
|
+
<a href="https://deploy.cloud.google.com?repo=https://github.com/enriquekalven/agent-cockpit">
|
|
30
|
+
<img src="https://deploy.cloud.google.com/button.svg" alt="Deploy to Google Cloud" />
|
|
31
|
+
</a>
|
|
32
|
+
<br />
|
|
33
|
+
<br />
|
|
21
34
|
<img src="https://img.shields.io/github/stars/enriquekalven/agent-cockpit?style=for-the-badge&color=ffd700" alt="GitHub Stars" />
|
|
22
35
|
<img src="https://img.shields.io/github/license/enriquekalven/agent-cockpit?style=for-the-badge&color=007bff" alt="License" />
|
|
23
36
|
<img src="https://img.shields.io/badge/Google-Well--Architected-4285F4?style=for-the-badge&logo=google-cloud" alt="Google Well-Architected" />
|
|
24
|
-
<img src="https://img.shields.io/badge/
|
|
37
|
+
<img src="https://img.shields.io/badge/A2A_Standard-Enabled-10b981?style=for-the-badge" alt="A2A Standard" />
|
|
25
38
|
</div>
|
|
26
39
|
|
|
27
40
|
<br />
|
|
@@ -34,7 +47,12 @@ Description-Content-Type: text/markdown
|
|
|
34
47
|
---
|
|
35
48
|
|
|
36
49
|
## 📽️ The Mission
|
|
37
|
-
Most AI agent templates stop at a single Python file and an API key. **The AgentOps Cockpit** is for developers moving into production.
|
|
50
|
+
Most AI agent templates stop at a single Python file and an API key. **The AgentOps Cockpit** is for developers moving into production. It provides framework-agnostic governance, safety, and cost guardrails for the entire agentic ecosystem.
|
|
51
|
+
|
|
52
|
+
### Key Pillars:
|
|
53
|
+
- **Governance-as-Code**: Audit your agent against [Google Well-Architected](/docs/google-architecture) best practices.
|
|
54
|
+
- **Agentic Trinity**: Dedicated layers for the Engine (Logic), Face (UX), and Cockpit (Ops).
|
|
55
|
+
- **A2A Connectivity**: Implements the [Agent-to-Agent Transmission Standard](/A2A_GUIDE.md) for secure swarm orchestration.
|
|
38
56
|
|
|
39
57
|
---
|
|
40
58
|
|
|
@@ -86,6 +104,9 @@ Don't wait for your users to find prompt injections. Use the built-in Adversaria
|
|
|
86
104
|
### 🏛️ Arch Review & Framework Detection
|
|
87
105
|
Every agent in the cockpit is graded against a framework-aware checklist. The Cockpit intelligently detects your stack—**Google ADK**, **OpenAI Agentkit**, **Anthropic Claude**, **Microsoft AutoGen/Semantic Kernel**, **AWS Bedrock Agents**, or **CopilotKit**—and runs a tailored audit against corresponding production standards. Use `make arch-review` to verify your **Governance-as-Code**.
|
|
88
106
|
|
|
107
|
+
### 🕹️ MCP Connectivity Hub (Model Context Protocol)
|
|
108
|
+
Stop building one-off tool integrations. The Cockpit provides a unified hub for **MCP Servers**. Connect to Google Search, Slack, or your internal databases via the standardized Model Context Protocol for secure, audited tool execution.
|
|
109
|
+
|
|
89
110
|
### 🧗 Quality Hill Climbing (ADK Evaluation)
|
|
90
111
|
Following **Google ADK Evaluation** best practices, the Cockpit provides an iterative optimization loop. `make quality-baseline` runs your agent against a "Golden Dataset" using **LLM-as-a-Judge** scoring (Response Match & Tool Trajectory), climbing the quality curve until production-grade fidelity is reached.
|
|
91
112
|
|
|
@@ -133,9 +154,9 @@ make deploy-prod # 🚀 1-click deploy to Google Cloud
|
|
|
133
154
|
---
|
|
134
155
|
|
|
135
156
|
## 🧭 Roadmap
|
|
136
|
-
- [
|
|
137
|
-
- [
|
|
138
|
-
- [ ] **Visual Mission Control**: Real-time observability dashboard.
|
|
157
|
+
- [x] **One-Click GitHub Action**: Automated governance audits on every PR.
|
|
158
|
+
- [x] **Multi-Agent Orchestrator**: Standardized A2A Swarm/Coordinator patterns.
|
|
159
|
+
- [ ] **Visual Mission Control**: Real-time cockpit observability dashboard.
|
|
139
160
|
|
|
140
161
|
[View full roadmap →](/ROADMAP.md)
|
|
141
162
|
|
|
@@ -14,17 +14,18 @@ agent_ops_cockpit/ops/arch_review.py,sha256=o8ZKYSrmtt-dw74QBROObKz-w8Z-ZwC4G_yk
|
|
|
14
14
|
agent_ops_cockpit/ops/cost_optimizer.py,sha256=fisPPo1hykcDBqljs05OG8xn0MBA_HPg7X8SlNDsx0M,1454
|
|
15
15
|
agent_ops_cockpit/ops/evidence.py,sha256=LRAW57c-2R4ICiMLtc-JA1Tu5dlfO9-VBSUMc3TCLuo,1051
|
|
16
16
|
agent_ops_cockpit/ops/frameworks.py,sha256=gJdisK8JOs79BY5x0yKu75Lu8WesgDcGJgQrjL9AE7U,19054
|
|
17
|
-
agent_ops_cockpit/ops/mcp_hub.py,sha256=
|
|
17
|
+
agent_ops_cockpit/ops/mcp_hub.py,sha256=Km-gXPNU0ulrFOe7fg9kPvhS3enataLKN8zyOoyzF6k,3184
|
|
18
18
|
agent_ops_cockpit/ops/memory_optimizer.py,sha256=whsKhAuJkEJRa2dxfVeJC_xxwDwKjhx5tnmOmkiKgIQ,1635
|
|
19
19
|
agent_ops_cockpit/ops/orchestrator.py,sha256=WnJ7nv99Ir7lvkWq0EIOEHE2rRzgJv2E4iRi8oDQcPc,3904
|
|
20
20
|
agent_ops_cockpit/ops/pii_scrubber.py,sha256=HBRzzYv97f8VqIx2Gse9o6UVf6QWXSuop-xF-wVhuKU,1524
|
|
21
21
|
agent_ops_cockpit/ops/reliability.py,sha256=Vuh7ZShjZQkXI8CWhL67LeacwEE75JNM6HgRTGLmt7o,2003
|
|
22
22
|
agent_ops_cockpit/ops/secret_scanner.py,sha256=OKojiW8umarrp5ywS4InCTnzzky1hcdBmOfGa-uVIuE,3124
|
|
23
|
+
agent_ops_cockpit/ops/swarm.py,sha256=wptxkdz-ORr4hqmMeQ3tiqw93U4y4XDBtu4xdVToqeQ,2457
|
|
23
24
|
agent_ops_cockpit/ops/ui_auditor.py,sha256=3Cmc8i3oMQ9Wa0hSkeR0t_J8_s1c-u1_kj2PwxDGD6o,5542
|
|
24
25
|
agent_ops_cockpit/shadow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
26
|
agent_ops_cockpit/shadow/router.py,sha256=HRsgrrd3sQeabi58Ub8pOaDL9c7j4WpayeT9D8zPvOo,2725
|
|
26
|
-
agentops_cockpit-0.
|
|
27
|
-
agentops_cockpit-0.
|
|
28
|
-
agentops_cockpit-0.
|
|
29
|
-
agentops_cockpit-0.
|
|
30
|
-
agentops_cockpit-0.
|
|
27
|
+
agentops_cockpit-0.4.1.dist-info/METADATA,sha256=mgrusibi7Cx9GwdqPkenRC--OmNMFV9KqZWce4Vsfo4,8471
|
|
28
|
+
agentops_cockpit-0.4.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
29
|
+
agentops_cockpit-0.4.1.dist-info/entry_points.txt,sha256=SOGYPNtUGhMVgxLQ9dEYo7L3M_dvhWEU2eQz2zhaTkY,112
|
|
30
|
+
agentops_cockpit-0.4.1.dist-info/licenses/LICENSE,sha256=XNJEk4bvf88tBnKqHdGBGi10l9yJWv2yLWPJvvVie1c,1071
|
|
31
|
+
agentops_cockpit-0.4.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|