hvtracker-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.
- hvtracker_mcp-0.1.0/LICENSE +22 -0
- hvtracker_mcp-0.1.0/PKG-INFO +132 -0
- hvtracker_mcp-0.1.0/README.md +102 -0
- hvtracker_mcp-0.1.0/pyproject.toml +54 -0
- hvtracker_mcp-0.1.0/setup.cfg +4 -0
- hvtracker_mcp-0.1.0/src/hvtracker_mcp/__init__.py +4 -0
- hvtracker_mcp-0.1.0/src/hvtracker_mcp/__main__.py +6 -0
- hvtracker_mcp-0.1.0/src/hvtracker_mcp/server.py +150 -0
- hvtracker_mcp-0.1.0/src/hvtracker_mcp.egg-info/PKG-INFO +132 -0
- hvtracker_mcp-0.1.0/src/hvtracker_mcp.egg-info/SOURCES.txt +13 -0
- hvtracker_mcp-0.1.0/src/hvtracker_mcp.egg-info/dependency_links.txt +1 -0
- hvtracker_mcp-0.1.0/src/hvtracker_mcp.egg-info/entry_points.txt +2 -0
- hvtracker_mcp-0.1.0/src/hvtracker_mcp.egg-info/requires.txt +8 -0
- hvtracker_mcp-0.1.0/src/hvtracker_mcp.egg-info/top_level.txt +1 -0
- hvtracker_mcp-0.1.0/tests/test_server.py +74 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 YugantM
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hvtracker-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server for HVTracker trust checks.
|
|
5
|
+
Author: YugantM
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://hvtracker.net
|
|
8
|
+
Project-URL: Repository, https://github.com/YugantM/hvtracker-mcp
|
|
9
|
+
Project-URL: Issues, https://github.com/YugantM/hvtracker-mcp/issues
|
|
10
|
+
Keywords: mcp,model-context-protocol,ai-agents,trust,supply-chain
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Security
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: mcp>=1.27.2
|
|
23
|
+
Requires-Dist: requests>=2.32.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: build>=1.2.0; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest>=9.0.0; extra == "dev"
|
|
27
|
+
Requires-Dist: ruff>=0.15.0; extra == "dev"
|
|
28
|
+
Requires-Dist: twine>=6.0.0; extra == "dev"
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# HVTracker MCP
|
|
32
|
+
|
|
33
|
+
MCP server for checking supply-chain trust before connecting to AI agents,
|
|
34
|
+
frameworks, or MCP servers.
|
|
35
|
+
|
|
36
|
+
The hosted remote server is:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"mcpServers": {
|
|
41
|
+
"hvtracker": {
|
|
42
|
+
"url": "https://hvtracker.net/mcp"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
This repository also provides a local stdio package for clients that prefer
|
|
49
|
+
package-based installation.
|
|
50
|
+
|
|
51
|
+
<!-- mcp-name: io.github.yugantm/hvtracker-mcp -->
|
|
52
|
+
|
|
53
|
+
## Tools
|
|
54
|
+
|
|
55
|
+
- `verify_mcp_server`: pre-connect trust verdict for an MCP server, package, GitHub repo, or agent name.
|
|
56
|
+
- `check_agent_trust`: compact trust profile for a tracked AI agent or framework.
|
|
57
|
+
- `search_agents`: search the HVTracker registry by name, repo, description, or category.
|
|
58
|
+
|
|
59
|
+
## Local Install
|
|
60
|
+
|
|
61
|
+
With npm:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npm install -g hvtracker-mcp
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
With PyPI:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
python3 -m pip install hvtracker-mcp
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Example MCP client config:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"mcpServers": {
|
|
78
|
+
"hvtracker": {
|
|
79
|
+
"command": "hvtracker-mcp"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Development
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
python3 -m pip install -e ".[dev]"
|
|
89
|
+
python3 -m pytest
|
|
90
|
+
hvtracker-mcp
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Use a different HVTracker base URL while testing:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
HVTRACKER_BASE_URL=http://localhost:8080 hvtracker-mcp
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Registry Publishing
|
|
100
|
+
|
|
101
|
+
The official MCP Registry manifest is `server.json`.
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
mcp-publisher login github
|
|
105
|
+
mcp-publisher publish
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
In GitHub Actions, run the "Publish MCP Registry" workflow after the npm,
|
|
109
|
+
PyPI, and GHCR packages for the same version are live.
|
|
110
|
+
|
|
111
|
+
The server name is:
|
|
112
|
+
|
|
113
|
+
```text
|
|
114
|
+
io.github.yugantm/hvtracker-mcp
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Claude Desktop Extension
|
|
118
|
+
|
|
119
|
+
Tagged releases build an `.mcpb` bundle for Claude Desktop from `manifest.json`.
|
|
120
|
+
To build it locally:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
npm ci --omit=dev
|
|
124
|
+
npx @anthropic-ai/mcpb@2.1.2 pack
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Privacy
|
|
128
|
+
|
|
129
|
+
HVTracker MCP sends the user-supplied search string or server identifier to
|
|
130
|
+
`https://hvtracker.net` to fetch public trust data. It does not require an API
|
|
131
|
+
key and does not write to user systems. See the HVTracker site for current data
|
|
132
|
+
and methodology, and see `PRIVACY.md` for the repository privacy note.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# HVTracker MCP
|
|
2
|
+
|
|
3
|
+
MCP server for checking supply-chain trust before connecting to AI agents,
|
|
4
|
+
frameworks, or MCP servers.
|
|
5
|
+
|
|
6
|
+
The hosted remote server is:
|
|
7
|
+
|
|
8
|
+
```json
|
|
9
|
+
{
|
|
10
|
+
"mcpServers": {
|
|
11
|
+
"hvtracker": {
|
|
12
|
+
"url": "https://hvtracker.net/mcp"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
This repository also provides a local stdio package for clients that prefer
|
|
19
|
+
package-based installation.
|
|
20
|
+
|
|
21
|
+
<!-- mcp-name: io.github.yugantm/hvtracker-mcp -->
|
|
22
|
+
|
|
23
|
+
## Tools
|
|
24
|
+
|
|
25
|
+
- `verify_mcp_server`: pre-connect trust verdict for an MCP server, package, GitHub repo, or agent name.
|
|
26
|
+
- `check_agent_trust`: compact trust profile for a tracked AI agent or framework.
|
|
27
|
+
- `search_agents`: search the HVTracker registry by name, repo, description, or category.
|
|
28
|
+
|
|
29
|
+
## Local Install
|
|
30
|
+
|
|
31
|
+
With npm:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install -g hvtracker-mcp
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
With PyPI:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
python3 -m pip install hvtracker-mcp
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Example MCP client config:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"mcpServers": {
|
|
48
|
+
"hvtracker": {
|
|
49
|
+
"command": "hvtracker-mcp"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Development
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
python3 -m pip install -e ".[dev]"
|
|
59
|
+
python3 -m pytest
|
|
60
|
+
hvtracker-mcp
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Use a different HVTracker base URL while testing:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
HVTRACKER_BASE_URL=http://localhost:8080 hvtracker-mcp
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Registry Publishing
|
|
70
|
+
|
|
71
|
+
The official MCP Registry manifest is `server.json`.
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
mcp-publisher login github
|
|
75
|
+
mcp-publisher publish
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
In GitHub Actions, run the "Publish MCP Registry" workflow after the npm,
|
|
79
|
+
PyPI, and GHCR packages for the same version are live.
|
|
80
|
+
|
|
81
|
+
The server name is:
|
|
82
|
+
|
|
83
|
+
```text
|
|
84
|
+
io.github.yugantm/hvtracker-mcp
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Claude Desktop Extension
|
|
88
|
+
|
|
89
|
+
Tagged releases build an `.mcpb` bundle for Claude Desktop from `manifest.json`.
|
|
90
|
+
To build it locally:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
npm ci --omit=dev
|
|
94
|
+
npx @anthropic-ai/mcpb@2.1.2 pack
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Privacy
|
|
98
|
+
|
|
99
|
+
HVTracker MCP sends the user-supplied search string or server identifier to
|
|
100
|
+
`https://hvtracker.net` to fetch public trust data. It does not require an API
|
|
101
|
+
key and does not write to user systems. See the HVTracker site for current data
|
|
102
|
+
and methodology, and see `PRIVACY.md` for the repository privacy note.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=69", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "hvtracker-mcp"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "MCP server for HVTracker trust checks."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "YugantM" }
|
|
14
|
+
]
|
|
15
|
+
keywords = ["mcp", "model-context-protocol", "ai-agents", "trust", "supply-chain"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.10",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Topic :: Security",
|
|
24
|
+
"Topic :: Software Development :: Libraries :: Python Modules"
|
|
25
|
+
]
|
|
26
|
+
dependencies = [
|
|
27
|
+
"mcp>=1.27.2",
|
|
28
|
+
"requests>=2.32.0"
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
dev = [
|
|
33
|
+
"build>=1.2.0",
|
|
34
|
+
"pytest>=9.0.0",
|
|
35
|
+
"ruff>=0.15.0",
|
|
36
|
+
"twine>=6.0.0"
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
[project.scripts]
|
|
40
|
+
hvtracker-mcp = "hvtracker_mcp.server:main"
|
|
41
|
+
|
|
42
|
+
[project.urls]
|
|
43
|
+
Homepage = "https://hvtracker.net"
|
|
44
|
+
Repository = "https://github.com/YugantM/hvtracker-mcp"
|
|
45
|
+
Issues = "https://github.com/YugantM/hvtracker-mcp/issues"
|
|
46
|
+
|
|
47
|
+
[tool.setuptools.packages.find]
|
|
48
|
+
where = ["src"]
|
|
49
|
+
|
|
50
|
+
[tool.ruff]
|
|
51
|
+
line-length = 100
|
|
52
|
+
|
|
53
|
+
[tool.pytest.ini_options]
|
|
54
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"""Standalone HVTracker MCP server.
|
|
2
|
+
|
|
3
|
+
The hosted production endpoint is https://hvtracker.net/mcp. This package is
|
|
4
|
+
the local stdio distribution path: it exposes the same user-facing tools and
|
|
5
|
+
delegates verdicts/searches to HVTracker's public HTTPS API.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import argparse
|
|
11
|
+
import os
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
import requests
|
|
15
|
+
from mcp.server.fastmcp import FastMCP
|
|
16
|
+
from mcp.types import ToolAnnotations
|
|
17
|
+
|
|
18
|
+
from . import __version__
|
|
19
|
+
|
|
20
|
+
DEFAULT_BASE_URL = "https://hvtracker.net"
|
|
21
|
+
BASE_URL = os.environ.get("HVTRACKER_BASE_URL", DEFAULT_BASE_URL).rstrip("/")
|
|
22
|
+
TIMEOUT_SECONDS = float(os.environ.get("HVTRACKER_TIMEOUT_SECONDS", "20"))
|
|
23
|
+
|
|
24
|
+
mcp = FastMCP("hvtracker", instructions="Check trust signals for AI agents and MCP servers.")
|
|
25
|
+
READ_ONLY = ToolAnnotations(readOnlyHint=True, destructiveHint=False, idempotentHint=True, openWorldHint=True)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _api_get(path: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
29
|
+
url = f"{BASE_URL}{path}"
|
|
30
|
+
response = requests.get(
|
|
31
|
+
url,
|
|
32
|
+
params=params,
|
|
33
|
+
timeout=TIMEOUT_SECONDS,
|
|
34
|
+
headers={"User-Agent": f"hvtracker-mcp/{__version__}"},
|
|
35
|
+
)
|
|
36
|
+
response.raise_for_status()
|
|
37
|
+
payload = response.json()
|
|
38
|
+
if not isinstance(payload, dict):
|
|
39
|
+
raise ValueError(f"Unexpected response shape from {url}")
|
|
40
|
+
return payload
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _agent_profile(agent: dict[str, Any]) -> dict[str, Any]:
|
|
44
|
+
slug = agent.get("slug")
|
|
45
|
+
return {
|
|
46
|
+
"tracked": True,
|
|
47
|
+
"name": agent.get("name"),
|
|
48
|
+
"repo": agent.get("repo"),
|
|
49
|
+
"trust_score": agent.get("trust_score"),
|
|
50
|
+
"evidence_grade": agent.get("evidence_grade"),
|
|
51
|
+
"rank": agent.get("rank"),
|
|
52
|
+
"category": agent.get("category"),
|
|
53
|
+
"has_provenance": agent.get("has_provenance"),
|
|
54
|
+
"scorecard_score": agent.get("scorecard_score"),
|
|
55
|
+
"mcp_server_support": (agent.get("mcp_server_support") or {}).get("status"),
|
|
56
|
+
"profile_url": f"{BASE_URL}/agents/{slug}/" if slug else None,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@mcp.tool(title="Verify MCP Server", annotations=READ_ONLY)
|
|
61
|
+
def verify_mcp_server(server: str) -> dict[str, Any]:
|
|
62
|
+
"""Pre-connect trust verdict for an MCP server or AI agent.
|
|
63
|
+
|
|
64
|
+
Pass a GitHub owner/repo, GitHub URL, npm/PyPI package, display name, slug,
|
|
65
|
+
or MCP server URL. Unknown servers return trusted=false because HVTracker has
|
|
66
|
+
no independent evidence, not because harm is proven.
|
|
67
|
+
"""
|
|
68
|
+
try:
|
|
69
|
+
return _api_get("/api/v1/mcp/verify", {"server": server})
|
|
70
|
+
except Exception as exc:
|
|
71
|
+
return {
|
|
72
|
+
"server": server,
|
|
73
|
+
"tracked": False,
|
|
74
|
+
"trusted": False,
|
|
75
|
+
"error": str(exc),
|
|
76
|
+
"reasons": ["HVTracker could not fetch a verdict right now."],
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@mcp.tool(title="Check Agent Trust", annotations=READ_ONLY)
|
|
81
|
+
def check_agent_trust(name_or_repo: str) -> dict[str, Any]:
|
|
82
|
+
"""Get the HVTracker trust profile for a tracked AI agent or framework."""
|
|
83
|
+
verdict = verify_mcp_server(name_or_repo)
|
|
84
|
+
if not verdict.get("tracked"):
|
|
85
|
+
return {
|
|
86
|
+
"query": name_or_repo,
|
|
87
|
+
"tracked": False,
|
|
88
|
+
"trusted": False,
|
|
89
|
+
"message": "Not in the HVTracker registry; treat as unverified.",
|
|
90
|
+
"submit_url": f"{BASE_URL}/submit",
|
|
91
|
+
"verdict": verdict,
|
|
92
|
+
}
|
|
93
|
+
slug = verdict.get("slug")
|
|
94
|
+
return {
|
|
95
|
+
"query": name_or_repo,
|
|
96
|
+
"tracked": True,
|
|
97
|
+
"trusted": verdict.get("trusted"),
|
|
98
|
+
"repo": verdict.get("resolved"),
|
|
99
|
+
"slug": slug,
|
|
100
|
+
"trust_score": verdict.get("trust_score"),
|
|
101
|
+
"evidence_grade": verdict.get("grade"),
|
|
102
|
+
"confidence": verdict.get("confidence"),
|
|
103
|
+
"mcp_server_support": verdict.get("mcp_server_support"),
|
|
104
|
+
"tool_permissions": verdict.get("tool_permissions") or [],
|
|
105
|
+
"profile_url": f"{BASE_URL}/agents/{slug}/" if slug else None,
|
|
106
|
+
"reasons": verdict.get("reasons") or [],
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@mcp.tool(title="Search Agents", annotations=READ_ONLY)
|
|
111
|
+
def search_agents(query: str = "", category: str = "", limit: int = 10) -> dict[str, Any]:
|
|
112
|
+
"""Search tracked AI agents and frameworks by name, repo, or description."""
|
|
113
|
+
try:
|
|
114
|
+
data = _api_get("/api/v1/agents")
|
|
115
|
+
except Exception as exc:
|
|
116
|
+
return {"count": 0, "results": [], "error": str(exc)}
|
|
117
|
+
|
|
118
|
+
ql = (query or "").strip().lower()
|
|
119
|
+
cl = (category or "").strip().lower()
|
|
120
|
+
matches = []
|
|
121
|
+
for agent in data.get("agents", []):
|
|
122
|
+
haystack = " ".join(
|
|
123
|
+
str(agent.get(key) or "") for key in ("name", "repo", "description", "slug")
|
|
124
|
+
).lower()
|
|
125
|
+
if ql and ql not in haystack:
|
|
126
|
+
continue
|
|
127
|
+
if cl and (agent.get("category") or "").lower() != cl:
|
|
128
|
+
continue
|
|
129
|
+
matches.append(_agent_profile(agent))
|
|
130
|
+
|
|
131
|
+
matches.sort(key=lambda row: (row["trust_score"] is None, -(row["trust_score"] or 0)))
|
|
132
|
+
limit = max(1, min(int(limit or 10), 50))
|
|
133
|
+
return {"count": len(matches), "results": matches[:limit]}
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def main(argv: list[str] | None = None) -> None:
|
|
137
|
+
parser = argparse.ArgumentParser(description="Run the HVTracker MCP server.")
|
|
138
|
+
parser.add_argument(
|
|
139
|
+
"--transport",
|
|
140
|
+
choices=["stdio", "streamable-http"],
|
|
141
|
+
default=os.environ.get("HVTRACKER_MCP_TRANSPORT", "stdio"),
|
|
142
|
+
help="Transport to run. Use stdio for local MCP clients.",
|
|
143
|
+
)
|
|
144
|
+
args = parser.parse_args(argv)
|
|
145
|
+
mcp.run(transport=args.transport)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
if __name__ == "__main__":
|
|
149
|
+
main()
|
|
150
|
+
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hvtracker-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server for HVTracker trust checks.
|
|
5
|
+
Author: YugantM
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://hvtracker.net
|
|
8
|
+
Project-URL: Repository, https://github.com/YugantM/hvtracker-mcp
|
|
9
|
+
Project-URL: Issues, https://github.com/YugantM/hvtracker-mcp/issues
|
|
10
|
+
Keywords: mcp,model-context-protocol,ai-agents,trust,supply-chain
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Security
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: mcp>=1.27.2
|
|
23
|
+
Requires-Dist: requests>=2.32.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: build>=1.2.0; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest>=9.0.0; extra == "dev"
|
|
27
|
+
Requires-Dist: ruff>=0.15.0; extra == "dev"
|
|
28
|
+
Requires-Dist: twine>=6.0.0; extra == "dev"
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# HVTracker MCP
|
|
32
|
+
|
|
33
|
+
MCP server for checking supply-chain trust before connecting to AI agents,
|
|
34
|
+
frameworks, or MCP servers.
|
|
35
|
+
|
|
36
|
+
The hosted remote server is:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"mcpServers": {
|
|
41
|
+
"hvtracker": {
|
|
42
|
+
"url": "https://hvtracker.net/mcp"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
This repository also provides a local stdio package for clients that prefer
|
|
49
|
+
package-based installation.
|
|
50
|
+
|
|
51
|
+
<!-- mcp-name: io.github.yugantm/hvtracker-mcp -->
|
|
52
|
+
|
|
53
|
+
## Tools
|
|
54
|
+
|
|
55
|
+
- `verify_mcp_server`: pre-connect trust verdict for an MCP server, package, GitHub repo, or agent name.
|
|
56
|
+
- `check_agent_trust`: compact trust profile for a tracked AI agent or framework.
|
|
57
|
+
- `search_agents`: search the HVTracker registry by name, repo, description, or category.
|
|
58
|
+
|
|
59
|
+
## Local Install
|
|
60
|
+
|
|
61
|
+
With npm:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npm install -g hvtracker-mcp
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
With PyPI:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
python3 -m pip install hvtracker-mcp
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Example MCP client config:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"mcpServers": {
|
|
78
|
+
"hvtracker": {
|
|
79
|
+
"command": "hvtracker-mcp"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Development
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
python3 -m pip install -e ".[dev]"
|
|
89
|
+
python3 -m pytest
|
|
90
|
+
hvtracker-mcp
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Use a different HVTracker base URL while testing:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
HVTRACKER_BASE_URL=http://localhost:8080 hvtracker-mcp
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Registry Publishing
|
|
100
|
+
|
|
101
|
+
The official MCP Registry manifest is `server.json`.
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
mcp-publisher login github
|
|
105
|
+
mcp-publisher publish
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
In GitHub Actions, run the "Publish MCP Registry" workflow after the npm,
|
|
109
|
+
PyPI, and GHCR packages for the same version are live.
|
|
110
|
+
|
|
111
|
+
The server name is:
|
|
112
|
+
|
|
113
|
+
```text
|
|
114
|
+
io.github.yugantm/hvtracker-mcp
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Claude Desktop Extension
|
|
118
|
+
|
|
119
|
+
Tagged releases build an `.mcpb` bundle for Claude Desktop from `manifest.json`.
|
|
120
|
+
To build it locally:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
npm ci --omit=dev
|
|
124
|
+
npx @anthropic-ai/mcpb@2.1.2 pack
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Privacy
|
|
128
|
+
|
|
129
|
+
HVTracker MCP sends the user-supplied search string or server identifier to
|
|
130
|
+
`https://hvtracker.net` to fetch public trust data. It does not require an API
|
|
131
|
+
key and does not write to user systems. See the HVTracker site for current data
|
|
132
|
+
and methodology, and see `PRIVACY.md` for the repository privacy note.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/hvtracker_mcp/__init__.py
|
|
5
|
+
src/hvtracker_mcp/__main__.py
|
|
6
|
+
src/hvtracker_mcp/server.py
|
|
7
|
+
src/hvtracker_mcp.egg-info/PKG-INFO
|
|
8
|
+
src/hvtracker_mcp.egg-info/SOURCES.txt
|
|
9
|
+
src/hvtracker_mcp.egg-info/dependency_links.txt
|
|
10
|
+
src/hvtracker_mcp.egg-info/entry_points.txt
|
|
11
|
+
src/hvtracker_mcp.egg-info/requires.txt
|
|
12
|
+
src/hvtracker_mcp.egg-info/top_level.txt
|
|
13
|
+
tests/test_server.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
hvtracker_mcp
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
from hvtracker_mcp import server
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_verify_mcp_server_delegates_to_api(monkeypatch):
|
|
7
|
+
def fake_get(path, params=None):
|
|
8
|
+
assert path == "/api/v1/mcp/verify"
|
|
9
|
+
assert params == {"server": "langchain-ai/langgraph"}
|
|
10
|
+
return {"tracked": True, "trusted": True, "resolved": "langchain-ai/langgraph"}
|
|
11
|
+
|
|
12
|
+
monkeypatch.setattr(server, "_api_get", fake_get)
|
|
13
|
+
assert server.verify_mcp_server("langchain-ai/langgraph")["trusted"] is True
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_check_agent_trust_maps_verdict(monkeypatch):
|
|
17
|
+
monkeypatch.setattr(
|
|
18
|
+
server,
|
|
19
|
+
"verify_mcp_server",
|
|
20
|
+
lambda query: {
|
|
21
|
+
"tracked": True,
|
|
22
|
+
"trusted": True,
|
|
23
|
+
"resolved": "langchain-ai/langgraph",
|
|
24
|
+
"slug": "langgraph",
|
|
25
|
+
"trust_score": 92.8,
|
|
26
|
+
"grade": "A",
|
|
27
|
+
"confidence": 1.0,
|
|
28
|
+
"mcp_server_support": "none",
|
|
29
|
+
"tool_permissions": ["code"],
|
|
30
|
+
"reasons": ["Build provenance present."],
|
|
31
|
+
},
|
|
32
|
+
)
|
|
33
|
+
result = server.check_agent_trust("LangGraph")
|
|
34
|
+
assert result["repo"] == "langchain-ai/langgraph"
|
|
35
|
+
assert result["profile_url"].endswith("/agents/langgraph/")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_search_agents_filters_and_sorts(monkeypatch):
|
|
39
|
+
monkeypatch.setattr(
|
|
40
|
+
server,
|
|
41
|
+
"_api_get",
|
|
42
|
+
lambda path: {
|
|
43
|
+
"agents": [
|
|
44
|
+
{
|
|
45
|
+
"name": "Lower",
|
|
46
|
+
"repo": "example/lower",
|
|
47
|
+
"slug": "lower",
|
|
48
|
+
"trust_score": 40,
|
|
49
|
+
"evidence_grade": "C",
|
|
50
|
+
"category": "Coding Agents",
|
|
51
|
+
"description": "agent",
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"name": "Higher",
|
|
55
|
+
"repo": "example/higher",
|
|
56
|
+
"slug": "higher",
|
|
57
|
+
"trust_score": 90,
|
|
58
|
+
"evidence_grade": "A",
|
|
59
|
+
"category": "Coding Agents",
|
|
60
|
+
"description": "agent",
|
|
61
|
+
},
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
)
|
|
65
|
+
result = server.search_agents(query="example", category="Coding Agents")
|
|
66
|
+
assert result["count"] == 2
|
|
67
|
+
assert [row["name"] for row in result["results"]] == ["Higher", "Lower"]
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_tools_have_read_only_annotations():
|
|
71
|
+
tools = {tool.name: tool for tool in asyncio.run(server.mcp.list_tools())}
|
|
72
|
+
assert set(tools) == {"verify_mcp_server", "check_agent_trust", "search_agents"}
|
|
73
|
+
assert tools["verify_mcp_server"].annotations.readOnlyHint is True
|
|
74
|
+
|