trustmodel-agentcert-tag 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.
@@ -0,0 +1,49 @@
1
+ Metadata-Version: 2.4
2
+ Name: trustmodel-agentcert-tag
3
+ Version: 0.1.0
4
+ Summary: Verify an AgentCert + TrustScore inside a Python MCP server (shadow mode, opt-in, dependency-free).
5
+ Author: TrustModel.ai
6
+ License: MIT
7
+ Project-URL: Homepage, https://trustmodel.ai/verify
8
+ Project-URL: Documentation, https://trustmodel.ai/wiki/agentcert/verify-gateway
9
+ Project-URL: Source, https://github.com/pdxlab/agentcert-tag
10
+ Keywords: mcp,agentcert,trustscore,verification,ai-agents,trustmodel
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Intended Audience :: Developers
14
+ Requires-Python: >=3.9
15
+ Description-Content-Type: text/markdown
16
+
17
+ # trustmodel-agentcert-tag
18
+
19
+ Verify an **AgentCert + TrustScore** inside a Python MCP server. Thin, dependency-free
20
+ client for a [TAG](https://trustmodel.ai/verify) verify endpoint — **off by default**,
21
+ **shadow mode** when on (logs, never blocks), safe to merge.
22
+
23
+ ```bash
24
+ pip install trustmodel-agentcert-tag
25
+ ```
26
+
27
+ ```python
28
+ from trustmodel_agentcert_tag import verify_gate, extract_token
29
+
30
+ guard = verify_gate(mode="shadow") # shadow | enforce
31
+
32
+ async def handle_tool_call(request):
33
+ token = extract_token(request.headers) # X-AgentCert-Token (or mTLS-derived)
34
+ await guard(token) # logs (shadow) / raises VerifyError (enforce)
35
+ return await dispatch(request)
36
+ ```
37
+
38
+ Enable per environment — nothing runs until you opt in:
39
+
40
+ | Env var | Meaning |
41
+ |---|---|
42
+ | `TRUSTMODEL_VERIFY=1` | turn the gate on (otherwise `guard` is a no-op) |
43
+ | `TRUSTMODEL_VERIFY_URL` | TAG verify endpoint (default `http://localhost:8080/verify`) |
44
+ | `TRUSTMODEL_MODE=enforce` | switch to enforcement |
45
+
46
+ The gate never reads request payloads (metadata only) and never makes the allow/deny
47
+ decision on its own — it returns a structured verdict (`VERIFIED` / `REVOKED` /
48
+ `UNVERIFIED` / `ERROR`) your server acts on. MIT licensed. Part of
49
+ [pdxlab/agentcert-tag](https://github.com/pdxlab/agentcert-tag).
@@ -0,0 +1,33 @@
1
+ # trustmodel-agentcert-tag
2
+
3
+ Verify an **AgentCert + TrustScore** inside a Python MCP server. Thin, dependency-free
4
+ client for a [TAG](https://trustmodel.ai/verify) verify endpoint — **off by default**,
5
+ **shadow mode** when on (logs, never blocks), safe to merge.
6
+
7
+ ```bash
8
+ pip install trustmodel-agentcert-tag
9
+ ```
10
+
11
+ ```python
12
+ from trustmodel_agentcert_tag import verify_gate, extract_token
13
+
14
+ guard = verify_gate(mode="shadow") # shadow | enforce
15
+
16
+ async def handle_tool_call(request):
17
+ token = extract_token(request.headers) # X-AgentCert-Token (or mTLS-derived)
18
+ await guard(token) # logs (shadow) / raises VerifyError (enforce)
19
+ return await dispatch(request)
20
+ ```
21
+
22
+ Enable per environment — nothing runs until you opt in:
23
+
24
+ | Env var | Meaning |
25
+ |---|---|
26
+ | `TRUSTMODEL_VERIFY=1` | turn the gate on (otherwise `guard` is a no-op) |
27
+ | `TRUSTMODEL_VERIFY_URL` | TAG verify endpoint (default `http://localhost:8080/verify`) |
28
+ | `TRUSTMODEL_MODE=enforce` | switch to enforcement |
29
+
30
+ The gate never reads request payloads (metadata only) and never makes the allow/deny
31
+ decision on its own — it returns a structured verdict (`VERIFIED` / `REVOKED` /
32
+ `UNVERIFIED` / `ERROR`) your server acts on. MIT licensed. Part of
33
+ [pdxlab/agentcert-tag](https://github.com/pdxlab/agentcert-tag).
@@ -0,0 +1,27 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "trustmodel-agentcert-tag"
7
+ version = "0.1.0"
8
+ description = "Verify an AgentCert + TrustScore inside a Python MCP server (shadow mode, opt-in, dependency-free)."
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.9"
12
+ authors = [{ name = "TrustModel.ai" }]
13
+ keywords = ["mcp", "agentcert", "trustscore", "verification", "ai-agents", "trustmodel"]
14
+ classifiers = [
15
+ "License :: OSI Approved :: MIT License",
16
+ "Programming Language :: Python :: 3",
17
+ "Intended Audience :: Developers",
18
+ ]
19
+ dependencies = []
20
+
21
+ [project.urls]
22
+ Homepage = "https://trustmodel.ai/verify"
23
+ Documentation = "https://trustmodel.ai/wiki/agentcert/verify-gateway"
24
+ Source = "https://github.com/pdxlab/agentcert-tag"
25
+
26
+ [tool.setuptools]
27
+ packages = ["trustmodel_agentcert_tag"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,133 @@
1
+ """trustmodel-agentcert-tag — verify an AgentCert + TrustScore inside a Python MCP server.
2
+
3
+ The verification decision itself is made by a TAG verify endpoint (a local sidecar or a
4
+ hosted endpoint); this package is a thin, dependency-free client + gate you drop in front
5
+ of your tool calls. It is a no-op unless verification is turned on, and defaults to shadow
6
+ mode (log, never block), so it is safe to merge.
7
+
8
+ Typical use inside an MCP server's tool-call path:
9
+
10
+ from trustmodel_agentcert_tag import verify_gate, extract_token
11
+
12
+ guard = verify_gate(mode="shadow") # shadow | enforce
13
+
14
+ async def handle_tool_call(request):
15
+ token = extract_token(request.headers) # X-AgentCert-Token or mTLS-derived
16
+ await guard(token) # logs (shadow) / raises (enforce) on bad verdict
17
+ return await dispatch(request)
18
+
19
+ Environment:
20
+ TRUSTMODEL_VERIFY=1 enable (otherwise verify_gate() is a no-op passthrough)
21
+ TRUSTMODEL_VERIFY_URL=... TAG verify endpoint (default http://localhost:8080/verify)
22
+ TRUSTMODEL_MODE=enforce override mode to enforce
23
+ """
24
+ from __future__ import annotations
25
+
26
+ import json
27
+ import logging
28
+ import os
29
+ import urllib.request
30
+ from typing import Awaitable, Callable, Iterable, Mapping, Optional
31
+
32
+ __version__ = "0.1.0"
33
+ __all__ = ["verify_gate", "verify", "extract_token", "VerificationResult", "VerifyError"]
34
+
35
+ log = logging.getLogger("agentcert-tag")
36
+
37
+ DEFAULT_HEADER = "x-agentcert-token"
38
+ DEFAULT_VERIFY_URL = "http://localhost:8080/verify"
39
+ DEFAULT_BLOCK_ON = ("REVOKED", "UNVERIFIED")
40
+
41
+
42
+ class VerificationResult(dict):
43
+ """Structured TAG result. Keys: verification_status, agent_id, cert_valid,
44
+ trust_score{value,tier}, detail."""
45
+
46
+ @property
47
+ def status(self) -> str:
48
+ return self.get("verification_status", "ERROR")
49
+
50
+ @property
51
+ def score(self):
52
+ return (self.get("trust_score") or {}).get("value")
53
+
54
+ @property
55
+ def tier(self) -> str:
56
+ return (self.get("trust_score") or {}).get("tier", "Unknown")
57
+
58
+
59
+ class VerifyError(Exception):
60
+ """Raised in enforce mode when a verdict is in block_on."""
61
+
62
+ def __init__(self, result: VerificationResult):
63
+ self.result = result
64
+ super().__init__(f"agentcert-tag blocked: {result.status} ({result.get('detail','')})")
65
+
66
+
67
+ def _enabled() -> bool:
68
+ return os.environ.get("TRUSTMODEL_VERIFY") == "1"
69
+
70
+
71
+ def verify(token: Optional[str], *, verify_url: Optional[str] = None, timeout: float = 3.0) -> VerificationResult:
72
+ """POST the presented credential to the TAG verify endpoint and return its result.
73
+ Never raises on transport error — returns an ERROR result so the caller's fail
74
+ policy decides."""
75
+ url = verify_url or os.environ.get("TRUSTMODEL_VERIFY_URL", DEFAULT_VERIFY_URL)
76
+ if not token:
77
+ return VerificationResult(verification_status="UNVERIFIED", cert_valid=False,
78
+ detail="no credential presented")
79
+ body = json.dumps({"credential": token}).encode()
80
+ req = urllib.request.Request(url, data=body, headers={"Content-Type": "application/json"})
81
+ try:
82
+ with urllib.request.urlopen(req, timeout=timeout) as r:
83
+ return VerificationResult(**json.loads(r.read().decode()))
84
+ except Exception as exc: # noqa: BLE001 - transport failures become an ERROR verdict
85
+ return VerificationResult(verification_status="ERROR", detail=f"verify unreachable: {exc}")
86
+
87
+
88
+ def extract_token(headers: Optional[Mapping[str, str]], header: str = DEFAULT_HEADER) -> Optional[str]:
89
+ """Case-insensitive lookup of the AgentCert credential header."""
90
+ if not headers:
91
+ return None
92
+ for k, v in headers.items():
93
+ if k.lower() == header.lower():
94
+ return v
95
+ return None
96
+
97
+
98
+ def verify_gate(
99
+ *,
100
+ mode: str = "shadow",
101
+ block_on: Iterable[str] = DEFAULT_BLOCK_ON,
102
+ verify_url: Optional[str] = None,
103
+ fail_mode: str = "closed",
104
+ on_result: Optional[Callable[[VerificationResult], None]] = None,
105
+ ) -> Callable[[Optional[str]], Awaitable[VerificationResult]]:
106
+ """Return an async guard(token) -> VerificationResult.
107
+
108
+ - Off entirely unless TRUSTMODEL_VERIFY=1 (guard returns immediately).
109
+ - shadow (default): logs the decision, never raises.
110
+ - enforce: raises VerifyError when the verdict is in block_on, or on ERROR when
111
+ fail_mode='closed'.
112
+ """
113
+ effective_mode = "enforce" if os.environ.get("TRUSTMODEL_MODE") == "enforce" else mode
114
+ block = set(block_on)
115
+
116
+ async def guard(token: Optional[str]) -> VerificationResult:
117
+ if not _enabled():
118
+ return VerificationResult(verification_status="DISABLED")
119
+ result = verify(token, verify_url=verify_url)
120
+ log.info("[agentcert-tag] mode=%s status=%s score=%s tier=%s",
121
+ effective_mode, result.status, result.score, result.tier)
122
+ if on_result:
123
+ try:
124
+ on_result(result)
125
+ except Exception: # noqa: BLE001 - a callback must never break the request
126
+ log.exception("[agentcert-tag] on_result callback failed")
127
+ if effective_mode == "enforce":
128
+ bad = result.status in block or (result.status == "ERROR" and fail_mode == "closed")
129
+ if bad:
130
+ raise VerifyError(result)
131
+ return result
132
+
133
+ return guard
@@ -0,0 +1,49 @@
1
+ Metadata-Version: 2.4
2
+ Name: trustmodel-agentcert-tag
3
+ Version: 0.1.0
4
+ Summary: Verify an AgentCert + TrustScore inside a Python MCP server (shadow mode, opt-in, dependency-free).
5
+ Author: TrustModel.ai
6
+ License: MIT
7
+ Project-URL: Homepage, https://trustmodel.ai/verify
8
+ Project-URL: Documentation, https://trustmodel.ai/wiki/agentcert/verify-gateway
9
+ Project-URL: Source, https://github.com/pdxlab/agentcert-tag
10
+ Keywords: mcp,agentcert,trustscore,verification,ai-agents,trustmodel
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Intended Audience :: Developers
14
+ Requires-Python: >=3.9
15
+ Description-Content-Type: text/markdown
16
+
17
+ # trustmodel-agentcert-tag
18
+
19
+ Verify an **AgentCert + TrustScore** inside a Python MCP server. Thin, dependency-free
20
+ client for a [TAG](https://trustmodel.ai/verify) verify endpoint — **off by default**,
21
+ **shadow mode** when on (logs, never blocks), safe to merge.
22
+
23
+ ```bash
24
+ pip install trustmodel-agentcert-tag
25
+ ```
26
+
27
+ ```python
28
+ from trustmodel_agentcert_tag import verify_gate, extract_token
29
+
30
+ guard = verify_gate(mode="shadow") # shadow | enforce
31
+
32
+ async def handle_tool_call(request):
33
+ token = extract_token(request.headers) # X-AgentCert-Token (or mTLS-derived)
34
+ await guard(token) # logs (shadow) / raises VerifyError (enforce)
35
+ return await dispatch(request)
36
+ ```
37
+
38
+ Enable per environment — nothing runs until you opt in:
39
+
40
+ | Env var | Meaning |
41
+ |---|---|
42
+ | `TRUSTMODEL_VERIFY=1` | turn the gate on (otherwise `guard` is a no-op) |
43
+ | `TRUSTMODEL_VERIFY_URL` | TAG verify endpoint (default `http://localhost:8080/verify`) |
44
+ | `TRUSTMODEL_MODE=enforce` | switch to enforcement |
45
+
46
+ The gate never reads request payloads (metadata only) and never makes the allow/deny
47
+ decision on its own — it returns a structured verdict (`VERIFIED` / `REVOKED` /
48
+ `UNVERIFIED` / `ERROR`) your server acts on. MIT licensed. Part of
49
+ [pdxlab/agentcert-tag](https://github.com/pdxlab/agentcert-tag).
@@ -0,0 +1,7 @@
1
+ README.md
2
+ pyproject.toml
3
+ trustmodel_agentcert_tag/__init__.py
4
+ trustmodel_agentcert_tag.egg-info/PKG-INFO
5
+ trustmodel_agentcert_tag.egg-info/SOURCES.txt
6
+ trustmodel_agentcert_tag.egg-info/dependency_links.txt
7
+ trustmodel_agentcert_tag.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ trustmodel_agentcert_tag