agentguardproxy 0.2.0__tar.gz → 0.2.2__tar.gz
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.
- {agentguardproxy-0.2.0 → agentguardproxy-0.2.2}/PKG-INFO +145 -142
- {agentguardproxy-0.2.0 → agentguardproxy-0.2.2}/README.md +5 -5
- {agentguardproxy-0.2.0 → agentguardproxy-0.2.2}/agentguard/__init__.py +47 -18
- {agentguardproxy-0.2.0 → agentguardproxy-0.2.2}/agentguard/adapters/browseruse.py +2 -2
- {agentguardproxy-0.2.0 → agentguardproxy-0.2.2}/agentguard/adapters/crewai.py +2 -2
- {agentguardproxy-0.2.0 → agentguardproxy-0.2.2}/agentguard/adapters/langchain.py +2 -2
- {agentguardproxy-0.2.0 → agentguardproxy-0.2.2}/agentguard/adapters/mcp.py +8 -4
- {agentguardproxy-0.2.0 → agentguardproxy-0.2.2}/agentguardproxy.egg-info/PKG-INFO +145 -142
- {agentguardproxy-0.2.0 → agentguardproxy-0.2.2}/agentguardproxy.egg-info/SOURCES.txt +5 -1
- {agentguardproxy-0.2.0 → agentguardproxy-0.2.2}/agentguardproxy.egg-info/requires.txt +4 -0
- {agentguardproxy-0.2.0 → agentguardproxy-0.2.2}/pyproject.toml +5 -1
- {agentguardproxy-0.2.0 → agentguardproxy-0.2.2}/setup.cfg +4 -4
- agentguardproxy-0.2.2/tests/test_adapters.py +216 -0
- agentguardproxy-0.2.2/tests/test_decorator.py +79 -0
- agentguardproxy-0.2.2/tests/test_guard.py +171 -0
- agentguardproxy-0.2.2/tests/test_integration.py +102 -0
- {agentguardproxy-0.2.0 → agentguardproxy-0.2.2}/agentguard/adapters/__init__.py +0 -0
- {agentguardproxy-0.2.0 → agentguardproxy-0.2.2}/agentguardproxy.egg-info/dependency_links.txt +0 -0
- {agentguardproxy-0.2.0 → agentguardproxy-0.2.2}/agentguardproxy.egg-info/top_level.txt +0 -0
|
@@ -1,142 +1,145 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: agentguardproxy
|
|
3
|
-
Version: 0.2.
|
|
4
|
-
Summary: Python SDK for AgentGuard — the firewall for AI agents
|
|
5
|
-
Author: AgentGuard Contributors
|
|
6
|
-
License-Expression: Apache-2.0
|
|
7
|
-
Project-URL: Homepage, https://github.com/Caua-ferraz/AgentGuard
|
|
8
|
-
Project-URL: Repository, https://github.com/Caua-ferraz/AgentGuard
|
|
9
|
-
Project-URL: Documentation, https://github.com/Caua-ferraz/AgentGuard/blob/master/docs/SETUP.md
|
|
10
|
-
Project-URL: Issues, https://github.com/Caua-ferraz/AgentGuard/issues
|
|
11
|
-
Keywords: ai,agents,firewall,policy,guardrails,safety
|
|
12
|
-
Classifier: Development Status :: 3 - Alpha
|
|
13
|
-
Classifier: Intended Audience :: Developers
|
|
14
|
-
Classifier: Programming Language :: Python :: 3
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
-
Classifier: Topic :: Security
|
|
22
|
-
Classifier: Topic :: Software Development :: Libraries
|
|
23
|
-
Requires-Python: >=3.8
|
|
24
|
-
Description-Content-Type: text/markdown
|
|
25
|
-
Provides-Extra: langchain
|
|
26
|
-
Requires-Dist: langchain>=0.1.0; extra == "langchain"
|
|
27
|
-
Provides-Extra: crewai
|
|
28
|
-
Requires-Dist: crewai>=0.1.0; extra == "crewai"
|
|
29
|
-
Provides-Extra: browser-use
|
|
30
|
-
Requires-Dist: browser-use>=0.1.0; extra == "browser-use"
|
|
31
|
-
Provides-Extra: mcp
|
|
32
|
-
Provides-Extra: all
|
|
33
|
-
Requires-Dist: langchain>=0.1.0; extra == "all"
|
|
34
|
-
Requires-Dist: crewai>=0.1.0; extra == "all"
|
|
35
|
-
Requires-Dist: browser-use>=0.1.0; extra == "all"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
pip install
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
pip install
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
agent
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
- `
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
- `.
|
|
134
|
-
- `.
|
|
135
|
-
- `.
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentguardproxy
|
|
3
|
+
Version: 0.2.2
|
|
4
|
+
Summary: Python SDK for AgentGuard — the firewall for AI agents
|
|
5
|
+
Author: AgentGuard Contributors
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/Caua-ferraz/AgentGuard
|
|
8
|
+
Project-URL: Repository, https://github.com/Caua-ferraz/AgentGuard
|
|
9
|
+
Project-URL: Documentation, https://github.com/Caua-ferraz/AgentGuard/blob/master/docs/SETUP.md
|
|
10
|
+
Project-URL: Issues, https://github.com/Caua-ferraz/AgentGuard/issues
|
|
11
|
+
Keywords: ai,agents,firewall,policy,guardrails,safety
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Security
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
23
|
+
Requires-Python: >=3.8
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
Provides-Extra: langchain
|
|
26
|
+
Requires-Dist: langchain>=0.1.0; extra == "langchain"
|
|
27
|
+
Provides-Extra: crewai
|
|
28
|
+
Requires-Dist: crewai>=0.1.0; extra == "crewai"
|
|
29
|
+
Provides-Extra: browser-use
|
|
30
|
+
Requires-Dist: browser-use>=0.1.0; extra == "browser-use"
|
|
31
|
+
Provides-Extra: mcp
|
|
32
|
+
Provides-Extra: all
|
|
33
|
+
Requires-Dist: langchain>=0.1.0; extra == "all"
|
|
34
|
+
Requires-Dist: crewai>=0.1.0; extra == "all"
|
|
35
|
+
Requires-Dist: browser-use>=0.1.0; extra == "all"
|
|
36
|
+
Provides-Extra: dev
|
|
37
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
38
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
39
|
+
|
|
40
|
+
# AgentGuard Python SDK
|
|
41
|
+
|
|
42
|
+
Lightweight Python client for [AgentGuard](https://github.com/Caua-ferraz/AgentGuard) — the firewall for AI agents.
|
|
43
|
+
|
|
44
|
+
## Install
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install agentguardproxy
|
|
48
|
+
|
|
49
|
+
# With framework adapters
|
|
50
|
+
pip install agentguardproxy[langchain]
|
|
51
|
+
pip install agentguardproxy[crewai]
|
|
52
|
+
pip install agentguardproxy[browser-use]
|
|
53
|
+
pip install agentguardproxy[all]
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Quick Start
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from agentguard import Guard
|
|
60
|
+
|
|
61
|
+
guard = Guard("http://localhost:8080", agent_id="my-agent")
|
|
62
|
+
|
|
63
|
+
# Check before executing
|
|
64
|
+
result = guard.check("shell", command="rm -rf ./old_data")
|
|
65
|
+
|
|
66
|
+
if result.allowed:
|
|
67
|
+
execute(command)
|
|
68
|
+
elif result.needs_approval:
|
|
69
|
+
print(f"Approve at: {result.approval_url}")
|
|
70
|
+
else:
|
|
71
|
+
print(f"Blocked: {result.reason}")
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Framework Adapters
|
|
75
|
+
|
|
76
|
+
### LangChain
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from agentguard.adapters.langchain import GuardedToolkit
|
|
80
|
+
|
|
81
|
+
toolkit = GuardedToolkit(
|
|
82
|
+
tools=my_tools,
|
|
83
|
+
guard_url="http://localhost:8080",
|
|
84
|
+
agent_id="langchain-agent",
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
agent = create_react_agent(llm, toolkit.tools, prompt)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### CrewAI
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from agentguard.adapters.crewai import guard_crew_tools
|
|
94
|
+
|
|
95
|
+
guarded_tools = guard_crew_tools(
|
|
96
|
+
tools=my_crew_tools,
|
|
97
|
+
guard_url="http://localhost:8080",
|
|
98
|
+
agent_id="crew-agent",
|
|
99
|
+
)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### browser-use
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from agentguard.adapters.browseruse import GuardedBrowser
|
|
106
|
+
|
|
107
|
+
browser = GuardedBrowser(guard_url="http://localhost:8080")
|
|
108
|
+
|
|
109
|
+
result = browser.check_navigation("https://example.com")
|
|
110
|
+
if result.allowed:
|
|
111
|
+
await page.goto("https://example.com")
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### MCP
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
from agentguard.adapters.mcp import GuardedMCPServer
|
|
118
|
+
|
|
119
|
+
server = GuardedMCPServer(guard_url="http://localhost:8080")
|
|
120
|
+
server.add_tool("my_tool", "Description", handler=my_handler)
|
|
121
|
+
server.run() # Starts stdio MCP server
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## API Reference
|
|
125
|
+
|
|
126
|
+
### `Guard(base_url, agent_id="")`
|
|
127
|
+
- `check(scope, *, action, command, path, domain, url, meta)` — Check an action against policy
|
|
128
|
+
- `approve(approval_id)` — Approve a pending action
|
|
129
|
+
- `deny(approval_id)` — Deny a pending action
|
|
130
|
+
- `wait_for_approval(approval_id, timeout=300)` — Block until resolved
|
|
131
|
+
|
|
132
|
+
### `CheckResult`
|
|
133
|
+
- `.allowed` — True if action is permitted
|
|
134
|
+
- `.denied` — True if action is blocked
|
|
135
|
+
- `.needs_approval` — True if human approval required
|
|
136
|
+
- `.decision` — Raw decision string
|
|
137
|
+
- `.reason` — Explanation
|
|
138
|
+
- `.approval_url` — URL to approve (when applicable)
|
|
139
|
+
|
|
140
|
+
### `@guarded(scope, guard=None)` decorator
|
|
141
|
+
Wraps a function so it's checked before execution.
|
|
142
|
+
|
|
143
|
+
## License
|
|
144
|
+
|
|
145
|
+
Apache 2.0
|
|
@@ -5,13 +5,13 @@ Lightweight Python client for [AgentGuard](https://github.com/Caua-ferraz/AgentG
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
pip install
|
|
8
|
+
pip install agentguardproxy
|
|
9
9
|
|
|
10
10
|
# With framework adapters
|
|
11
|
-
pip install
|
|
12
|
-
pip install
|
|
13
|
-
pip install
|
|
14
|
-
pip install
|
|
11
|
+
pip install agentguardproxy[langchain]
|
|
12
|
+
pip install agentguardproxy[crewai]
|
|
13
|
+
pip install agentguardproxy[browser-use]
|
|
14
|
+
pip install agentguardproxy[all]
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
## Quick Start
|
|
@@ -17,12 +17,31 @@ Usage:
|
|
|
17
17
|
print(f"Blocked: {result.reason}")
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
|
+
import functools
|
|
20
21
|
import json
|
|
22
|
+
import os
|
|
21
23
|
import time
|
|
22
24
|
from dataclasses import dataclass, field
|
|
23
25
|
from typing import Optional
|
|
24
26
|
from urllib import request, error
|
|
25
27
|
|
|
28
|
+
# --- Defaults and constants ---
|
|
29
|
+
DEFAULT_BASE_URL = "http://localhost:8080"
|
|
30
|
+
DEFAULT_TIMEOUT = 5 # seconds, for individual HTTP calls
|
|
31
|
+
DEFAULT_APPROVAL_TIMEOUT = 300 # seconds, for wait_for_approval
|
|
32
|
+
DEFAULT_POLL_INTERVAL = 2 # seconds
|
|
33
|
+
|
|
34
|
+
# Decision values (must match the Go backend)
|
|
35
|
+
DECISION_ALLOW = "ALLOW"
|
|
36
|
+
DECISION_DENY = "DENY"
|
|
37
|
+
DECISION_REQUIRE_APPROVAL = "REQUIRE_APPROVAL"
|
|
38
|
+
|
|
39
|
+
# API endpoint paths
|
|
40
|
+
ENDPOINT_CHECK = "/v1/check"
|
|
41
|
+
ENDPOINT_APPROVE = "/v1/approve/"
|
|
42
|
+
ENDPOINT_DENY = "/v1/deny/"
|
|
43
|
+
ENDPOINT_STATUS = "/v1/status/"
|
|
44
|
+
|
|
26
45
|
|
|
27
46
|
@dataclass
|
|
28
47
|
class CheckResult:
|
|
@@ -35,23 +54,24 @@ class CheckResult:
|
|
|
35
54
|
|
|
36
55
|
@property
|
|
37
56
|
def allowed(self) -> bool:
|
|
38
|
-
return self.decision ==
|
|
57
|
+
return self.decision == DECISION_ALLOW
|
|
39
58
|
|
|
40
59
|
@property
|
|
41
60
|
def denied(self) -> bool:
|
|
42
|
-
return self.decision ==
|
|
61
|
+
return self.decision == DECISION_DENY
|
|
43
62
|
|
|
44
63
|
@property
|
|
45
64
|
def needs_approval(self) -> bool:
|
|
46
|
-
return self.decision ==
|
|
65
|
+
return self.decision == DECISION_REQUIRE_APPROVAL
|
|
47
66
|
|
|
48
67
|
|
|
49
68
|
class Guard:
|
|
50
69
|
"""Client for the AgentGuard proxy."""
|
|
51
70
|
|
|
52
|
-
def __init__(self, base_url: str = "
|
|
53
|
-
self.base_url = base_url.rstrip("/")
|
|
71
|
+
def __init__(self, base_url: str = "", agent_id: str = "", timeout: int = DEFAULT_TIMEOUT):
|
|
72
|
+
self.base_url = (base_url or os.environ.get("AGENTGUARD_URL", DEFAULT_BASE_URL)).rstrip("/")
|
|
54
73
|
self.agent_id = agent_id
|
|
74
|
+
self.timeout = timeout
|
|
55
75
|
|
|
56
76
|
def check(
|
|
57
77
|
self,
|
|
@@ -97,17 +117,17 @@ class Guard:
|
|
|
97
117
|
|
|
98
118
|
data = json.dumps(payload).encode("utf-8")
|
|
99
119
|
req = request.Request(
|
|
100
|
-
f"{self.base_url}
|
|
120
|
+
f"{self.base_url}{ENDPOINT_CHECK}",
|
|
101
121
|
data=data,
|
|
102
122
|
headers={"Content-Type": "application/json"},
|
|
103
123
|
method="POST",
|
|
104
124
|
)
|
|
105
125
|
|
|
106
126
|
try:
|
|
107
|
-
with request.urlopen(req, timeout=
|
|
127
|
+
with request.urlopen(req, timeout=self.timeout) as resp:
|
|
108
128
|
body = json.loads(resp.read())
|
|
109
129
|
return CheckResult(
|
|
110
|
-
decision=body.get("decision",
|
|
130
|
+
decision=body.get("decision", DECISION_DENY),
|
|
111
131
|
reason=body.get("reason", ""),
|
|
112
132
|
matched_rule=body.get("matched_rule", ""),
|
|
113
133
|
approval_id=body.get("approval_id", ""),
|
|
@@ -116,18 +136,18 @@ class Guard:
|
|
|
116
136
|
except error.URLError as e:
|
|
117
137
|
# If AgentGuard is unreachable, default to deny (fail closed)
|
|
118
138
|
return CheckResult(
|
|
119
|
-
decision=
|
|
139
|
+
decision=DECISION_DENY,
|
|
120
140
|
reason=f"AgentGuard unreachable: {e}",
|
|
121
141
|
)
|
|
122
142
|
|
|
123
143
|
def approve(self, approval_id: str) -> bool:
|
|
124
144
|
"""Approve a pending action."""
|
|
125
145
|
req = request.Request(
|
|
126
|
-
f"{self.base_url}
|
|
146
|
+
f"{self.base_url}{ENDPOINT_APPROVE}{approval_id}",
|
|
127
147
|
method="POST",
|
|
128
148
|
)
|
|
129
149
|
try:
|
|
130
|
-
with request.urlopen(req, timeout=
|
|
150
|
+
with request.urlopen(req, timeout=self.timeout):
|
|
131
151
|
return True
|
|
132
152
|
except error.URLError:
|
|
133
153
|
return False
|
|
@@ -135,28 +155,36 @@ class Guard:
|
|
|
135
155
|
def deny(self, approval_id: str) -> bool:
|
|
136
156
|
"""Deny a pending action."""
|
|
137
157
|
req = request.Request(
|
|
138
|
-
f"{self.base_url}
|
|
158
|
+
f"{self.base_url}{ENDPOINT_DENY}{approval_id}",
|
|
139
159
|
method="POST",
|
|
140
160
|
)
|
|
141
161
|
try:
|
|
142
|
-
with request.urlopen(req, timeout=
|
|
162
|
+
with request.urlopen(req, timeout=self.timeout):
|
|
143
163
|
return True
|
|
144
164
|
except error.URLError:
|
|
145
165
|
return False
|
|
146
166
|
|
|
147
|
-
def wait_for_approval(
|
|
167
|
+
def wait_for_approval(
|
|
168
|
+
self,
|
|
169
|
+
approval_id: str,
|
|
170
|
+
timeout: int = DEFAULT_APPROVAL_TIMEOUT,
|
|
171
|
+
poll_interval: int = DEFAULT_POLL_INTERVAL,
|
|
172
|
+
) -> CheckResult:
|
|
148
173
|
"""Block until a pending action is approved or denied (or timeout)."""
|
|
149
174
|
deadline = time.time() + timeout
|
|
150
175
|
while time.time() < deadline:
|
|
151
176
|
# Poll the status endpoint for resolution
|
|
152
177
|
req = request.Request(
|
|
153
|
-
f"{self.base_url}
|
|
178
|
+
f"{self.base_url}{ENDPOINT_STATUS}{approval_id}",
|
|
154
179
|
method="GET",
|
|
155
180
|
)
|
|
156
181
|
try:
|
|
157
|
-
with request.urlopen(req, timeout=
|
|
182
|
+
with request.urlopen(req, timeout=self.timeout) as resp:
|
|
158
183
|
body = json.loads(resp.read())
|
|
159
|
-
if body.get("status") == "resolved" and body.get("decision") in (
|
|
184
|
+
if body.get("status") == "resolved" and body.get("decision") in (
|
|
185
|
+
DECISION_ALLOW,
|
|
186
|
+
DECISION_DENY,
|
|
187
|
+
):
|
|
160
188
|
return CheckResult(
|
|
161
189
|
decision=body["decision"],
|
|
162
190
|
reason=body.get("reason", "resolved"),
|
|
@@ -165,7 +193,7 @@ class Guard:
|
|
|
165
193
|
pass
|
|
166
194
|
time.sleep(poll_interval)
|
|
167
195
|
|
|
168
|
-
return CheckResult(decision=
|
|
196
|
+
return CheckResult(decision=DECISION_DENY, reason="Approval timed out")
|
|
169
197
|
|
|
170
198
|
|
|
171
199
|
# Convenience decorator for guarding functions
|
|
@@ -180,6 +208,7 @@ def guarded(scope: str, guard: Optional[Guard] = None, **check_kwargs):
|
|
|
180
208
|
os.system(cmd)
|
|
181
209
|
"""
|
|
182
210
|
def decorator(func):
|
|
211
|
+
@functools.wraps(func)
|
|
183
212
|
def wrapper(*args, **kwargs):
|
|
184
213
|
g = guard or Guard()
|
|
185
214
|
# Try to extract meaningful info from args
|
|
@@ -20,7 +20,7 @@ Usage:
|
|
|
20
20
|
|
|
21
21
|
from typing import Any, Optional
|
|
22
22
|
from urllib.parse import urlparse
|
|
23
|
-
from agentguard import Guard, CheckResult
|
|
23
|
+
from agentguard import Guard, CheckResult, DEFAULT_BASE_URL
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class GuardedBrowser:
|
|
@@ -34,7 +34,7 @@ class GuardedBrowser:
|
|
|
34
34
|
def __init__(
|
|
35
35
|
self,
|
|
36
36
|
guard: Optional[Guard] = None,
|
|
37
|
-
guard_url: str =
|
|
37
|
+
guard_url: str = DEFAULT_BASE_URL,
|
|
38
38
|
agent_id: str = "",
|
|
39
39
|
browser: Any = None,
|
|
40
40
|
):
|
|
@@ -18,7 +18,7 @@ Usage:
|
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
20
|
from typing import Any, List, Optional
|
|
21
|
-
from agentguard import Guard
|
|
21
|
+
from agentguard import Guard, DEFAULT_BASE_URL
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class GuardedCrewTool:
|
|
@@ -32,7 +32,7 @@ class GuardedCrewTool:
|
|
|
32
32
|
self,
|
|
33
33
|
tool: Any,
|
|
34
34
|
guard: Optional[Guard] = None,
|
|
35
|
-
guard_url: str =
|
|
35
|
+
guard_url: str = DEFAULT_BASE_URL,
|
|
36
36
|
agent_id: str = "",
|
|
37
37
|
scope: str = "shell",
|
|
38
38
|
):
|
|
@@ -16,7 +16,7 @@ Usage:
|
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
18
|
from typing import Any, List, Optional
|
|
19
|
-
from agentguard import Guard, CheckResult
|
|
19
|
+
from agentguard import Guard, CheckResult, DEFAULT_BASE_URL
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
class GuardedTool:
|
|
@@ -133,7 +133,7 @@ class GuardedToolkit:
|
|
|
133
133
|
def __init__(
|
|
134
134
|
self,
|
|
135
135
|
tools: List[Any],
|
|
136
|
-
guard_url: str =
|
|
136
|
+
guard_url: str = DEFAULT_BASE_URL,
|
|
137
137
|
agent_id: str = "",
|
|
138
138
|
default_scope: str = "shell",
|
|
139
139
|
):
|
|
@@ -35,7 +35,11 @@ MCP config (claude_desktop_config.json / .cursor/mcp.json):
|
|
|
35
35
|
import json
|
|
36
36
|
import sys
|
|
37
37
|
from typing import Any, Callable, Dict, List, Optional
|
|
38
|
-
from agentguard import Guard, CheckResult
|
|
38
|
+
from agentguard import Guard, CheckResult, DEFAULT_BASE_URL
|
|
39
|
+
|
|
40
|
+
# MCP protocol constants
|
|
41
|
+
MCP_PROTOCOL_VERSION = "2024-11-05"
|
|
42
|
+
SDK_VERSION = "0.2.2"
|
|
39
43
|
|
|
40
44
|
|
|
41
45
|
class ToolDefinition:
|
|
@@ -64,10 +68,10 @@ class GuardedMCPServer:
|
|
|
64
68
|
def __init__(
|
|
65
69
|
self,
|
|
66
70
|
guard: Optional[Guard] = None,
|
|
67
|
-
guard_url: str =
|
|
71
|
+
guard_url: str = DEFAULT_BASE_URL,
|
|
68
72
|
agent_id: str = "mcp-agent",
|
|
69
73
|
server_name: str = "agentguard",
|
|
70
|
-
server_version: str =
|
|
74
|
+
server_version: str = SDK_VERSION,
|
|
71
75
|
):
|
|
72
76
|
self._guard = guard or Guard(guard_url, agent_id=agent_id)
|
|
73
77
|
self._tools: Dict[str, ToolDefinition] = {}
|
|
@@ -141,7 +145,7 @@ class GuardedMCPServer:
|
|
|
141
145
|
"jsonrpc": "2.0",
|
|
142
146
|
"id": req_id,
|
|
143
147
|
"result": {
|
|
144
|
-
"protocolVersion":
|
|
148
|
+
"protocolVersion": MCP_PROTOCOL_VERSION,
|
|
145
149
|
"serverInfo": {
|
|
146
150
|
"name": self._server_name,
|
|
147
151
|
"version": self._server_version,
|