Skip to content

Commit 5e07c3e

Browse files
committed
Add MCP blast radius analyzer CLI
1 parent 9559992 commit 5e07c3e

6 files changed

Lines changed: 617 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
- Added `agentid mcp analyze` for scoring saved MCP `tools/list` output.
6+
- Added `agentid mcp diff` for detecting newly exposed tools and tool schema drift.
7+
- Added a sample MCP `tools/list` response for analyzer testing.
8+
39
## 0.1.2
410

511
- Added first-class just-in-time authorization support.

README.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,21 @@ agentid explain examples/provider-mcp-support-agent.yaml
135135
agentid risk-score examples/provider-mcp-support-agent.yaml
136136
agentid generate-policy examples/provider-mcp-support-agent.yaml --target opa
137137
agentid audit examples/sample-tool-log.json --manifest examples/customer-support-refund-agent.yaml
138+
agentid mcp analyze examples/mcp-tools-list-risky.json
139+
agentid mcp analyze examples/mcp-tools-list-risky.json --json
140+
agentid mcp diff old-tools-list.json new-tools-list.json
138141
agentid schema > schema/agentid.schema.json
139142
agentid config-ui --output agentid-policy-builder.html
140143
agentid gateway examples/provider-mcp-support-agent.yaml --host 127.0.0.1 --port 8787
141144
```
142145

143146
`config-ui` writes a self-contained browser UI for building an AgentID manifest and starter OPA policy.
144147

148+
`mcp analyze` scores a saved MCP `tools/list` response for tool capability
149+
risk, sensitive arguments, likely blast radius, and remediation steps. `mcp
150+
diff` compares two saved `tools/list` responses to detect newly exposed tools,
151+
schema changes, and increased tool risk.
152+
145153
The JSON Schema is available at [`schema/agentid.schema.json`](schema/agentid.schema.json)
146154
and can be emitted with `agentid schema`. Add this to a manifest for editor
147155
validation:
@@ -321,6 +329,8 @@ Implemented:
321329
- TypeScript gateway client helper
322330
- Reference MCP gateway adapter for `tools/list` and `tools/call`
323331
- MCP gateway adapter demo with mock provider server
332+
- MCP blast-radius analyzer CLI for saved `tools/list` output
333+
- MCP tool drift diff for newly exposed tools and schema changes
324334
- MCP gateway integration guide and enterprise/provider MCP example manifest
325335
- Hosted gateway-control demo with SaaS and MCP flows
326336
- CI checks for tests, schema validation, manifest risk, and TypeScript SDK
@@ -330,9 +340,8 @@ Next:
330340
- More ecommerce manifests and audit-log examples
331341
- MCP tool metadata import/export and tool drift detection for `tools/list`
332342
changes, schema changes, and newly exposed write/admin tools
333-
- MCP blast-radius analyzer for scoring tool capability risk, authorization
334-
posture, sensitive arguments, data-flow exposure, and remediation steps from
335-
saved `tools/list` output or live gateway metadata
343+
- MCP blast-radius analyzer improvements for authorization posture, data-flow
344+
exposure, manifest snippet generation, and live gateway metadata
336345
- Browser/local UI for MCP analysis with scorecards, tool tables, drift views,
337346
blast-radius summaries, remediation checklists, and generated AgentID
338347
manifest snippets

agentid/cli.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import argparse
4+
import json
45
import os
56
import sys
67

@@ -9,6 +10,15 @@
910
from agentid.explain import explain_manifest
1011
from agentid.gateway import serve
1112
from agentid.manifest import ManifestError, load_manifest, validate_manifest
13+
from agentid.mcp import (
14+
analysis_to_dict,
15+
analyze_tools,
16+
diff_to_dict,
17+
diff_tools,
18+
format_analysis,
19+
format_diff,
20+
load_tools_list,
21+
)
1222
from agentid.policy import generate_policy
1323
from agentid.risk import risk_label, risk_score
1424
from agentid.schema import schema_json
@@ -49,6 +59,16 @@ def main(argv: list[str] | None = None) -> int:
4959
audit_parser.add_argument("audit_log")
5060
audit_parser.add_argument("--manifest", required=True)
5161

62+
mcp_parser = subparsers.add_parser("mcp", help="Analyze MCP tool surfaces.")
63+
mcp_subparsers = mcp_parser.add_subparsers(dest="mcp_command", required=True)
64+
mcp_analyze_parser = mcp_subparsers.add_parser("analyze", help="Score an MCP tools/list response.")
65+
mcp_analyze_parser.add_argument("tools_list")
66+
mcp_analyze_parser.add_argument("--json", action="store_true", help="Print machine-readable JSON.")
67+
mcp_diff_parser = mcp_subparsers.add_parser("diff", help="Compare two MCP tools/list responses for drift.")
68+
mcp_diff_parser.add_argument("before")
69+
mcp_diff_parser.add_argument("after")
70+
mcp_diff_parser.add_argument("--json", action="store_true", help="Print machine-readable JSON.")
71+
5272
args = parser.parse_args(argv)
5373

5474
if args.command == "schema":
@@ -68,6 +88,26 @@ def main(argv: list[str] | None = None) -> int:
6888
return 2
6989
return 0
7090

91+
if args.command == "mcp":
92+
try:
93+
if args.mcp_command == "analyze":
94+
analysis = analyze_tools(load_tools_list(args.tools_list))
95+
if args.json:
96+
print(json.dumps(analysis_to_dict(analysis), indent=2))
97+
else:
98+
print(format_analysis(analysis), end="")
99+
return 0
100+
if args.mcp_command == "diff":
101+
diff = diff_tools(load_tools_list(args.before), load_tools_list(args.after))
102+
if args.json:
103+
print(json.dumps(diff_to_dict(diff), indent=2))
104+
else:
105+
print(format_diff(diff), end="")
106+
return 0
107+
except Exception as exc:
108+
print(f"ERROR: failed to analyze MCP tools: {exc}", file=sys.stderr)
109+
return 2
110+
71111
try:
72112
manifest = load_manifest(args.manifest)
73113
except ManifestError as exc:

0 commit comments

Comments
 (0)