veragent-mcp 0.1.0__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.
- veragent_mcp-0.1.0/.gitignore +53 -0
- veragent_mcp-0.1.0/PKG-INFO +62 -0
- veragent_mcp-0.1.0/README.md +48 -0
- veragent_mcp-0.1.0/pyproject.toml +27 -0
- veragent_mcp-0.1.0/test_client.py +42 -0
- veragent_mcp-0.1.0/veragent_mcp/__init__.py +2 -0
- veragent_mcp-0.1.0/veragent_mcp/client.py +103 -0
- veragent_mcp-0.1.0/veragent_mcp/server.py +47 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules/
|
|
3
|
+
venv/
|
|
4
|
+
.venv/
|
|
5
|
+
env/
|
|
6
|
+
__pycache__/
|
|
7
|
+
*.pyc
|
|
8
|
+
*.pyo
|
|
9
|
+
*.pyd
|
|
10
|
+
.pytest_cache/
|
|
11
|
+
.coverage
|
|
12
|
+
htmlcov/
|
|
13
|
+
|
|
14
|
+
# Build and Production
|
|
15
|
+
.next/
|
|
16
|
+
out/
|
|
17
|
+
build/
|
|
18
|
+
dist/
|
|
19
|
+
.vercel/
|
|
20
|
+
.turbo/
|
|
21
|
+
|
|
22
|
+
# Environment Files
|
|
23
|
+
.env
|
|
24
|
+
.env.local
|
|
25
|
+
.env.production
|
|
26
|
+
.env.development
|
|
27
|
+
.env.*.local
|
|
28
|
+
|
|
29
|
+
# Operating System
|
|
30
|
+
.DS_Store
|
|
31
|
+
Thumbs.db
|
|
32
|
+
|
|
33
|
+
# IDEs
|
|
34
|
+
.vscode/
|
|
35
|
+
.idea/
|
|
36
|
+
|
|
37
|
+
# Logs
|
|
38
|
+
*.log
|
|
39
|
+
npm-debug.log*
|
|
40
|
+
yarn-debug.log*
|
|
41
|
+
yarn-error.log*
|
|
42
|
+
|
|
43
|
+
# Playwright (frontend)
|
|
44
|
+
frontend/playwright-report/
|
|
45
|
+
frontend/test-results/
|
|
46
|
+
frontend/blob-report/
|
|
47
|
+
|
|
48
|
+
# Docker
|
|
49
|
+
.dockerignore
|
|
50
|
+
!backend/.dockerignore
|
|
51
|
+
!frontend/.dockerignore
|
|
52
|
+
mcp-server/node_modules/
|
|
53
|
+
.vercel
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: veragent-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Veragent MCP server — check the trust/security score of MCP tools before installing them in Claude.
|
|
5
|
+
Project-URL: Homepage, https://veragent.store
|
|
6
|
+
Project-URL: Registry, https://veragent.store/trust-registry
|
|
7
|
+
Author: Sean Li
|
|
8
|
+
License: MIT
|
|
9
|
+
Keywords: claude,mcp,model-context-protocol,security,trust,veragent
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Requires-Dist: httpx>=0.27
|
|
12
|
+
Requires-Dist: mcp>=1.2.0
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# Veragent MCP Server
|
|
16
|
+
|
|
17
|
+
The trust layer for MCP — as an MCP tool. Let Claude (or any MCP client/agent) check
|
|
18
|
+
whether an MCP tool is **safe before installing it**, look up the most trusted tools,
|
|
19
|
+
or score an entire MCP stack — all backed by the [Veragent](https://veragent.store)
|
|
20
|
+
trust registry.
|
|
21
|
+
|
|
22
|
+
## Tools
|
|
23
|
+
|
|
24
|
+
| Tool | What it does |
|
|
25
|
+
|------|--------------|
|
|
26
|
+
| `check_tool_trust(name)` | Veragent trust score + audit state for a tool/server/agent. Use **before** installing. |
|
|
27
|
+
| `list_trusted_tools(query, limit)` | The most trusted MCP tools, optionally filtered. |
|
|
28
|
+
| `scan_mcp_stack(mcp_config)` | Score a whole `mcp_settings.json` — per-server risk + summary. |
|
|
29
|
+
|
|
30
|
+
## Install (Claude Desktop)
|
|
31
|
+
|
|
32
|
+
Add to your `claude_desktop_config.json`:
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"mcpServers": {
|
|
37
|
+
"veragent": {
|
|
38
|
+
"command": "uvx",
|
|
39
|
+
"args": ["veragent-mcp"]
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Then ask Claude: *"Is the playwright-mcp server safe? Check Veragent."*
|
|
46
|
+
|
|
47
|
+
## Run locally
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
uvx veragent-mcp
|
|
51
|
+
# or
|
|
52
|
+
pip install veragent-mcp && veragent-mcp
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Configuration
|
|
56
|
+
|
|
57
|
+
- `VERAGENT_API_BASE` — override the API base (default `https://veragent.store/api/v1`).
|
|
58
|
+
|
|
59
|
+
## Honesty
|
|
60
|
+
|
|
61
|
+
Veragent labels static-analysis results as **Heuristic** and reserves **SGC Certified**
|
|
62
|
+
for behavioral-sandbox passes. Scores are reported with this distinction.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Veragent MCP Server
|
|
2
|
+
|
|
3
|
+
The trust layer for MCP — as an MCP tool. Let Claude (or any MCP client/agent) check
|
|
4
|
+
whether an MCP tool is **safe before installing it**, look up the most trusted tools,
|
|
5
|
+
or score an entire MCP stack — all backed by the [Veragent](https://veragent.store)
|
|
6
|
+
trust registry.
|
|
7
|
+
|
|
8
|
+
## Tools
|
|
9
|
+
|
|
10
|
+
| Tool | What it does |
|
|
11
|
+
|------|--------------|
|
|
12
|
+
| `check_tool_trust(name)` | Veragent trust score + audit state for a tool/server/agent. Use **before** installing. |
|
|
13
|
+
| `list_trusted_tools(query, limit)` | The most trusted MCP tools, optionally filtered. |
|
|
14
|
+
| `scan_mcp_stack(mcp_config)` | Score a whole `mcp_settings.json` — per-server risk + summary. |
|
|
15
|
+
|
|
16
|
+
## Install (Claude Desktop)
|
|
17
|
+
|
|
18
|
+
Add to your `claude_desktop_config.json`:
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"mcpServers": {
|
|
23
|
+
"veragent": {
|
|
24
|
+
"command": "uvx",
|
|
25
|
+
"args": ["veragent-mcp"]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Then ask Claude: *"Is the playwright-mcp server safe? Check Veragent."*
|
|
32
|
+
|
|
33
|
+
## Run locally
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
uvx veragent-mcp
|
|
37
|
+
# or
|
|
38
|
+
pip install veragent-mcp && veragent-mcp
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Configuration
|
|
42
|
+
|
|
43
|
+
- `VERAGENT_API_BASE` — override the API base (default `https://veragent.store/api/v1`).
|
|
44
|
+
|
|
45
|
+
## Honesty
|
|
46
|
+
|
|
47
|
+
Veragent labels static-analysis results as **Heuristic** and reserves **SGC Certified**
|
|
48
|
+
for behavioral-sandbox passes. Scores are reported with this distinction.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "veragent-mcp"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Veragent MCP server — check the trust/security score of MCP tools before installing them in Claude."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
license = { text = "MIT" }
|
|
8
|
+
authors = [{ name = "Sean Li" }]
|
|
9
|
+
keywords = ["mcp", "model-context-protocol", "security", "veragent", "claude", "trust"]
|
|
10
|
+
dependencies = [
|
|
11
|
+
"mcp>=1.2.0",
|
|
12
|
+
"httpx>=0.27",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[project.urls]
|
|
16
|
+
Homepage = "https://veragent.store"
|
|
17
|
+
Registry = "https://veragent.store/trust-registry"
|
|
18
|
+
|
|
19
|
+
[project.scripts]
|
|
20
|
+
veragent-mcp = "veragent_mcp.server:main"
|
|
21
|
+
|
|
22
|
+
[build-system]
|
|
23
|
+
requires = ["hatchling"]
|
|
24
|
+
build-backend = "hatchling.build"
|
|
25
|
+
|
|
26
|
+
[tool.hatch.build.targets.wheel]
|
|
27
|
+
packages = ["veragent_mcp"]
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Live integration tests for the Veragent MCP client (no mocks — hits the real API).
|
|
3
|
+
Run: python test_client.py
|
|
4
|
+
"""
|
|
5
|
+
from veragent_mcp import client
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_check_tool_trust_found():
|
|
9
|
+
res = client.check_tool_trust("playwright")
|
|
10
|
+
assert res["found"] is True, res
|
|
11
|
+
assert isinstance(res["trust_score_pct"], int)
|
|
12
|
+
assert res["audit_state"]
|
|
13
|
+
assert res["report_url"].startswith("https://veragent.store/agents/")
|
|
14
|
+
print("check_tool_trust(found):", res["name"], res["trust_score_pct"], res["audit_state"])
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_check_tool_trust_not_found():
|
|
18
|
+
res = client.check_tool_trust("zzz-nonexistent-tool-xyz-123")
|
|
19
|
+
assert res["found"] is False, res
|
|
20
|
+
print("check_tool_trust(not found): OK")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_list_trusted_tools():
|
|
24
|
+
res = client.list_trusted_tools(limit=5)
|
|
25
|
+
assert isinstance(res, list) and len(res) > 0, res
|
|
26
|
+
assert all("report_url" in t for t in res)
|
|
27
|
+
print("list_trusted_tools:", len(res), "tools; top:", res[0]["name"], res[0]["trust_score_pct"])
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_scan_mcp_stack():
|
|
31
|
+
cfg = {"mcpServers": {"playwright": {"command": "npx", "args": ["-y", "@playwright/mcp"]}}}
|
|
32
|
+
res = client.scan_mcp_stack(cfg)
|
|
33
|
+
assert "total" in res and res["total"] >= 1, res
|
|
34
|
+
print("scan_mcp_stack: total", res["total"], "summary:", res["summary"])
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
if __name__ == "__main__":
|
|
38
|
+
test_check_tool_trust_found()
|
|
39
|
+
test_check_tool_trust_not_found()
|
|
40
|
+
test_list_trusted_tools()
|
|
41
|
+
test_scan_mcp_stack()
|
|
42
|
+
print("\nAll live client tests passed ✓")
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Veragent API client — pure functions over the public Veragent API.
|
|
3
|
+
|
|
4
|
+
Kept free of MCP-protocol concerns so the trust logic is independently testable
|
|
5
|
+
against the live API (no mocks). Used by server.py to back the MCP tools.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
from typing import Any, Dict, List
|
|
11
|
+
|
|
12
|
+
import httpx
|
|
13
|
+
|
|
14
|
+
API_BASE = os.environ.get("VERAGENT_API_BASE", "https://veragent.store/api/v1").rstrip("/")
|
|
15
|
+
_TIMEOUT = httpx.Timeout(20.0)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _audit_label(audit_status: str, has_report: bool) -> str:
|
|
19
|
+
s = (audit_status or "unaudited").lower()
|
|
20
|
+
if "certified" in s and has_report:
|
|
21
|
+
return "SGC Certified (behavioral sandbox)"
|
|
22
|
+
if s in ("audited", "approved") or "audited" in s:
|
|
23
|
+
return "Heuristic (static analysis only)"
|
|
24
|
+
if "pending" in s or "review" in s:
|
|
25
|
+
return "Audit pending"
|
|
26
|
+
return "Unaudited"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def check_tool_trust(name: str) -> Dict[str, Any]:
|
|
30
|
+
"""Look up an MCP tool by name and return its Veragent trust assessment."""
|
|
31
|
+
with httpx.Client(timeout=_TIMEOUT) as c:
|
|
32
|
+
r = c.get(f"{API_BASE}/search/agents", params={"q": name, "page": 1, "limit": 5})
|
|
33
|
+
r.raise_for_status()
|
|
34
|
+
agents = (r.json() or {}).get("agents", [])
|
|
35
|
+
|
|
36
|
+
# Relevance guard: Typesense fuzzy-matches, so a non-indexed name can still return an
|
|
37
|
+
# unrelated tool. Require token overlap between the query and the candidate name/tagline
|
|
38
|
+
# so we never misreport an unrelated tool as if it were the one asked about.
|
|
39
|
+
def _relevant(a: Dict[str, Any]) -> bool:
|
|
40
|
+
q_tokens = {t for t in "".join(ch if ch.isalnum() else " " for ch in name.lower()).split() if len(t) > 2}
|
|
41
|
+
if not q_tokens:
|
|
42
|
+
return True
|
|
43
|
+
hay = f"{a.get('name','')} {a.get('tagline','')} {a.get('id','')}".lower()
|
|
44
|
+
return any(t in hay for t in q_tokens)
|
|
45
|
+
|
|
46
|
+
relevant = [a for a in agents if _relevant(a)] if agents else []
|
|
47
|
+
if not relevant:
|
|
48
|
+
return {"found": False, "query": name,
|
|
49
|
+
"message": f"No tool matching '{name}' is indexed in the Veragent trust registry. "
|
|
50
|
+
"Treat it as unverified."}
|
|
51
|
+
|
|
52
|
+
a = relevant[0]
|
|
53
|
+
pct = round((a.get("trust_score") or a.get("sgc_confidence") or 0) * 100)
|
|
54
|
+
label = _audit_label(a.get("audit_status", ""), bool(a.get("sgc_report_id")))
|
|
55
|
+
return {
|
|
56
|
+
"found": True,
|
|
57
|
+
"name": a.get("name"),
|
|
58
|
+
"trust_score_pct": pct,
|
|
59
|
+
"audit_state": label,
|
|
60
|
+
"risk_tier": a.get("sgc_risk_tier") or a.get("risk_tier"),
|
|
61
|
+
"listing_type": a.get("listing_type"),
|
|
62
|
+
"publisher": (a.get("publisher") or {}).get("name"),
|
|
63
|
+
"report_url": f"https://veragent.store/agents/{a.get('id')}",
|
|
64
|
+
"advice": (
|
|
65
|
+
"Heuristic score reflects static analysis only — review the source before "
|
|
66
|
+
"installing in production." if "Heuristic" in label
|
|
67
|
+
else "Passed Veragent behavioral sandbox audit." if "Certified" in label
|
|
68
|
+
else "Not yet audited — install with caution."
|
|
69
|
+
),
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def list_trusted_tools(query: str = "*", limit: int = 10) -> List[Dict[str, Any]]:
|
|
74
|
+
"""Return the most trusted tools matching a query (or overall)."""
|
|
75
|
+
with httpx.Client(timeout=_TIMEOUT) as c:
|
|
76
|
+
r = c.get(f"{API_BASE}/search/agents",
|
|
77
|
+
params={"q": query or "*", "sort_by": "trust_score", "page": 1, "limit": limit})
|
|
78
|
+
r.raise_for_status()
|
|
79
|
+
agents = (r.json() or {}).get("agents", [])
|
|
80
|
+
return [{
|
|
81
|
+
"name": a.get("name"),
|
|
82
|
+
"trust_score_pct": round((a.get("trust_score") or a.get("sgc_confidence") or 0) * 100),
|
|
83
|
+
"audit_state": _audit_label(a.get("audit_status", ""), bool(a.get("sgc_report_id"))),
|
|
84
|
+
"report_url": f"https://veragent.store/agents/{a.get('id')}",
|
|
85
|
+
} for a in agents]
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def scan_mcp_stack(mcp_config: Dict[str, Any]) -> Dict[str, Any]:
|
|
89
|
+
"""Score a whole MCP stack. Pass a parsed mcp_settings.json (or its mcpServers block)."""
|
|
90
|
+
with httpx.Client(timeout=_TIMEOUT) as c:
|
|
91
|
+
r = c.post(f"{API_BASE}/stack/health-check", json={"mcp_config": mcp_config})
|
|
92
|
+
r.raise_for_status()
|
|
93
|
+
rep = r.json()
|
|
94
|
+
return {
|
|
95
|
+
"total": rep.get("total_servers"),
|
|
96
|
+
"safe": rep.get("green"), "caution": rep.get("yellow"),
|
|
97
|
+
"high_risk": rep.get("red"), "unregistered": rep.get("unknown"),
|
|
98
|
+
"summary": rep.get("summary"),
|
|
99
|
+
"details": [
|
|
100
|
+
{"server": s.get("server_key"), "risk": s.get("risk_level"),
|
|
101
|
+
"signals": s.get("signals")} for s in rep.get("servers", [])
|
|
102
|
+
],
|
|
103
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Veragent MCP server — the trust layer, as an MCP tool.
|
|
3
|
+
|
|
4
|
+
Exposes Veragent's trust registry as MCP tools so Claude (and any MCP client/agent)
|
|
5
|
+
can vet MCP tools *before* installing them, or score an existing stack — turning
|
|
6
|
+
Veragent from "a site you visit" into "a tool the agent calls".
|
|
7
|
+
|
|
8
|
+
Run:
|
|
9
|
+
uvx veragent-mcp # or: python -m veragent_mcp.server
|
|
10
|
+
"""
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from typing import Any, Dict
|
|
14
|
+
|
|
15
|
+
from mcp.server.fastmcp import FastMCP
|
|
16
|
+
|
|
17
|
+
from veragent_mcp import client
|
|
18
|
+
|
|
19
|
+
mcp = FastMCP("veragent")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@mcp.tool()
|
|
23
|
+
def check_tool_trust(name: str) -> Dict[str, Any]:
|
|
24
|
+
"""Check the Veragent trust score and audit state of an MCP tool / server / agent by name.
|
|
25
|
+
Use this BEFORE installing or recommending an MCP tool to verify it is safe."""
|
|
26
|
+
return client.check_tool_trust(name)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@mcp.tool()
|
|
30
|
+
def list_trusted_tools(query: str = "*", limit: int = 10) -> Any:
|
|
31
|
+
"""List the most trusted MCP tools, optionally filtered by a search query."""
|
|
32
|
+
return client.list_trusted_tools(query=query, limit=limit)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@mcp.tool()
|
|
36
|
+
def scan_mcp_stack(mcp_config: Dict[str, Any]) -> Dict[str, Any]:
|
|
37
|
+
"""Score a whole MCP stack for security. Pass a parsed mcp_settings.json object
|
|
38
|
+
(or just its mcpServers block). Returns per-server risk levels and a summary."""
|
|
39
|
+
return client.scan_mcp_stack(mcp_config)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def main() -> None:
|
|
43
|
+
mcp.run()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
if __name__ == "__main__":
|
|
47
|
+
main()
|