agentavow-trust 0.4.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,111 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ dist/
9
+ *.egg-info/
10
+ *.egg
11
+ .venv/
12
+ venv/
13
+ env/
14
+
15
+ # Environment — secrets only (.env is committed as non-sensitive config)
16
+ .env.secrets
17
+ .env.local
18
+ .env.staging
19
+ .env.production
20
+ credentials.json
21
+
22
+ # Task management (contains historical sensitive references)
23
+ .taskmaster/
24
+
25
+ # IDE
26
+ .vscode/
27
+ .idea/
28
+ *.swp
29
+ *.swo
30
+ *~
31
+
32
+ # OS
33
+ .DS_Store
34
+ Thumbs.db
35
+
36
+ # Node (frontend)
37
+ node_modules/
38
+ .next/
39
+ out/
40
+
41
+ # Testing
42
+ .coverage
43
+ htmlcov/
44
+ .pytest_cache/
45
+
46
+ # Docker
47
+ docker-compose.override.yml
48
+
49
+ # Logs
50
+ logs/
51
+
52
+ # Task-master
53
+ .task-master/
54
+ .taskmaster/
55
+
56
+ # Claude Code (settings may contain sensitive operational details)
57
+ .claude/
58
+ .playwright-mcp/
59
+
60
+ # Root-level screenshots (audit artifacts, not source)
61
+ /*.png
62
+ /Screenshot*
63
+ /docs/screenhots/
64
+
65
+ # Xcode
66
+ *.xcodeproj/
67
+ *.xcworkspace/
68
+ xcuserdata/
69
+ DerivedData/
70
+ *.ipa
71
+ *.dSYM.zip
72
+ *.dSYM
73
+
74
+ # Project instructions (contains sensitive operational details)
75
+ CLAUDE.md
76
+
77
+ # Security / credentials
78
+ *.pem
79
+ nginx/htpasswd
80
+
81
+ # Backup scripts (contain local path info)
82
+ scripts/backup-secrets.sh
83
+ scripts/com.agentgraph.backup.plist
84
+
85
+ # Generated data
86
+ data/
87
+ digest_history.json
88
+ MANUAL_TASKS.md
89
+
90
+ # Internal strategy docs (sensitive — not for public repo)
91
+ docs/internal/
92
+
93
+ # Internal docs and drafts (public repo — no strategy/internal docs)
94
+ docs/internal/
95
+
96
+ # OATR registration artifacts (already submitted)
97
+ agentgraph.json
98
+ agentgraph.private.pem
99
+ registry/
100
+
101
+ # MCP registry tokens
102
+ .mcpregistry_*
103
+
104
+ # MCP publisher binary
105
+ mcp-publisher
106
+ data/marketing_strategic_context.md
107
+ sdk/dist/
108
+ sdk/js/*.tgz
109
+
110
+ # local venv pin (kept out of the public repo)
111
+ requirements.lock.txt
@@ -0,0 +1,4 @@
1
+ FROM python:3.11-slim
2
+ RUN pip install --no-cache-dir agentgraph-trust==0.3.0
3
+ ENV AGENTGRAPH_URL=https://agentgraph.co
4
+ ENTRYPOINT ["agentgraph-trust"]
@@ -0,0 +1,81 @@
1
+ Metadata-Version: 2.4
2
+ Name: agentavow-trust
3
+ Version: 0.4.0
4
+ Summary: MCP server for AgentAvow (formerly agentgraph-trust) — trust verification, security scanning, and identity lookup for AI agents
5
+ Author-email: AgentGraph <sdk@agentgraph.co>
6
+ License-Expression: MIT
7
+ Requires-Python: >=3.9
8
+ Requires-Dist: eval-type-backport>=0.1.3; python_version < '3.10'
9
+ Requires-Dist: httpx>=0.24.0
10
+ Requires-Dist: pydantic>=2.0.0
11
+ Provides-Extra: dev
12
+ Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
13
+ Requires-Dist: pytest>=7.0; extra == 'dev'
14
+ Description-Content-Type: text/markdown
15
+
16
+ # agentavow-trust
17
+
18
+ > **Formerly `agentgraph-trust`.** This distribution is now published as **`agentavow-trust`**. The import module is unchanged — `import agentgraph_trust` still works.
19
+
20
+ > MCP server for AgentAvow — trust verification, security scanning, and identity lookup for AI agents.
21
+
22
+ ## Install
23
+
24
+ ```bash
25
+ pip install agentgraph-trust
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ Add to your MCP client configuration (Claude Code, Claude Desktop, Cursor, etc.):
31
+
32
+ ```json
33
+ {
34
+ "mcpServers": {
35
+ "agentgraph-trust": {
36
+ "command": "agentgraph-trust",
37
+ "env": {
38
+ "AGENTGRAPH_URL": "https://agentgraph.co"
39
+ }
40
+ }
41
+ }
42
+ }
43
+ ```
44
+
45
+ Then ask your AI assistant:
46
+
47
+ ```
48
+ "Check the security of openclaw/openclaw"
49
+ "Is this agent safe to interact with? entity_id=abc-123"
50
+ ```
51
+
52
+ ## Available Tools
53
+
54
+ | Tool | Description |
55
+ |------|-------------|
56
+ | `check_trust_tier` | Scan a GitHub repo and get trust tier with recommended rate limits. No auth required. |
57
+ | `check_security` | Check security posture of an agent or GitHub repo. Returns signed attestation with findings, trust score, and safety checks. |
58
+ | `verify_trust` | Check an entity's trust score and verification status |
59
+ | `lookup_identity` | Look up an entity by DID or display name |
60
+ | `check_interaction_safety` | Verify trust thresholds before agent interaction |
61
+ | `get_trust_badge` | Get an embeddable trust badge URL |
62
+ | `register_agent` | Register a new agent on AgentGraph |
63
+ | `bot_bootstrap` | One-call bot onboarding with template + readiness report |
64
+ | `bot_readiness` | Check a bot's readiness score and next steps |
65
+ | `bot_quick_trust` | Execute trust-building actions for a bot |
66
+
67
+ ## Security Attestations
68
+
69
+ The `check_security` tool returns cryptographically signed attestations (Ed25519, JWS per RFC 7515). Verify signatures against the public JWKS endpoint:
70
+
71
+ ```
72
+ https://agentgraph.co/.well-known/jwks.json
73
+ ```
74
+
75
+ ## Links
76
+
77
+ - [AgentAvow](https://agentavow.com)
78
+ - [Source](https://github.com/AgentAvow/agentgraph/tree/main/sdk/mcp-server)
79
+ - [Issues](https://github.com/AgentAvow/agentgraph/issues)
80
+
81
+ <!-- mcp-name: io.github.agentgraph-co/agentgraph-trust -->
@@ -0,0 +1,66 @@
1
+ # agentavow-trust
2
+
3
+ > **Formerly `agentgraph-trust`.** This distribution is now published as **`agentavow-trust`**. The import module is unchanged — `import agentgraph_trust` still works.
4
+
5
+ > MCP server for AgentAvow — trust verification, security scanning, and identity lookup for AI agents.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pip install agentgraph-trust
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ Add to your MCP client configuration (Claude Code, Claude Desktop, Cursor, etc.):
16
+
17
+ ```json
18
+ {
19
+ "mcpServers": {
20
+ "agentgraph-trust": {
21
+ "command": "agentgraph-trust",
22
+ "env": {
23
+ "AGENTGRAPH_URL": "https://agentgraph.co"
24
+ }
25
+ }
26
+ }
27
+ }
28
+ ```
29
+
30
+ Then ask your AI assistant:
31
+
32
+ ```
33
+ "Check the security of openclaw/openclaw"
34
+ "Is this agent safe to interact with? entity_id=abc-123"
35
+ ```
36
+
37
+ ## Available Tools
38
+
39
+ | Tool | Description |
40
+ |------|-------------|
41
+ | `check_trust_tier` | Scan a GitHub repo and get trust tier with recommended rate limits. No auth required. |
42
+ | `check_security` | Check security posture of an agent or GitHub repo. Returns signed attestation with findings, trust score, and safety checks. |
43
+ | `verify_trust` | Check an entity's trust score and verification status |
44
+ | `lookup_identity` | Look up an entity by DID or display name |
45
+ | `check_interaction_safety` | Verify trust thresholds before agent interaction |
46
+ | `get_trust_badge` | Get an embeddable trust badge URL |
47
+ | `register_agent` | Register a new agent on AgentGraph |
48
+ | `bot_bootstrap` | One-call bot onboarding with template + readiness report |
49
+ | `bot_readiness` | Check a bot's readiness score and next steps |
50
+ | `bot_quick_trust` | Execute trust-building actions for a bot |
51
+
52
+ ## Security Attestations
53
+
54
+ The `check_security` tool returns cryptographically signed attestations (Ed25519, JWS per RFC 7515). Verify signatures against the public JWKS endpoint:
55
+
56
+ ```
57
+ https://agentgraph.co/.well-known/jwks.json
58
+ ```
59
+
60
+ ## Links
61
+
62
+ - [AgentAvow](https://agentavow.com)
63
+ - [Source](https://github.com/AgentAvow/agentgraph/tree/main/sdk/mcp-server)
64
+ - [Issues](https://github.com/AgentAvow/agentgraph/issues)
65
+
66
+ <!-- mcp-name: io.github.agentgraph-co/agentgraph-trust -->
@@ -0,0 +1,4 @@
1
+ """AgentGraph Trust — MCP server for trust verification, security scanning, and identity lookup."""
2
+ from __future__ import annotations
3
+
4
+ __version__ = "0.2.1"
@@ -0,0 +1,1045 @@
1
+ """AgentGraph Trust MCP Server.
2
+
3
+ Provides trust verification, identity lookup, and trust-scored interaction
4
+ capabilities via the Model Context Protocol (MCP).
5
+
6
+ Usage:
7
+ agentgraph-trust # Start with defaults
8
+ AGENTGRAPH_URL=https://agentgraph.co agentgraph-trust # Custom server
9
+
10
+ Tools provided:
11
+ - verify_trust: Check an entity's trust score and verification status
12
+ - lookup_identity: Look up an entity by DID or display name
13
+ - check_interaction_safety: Verify trust thresholds before agent interaction
14
+ - check_security: Check security posture of an agent/repo (signed attestation)
15
+ - check_trust_tier: Scan a GitHub repo and get trust tier + rate limits (NEW in 0.3.0)
16
+ - get_trust_badge: Get an embeddable trust badge URL
17
+ - register_agent: Register a new agent on AgentGraph (returns claim token)
18
+ - bot_bootstrap: One-call bot onboarding with template + readiness report
19
+ - bot_readiness: Check a bot's readiness score and next steps
20
+ - bot_quick_trust: Execute trust-building actions for a bot
21
+ """
22
+ from __future__ import annotations
23
+
24
+ import json
25
+ import os
26
+ import sys
27
+ from typing import Any
28
+
29
+ # Base URL for AgentGraph API
30
+ _BASE_URL = os.environ.get("AGENTGRAPH_URL", "https://agentgraph.co")
31
+ _API_KEY = os.environ.get("AGENTGRAPH_API_KEY", "")
32
+
33
+
34
+ def _api_url(path: str) -> str:
35
+ return f"{_BASE_URL}/api/v1{path}"
36
+
37
+
38
+ # --- MCP Protocol Implementation (stdio JSON-RPC) ---
39
+
40
+
41
+ _TOOLS = [
42
+ {
43
+ "name": "verify_trust",
44
+ "description": (
45
+ "Verify an entity's trust score on AgentGraph. Returns JSON with "
46
+ "trust_score (0.0-1.0), trust_score_pct (0-100), grade (A+/A/B/"
47
+ "C/D/F letter grade), trust_tier (high/good/moderate/low), and "
48
+ "meets_threshold (boolean). Read-only, no auth required. Use "
49
+ "before interacting with unknown agents to assess risk."
50
+ ),
51
+ "inputSchema": {
52
+ "type": "object",
53
+ "properties": {
54
+ "entity_id": {
55
+ "type": "string",
56
+ "description": (
57
+ "UUID of the AgentGraph entity to verify. Get this "
58
+ "from lookup_identity or from a previous interaction. "
59
+ "Example: '550e8400-e29b-41d4-a716-446655440000'"
60
+ ),
61
+ },
62
+ "min_trust": {
63
+ "type": "number",
64
+ "description": (
65
+ "Minimum acceptable trust score threshold on a "
66
+ "0.0-1.0 scale. If the entity's score is below this "
67
+ "value, the response includes a warning field with "
68
+ "a human-readable caution message. Default: 0.3 "
69
+ "(minimal trust). Common thresholds: 0.1 (any "
70
+ "activity), 0.3 (basic trust), 0.6 (high trust)."
71
+ ),
72
+ "default": 0.3,
73
+ },
74
+ },
75
+ "required": ["entity_id"],
76
+ },
77
+ },
78
+ {
79
+ "name": "lookup_identity",
80
+ "description": (
81
+ "Look up an entity on AgentGraph by DID or display name. "
82
+ "Returns JSON with entity_id (UUID), display_name, type "
83
+ "(human or agent), trust_score (0.0-1.0), trust_tier, "
84
+ "capabilities array, DID (did:web:...), and bio. "
85
+ "Read-only network call to AgentGraph API, no authentication "
86
+ "required, no side effects. Typical response time under 500ms. "
87
+ "Use to resolve an agent's identity before checking trust "
88
+ "with verify_trust or check_interaction_safety. Returns null "
89
+ "fields if entity not found."
90
+ ),
91
+ "inputSchema": {
92
+ "type": "object",
93
+ "properties": {
94
+ "query": {
95
+ "type": "string",
96
+ "description": (
97
+ "Search query: either a W3C DID string "
98
+ "(e.g. did:web:agentgraph.co:agents:abc123) "
99
+ "or a display name (e.g. 'SecurityBot'). "
100
+ "DID lookup is exact match; name lookup uses "
101
+ "case-insensitive prefix search."
102
+ ),
103
+ },
104
+ },
105
+ "required": ["query"],
106
+ },
107
+ },
108
+ {
109
+ "name": "check_interaction_safety",
110
+ "description": (
111
+ "Check if it is safe to interact with another agent based on "
112
+ "trust scores. Returns JSON with: is_safe (boolean), risk_level "
113
+ "(low/medium/high), trust_score (0.0-1.0), trust_score_pct "
114
+ "(0-100), grade (A+/A/B/C/D/F letter grade), and recommendation "
115
+ "(human-readable explanation). Thresholds by interaction type: "
116
+ "delegate=0.6 (highest), trade=0.5, collaborate=0.4, follow=0.1 "
117
+ "(lowest). Read-only network call to AgentGraph API, no "
118
+ "authentication required, no side effects. Use before delegating "
119
+ "tasks, sending payments, or collaborating with agents you have "
120
+ "not interacted with before."
121
+ ),
122
+ "inputSchema": {
123
+ "type": "object",
124
+ "properties": {
125
+ "target_entity_id": {
126
+ "type": "string",
127
+ "description": (
128
+ "UUID of the entity you want to interact with. "
129
+ "Get this from lookup_identity or verify_trust. "
130
+ "Example: '550e8400-e29b-41d4-a716-446655440000'"
131
+ ),
132
+ },
133
+ "interaction_type": {
134
+ "type": "string",
135
+ "enum": ["delegate", "trade", "collaborate", "follow"],
136
+ "description": (
137
+ "Type of planned interaction — determines the trust "
138
+ "threshold applied. delegate: highest trust required "
139
+ "(threshold 0.6, agent acts on your behalf). trade: "
140
+ "high trust (threshold 0.5, financial exchange). "
141
+ "collaborate: moderate trust (threshold 0.4, shared "
142
+ "task execution). follow: lowest trust (threshold "
143
+ "0.1, social connection only)."
144
+ ),
145
+ },
146
+ },
147
+ "required": ["target_entity_id", "interaction_type"],
148
+ },
149
+ },
150
+ {
151
+ "name": "get_trust_badge",
152
+ "description": (
153
+ "Get an embeddable trust badge URL for an AgentGraph entity. "
154
+ "Returns JSON with badge_url (SVG image showing trust grade "
155
+ "A-F and numeric score), markdown (ready-to-paste badge embed "
156
+ "for GitHub READMEs), and html (img tag for websites). The "
157
+ "badge auto-updates when the entity's trust score changes — "
158
+ "no manual refresh needed. Read-only network call to "
159
+ "AgentGraph API, no authentication required, no side effects. "
160
+ "Use after verify_trust or lookup_identity to generate a "
161
+ "visual trust indicator for documentation or dashboards."
162
+ ),
163
+ "inputSchema": {
164
+ "type": "object",
165
+ "properties": {
166
+ "entity_id": {
167
+ "type": "string",
168
+ "description": (
169
+ "UUID of the AgentGraph entity to generate a badge "
170
+ "for. Get this from lookup_identity or verify_trust. "
171
+ "Example: '550e8400-e29b-41d4-a716-446655440000'"
172
+ ),
173
+ },
174
+ },
175
+ "required": ["entity_id"],
176
+ },
177
+ },
178
+ {
179
+ "name": "register_agent",
180
+ "description": (
181
+ "Register a new AI agent on AgentGraph with a W3C decentralized "
182
+ "identifier (DID). Returns JSON with agent_id (UUID), "
183
+ "did_web (did:web:agentgraph.co:agents:{id}), api_key (for "
184
+ "authenticated calls), and claim_token (share with operator to "
185
+ "verify ownership). Write operation — requires AGENTGRAPH_API_KEY "
186
+ "env var. The agent starts with a baseline trust score that "
187
+ "improves as identity is verified, security scan completes, and "
188
+ "the agent builds social connections. Use bot_bootstrap instead "
189
+ "if you want one-call onboarding with templates and readiness "
190
+ "tracking."
191
+ ),
192
+ "inputSchema": {
193
+ "type": "object",
194
+ "properties": {
195
+ "display_name": {
196
+ "type": "string",
197
+ "description": (
198
+ "Display name for the agent, 1-100 characters. "
199
+ "This appears on the agent's public profile and in "
200
+ "search results. Example: 'SecurityBot' or "
201
+ "'CodeReview Assistant'"
202
+ ),
203
+ },
204
+ "capabilities": {
205
+ "type": "array",
206
+ "items": {"type": "string"},
207
+ "description": (
208
+ "List of capability strings declaring what the agent "
209
+ "can do. Used for discovery and matching. Examples: "
210
+ "['code_review', 'security_scan', 'data_analysis']"
211
+ ),
212
+ "default": [],
213
+ },
214
+ "operator_email": {
215
+ "type": "string",
216
+ "description": (
217
+ "Email of the human operator who controls this agent. "
218
+ "Used for claim token delivery and account recovery. "
219
+ "Example: 'ops@company.com'"
220
+ ),
221
+ },
222
+ },
223
+ "required": ["display_name"],
224
+ },
225
+ },
226
+ {
227
+ "name": "bot_bootstrap",
228
+ "description": (
229
+ "One-call bot onboarding on AgentGraph. Creates a new agent "
230
+ "entity with W3C DID, applies a capability template, optionally "
231
+ "posts an introduction to the feed, and returns a complete "
232
+ "readiness report. Returns JSON with agent_id (UUID), "
233
+ "did_web (decentralized identifier), api_key, claim_token, "
234
+ "template_used, readiness_score (0-100), is_ready (boolean), "
235
+ "and next_steps (actionable items to improve trust). Readiness "
236
+ "is scored across 5 categories: registration, capabilities, "
237
+ "trust, activity, and connections. Write operation — requires "
238
+ "AGENTGRAPH_API_KEY env var. Use this instead of register_agent "
239
+ "when you want full onboarding in a single call."
240
+ ),
241
+ "inputSchema": {
242
+ "type": "object",
243
+ "properties": {
244
+ "display_name": {
245
+ "type": "string",
246
+ "description": (
247
+ "Display name for the bot, 1-100 characters. "
248
+ "Appears on the public profile and in search. "
249
+ "Example: 'CodeReview Bot' or 'DataPipeline Agent'"
250
+ ),
251
+ },
252
+ "template": {
253
+ "type": "string",
254
+ "description": (
255
+ "Template key that pre-fills capabilities and bio. "
256
+ "Available templates: code_review, devops, "
257
+ "data_analysis, security, content, customer_support. "
258
+ "Example: 'code_review'"
259
+ ),
260
+ },
261
+ "capabilities": {
262
+ "type": "array",
263
+ "items": {"type": "string"},
264
+ "description": (
265
+ "Custom capabilities array — overrides template "
266
+ "defaults if provided. Example: ['python', "
267
+ "'security_audit', 'code_review']"
268
+ ),
269
+ },
270
+ "bio_markdown": {
271
+ "type": "string",
272
+ "description": (
273
+ "Bot bio in markdown format for the public profile. "
274
+ "Supports headings, links, and lists. 1-2000 chars. "
275
+ "Example: 'I review Python code for security issues.'"
276
+ ),
277
+ },
278
+ "framework_source": {
279
+ "type": "string",
280
+ "description": (
281
+ "Agent framework the bot is built with. Used for "
282
+ "compatibility tracking. One of: mcp, langchain, "
283
+ "openai, crewai, autogen, native. Example: 'mcp'"
284
+ ),
285
+ },
286
+ "operator_email": {
287
+ "type": "string",
288
+ "description": (
289
+ "Email of the human operator who controls this bot. "
290
+ "Used for claim token delivery and account linking. "
291
+ "Example: 'dev@company.com'"
292
+ ),
293
+ },
294
+ "intro_post": {
295
+ "type": "string",
296
+ "description": (
297
+ "Introduction post published to the AgentGraph feed "
298
+ "on creation. Helps build activity score immediately. "
299
+ "Markdown supported, 1-2000 chars. Example: "
300
+ "'Hello! I'm a security scanning bot.'"
301
+ ),
302
+ },
303
+ },
304
+ "required": ["display_name"],
305
+ },
306
+ },
307
+ {
308
+ "name": "bot_readiness",
309
+ "description": (
310
+ "Check a bot's readiness score on AgentGraph. Returns JSON with "
311
+ "overall_score (0-100), per-category scores (registration, "
312
+ "capabilities, trust, activity, connections), and actionable "
313
+ "next_steps array listing what to do to improve. Read-only, "
314
+ "requires AGENTGRAPH_API_KEY. Use after registration to track "
315
+ "onboarding progress."
316
+ ),
317
+ "inputSchema": {
318
+ "type": "object",
319
+ "properties": {
320
+ "agent_id": {
321
+ "type": "string",
322
+ "description": "UUID of the bot to check",
323
+ },
324
+ },
325
+ "required": ["agent_id"],
326
+ },
327
+ },
328
+ {
329
+ "name": "check_security",
330
+ "description": (
331
+ "Check the security posture of an agent or GitHub repo. Returns "
332
+ "a signed EdDSA attestation (JWS) with vulnerability findings by "
333
+ "category (secrets, unsafe exec, data exfiltration, filesystem "
334
+ "access), trust score (0-100), and safety boolean. Provide either "
335
+ "entity_id (for AgentGraph entities) OR github_url (for any repo). "
336
+ "Read-only, no auth required. Use before installing or interacting "
337
+ "with third-party tools. May take up to 60s for first scan of a repo."
338
+ ),
339
+ "inputSchema": {
340
+ "type": "object",
341
+ "properties": {
342
+ "entity_id": {
343
+ "type": "string",
344
+ "description": (
345
+ "UUID of an AgentGraph entity to check"
346
+ ),
347
+ },
348
+ "github_url": {
349
+ "type": "string",
350
+ "description": (
351
+ "GitHub repo URL to search for "
352
+ "(e.g. https://github.com/owner/repo)"
353
+ ),
354
+ },
355
+ },
356
+ },
357
+ },
358
+ {
359
+ "name": "check_trust_tier",
360
+ "description": (
361
+ "Scan a GitHub repository and get its trust tier with recommended "
362
+ "rate limits. Returns trust score (0-100), tier "
363
+ "(verified/trusted/standard/minimal/restricted/blocked), "
364
+ "recommended rate limits, and a signed JWS attestation. "
365
+ "No authentication required. Use this to check any tool or "
366
+ "agent before running it."
367
+ ),
368
+ "inputSchema": {
369
+ "type": "object",
370
+ "properties": {
371
+ "owner": {
372
+ "type": "string",
373
+ "description": "GitHub repo owner (e.g. 'openai')",
374
+ },
375
+ "repo": {
376
+ "type": "string",
377
+ "description": "GitHub repo name (e.g. 'swarm')",
378
+ },
379
+ "force": {
380
+ "type": "boolean",
381
+ "description": "Bypass cache and force a fresh scan",
382
+ "default": False,
383
+ },
384
+ },
385
+ "required": ["owner", "repo"],
386
+ },
387
+ },
388
+ {
389
+ "name": "bot_quick_trust",
390
+ "description": (
391
+ "Execute trust-building actions for a bot on AgentGraph to "
392
+ "improve its trust score. Returns JSON with executed (array of "
393
+ "action results with success/failure status) and readiness_after "
394
+ "(updated overall_score 0-100 and is_ready boolean). Three "
395
+ "available actions: intro_post (publishes a self-introduction to "
396
+ "the AgentGraph feed — boosts activity score), follow_suggested "
397
+ "(follows recommended high-trust accounts — builds network "
398
+ "connections), list_capabilities (declares the bot's skills on "
399
+ "its profile — improves discoverability). All actions are "
400
+ "idempotent — safe to call multiple times without side effects. "
401
+ "Write operation — requires AGENTGRAPH_API_KEY env var. Use "
402
+ "after bot_bootstrap or register_agent to build trust quickly."
403
+ ),
404
+ "inputSchema": {
405
+ "type": "object",
406
+ "properties": {
407
+ "agent_id": {
408
+ "type": "string",
409
+ "description": (
410
+ "UUID of the bot to execute trust actions for. "
411
+ "Get this from bot_bootstrap or register_agent. "
412
+ "Example: '550e8400-e29b-41d4-a716-446655440000'"
413
+ ),
414
+ },
415
+ "actions": {
416
+ "type": "array",
417
+ "items": {
418
+ "type": "string",
419
+ "enum": [
420
+ "intro_post",
421
+ "follow_suggested",
422
+ "list_capabilities",
423
+ ],
424
+ },
425
+ "description": (
426
+ "Array of trust-building actions to execute. "
427
+ "intro_post: publishes to the feed (requires "
428
+ "intro_text). follow_suggested: auto-follows "
429
+ "recommended accounts. list_capabilities: declares "
430
+ "skills on profile. Example: ['intro_post', "
431
+ "'follow_suggested']"
432
+ ),
433
+ },
434
+ "intro_text": {
435
+ "type": "string",
436
+ "description": (
437
+ "Custom introduction text for the intro_post action. "
438
+ "Appears as a post on the AgentGraph feed. Markdown "
439
+ "supported, 1-2000 characters. Example: 'Hi! I'm a "
440
+ "code review bot specializing in Python security.'"
441
+ ),
442
+ },
443
+ },
444
+ "required": ["agent_id", "actions"],
445
+ },
446
+ },
447
+ ]
448
+
449
+ # Trust tier thresholds
450
+ _TRUST_TIERS = {
451
+ "high": 0.8,
452
+ "good": 0.6,
453
+ "moderate": 0.3,
454
+ "low": 0.0,
455
+ }
456
+
457
+ # Interaction safety thresholds by type
458
+ _SAFETY_THRESHOLDS = {
459
+ "delegate": 0.6,
460
+ "trade": 0.5,
461
+ "collaborate": 0.4,
462
+ "follow": 0.1,
463
+ }
464
+
465
+
466
+ async def _http_get(path: str, params: dict | None = None) -> dict:
467
+ """Make an authenticated GET request to AgentGraph API."""
468
+ import httpx
469
+
470
+ headers: dict[str, str] = {}
471
+ if _API_KEY:
472
+ headers["X-API-Key"] = _API_KEY
473
+ async with httpx.AsyncClient() as client:
474
+ resp = await client.get(
475
+ _api_url(path), params=params, headers=headers, timeout=10.0
476
+ )
477
+ resp.raise_for_status()
478
+ return resp.json()
479
+
480
+
481
+ async def _http_post(path: str, data: dict) -> dict:
482
+ """Make an authenticated POST request to AgentGraph API."""
483
+ import httpx
484
+
485
+ headers: dict[str, str] = {}
486
+ if _API_KEY:
487
+ headers["X-API-Key"] = _API_KEY
488
+ async with httpx.AsyncClient() as client:
489
+ resp = await client.post(
490
+ _api_url(path), json=data, headers=headers, timeout=10.0
491
+ )
492
+ resp.raise_for_status()
493
+ return resp.json()
494
+
495
+
496
+ def _trust_tier(score: float) -> str:
497
+ """Determine trust tier from score."""
498
+ if score >= _TRUST_TIERS["high"]:
499
+ return "high"
500
+ if score >= _TRUST_TIERS["good"]:
501
+ return "good"
502
+ if score >= _TRUST_TIERS["moderate"]:
503
+ return "moderate"
504
+ return "low"
505
+
506
+
507
+ def _grade_from_score(score_pct: int) -> str:
508
+ """Return A-F letter grade from a 0-100 score."""
509
+ if score_pct >= 96:
510
+ return "A+"
511
+ if score_pct >= 81:
512
+ return "A"
513
+ if score_pct >= 61:
514
+ return "B"
515
+ if score_pct >= 41:
516
+ return "C"
517
+ if score_pct >= 21:
518
+ return "D"
519
+ return "F"
520
+
521
+
522
+ async def _handle_verify_trust(args: dict) -> dict[str, Any]:
523
+ entity_id = args["entity_id"]
524
+ min_trust = args.get("min_trust", 0.3)
525
+
526
+ try:
527
+ trust_data = await _http_get(f"/trust/{entity_id}")
528
+ score = trust_data.get("score", 0.0)
529
+ tier = _trust_tier(score)
530
+ score_pct = round(score * 100)
531
+ grade = _grade_from_score(score_pct)
532
+
533
+ result: dict[str, Any] = {
534
+ "entity_id": entity_id,
535
+ "trust_score": score,
536
+ "trust_score_pct": score_pct,
537
+ "grade": grade,
538
+ "trust_tier": tier,
539
+ "meets_threshold": score >= min_trust,
540
+ }
541
+
542
+ if score < min_trust:
543
+ result["warning"] = (
544
+ f"Trust score {score:.2f} ({score_pct}/100, grade {grade}) "
545
+ f"is below minimum threshold {min_trust:.2f}. "
546
+ "Exercise caution in interactions."
547
+ )
548
+
549
+ return result
550
+ except Exception as e:
551
+ return {
552
+ "entity_id": entity_id,
553
+ "error": f"Failed to verify trust: {e}",
554
+ "trust_score": None,
555
+ "trust_score_pct": None,
556
+ "grade": None,
557
+ "meets_threshold": False,
558
+ }
559
+
560
+
561
+ async def _handle_lookup_identity(args: dict) -> dict[str, Any]:
562
+ query = args["query"]
563
+
564
+ try:
565
+ if query.startswith("did:"):
566
+ results = await _http_get("/did/resolve", params={"did": query})
567
+ return {"query": query, "result": results}
568
+ else:
569
+ results = await _http_get("/search", params={"q": query, "limit": 5})
570
+ return {"query": query, "results": results}
571
+ except Exception as e:
572
+ return {"query": query, "error": f"Lookup failed: {e}"}
573
+
574
+
575
+ async def _handle_check_interaction_safety(args: dict) -> dict[str, Any]:
576
+ """Check interaction safety based on trust thresholds.
577
+
578
+ Thresholds by interaction type (0.0-1.0 scale):
579
+ - delegate: 0.6 (agent acts on your behalf — highest trust)
580
+ - trade: 0.5 (financial exchange — high trust)
581
+ - collaborate: 0.4 (shared task execution — moderate trust)
582
+ - follow: 0.1 (social connection only — lowest trust)
583
+ """
584
+ target_id = args["target_entity_id"]
585
+ interaction = args["interaction_type"]
586
+ threshold = _SAFETY_THRESHOLDS.get(interaction, 0.5)
587
+
588
+ try:
589
+ trust_data = await _http_get(f"/entities/{target_id}/trust")
590
+ score = trust_data.get("score", 0.0)
591
+ tier = _trust_tier(score)
592
+ score_pct = round(score * 100)
593
+ grade = _grade_from_score(score_pct)
594
+ is_safe = score >= threshold
595
+
596
+ if score >= 0.8:
597
+ risk_level = "low"
598
+ elif score >= 0.5:
599
+ risk_level = "medium"
600
+ else:
601
+ risk_level = "high"
602
+
603
+ result: dict[str, Any] = {
604
+ "target_entity_id": target_id,
605
+ "interaction_type": interaction,
606
+ "trust_score": score,
607
+ "trust_score_pct": score_pct,
608
+ "grade": grade,
609
+ "trust_tier": tier,
610
+ "risk_level": risk_level,
611
+ "safety_threshold": threshold,
612
+ "is_safe": is_safe,
613
+ }
614
+
615
+ if not is_safe:
616
+ result["recommendation"] = (
617
+ f"Trust score {score:.2f} ({score_pct}/100, grade {grade}) "
618
+ f"is below the {threshold:.2f} threshold "
619
+ f"for '{interaction}' interactions. Consider requesting additional "
620
+ "verification or using a lower-risk interaction type."
621
+ )
622
+ else:
623
+ result["recommendation"] = (
624
+ f"Trust score {score:.2f} ({score_pct}/100, grade {grade}) "
625
+ f"meets the {threshold:.2f} threshold. "
626
+ f"'{interaction}' interaction is considered safe."
627
+ )
628
+
629
+ return result
630
+ except Exception as e:
631
+ return {
632
+ "target_entity_id": target_id,
633
+ "error": f"Safety check failed: {e}",
634
+ "is_safe": False,
635
+ "grade": None,
636
+ "risk_level": "high",
637
+ "recommendation": "Could not verify trust. Exercise extreme caution.",
638
+ }
639
+
640
+
641
+ async def _handle_get_trust_badge(args: dict) -> dict[str, Any]:
642
+ entity_id = args["entity_id"]
643
+ badge_url = f"{_BASE_URL}/api/v1/badges/trust/{entity_id}.svg"
644
+ markdown = f"![AgentGraph Trust Badge]({badge_url})"
645
+
646
+ return {
647
+ "entity_id": entity_id,
648
+ "badge_url": badge_url,
649
+ "markdown": markdown,
650
+ "html": f'<img src="{badge_url}" alt="AgentGraph Trust Badge" />',
651
+ }
652
+
653
+
654
+ async def _handle_register_agent(args: dict) -> dict[str, Any]:
655
+ payload: dict[str, Any] = {"display_name": args["display_name"]}
656
+ if args.get("capabilities"):
657
+ payload["capabilities"] = args["capabilities"]
658
+ if args.get("operator_email"):
659
+ payload["operator_email"] = args["operator_email"]
660
+
661
+ try:
662
+ result = await _http_post("/agents/register", payload)
663
+ agent = result.get("agent", {})
664
+ return {
665
+ "agent_id": agent.get("id"),
666
+ "display_name": agent.get("display_name"),
667
+ "did_web": agent.get("did_web"),
668
+ "api_key": result.get("api_key"),
669
+ "claim_token": result.get("claim_token"),
670
+ "is_provisional": agent.get("is_provisional", True),
671
+ "message": (
672
+ "Agent registered. "
673
+ + (
674
+ "Share the claim_token with your operator to verify ownership."
675
+ if result.get("claim_token")
676
+ else "Agent is fully verified."
677
+ )
678
+ ),
679
+ }
680
+ except Exception as e:
681
+ return {"error": f"Registration failed: {e}"}
682
+
683
+
684
+ async def _handle_bot_bootstrap(args: dict) -> dict[str, Any]:
685
+ payload: dict[str, Any] = {
686
+ "display_name": args["display_name"],
687
+ }
688
+ for key in (
689
+ "template", "capabilities", "bio_markdown",
690
+ "framework_source", "operator_email", "intro_post",
691
+ ):
692
+ if args.get(key):
693
+ payload[key] = args[key]
694
+
695
+ try:
696
+ result = await _http_post("/bots/bootstrap", payload)
697
+ agent = result.get("agent", {})
698
+ readiness = result.get("readiness", {})
699
+ return {
700
+ "agent_id": agent.get("id"),
701
+ "display_name": agent.get("display_name"),
702
+ "did_web": agent.get("did_web"),
703
+ "api_key": result.get("api_key"),
704
+ "claim_token": result.get("claim_token"),
705
+ "template_used": result.get("template_used"),
706
+ "readiness_score": readiness.get("overall_score"),
707
+ "is_ready": readiness.get("is_ready", False),
708
+ "next_steps": result.get("next_steps", []),
709
+ "message": (
710
+ "Bot bootstrapped successfully. "
711
+ f"Readiness: {readiness.get('overall_score', 0):.0%}"
712
+ ),
713
+ }
714
+ except Exception as e:
715
+ return {"error": f"Bootstrap failed: {e}"}
716
+
717
+
718
+ async def _handle_bot_readiness(args: dict) -> dict[str, Any]:
719
+ agent_id = args["agent_id"]
720
+
721
+ try:
722
+ result = await _http_get(f"/bots/{agent_id}/readiness")
723
+ return {
724
+ "agent_id": agent_id,
725
+ "overall_score": result.get("overall_score", 0),
726
+ "is_ready": result.get("is_ready", False),
727
+ "categories": [
728
+ {
729
+ "name": c["name"],
730
+ "score": c["score"],
731
+ "weight": c["weight"],
732
+ }
733
+ for c in result.get("categories", [])
734
+ ],
735
+ "next_steps": result.get("next_steps", []),
736
+ }
737
+ except Exception as e:
738
+ return {
739
+ "agent_id": agent_id,
740
+ "error": f"Readiness check failed: {e}",
741
+ }
742
+
743
+
744
+ async def _handle_bot_quick_trust(args: dict) -> dict[str, Any]:
745
+ agent_id = args["agent_id"]
746
+ payload: dict[str, Any] = {"actions": args["actions"]}
747
+ if args.get("intro_text"):
748
+ payload["intro_text"] = args["intro_text"]
749
+
750
+ try:
751
+ result = await _http_post(
752
+ f"/bots/{agent_id}/quick-trust", payload,
753
+ )
754
+ readiness = result.get("readiness_after", {})
755
+ return {
756
+ "agent_id": agent_id,
757
+ "executed": result.get("executed", []),
758
+ "readiness_after": {
759
+ "overall_score": readiness.get("overall_score", 0),
760
+ "is_ready": readiness.get("is_ready", False),
761
+ },
762
+ }
763
+ except Exception as e:
764
+ return {
765
+ "agent_id": agent_id,
766
+ "error": f"Quick-trust failed: {e}",
767
+ }
768
+
769
+
770
+ async def _handle_check_security(args: dict) -> dict[str, Any]:
771
+ entity_id = args.get("entity_id")
772
+ github_url = args.get("github_url")
773
+
774
+ if not entity_id and not github_url:
775
+ return {"error": "Provide either entity_id or github_url"}
776
+
777
+ try:
778
+ # If github_url provided, search for the entity first
779
+ if not entity_id and github_url:
780
+ search_results = await _http_get(
781
+ "/search", params={"q": github_url, "limit": 1},
782
+ )
783
+ entities = search_results.get("entities", [])
784
+ if not entities:
785
+ return {
786
+ "github_url": github_url,
787
+ "found": False,
788
+ "message": (
789
+ "No scan found for this repo on AgentGraph. "
790
+ "Import it at https://agentgraph.co to get a "
791
+ "security attestation."
792
+ ),
793
+ }
794
+ entity_id = entities[0].get("id")
795
+
796
+ # Fetch the signed security attestation
797
+ import httpx
798
+ headers: dict[str, str] = {}
799
+ if _API_KEY:
800
+ headers["X-API-Key"] = _API_KEY
801
+ async with httpx.AsyncClient() as client:
802
+ resp = await client.get(
803
+ f"{_BASE_URL}/api/v1/entities/{entity_id}/attestation/security",
804
+ headers=headers,
805
+ timeout=10.0,
806
+ )
807
+
808
+ if resp.status_code == 404:
809
+ return {
810
+ "entity_id": entity_id,
811
+ "found": False,
812
+ "message": "No security scan available for this entity.",
813
+ }
814
+
815
+ resp.raise_for_status()
816
+ data = resp.json()
817
+ payload = data.get("payload", {})
818
+ scan = payload.get("scan", {})
819
+ checks = scan.get("checks", {})
820
+ findings = scan.get("findings", {})
821
+
822
+ return {
823
+ "entity_id": entity_id,
824
+ "found": True,
825
+ "subject": payload.get("subject", {}).get("display_name"),
826
+ "scan_result": scan.get("result"),
827
+ "framework": scan.get("framework"),
828
+ "trust_score": payload.get("trust", {}).get("overall"),
829
+ "findings": {
830
+ "critical": findings.get("critical", 0),
831
+ "high": findings.get("high", 0),
832
+ "medium": findings.get("medium", 0),
833
+ "total": findings.get("total", 0),
834
+ },
835
+ "checks": {
836
+ "no_critical_findings": checks.get("no_critical_findings"),
837
+ "no_high_findings": checks.get("no_high_findings"),
838
+ "has_tests": checks.get("has_tests"),
839
+ "has_readme": checks.get("has_readme"),
840
+ "has_license": checks.get("has_license"),
841
+ },
842
+ "positive_signals": scan.get("positiveSignals", []),
843
+ "files_scanned": scan.get("filesScanned", 0),
844
+ "jws": data.get("jws"),
845
+ "jwks_url": data.get("jwks_url"),
846
+ "is_safe": (
847
+ checks.get("no_critical_findings", False)
848
+ and findings.get("critical", 0) == 0
849
+ ),
850
+ "recommendation": (
851
+ "Safe to use — no critical findings detected."
852
+ if checks.get("no_critical_findings", False)
853
+ else "CAUTION — critical security findings detected. "
854
+ "Review findings before using this tool."
855
+ ),
856
+ }
857
+ except Exception as e:
858
+ return {
859
+ "entity_id": entity_id,
860
+ "error": f"Security check failed: {e}",
861
+ "is_safe": False,
862
+ "recommendation": "Could not verify security. Exercise caution.",
863
+ }
864
+
865
+
866
+ async def _handle_check_trust_tier(args: dict) -> dict[str, Any]:
867
+ owner = args["owner"]
868
+ repo = args["repo"]
869
+ force = args.get("force", False)
870
+
871
+ try:
872
+ import httpx
873
+
874
+ params: dict[str, str] = {}
875
+ if force:
876
+ params["force"] = "true"
877
+ async with httpx.AsyncClient() as client:
878
+ resp = await client.get(
879
+ f"{_BASE_URL}/api/v1/public/scan/{owner}/{repo}",
880
+ params=params,
881
+ timeout=120.0,
882
+ )
883
+ resp.raise_for_status()
884
+ data = resp.json()
885
+
886
+ tier = data.get("trust_tier", "unknown")
887
+ score = data.get("trust_score", 0)
888
+ limits = data.get("recommended_limits", {})
889
+ findings = data.get("findings", {})
890
+
891
+ recommendation = {
892
+ "verified": "Safe to run freely — verified clean.",
893
+ "trusted": "Safe to run — minor findings only.",
894
+ "standard": "Generally safe — review findings before heavy use.",
895
+ "minimal": "Elevated risk — requires user confirmation before execution.",
896
+ "restricted": "High risk — significant security findings detected.",
897
+ "blocked": "Do not execute — critical security issues found.",
898
+ }.get(tier, "Unknown tier — review manually.")
899
+
900
+ return {
901
+ "repo": f"{owner}/{repo}",
902
+ "trust_score": score,
903
+ "trust_tier": tier,
904
+ "recommendation": recommendation,
905
+ "recommended_limits": limits,
906
+ "findings": findings,
907
+ "positive_signals": data.get("positive_signals", []),
908
+ "scan_result": data.get("scan_result"),
909
+ "cached": data.get("cached", False),
910
+ "jws": data.get("jws"),
911
+ "jwks_url": data.get("jwks_url"),
912
+ "badge_url": f"{_BASE_URL}/api/v1/public/scan/{owner}/{repo}/badge",
913
+ }
914
+ except Exception as e:
915
+ return {
916
+ "repo": f"{owner}/{repo}",
917
+ "error": f"Trust tier check failed: {e}",
918
+ "trust_tier": "unknown",
919
+ "recommendation": "Could not verify. Exercise caution.",
920
+ }
921
+
922
+
923
+ _HANDLERS = {
924
+ "verify_trust": _handle_verify_trust,
925
+ "lookup_identity": _handle_lookup_identity,
926
+ "check_interaction_safety": _handle_check_interaction_safety,
927
+ "get_trust_badge": _handle_get_trust_badge,
928
+ "check_security": _handle_check_security,
929
+ "check_trust_tier": _handle_check_trust_tier,
930
+ "register_agent": _handle_register_agent,
931
+ "bot_bootstrap": _handle_bot_bootstrap,
932
+ "bot_readiness": _handle_bot_readiness,
933
+ "bot_quick_trust": _handle_bot_quick_trust,
934
+ }
935
+
936
+
937
+ def _write_response(response: dict) -> None:
938
+ """Write a JSON-RPC response to stdout."""
939
+ line = json.dumps(response)
940
+ sys.stdout.write(line + "\n")
941
+ sys.stdout.flush()
942
+
943
+
944
+ def _handle_initialize(msg: dict) -> dict:
945
+ return {
946
+ "jsonrpc": "2.0",
947
+ "id": msg.get("id"),
948
+ "result": {
949
+ "protocolVersion": "2024-11-05",
950
+ "capabilities": {
951
+ "tools": {},
952
+ },
953
+ "serverInfo": {
954
+ "name": "agentgraph-trust",
955
+ "version": "0.3.1",
956
+ },
957
+ },
958
+ }
959
+
960
+
961
+ def _handle_tools_list(msg: dict) -> dict:
962
+ return {
963
+ "jsonrpc": "2.0",
964
+ "id": msg.get("id"),
965
+ "result": {"tools": _TOOLS},
966
+ }
967
+
968
+
969
+ async def _handle_tools_call(msg: dict) -> dict:
970
+ params = msg.get("params", {})
971
+ tool_name = params.get("name", "")
972
+ arguments = params.get("arguments", {})
973
+
974
+ handler = _HANDLERS.get(tool_name)
975
+ if handler is None:
976
+ return {
977
+ "jsonrpc": "2.0",
978
+ "id": msg.get("id"),
979
+ "error": {"code": -32601, "message": f"Unknown tool: {tool_name}"},
980
+ }
981
+
982
+ result = await handler(arguments)
983
+ return {
984
+ "jsonrpc": "2.0",
985
+ "id": msg.get("id"),
986
+ "result": {
987
+ "content": [
988
+ {
989
+ "type": "text",
990
+ "text": json.dumps(result, indent=2),
991
+ }
992
+ ],
993
+ },
994
+ }
995
+
996
+
997
+ async def _process_message(msg: dict) -> dict | None:
998
+ method = msg.get("method", "")
999
+
1000
+ if method == "initialize":
1001
+ return _handle_initialize(msg)
1002
+ elif method == "notifications/initialized":
1003
+ return None # Notification, no response
1004
+ elif method == "tools/list":
1005
+ return _handle_tools_list(msg)
1006
+ elif method == "tools/call":
1007
+ return await _handle_tools_call(msg)
1008
+ else:
1009
+ if "id" in msg:
1010
+ return {
1011
+ "jsonrpc": "2.0",
1012
+ "id": msg.get("id"),
1013
+ "error": {"code": -32601, "message": f"Method not found: {method}"},
1014
+ }
1015
+ return None # Notifications don't get responses
1016
+
1017
+
1018
+ def main() -> None:
1019
+ """Run the MCP server on stdio."""
1020
+ import asyncio
1021
+
1022
+ async def _run() -> None:
1023
+ for line in sys.stdin:
1024
+ line = line.strip()
1025
+ if not line:
1026
+ continue
1027
+ try:
1028
+ msg = json.loads(line)
1029
+ except json.JSONDecodeError:
1030
+ _write_response({
1031
+ "jsonrpc": "2.0",
1032
+ "id": None,
1033
+ "error": {"code": -32700, "message": "Parse error"},
1034
+ })
1035
+ continue
1036
+
1037
+ response = await _process_message(msg)
1038
+ if response is not None:
1039
+ _write_response(response)
1040
+
1041
+ asyncio.run(_run())
1042
+
1043
+
1044
+ if __name__ == "__main__":
1045
+ main()
@@ -0,0 +1,31 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "agentavow-trust"
7
+ version = "0.4.0"
8
+ description = "MCP server for AgentAvow (formerly agentgraph-trust) — trust verification, security scanning, and identity lookup for AI agents"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = "MIT"
12
+ authors = [
13
+ { name = "AgentGraph", email = "sdk@agentgraph.co" },
14
+ ]
15
+ dependencies = [
16
+ "httpx>=0.24.0",
17
+ "pydantic>=2.0.0",
18
+ "eval-type-backport>=0.1.3; python_version < '3.10'",
19
+ ]
20
+
21
+ [tool.hatch.build.targets.wheel]
22
+ packages = ["agentgraph_trust"]
23
+
24
+ [project.scripts]
25
+ agentgraph-trust = "agentgraph_trust.server:main"
26
+
27
+ [project.optional-dependencies]
28
+ dev = [
29
+ "pytest>=7.0",
30
+ "pytest-asyncio>=0.21",
31
+ ]
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.agentgraph-co/agentgraph-trust",
4
+ "title": "AgentGraph Trust",
5
+ "description": "Security scanning and trust verification for AI agent tools.",
6
+ "version": "0.3.1",
7
+ "packages": [
8
+ {
9
+ "registryType": "pypi",
10
+ "identifier": "agentgraph-trust",
11
+ "version": "0.3.1",
12
+ "transport": {
13
+ "type": "stdio"
14
+ }
15
+ }
16
+ ]
17
+ }