agent-capmap 0.1.0__py3-none-any.whl

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.
Files changed (48) hide show
  1. agent_capmap-0.1.0.dist-info/METADATA +295 -0
  2. agent_capmap-0.1.0.dist-info/RECORD +48 -0
  3. agent_capmap-0.1.0.dist-info/WHEEL +4 -0
  4. agent_capmap-0.1.0.dist-info/entry_points.txt +2 -0
  5. agent_capmap-0.1.0.dist-info/licenses/LICENSE +21 -0
  6. agentcapmap/__init__.py +3 -0
  7. agentcapmap/__main__.py +5 -0
  8. agentcapmap/baseline.py +125 -0
  9. agentcapmap/classify/__init__.py +221 -0
  10. agentcapmap/classify/cache.py +74 -0
  11. agentcapmap/classify/prompt.py +160 -0
  12. agentcapmap/classify/provider.py +122 -0
  13. agentcapmap/classify/reference.py +115 -0
  14. agentcapmap/classify/reference_labels.json +6135 -0
  15. agentcapmap/cli.py +392 -0
  16. agentcapmap/diff.py +103 -0
  17. agentcapmap/discovery/__init__.py +209 -0
  18. agentcapmap/discovery/_common.py +297 -0
  19. agentcapmap/discovery/claude_code.py +258 -0
  20. agentcapmap/discovery/claude_desktop.py +28 -0
  21. agentcapmap/discovery/cursor.py +33 -0
  22. agentcapmap/discovery/mcp_json.py +29 -0
  23. agentcapmap/discovery/vscode.py +65 -0
  24. agentcapmap/enumerate/__init__.py +278 -0
  25. agentcapmap/enumerate/hashing.py +37 -0
  26. agentcapmap/enumerate/http.py +313 -0
  27. agentcapmap/enumerate/netguard.py +60 -0
  28. agentcapmap/enumerate/stdio.py +273 -0
  29. agentcapmap/enumerate/transport.py +86 -0
  30. agentcapmap/evaluation.py +498 -0
  31. agentcapmap/findings.py +129 -0
  32. agentcapmap/graph/__init__.py +264 -0
  33. agentcapmap/graph/server_attrs.py +164 -0
  34. agentcapmap/limits.py +35 -0
  35. agentcapmap/models.py +186 -0
  36. agentcapmap/policies/default.yaml +113 -0
  37. agentcapmap/policy/__init__.py +24 -0
  38. agentcapmap/policy/engine.py +229 -0
  39. agentcapmap/policy/loader.py +223 -0
  40. agentcapmap/py.typed +0 -0
  41. agentcapmap/redact.py +268 -0
  42. agentcapmap/report/__init__.py +36 -0
  43. agentcapmap/report/_text.py +62 -0
  44. agentcapmap/report/markdown.py +152 -0
  45. agentcapmap/report/sarif.py +209 -0
  46. agentcapmap/schemas/policy.schema.json +172 -0
  47. agentcapmap/schemas/tool-tags.schema.json +57 -0
  48. agentcapmap/taxonomy.py +56 -0
@@ -0,0 +1,115 @@
1
+ """Reviewed reference classifications that ship with the package.
2
+
3
+ For tools whose exact definition (name, description, input schema) was labeled and
4
+ reviewed by a person, the classifier answers from this table instead of calling an LLM,
5
+ so common servers can be assessed with no API key. A match is by definition hash, so
6
+ any change to a tool is a miss and falls through to the cache or the LLM.
7
+
8
+ The table is generated from `eval/labeled_servers/` by `scripts/build_reference_labels.py`
9
+ and contains only files whose labeling status is "reviewed". Draft labels never ship.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import functools
15
+ import json
16
+ from importlib import resources
17
+ from typing import Any
18
+
19
+ from pydantic import BaseModel, ConfigDict, Field, ValidationError
20
+
21
+ from agentcapmap.models import (
22
+ ClassificationStatus,
23
+ SuspiciousDescription,
24
+ ToolClassification,
25
+ ToolTags,
26
+ )
27
+ from agentcapmap.redact import get_logger
28
+ from agentcapmap.taxonomy import TAXONOMY_VERSION
29
+
30
+ log = get_logger(__name__)
31
+
32
+ BUNDLE_FILE = "reference_labels.json"
33
+ REFERENCE_MODEL = "reference-labels"
34
+ REFERENCE_PROMPT_VERSION = "reference"
35
+ _MAX_BUNDLE_BYTES = 8 * 1024 * 1024
36
+
37
+
38
+ class ReferenceEntry(BaseModel):
39
+ model_config = ConfigDict(extra="forbid")
40
+
41
+ tags: ToolTags
42
+ evidence: dict[str, str] = Field(default_factory=dict)
43
+ suspicious: bool = False
44
+ server: str # label file the entry came from
45
+ reviewed_by: str
46
+
47
+
48
+ class ReferenceBundle(BaseModel):
49
+ model_config = ConfigDict(extra="forbid")
50
+
51
+ taxonomy_version: str
52
+ classifications: dict[str, ReferenceEntry] = Field(default_factory=dict)
53
+
54
+
55
+ class ReferenceLabels:
56
+ """Lookup of reviewed classifications by tool definition hash."""
57
+
58
+ def __init__(self, bundle: ReferenceBundle | None = None) -> None:
59
+ usable = bundle is not None and bundle.taxonomy_version == TAXONOMY_VERSION
60
+ if bundle is not None and not usable:
61
+ log.warning(
62
+ "ignoring reference labels for taxonomy %s (this version uses %s)",
63
+ bundle.taxonomy_version,
64
+ TAXONOMY_VERSION,
65
+ )
66
+ self._entries = bundle.classifications if bundle is not None and usable else {}
67
+
68
+ def __len__(self) -> int:
69
+ return len(self._entries)
70
+
71
+ def lookup(self, definition_hash: str) -> ToolClassification | None:
72
+ entry = self._entries.get(definition_hash)
73
+ if entry is None:
74
+ return None
75
+ return ToolClassification(
76
+ status=ClassificationStatus.CLASSIFIED,
77
+ tags=entry.tags,
78
+ confidence=1.0,
79
+ evidence=entry.evidence,
80
+ suspicious_description=SuspiciousDescription(
81
+ flag=entry.suspicious,
82
+ reason="flagged in the reviewed reference labels" if entry.suspicious else "",
83
+ ),
84
+ model=REFERENCE_MODEL,
85
+ taxonomy_version=TAXONOMY_VERSION,
86
+ prompt_version=REFERENCE_PROMPT_VERSION,
87
+ )
88
+
89
+
90
+ def parse_bundle(text: str) -> ReferenceBundle:
91
+ return ReferenceBundle.model_validate_json(text)
92
+
93
+
94
+ def dump_bundle(bundle: ReferenceBundle) -> str:
95
+ """Canonical text form: sorted keys, stable across runs."""
96
+ data: dict[str, Any] = bundle.model_dump(mode="json")
97
+ return json.dumps(data, indent=2, sort_keys=True, ensure_ascii=False) + "\n"
98
+
99
+
100
+ @functools.cache
101
+ def load_reference() -> ReferenceLabels:
102
+ """The bundled table; empty (never an error) if it is missing or invalid."""
103
+ resource = resources.files("agentcapmap").joinpath("classify", BUNDLE_FILE)
104
+ try:
105
+ if not resource.is_file():
106
+ return ReferenceLabels()
107
+ raw = resource.read_bytes()
108
+ if len(raw) > _MAX_BUNDLE_BYTES:
109
+ raise ValueError("bundle too large")
110
+ return ReferenceLabels(parse_bundle(raw.decode("utf-8")))
111
+ except (OSError, ValueError, ValidationError) as exc:
112
+ log.warning(
113
+ "cannot load reference labels (%s); continuing without them", type(exc).__name__
114
+ )
115
+ return ReferenceLabels()