@aporthq/aport-agent-guardrails 1.0.8

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 (237) hide show
  1. package/LICENSE +217 -0
  2. package/README.md +481 -0
  3. package/bin/agent-guardrails +133 -0
  4. package/bin/aport-create-passport.sh +444 -0
  5. package/bin/aport-cursor-hook.sh +90 -0
  6. package/bin/aport-guardrail-api.sh +108 -0
  7. package/bin/aport-guardrail-bash.sh +394 -0
  8. package/bin/aport-guardrail-v2.sh +5 -0
  9. package/bin/aport-guardrail.sh +5 -0
  10. package/bin/aport-resolve-paths.sh +71 -0
  11. package/bin/aport-status.sh +276 -0
  12. package/bin/frameworks/crewai.sh +49 -0
  13. package/bin/frameworks/cursor.sh +95 -0
  14. package/bin/frameworks/langchain.sh +48 -0
  15. package/bin/frameworks/n8n.sh +36 -0
  16. package/bin/frameworks/openclaw.sh +19 -0
  17. package/bin/lib/allowlist.sh +18 -0
  18. package/bin/lib/common.sh +28 -0
  19. package/bin/lib/config.sh +46 -0
  20. package/bin/lib/constants.sh +232 -0
  21. package/bin/lib/detect.sh +65 -0
  22. package/bin/lib/error.sh +269 -0
  23. package/bin/lib/passport.sh +19 -0
  24. package/bin/lib/templates/.gitkeep +1 -0
  25. package/bin/lib/templates/config.yaml +6 -0
  26. package/bin/lib/validation.sh +206 -0
  27. package/bin/openclaw +660 -0
  28. package/docs/ADDING_A_FRAMEWORK.md +87 -0
  29. package/docs/AGENTS.md.example +40 -0
  30. package/docs/CODE_REVIEW.md +192 -0
  31. package/docs/DEPLOYMENT_READINESS.md +81 -0
  32. package/docs/FAQ_SECURITY_SCANNERS.md +373 -0
  33. package/docs/FRAMEWORK_ROADMAP.md +41 -0
  34. package/docs/HOSTED_PASSPORT_SETUP.md +362 -0
  35. package/docs/IMPLEMENTING_YOUR_OWN_EVALUATOR.md +433 -0
  36. package/docs/OPENCLAW_COMPATIBILITY.md +73 -0
  37. package/docs/OPENCLAW_LOCAL_INTEGRATION.md +596 -0
  38. package/docs/OPENCLAW_TOOLS_AND_POLICIES.md +54 -0
  39. package/docs/QUICKSTART.md +470 -0
  40. package/docs/QUICKSTART_OPENCLAW_PLUGIN.md +470 -0
  41. package/docs/README.md +28 -0
  42. package/docs/RELEASE.md +87 -0
  43. package/docs/REPO_LAYOUT.md +47 -0
  44. package/docs/SKILLS_ECOSYSTEM_ANALYSIS_FEB17.md +1260 -0
  45. package/docs/TOOL_POLICY_MAPPING.md +46 -0
  46. package/docs/UPGRADE.md +46 -0
  47. package/docs/VERIFICATION_METHODS.md +97 -0
  48. package/docs/assets/README.md +8 -0
  49. package/docs/assets/porter.svg +54 -0
  50. package/docs/development/ERROR_CODES.md +616 -0
  51. package/docs/frameworks/GITHUB_ISSUE_PROPOSALS.md +1105 -0
  52. package/docs/frameworks/crewai.md +114 -0
  53. package/docs/frameworks/cursor.md +159 -0
  54. package/docs/frameworks/langchain.md +72 -0
  55. package/docs/frameworks/n8n.md +40 -0
  56. package/docs/frameworks/openclaw.md +40 -0
  57. package/docs/launch/ADD_APORT_AWESOME_LISTS_INSTRUCTIONS.md +146 -0
  58. package/docs/launch/ANNOUNCEMENT_GUIDE.md +266 -0
  59. package/docs/launch/AWESOME_REPOS.md +53 -0
  60. package/docs/launch/CURSOR_VSCODE_HOOKS_RESEARCH.md +77 -0
  61. package/docs/launch/DEMO_TERMINAL_OUTPUT.txt +48 -0
  62. package/docs/launch/DRY_AND_PLAN_CHECKLIST.md +47 -0
  63. package/docs/launch/EVIDENCE_README.md +61 -0
  64. package/docs/launch/EVIDENCE_TERMINAL_CAPTURE.txt +10 -0
  65. package/docs/launch/FRAMEWORK_SUPPORT_PLAN.md +1640 -0
  66. package/docs/launch/LAUNCH_READINESS_CHECKLIST.md +237 -0
  67. package/docs/launch/LAUNCH_STRATEGY_SUMMARY.md +464 -0
  68. package/docs/launch/OPENCLAW_FEEDBACK_AND_FIXES.md +85 -0
  69. package/docs/launch/POST_1_VALENTINE_IMPROVED.md +233 -0
  70. package/docs/launch/POST_2_GUARDRAIL_IMPROVED.md +369 -0
  71. package/docs/launch/PRE_LAUNCH_FIXES.md +766 -0
  72. package/docs/launch/QUICK_LAUNCH_CHECKLIST.md +400 -0
  73. package/docs/launch/READINESS_SUMMARY.md +262 -0
  74. package/docs/launch/README.md +68 -0
  75. package/docs/launch/USER_STORIES.md +327 -0
  76. package/docs/launch/scripts/add-aport-awesome-pr.sh +69 -0
  77. package/docs/operations/MONITORING.md +588 -0
  78. package/docs/reviews/2026-02-18-staff-review.md +268 -0
  79. package/extensions/openclaw-aport/README.md +415 -0
  80. package/extensions/openclaw-aport/index.js +625 -0
  81. package/extensions/openclaw-aport/openclaw-aport.js +7 -0
  82. package/extensions/openclaw-aport/openclaw.plugin.json +46 -0
  83. package/extensions/openclaw-aport/package.json +36 -0
  84. package/extensions/openclaw-aport/test.js +307 -0
  85. package/external/aport-policies/README.md +363 -0
  86. package/external/aport-policies/agent.session.create.v1/README.md +345 -0
  87. package/external/aport-policies/agent.session.create.v1/policy.json +162 -0
  88. package/external/aport-policies/agent.tool.register.v1/README.md +361 -0
  89. package/external/aport-policies/agent.tool.register.v1/policy.json +172 -0
  90. package/external/aport-policies/code.release.publish.v1/README.md +51 -0
  91. package/external/aport-policies/code.release.publish.v1/policy.json +121 -0
  92. package/external/aport-policies/code.repository.merge.v1/README.md +287 -0
  93. package/external/aport-policies/code.repository.merge.v1/express.example.js +332 -0
  94. package/external/aport-policies/code.repository.merge.v1/fastapi.example.py +370 -0
  95. package/external/aport-policies/code.repository.merge.v1/policy.json +162 -0
  96. package/external/aport-policies/data.export.create.v1/README.md +226 -0
  97. package/external/aport-policies/data.export.create.v1/express.example.js +172 -0
  98. package/external/aport-policies/data.export.create.v1/fastapi.example.py +165 -0
  99. package/external/aport-policies/data.export.create.v1/policy.json +133 -0
  100. package/external/aport-policies/data.report.ingest.v1/README.md +134 -0
  101. package/external/aport-policies/data.report.ingest.v1/express.example.js +105 -0
  102. package/external/aport-policies/data.report.ingest.v1/minimal-example.js +68 -0
  103. package/external/aport-policies/data.report.ingest.v1/policy.json +174 -0
  104. package/external/aport-policies/finance.crypto.trade.v1/README.md +146 -0
  105. package/external/aport-policies/finance.crypto.trade.v1/express.example.js +109 -0
  106. package/external/aport-policies/finance.crypto.trade.v1/minimal-example.js +65 -0
  107. package/external/aport-policies/finance.crypto.trade.v1/policy.json +176 -0
  108. package/external/aport-policies/finance.payment.charge.v1/README.md +326 -0
  109. package/external/aport-policies/finance.payment.charge.v1/express.example.js +250 -0
  110. package/external/aport-policies/finance.payment.charge.v1/fastapi.example.py +227 -0
  111. package/external/aport-policies/finance.payment.charge.v1/minimal-example.js +64 -0
  112. package/external/aport-policies/finance.payment.charge.v1/policy.json +224 -0
  113. package/external/aport-policies/finance.payment.charge.v1/tests/contexts.jsonl +12 -0
  114. package/external/aport-policies/finance.payment.charge.v1/tests/expected.jsonl +12 -0
  115. package/external/aport-policies/finance.payment.charge.v1/tests/passport.instance.json +42 -0
  116. package/external/aport-policies/finance.payment.charge.v1/tests/passport.template.json +40 -0
  117. package/external/aport-policies/finance.payment.charge.v1/tests/payments-charge-policy.test.js +817 -0
  118. package/external/aport-policies/finance.payment.charge.v1/tests/test_payments_charge_policy.py +486 -0
  119. package/external/aport-policies/finance.payment.payout.v1/README.md +78 -0
  120. package/external/aport-policies/finance.payment.payout.v1/policy.json +181 -0
  121. package/external/aport-policies/finance.payment.refund.v1/README.md +275 -0
  122. package/external/aport-policies/finance.payment.refund.v1/express.example.js +167 -0
  123. package/external/aport-policies/finance.payment.refund.v1/fastapi.example.py +136 -0
  124. package/external/aport-policies/finance.payment.refund.v1/minimal-example.js +183 -0
  125. package/external/aport-policies/finance.payment.refund.v1/policy.json +216 -0
  126. package/external/aport-policies/finance.payment.refund.v1/tests/refunds-policy.test.js +924 -0
  127. package/external/aport-policies/finance.payment.refund.v1/tests/test_refunds_policy.py +778 -0
  128. package/external/aport-policies/finance.transaction.execute.v1/README.md +309 -0
  129. package/external/aport-policies/finance.transaction.execute.v1/express.example.js +261 -0
  130. package/external/aport-policies/finance.transaction.execute.v1/fastapi.example.py +231 -0
  131. package/external/aport-policies/finance.transaction.execute.v1/minimal-example.js +78 -0
  132. package/external/aport-policies/finance.transaction.execute.v1/policy.json +189 -0
  133. package/external/aport-policies/finance.transaction.execute.v1/tests/contexts.jsonl +12 -0
  134. package/external/aport-policies/finance.transaction.execute.v1/tests/expected.jsonl +12 -0
  135. package/external/aport-policies/finance.transaction.execute.v1/tests/passport.instance.json +42 -0
  136. package/external/aport-policies/finance.transaction.execute.v1/tests/passport.template.json +42 -0
  137. package/external/aport-policies/finance.transaction.execute.v1/tests/test_transactions_policy.py +214 -0
  138. package/external/aport-policies/finance.transaction.execute.v1/tests/transactions-policy.test.js +306 -0
  139. package/external/aport-policies/governance.data.access.v1/README.md +292 -0
  140. package/external/aport-policies/governance.data.access.v1/express.example.js +321 -0
  141. package/external/aport-policies/governance.data.access.v1/fastapi.example.py +279 -0
  142. package/external/aport-policies/governance.data.access.v1/minimal-example.js +65 -0
  143. package/external/aport-policies/governance.data.access.v1/policy.json +208 -0
  144. package/external/aport-policies/governance.data.access.v1/tests/contexts.jsonl +12 -0
  145. package/external/aport-policies/governance.data.access.v1/tests/data-access-policy.test.js +308 -0
  146. package/external/aport-policies/governance.data.access.v1/tests/expected.jsonl +12 -0
  147. package/external/aport-policies/governance.data.access.v1/tests/passport.instance.json +56 -0
  148. package/external/aport-policies/governance.data.access.v1/tests/passport.template.json +56 -0
  149. package/external/aport-policies/governance.data.access.v1/tests/test_data_access_policy.py +214 -0
  150. package/external/aport-policies/legal.contract.review.v1/README.md +109 -0
  151. package/external/aport-policies/legal.contract.review.v1/policy.json +378 -0
  152. package/external/aport-policies/legal.contract.review.v1/tests/legal-contract-review-policy.test.js +609 -0
  153. package/external/aport-policies/legal.contract.review.v1/tests/passport.template.json +49 -0
  154. package/external/aport-policies/mcp.tool.execute.v1/README.md +301 -0
  155. package/external/aport-policies/mcp.tool.execute.v1/policy.json +141 -0
  156. package/external/aport-policies/messaging.message.send.v1/README.md +230 -0
  157. package/external/aport-policies/messaging.message.send.v1/express.example.js +183 -0
  158. package/external/aport-policies/messaging.message.send.v1/fastapi.example.py +193 -0
  159. package/external/aport-policies/messaging.message.send.v1/policy.json +144 -0
  160. package/external/aport-policies/policy-template.json +107 -0
  161. package/external/aport-policies/system.command.execute.v1/README.md +275 -0
  162. package/external/aport-policies/system.command.execute.v1/policy.json +146 -0
  163. package/external/aport-spec/CONTRIBUTING.md +273 -0
  164. package/external/aport-spec/LICENSE +21 -0
  165. package/external/aport-spec/README.md +168 -0
  166. package/external/aport-spec/conformance/README.md +294 -0
  167. package/external/aport-spec/conformance/cases/data.export.v1/contexts/allow_users.json +6 -0
  168. package/external/aport-spec/conformance/cases/data.export.v1/contexts/deny_pii.json +6 -0
  169. package/external/aport-spec/conformance/cases/data.export.v1/expected/allow_users.decision.json +19 -0
  170. package/external/aport-spec/conformance/cases/data.export.v1/expected/deny_pii.decision.json +19 -0
  171. package/external/aport-spec/conformance/cases/data.export.v1/passports/template.json +29 -0
  172. package/external/aport-spec/conformance/cases/payments.refunds.v1/contexts/allow_50usd.json +9 -0
  173. package/external/aport-spec/conformance/cases/payments.refunds.v1/contexts/deny_150usd.json +9 -0
  174. package/external/aport-spec/conformance/cases/payments.refunds.v1/contexts/deny_currency.json +9 -0
  175. package/external/aport-spec/conformance/cases/payments.refunds.v1/expected/allow_50usd.decision.json +19 -0
  176. package/external/aport-spec/conformance/cases/payments.refunds.v1/expected/deny_150usd.decision.json +19 -0
  177. package/external/aport-spec/conformance/cases/payments.refunds.v1/expected/deny_currency.decision.json +19 -0
  178. package/external/aport-spec/conformance/cases/payments.refunds.v1/passports/template.json +42 -0
  179. package/external/aport-spec/conformance/package.json +44 -0
  180. package/external/aport-spec/conformance/pnpm-lock.yaml +642 -0
  181. package/external/aport-spec/conformance/src/cases.ts +371 -0
  182. package/external/aport-spec/conformance/src/ed25519.ts +167 -0
  183. package/external/aport-spec/conformance/src/jcs.ts +85 -0
  184. package/external/aport-spec/conformance/src/runner.ts +533 -0
  185. package/external/aport-spec/conformance/src/validators.ts +185 -0
  186. package/external/aport-spec/conformance/test-runner.js +315 -0
  187. package/external/aport-spec/conformance/tsconfig.json +21 -0
  188. package/external/aport-spec/error-schema.json +192 -0
  189. package/external/aport-spec/index.json +12 -0
  190. package/external/aport-spec/integrations/clawmoat/README.md +12 -0
  191. package/external/aport-spec/integrations/shield/README.md +245 -0
  192. package/external/aport-spec/integrations/shield/adapters/index.js +116 -0
  193. package/external/aport-spec/integrations/shield/adapters/system-command-execute.js +133 -0
  194. package/external/aport-spec/integrations/shield/test/README.md +58 -0
  195. package/external/aport-spec/integrations/shield/test/shield.md +40 -0
  196. package/external/aport-spec/integrations/shield/test/test-shield-to-verify.js +274 -0
  197. package/external/aport-spec/metrics-schema.json +504 -0
  198. package/external/aport-spec/oap/CHANGELOG.md +54 -0
  199. package/external/aport-spec/oap/VERSION.md +40 -0
  200. package/external/aport-spec/oap/capability-registry.md +229 -0
  201. package/external/aport-spec/oap/conformance.md +257 -0
  202. package/external/aport-spec/oap/decision-schema.json +114 -0
  203. package/external/aport-spec/oap/examples/context.refund.usd.50.json +9 -0
  204. package/external/aport-spec/oap/examples/decision.allow.sample.json +20 -0
  205. package/external/aport-spec/oap/examples/decision.deny.sample.json +23 -0
  206. package/external/aport-spec/oap/examples/passport.instance.v1.json +50 -0
  207. package/external/aport-spec/oap/examples/passport.template.v1.json +71 -0
  208. package/external/aport-spec/oap/oap-spec.md +426 -0
  209. package/external/aport-spec/oap/passport-schema.json +396 -0
  210. package/external/aport-spec/oap/security.md +213 -0
  211. package/external/aport-spec/oap/vc/context-oap-v1.jsonld +137 -0
  212. package/external/aport-spec/oap/vc/examples/oap-decision-vc.json +37 -0
  213. package/external/aport-spec/oap/vc/examples/oap-passport-vc.json +68 -0
  214. package/external/aport-spec/oap/vc/tools/INTEGRATION.md +375 -0
  215. package/external/aport-spec/oap/vc/tools/README.md +278 -0
  216. package/external/aport-spec/oap/vc/tools/examples/decision-to-vc.js +66 -0
  217. package/external/aport-spec/oap/vc/tools/examples/passport-to-vc.js +83 -0
  218. package/external/aport-spec/oap/vc/tools/examples/vc-to-decision.js +77 -0
  219. package/external/aport-spec/oap/vc/tools/examples/vc-to-passport.js +94 -0
  220. package/external/aport-spec/oap/vc/tools/package.json +38 -0
  221. package/external/aport-spec/oap/vc/tools/pnpm-lock.yaml +472 -0
  222. package/external/aport-spec/oap/vc/tools/src/cli.ts +226 -0
  223. package/external/aport-spec/oap/vc/tools/src/crypto-utils.ts +427 -0
  224. package/external/aport-spec/oap/vc/tools/src/index.ts +653 -0
  225. package/external/aport-spec/oap/vc/tools/src/test.ts +148 -0
  226. package/external/aport-spec/oap/vc/tools/src/vp.ts +382 -0
  227. package/external/aport-spec/oap/vc/tools/test-simple.js +214 -0
  228. package/external/aport-spec/oap/vc/tools/tsconfig.json +19 -0
  229. package/external/aport-spec/oap/vc/vc-mapping.md +443 -0
  230. package/external/aport-spec/passport-schema.json +586 -0
  231. package/external/aport-spec/rate-limiting.md +136 -0
  232. package/external/aport-spec/transport-profile.md +325 -0
  233. package/external/aport-spec/webhook-spec.md +314 -0
  234. package/package.json +70 -0
  235. package/skills/aport-agent-guardrail/SKILL.md +314 -0
  236. package/src/evaluator.js +252 -0
  237. package/src/server/index.js +72 -0
@@ -0,0 +1,301 @@
1
+ # MCP Tool Execution Policy v1
2
+
3
+ **Policy ID:** `mcp.tool.execute.v1`
4
+ **Status:** Active
5
+ **Min Assurance:** L1
6
+
7
+ ## Overview
8
+
9
+ The MCP Tool Execution Policy provides pre-action governance for Model Context Protocol (MCP) tool execution by AI agents. This policy enforces server allowlists, tool restrictions, parameter validation, and rate limits to ensure secure MCP integration.
10
+
11
+ ## Use Cases
12
+
13
+ - **Multi-Tool AI Agents**: Executing tools across multiple MCP servers
14
+ - **GitHub Integration**: Using GitHub MCP tools (pull requests, issues, etc.)
15
+ - **Database Operations**: Executing database queries via MCP
16
+ - **API Integration**: Calling external APIs through MCP tools
17
+ - **Development Workflows**: Automating development tasks with MCP
18
+
19
+ ## Required Capabilities
20
+
21
+ - `mcp.tool.execute`
22
+
23
+ ## Required Limits
24
+
25
+ - `allowed_servers` (array of strings): Allowlist of MCP server URLs
26
+ - `max_calls_per_minute` (integer): Maximum tool calls per minute
27
+
28
+ ## Optional Limits
29
+
30
+ - `allowed_tools` (array of strings): Specific tools allowed
31
+ - `allowed_tool_prefixes` (array of strings): Tool name prefixes allowed
32
+ - `blocked_tools` (array of strings): Specific tools blocked
33
+ - `max_timeout` (integer): Maximum tool execution timeout
34
+ - `max_parameter_size` (integer): Maximum parameter size in bytes
35
+ - `require_session_tracking` (boolean): Require session IDs for all calls
36
+
37
+ ## Context Schema
38
+
39
+ ### Required Fields
40
+
41
+ - `server` (string): MCP server URL
42
+ - `tool` (string): MCP tool name
43
+ - `parameters` (object): Tool-specific parameters
44
+
45
+ ### Optional Fields
46
+
47
+ - `session_id` (string): MCP session identifier
48
+ - `timeout` (integer): Tool execution timeout
49
+ - `context` (object): Additional context
50
+ - `user_id` (string): User on whose behalf tool is executed
51
+ - `mcp_servers`, `mcp_tools`, `mcp_session`: Audit trail fields
52
+
53
+ ## Evaluation Rules
54
+
55
+ 1. **passport_status_active**: Passport must be active
56
+ 2. **mcp_capability**: Agent must have `mcp.tool.execute` capability
57
+ 3. **server_allowlist**: MCP server must be in allowed list
58
+ 4. **tool_allowlist**: Tool must be allowed (exact match or prefix match)
59
+ 5. **rate_limit**: Calls per minute must not exceed limit
60
+ 6. **timeout_limit**: Timeout must not exceed maximum
61
+ 7. **parameter_size_limit**: Parameters must not exceed size limit
62
+
63
+ ## Example Passport Limits
64
+
65
+ ```json
66
+ {
67
+ "limits": {
68
+ "mcp.tool.execute": {
69
+ "allowed_servers": [
70
+ "https://mcp.github.com",
71
+ "https://mcp.stripe.com",
72
+ "https://mcp.internal.company.com"
73
+ ],
74
+ "allowed_tools": [
75
+ "github.pull_requests.create",
76
+ "github.pull_requests.merge",
77
+ "github.issues.create",
78
+ "stripe.customers.create",
79
+ "stripe.charges.create"
80
+ ],
81
+ "allowed_tool_prefixes": [
82
+ "github.pull_requests.",
83
+ "github.issues.",
84
+ "stripe.customers."
85
+ ],
86
+ "blocked_tools": [
87
+ "github.repos.delete",
88
+ "stripe.subscriptions.cancel"
89
+ ],
90
+ "max_calls_per_minute": 60,
91
+ "max_timeout": 120,
92
+ "max_parameter_size": 102400,
93
+ "require_session_tracking": true
94
+ }
95
+ }
96
+ }
97
+ ```
98
+
99
+ ## Example Request Context
100
+
101
+ ```json
102
+ {
103
+ "server": "https://mcp.github.com",
104
+ "tool": "github.pull_requests.create",
105
+ "parameters": {
106
+ "owner": "myorg",
107
+ "repo": "myrepo",
108
+ "title": "Add new feature",
109
+ "head": "feature-branch",
110
+ "base": "main",
111
+ "body": "This PR adds a new feature"
112
+ },
113
+ "session_id": "sess_abc123",
114
+ "timeout": 60,
115
+ "user_id": "user_xyz789"
116
+ }
117
+ ```
118
+
119
+ ## Example Decision (Allow)
120
+
121
+ ```json
122
+ {
123
+ "decision_id": "dec_mcp001",
124
+ "policy_id": "mcp.tool.execute.v1",
125
+ "passport_id": "pass_abc123",
126
+ "owner_id": "org_12345",
127
+ "assurance_level": "L1",
128
+ "allow": true,
129
+ "reasons": [{
130
+ "code": "oap.allowed",
131
+ "message": "All policy checks passed"
132
+ }],
133
+ "issued_at": "2026-02-14T22:00:00Z",
134
+ "expires_at": "2026-02-14T22:00:30Z",
135
+ "passport_digest": "sha256:...",
136
+ "signature": "ed25519:...",
137
+ "kid": "oap:registry:key-2026-02"
138
+ }
139
+ ```
140
+
141
+ ## Example Decision (Deny - Tool Not Allowed)
142
+
143
+ ```json
144
+ {
145
+ "decision_id": "dec_mcp002",
146
+ "policy_id": "mcp.tool.execute.v1",
147
+ "passport_id": "pass_abc123",
148
+ "owner_id": "org_12345",
149
+ "assurance_level": "L1",
150
+ "allow": false,
151
+ "reasons": [{
152
+ "code": "oap.tool_not_allowed",
153
+ "message": "MCP tool 'github.repos.delete' is not in allowed list"
154
+ }],
155
+ "issued_at": "2026-02-14T22:00:00Z",
156
+ "expires_at": "2026-02-14T22:00:30Z",
157
+ "passport_digest": "sha256:...",
158
+ "signature": "ed25519:...",
159
+ "kid": "oap:registry:key-2026-02"
160
+ }
161
+ ```
162
+
163
+ ## Security Best Practices
164
+
165
+ 1. **Server Allowlist**: Only allow trusted MCP servers
166
+ 2. **Tool Restrictions**: Use granular tool permissions (not wildcards)
167
+ 3. **Rate Limiting**: Prevent abuse with conservative rate limits
168
+ 4. **Session Tracking**: Require session IDs for audit trails
169
+ 5. **Parameter Validation**: Enforce parameter size limits
170
+ 6. **Tool Prefixes**: Use prefixes for tool families (e.g., "github.pull_requests.")
171
+ 7. **Block Dangerous Tools**: Explicitly block destructive operations
172
+ 8. **Progressive Limits**: Start strict and relax based on behavior
173
+ 9. **Status Webhooks**: Subscribe for instant revocation
174
+ 10. **Audit Logging**: Log all MCP tool calls with parameters
175
+
176
+ ## Error Codes
177
+
178
+ - `oap.passport_suspended`: Passport is not active
179
+ - `oap.unknown_capability`: Missing mcp.tool.execute capability
180
+ - `oap.server_not_allowed`: MCP server not in allowlist
181
+ - `oap.tool_not_allowed`: Tool not in allowlist
182
+ - `oap.rate_limit_exceeded`: Too many calls per minute
183
+ - `oap.timeout_exceeded`: Timeout exceeds maximum
184
+ - `oap.parameter_size_exceeded`: Parameters too large
185
+
186
+ ## Integration Examples
187
+
188
+ ### TypeScript (MCP Client)
189
+
190
+ ```typescript
191
+ import { MCPClient } from '@modelcontextprotocol/client';
192
+ import axios from 'axios';
193
+
194
+ async function executeMCPTool(
195
+ passport: Passport,
196
+ server: string,
197
+ tool: string,
198
+ parameters: Record<string, any>
199
+ ) {
200
+ const context = {
201
+ server,
202
+ tool,
203
+ parameters,
204
+ session_id: generateSessionId(),
205
+ timeout: 60
206
+ };
207
+
208
+ // Check policy
209
+ const decision = await axios.post('https://api.aport.io/v1/decide', {
210
+ passport_id: passport.passport_id,
211
+ policy_id: 'mcp.tool.execute.v1',
212
+ context
213
+ });
214
+
215
+ if (!decision.data.allow) {
216
+ throw new Error(`MCP tool blocked: ${decision.data.reasons[0].message}`);
217
+ }
218
+
219
+ // Execute MCP tool
220
+ const client = new MCPClient(server);
221
+ const result = await client.callTool(tool, parameters, {
222
+ timeout: context.timeout * 1000
223
+ });
224
+
225
+ return result;
226
+ }
227
+ ```
228
+
229
+ ### Python (MCP Integration)
230
+
231
+ ```python
232
+ import httpx
233
+ from mcp_client import MCPClient
234
+
235
+ async def execute_mcp_tool(
236
+ passport: dict,
237
+ server: str,
238
+ tool: str,
239
+ parameters: dict
240
+ ):
241
+ context = {
242
+ "server": server,
243
+ "tool": tool,
244
+ "parameters": parameters,
245
+ "session_id": generate_session_id(),
246
+ "timeout": 60
247
+ }
248
+
249
+ # Check policy
250
+ async with httpx.AsyncClient() as client:
251
+ response = await client.post(
252
+ "https://api.aport.io/v1/decide",
253
+ json={
254
+ "passport_id": passport["passport_id"],
255
+ "policy_id": "mcp.tool.execute.v1",
256
+ "context": context
257
+ }
258
+ )
259
+ decision = response.json()
260
+
261
+ if not decision["allow"]:
262
+ raise PermissionError(f"MCP tool blocked: {decision['reasons'][0]['message']}")
263
+
264
+ # Execute MCP tool
265
+ mcp_client = MCPClient(server)
266
+ result = await mcp_client.call_tool(
267
+ tool,
268
+ parameters,
269
+ timeout=context["timeout"]
270
+ )
271
+
272
+ return result
273
+ ```
274
+
275
+ ## MCP Tool Name Conventions
276
+
277
+ MCP tools follow the convention: `<service>.<resource>.<action>`
278
+
279
+ Examples:
280
+ - `github.pull_requests.create`
281
+ - `github.pull_requests.merge`
282
+ - `github.issues.create`
283
+ - `stripe.customers.create`
284
+ - `stripe.charges.refund`
285
+ - `database.queries.execute`
286
+ - `api.endpoints.call`
287
+
288
+ Use `allowed_tool_prefixes` for tool families:
289
+ - `github.pull_requests.*` → All PR operations
290
+ - `github.issues.*` → All issue operations
291
+ - `stripe.customers.*` → All customer operations
292
+
293
+ ## Version History
294
+
295
+ - **v1.0.0** (2026-02-14): Initial release
296
+
297
+ ## References
298
+
299
+ - [Model Context Protocol Specification](https://modelcontextprotocol.io)
300
+ - [OAP Specification](https://github.com/aporthq/aport-spec)
301
+ - [MCP Tool Registry](https://mcp.tools)
@@ -0,0 +1,141 @@
1
+ {
2
+ "id": "mcp.tool.execute.v1",
3
+ "name": "MCP Tool Execution Policy",
4
+ "description": "Pre-action governance for Model Context Protocol (MCP) tool execution. Enforces server allowlists, tool restrictions, parameter validation, and rate limits for secure MCP integration.",
5
+ "version": "1.0.0",
6
+ "status": "active",
7
+ "requires_capabilities": ["mcp.tool.execute"],
8
+ "min_assurance": "L0",
9
+ "limits_required": ["allowed_servers", "max_calls_per_minute"],
10
+ "required_fields": ["server", "tool", "parameters"],
11
+ "optional_fields": ["session_id", "timeout", "context", "user_id"],
12
+ "enforcement": {
13
+ "server_allowlist_enforced": true,
14
+ "tool_allowlist_enforced": true,
15
+ "rate_limits_enforced": true,
16
+ "parameter_validation_enforced": true,
17
+ "session_tracking_enforced": false
18
+ },
19
+ "mcp": {
20
+ "require_allowlisted_if_present": true
21
+ },
22
+ "advice": [
23
+ "Use server allowlists to prevent unauthorized MCP connections",
24
+ "Restrict tools to minimum required for agent functionality",
25
+ "Enforce rate limits to prevent MCP server abuse",
26
+ "Validate tool parameters against expected schemas",
27
+ "Log all MCP tool calls for Verifiable Attestation",
28
+ "Use session tracking for cross-tool audit trails",
29
+ "Subscribe to status webhooks for instant suspend",
30
+ "Implement progressive limits for new MCP integrations",
31
+ "Monitor MCP usage patterns for anomalies",
32
+ "Consider tool-specific parameter restrictions"
33
+ ],
34
+ "required_context": {
35
+ "$schema": "http://json-schema.org/draft-07/schema#",
36
+ "type": "object",
37
+ "required": ["server", "tool", "parameters"],
38
+ "properties": {
39
+ "server": {
40
+ "type": "string",
41
+ "format": "uri",
42
+ "description": "MCP server URL (e.g., 'https://mcp.github.com')"
43
+ },
44
+ "tool": {
45
+ "type": "string",
46
+ "minLength": 1,
47
+ "maxLength": 200,
48
+ "pattern": "^[a-zA-Z0-9._-]+$",
49
+ "description": "MCP tool name (e.g., 'github.pull_requests.create')"
50
+ },
51
+ "parameters": {
52
+ "type": "object",
53
+ "description": "Tool-specific parameters"
54
+ },
55
+ "session_id": {
56
+ "type": "string",
57
+ "description": "MCP session identifier for tracking"
58
+ },
59
+ "timeout": {
60
+ "type": "integer",
61
+ "minimum": 1,
62
+ "maximum": 300,
63
+ "description": "Tool execution timeout in seconds"
64
+ },
65
+ "context": {
66
+ "type": "object",
67
+ "description": "Additional context for tool execution"
68
+ },
69
+ "user_id": {
70
+ "type": "string",
71
+ "description": "User on whose behalf the tool is being executed"
72
+ },
73
+ "mcp_servers": {
74
+ "type": "array",
75
+ "items": { "type": "string" },
76
+ "description": "Additional MCP servers being used"
77
+ },
78
+ "mcp_tools": {
79
+ "type": "array",
80
+ "items": { "type": "string" },
81
+ "description": "Additional MCP tools being used"
82
+ },
83
+ "mcp_session": {
84
+ "type": "string",
85
+ "description": "MCP session identifier for audit trail"
86
+ }
87
+ }
88
+ },
89
+ "evaluation_rules_version": "1.0",
90
+ "evaluation_rules": [
91
+ {
92
+ "name": "server_allowlist",
93
+ "type": "expression",
94
+ "condition": "limits.allowed_servers.includes(context.server) || limits.allowed_servers.includes('*')",
95
+ "deny_code": "oap.server_not_allowed",
96
+ "description": "MCP server must be in allowed list"
97
+ },
98
+ {
99
+ "name": "server_url_format",
100
+ "type": "custom_validator",
101
+ "validator": "validateMCPServer",
102
+ "deny_code": "oap.invalid_server_url",
103
+ "description": "MCP server URL must be valid and secure"
104
+ },
105
+ {
106
+ "name": "tool_allowlist",
107
+ "type": "expression",
108
+ "condition": "(limits.allowed_tools && (limits.allowed_tools.includes(context.tool) || limits.allowed_tools.includes('*'))) || (limits.allowed_tool_prefixes && limits.allowed_tool_prefixes.some(prefix => context.tool.startsWith(prefix)))",
109
+ "deny_code": "oap.tool_not_allowed",
110
+ "description": "MCP tool must be in allowed list or match allowed prefix"
111
+ },
112
+ {
113
+ "name": "rate_limit",
114
+ "type": "custom_validator",
115
+ "validator": "validateMCPRateLimit",
116
+ "deny_code": "oap.rate_limit_exceeded",
117
+ "description": "MCP tool calls must not exceed rate limit"
118
+ },
119
+ {
120
+ "name": "timeout_limit",
121
+ "type": "expression",
122
+ "condition": "!context.timeout || !limits.max_timeout || context.timeout <= limits.max_timeout",
123
+ "deny_code": "oap.timeout_exceeded",
124
+ "description": "Tool timeout must not exceed limit"
125
+ },
126
+ {
127
+ "name": "parameter_size_limit",
128
+ "type": "custom_validator",
129
+ "validator": "validateParameterSize",
130
+ "deny_code": "oap.parameter_size_exceeded",
131
+ "description": "Tool parameters must not exceed size limit"
132
+ }
133
+ ],
134
+ "cache": {
135
+ "default_ttl_seconds": 30,
136
+ "suspend_invalidate_seconds": 15
137
+ },
138
+ "deprecation": null,
139
+ "created_at": "2026-02-14T00:00:00Z",
140
+ "updated_at": "2026-02-14T00:00:00Z"
141
+ }
@@ -0,0 +1,230 @@
1
+ # Messaging Policy Pack v1
2
+
3
+ ## Overview
4
+
5
+ The `messaging.message.send.v1` policy pack protects messaging endpoints with rate limits, channel restrictions, and mention policies. This is designed as a PLG (Product-Led Growth) on-ramp for harmless messaging use cases across Slack, Discord, Email, and other channels.
6
+
7
+ ## Policy Requirements
8
+
9
+ | **Requirement** | **Value** | **Description** |
10
+ |-----------------|-----------|-----------------|
11
+ | **Capability** | `messaging.send` | Agent must have messaging capability |
12
+ | **Assurance** | L0 | Minimum assurance level required |
13
+ | **Rate Limits** | `msgs_per_min`, `msgs_per_day` | Required rate limiting configuration |
14
+
15
+ ## Limits Configuration
16
+
17
+ ### Required Limits
18
+
19
+ - **`msgs_per_min`**: Maximum messages per minute (1-1000)
20
+ - **`msgs_per_day`**: Maximum messages per day (1-50000)
21
+
22
+ ### Capability Parameters
23
+
24
+ - **`channels_allowlist`**: Comma-separated list of allowed channels (slack, discord, email)
25
+ - **`mention_policy`**: Policy for @mentions (none, limited, all)
26
+ - **`max_recipients`**: Maximum number of recipients per message
27
+
28
+ ## Example Usage
29
+
30
+ ### Express.js
31
+
32
+ ```javascript
33
+ const { requirePolicy } = require("@aporthq/middleware-express");
34
+
35
+ app.post("/messages", requirePolicy("messaging.message.send.v1"), async (req, res) => {
36
+ const { channel, recipients, content, mentions } = req.body;
37
+ const passport = req.policyResult.passport;
38
+
39
+ // Policy automatically enforces:
40
+ // - Channel allowlist validation
41
+ // - Rate limiting (msgs_per_min, msgs_per_day)
42
+ // - Mention policy enforcement
43
+ // - Assurance level checking (L0+)
44
+
45
+ // Your messaging logic here
46
+ const message_id = await sendMessage({
47
+ channel,
48
+ recipients,
49
+ content,
50
+ mentions,
51
+ agent_id: passport.agent_id,
52
+ });
53
+
54
+ res.json({ success: true, message_id });
55
+ });
56
+ ```
57
+
58
+ ### FastAPI
59
+
60
+ ```python
61
+ from aport.middleware import require_policy
62
+
63
+ @app.post("/messages")
64
+ @require_policy("messaging.message.send.v1")
65
+ async def send_message(request: Request, message_data: MessageRequest):
66
+ passport = request.state.policy_result.passport
67
+
68
+ # Policy automatically enforces all requirements
69
+ # Your messaging logic here
70
+
71
+ return {"success": True, "message_id": message_id}
72
+ ```
73
+
74
+ ## Policy Violations
75
+
76
+ ### Channel Not Allowlisted
77
+
78
+ ```json
79
+ {
80
+ "error": "messaging_policy_violation",
81
+ "reason": "channel_not_allowlisted",
82
+ "channel": "teams",
83
+ "allowed_channels": ["slack", "discord", "email"],
84
+ "upgrade_instructions": "Add 'teams' to your passport's channels_allowlist parameter"
85
+ }
86
+ ```
87
+
88
+ ### Rate Limit Exceeded
89
+
90
+ ```json
91
+ {
92
+ "error": "messaging_policy_violation",
93
+ "reason": "rate_limit_exceeded",
94
+ "limit_type": "per_minute",
95
+ "current_usage": 95,
96
+ "limit": 100,
97
+ "retry_after": 60
98
+ }
99
+ ```
100
+
101
+ ### Mention Policy Violation
102
+
103
+ ```json
104
+ {
105
+ "error": "messaging_policy_violation",
106
+ "reason": "mention_not_allowed",
107
+ "mention_policy": "limited",
108
+ "violation": "@everyone mentions not allowed with limited policy"
109
+ }
110
+ ```
111
+
112
+ ## Best Practices
113
+
114
+ ### Implementation
115
+
116
+ 1. **Rate Limiting**: Implement proper rate limiting per agent and per channel
117
+ 2. **Channel Validation**: Always validate channels against the allowlist
118
+ 3. **Mention Control**: Enforce mention policies to prevent spam
119
+ 4. **Verifiable Attestation**: Log all message attempts for security monitoring
120
+ 5. **Error Handling**: Provide clear error messages for policy violations
121
+
122
+ ### Security
123
+
124
+ 1. **Monitor Patterns**: Watch for spam patterns and suspicious activity
125
+ 2. **Webhook Integration**: Subscribe to status webhooks for instant suspend
126
+ 3. **Content Filtering**: Consider implementing content filtering for harmful messages
127
+ 4. **Channel-Specific Limits**: Implement different limits for different channels
128
+
129
+ ### Performance
130
+
131
+ 1. **Cache Verification**: Cache passport verification results (60s TTL recommended)
132
+ 2. **Async Processing**: Use async processing for bulk message operations
133
+ 3. **Rate Limiter**: Use Redis or similar for distributed rate limiting
134
+ 4. **Batch Operations**: Support batch messaging with proper limit checking
135
+
136
+ ## Why This Policy Pack?
137
+
138
+ - **Mass Market**: Messaging is harmless and perfect for PLG onboarding
139
+ - **Demo Friendly**: Easy to demonstrate limits and suspend functionality
140
+ - **Channel Diversity**: Supports multiple messaging platforms (Slack, Discord, Email)
141
+ - **Scalable**: Rate limits prevent abuse while allowing legitimate use
142
+ - **Compliance Ready**: Built-in Verifiable Attestation and policy enforcement
143
+
144
+ ## Integration Examples
145
+
146
+ - **Customer Support**: Automated responses via Slack/Discord
147
+ - **Marketing**: Email campaigns with rate limiting
148
+ - **Notifications**: System alerts across multiple channels
149
+ - **Community Management**: Moderated Discord/Slack interactions
150
+ - **Internal Tools**: Employee messaging and announcements
151
+
152
+
153
+ ## Required Context
154
+
155
+ This policy requires the following context (JSON Schema):
156
+
157
+ ```json
158
+ {
159
+ "$schema": "http://json-schema.org/draft-07/schema#",
160
+ "type": "object",
161
+ "required": [
162
+ "channel_id",
163
+ "message",
164
+ "message_type"
165
+ ],
166
+ "properties": {
167
+ "channel_id": {
168
+ "type": "string",
169
+ "minLength": 1,
170
+ "description": "Target channel identifier"
171
+ },
172
+ "message": {
173
+ "type": "string",
174
+ "minLength": 1,
175
+ "maxLength": 2000,
176
+ "description": "Message content"
177
+ },
178
+ "message_type": {
179
+ "type": "string",
180
+ "enum": [
181
+ "text",
182
+ "embed",
183
+ "file",
184
+ "reaction"
185
+ ],
186
+ "description": "Type of message"
187
+ },
188
+ "mentions": {
189
+ "type": "array",
190
+ "items": {
191
+ "type": "string"
192
+ },
193
+ "description": "User or role mentions in the message"
194
+ },
195
+ "attachments": {
196
+ "type": "array",
197
+ "items": {
198
+ "type": "object",
199
+ "properties": {
200
+ "url": {
201
+ "type": "string"
202
+ },
203
+ "filename": {
204
+ "type": "string"
205
+ },
206
+ "size": {
207
+ "type": "integer"
208
+ }
209
+ }
210
+ },
211
+ "description": "File attachments"
212
+ },
213
+ "thread_id": {
214
+ "type": "string",
215
+ "description": "Thread identifier for threaded messages"
216
+ },
217
+ "reply_to": {
218
+ "type": "string",
219
+ "description": "Message ID being replied to"
220
+ }
221
+ }
222
+ }
223
+ ```
224
+
225
+ You can also fetch this live via the discovery endpoint:
226
+
227
+ ```bash
228
+ curl -s "https://aport.io/api/policies/messaging.message.send.v1?format=schema"
229
+ ```
230
+