@kryptosai/mcp-observatory 0.27.0 → 0.28.0

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 (123) hide show
  1. package/COMMERCIAL.md +6 -1
  2. package/CONTRIBUTORS.md +39 -0
  3. package/README.md +57 -18
  4. package/dist/src/adapters/http.js +1 -5
  5. package/dist/src/adapters/http.js.map +1 -1
  6. package/dist/src/cassette.js +3 -2
  7. package/dist/src/cassette.js.map +1 -1
  8. package/dist/src/checks/attack-sim.d.ts +18 -0
  9. package/dist/src/checks/attack-sim.js +304 -0
  10. package/dist/src/checks/attack-sim.js.map +1 -0
  11. package/dist/src/ci-issue.js +4 -3
  12. package/dist/src/ci-issue.js.map +1 -1
  13. package/dist/src/cli.js +17 -3
  14. package/dist/src/cli.js.map +1 -1
  15. package/dist/src/commands/attack-sim.d.ts +2 -0
  16. package/dist/src/commands/attack-sim.js +168 -0
  17. package/dist/src/commands/attack-sim.js.map +1 -0
  18. package/dist/src/commands/init-ci.d.ts +1 -0
  19. package/dist/src/commands/init-ci.js +8 -3
  20. package/dist/src/commands/init-ci.js.map +1 -1
  21. package/dist/src/commands/legacy.js +6 -1
  22. package/dist/src/commands/legacy.js.map +1 -1
  23. package/dist/src/commands/scan.js +7 -1
  24. package/dist/src/commands/scan.js.map +1 -1
  25. package/dist/src/commands/serve.js +9 -1
  26. package/dist/src/commands/serve.js.map +1 -1
  27. package/dist/src/commands/setup-ci-conversion.d.ts +1 -0
  28. package/dist/src/commands/setup-ci-conversion.js +1 -0
  29. package/dist/src/commands/setup-ci-conversion.js.map +1 -1
  30. package/dist/src/commands/telemetry.js +20 -14
  31. package/dist/src/commands/telemetry.js.map +1 -1
  32. package/dist/src/commands/test.js +13 -1
  33. package/dist/src/commands/test.js.map +1 -1
  34. package/dist/src/findings.js +41 -1
  35. package/dist/src/findings.js.map +1 -1
  36. package/dist/src/history.js +3 -2
  37. package/dist/src/history.js.map +1 -1
  38. package/dist/src/index.d.ts +2 -0
  39. package/dist/src/index.js +2 -0
  40. package/dist/src/index.js.map +1 -1
  41. package/dist/src/integrations/smithery.js +5 -1
  42. package/dist/src/integrations/smithery.js.map +1 -1
  43. package/dist/src/reporters/attack-sim.d.ts +2 -0
  44. package/dist/src/reporters/attack-sim.js +84 -0
  45. package/dist/src/reporters/attack-sim.js.map +1 -0
  46. package/dist/src/reporters/pr-comment.js +20 -6
  47. package/dist/src/reporters/pr-comment.js.map +1 -1
  48. package/dist/src/runner.d.ts +3 -0
  49. package/dist/src/runner.js +5 -0
  50. package/dist/src/runner.js.map +1 -1
  51. package/dist/src/score.js +1 -1
  52. package/dist/src/score.js.map +1 -1
  53. package/dist/src/storage.js +3 -2
  54. package/dist/src/storage.js.map +1 -1
  55. package/dist/src/telemetry.d.ts +3 -0
  56. package/dist/src/telemetry.js +17 -1
  57. package/dist/src/telemetry.js.map +1 -1
  58. package/dist/src/types.d.ts +1 -1
  59. package/dist/src/utils/files.d.ts +1 -0
  60. package/dist/src/utils/files.js +21 -0
  61. package/dist/src/utils/files.js.map +1 -0
  62. package/dist/src/utils/ids.js +18 -5
  63. package/dist/src/utils/ids.js.map +1 -1
  64. package/dist/src/utils/url.d.ts +2 -0
  65. package/dist/src/utils/url.js +15 -0
  66. package/dist/src/utils/url.js.map +1 -0
  67. package/dist/src/validate.js +1 -1
  68. package/dist/src/validate.js.map +1 -1
  69. package/docs/agent-ecosystem-promotion-plan.md +244 -0
  70. package/docs/agent-tasks.md +95 -0
  71. package/docs/automatic-ci-integration.md +33 -0
  72. package/docs/campaign-attribution.md +58 -0
  73. package/docs/code-scanning-demo.md +57 -0
  74. package/docs/contributor-proof-cards/README.md +33 -0
  75. package/docs/contributor-recognition.md +92 -0
  76. package/docs/feishu-lark-mcp.md +1 -1
  77. package/docs/github-code-scanning-for-mcp.md +1 -1
  78. package/docs/launch.md +64 -0
  79. package/docs/mcp-attack-simulator.md +57 -0
  80. package/docs/mcp-server-safety-index.md +18 -12
  81. package/docs/proof.md +5 -2
  82. package/docs/receipt-graph.md +54 -0
  83. package/docs/safety-index/artifacts/antv-chart-server.json +21 -21
  84. package/docs/safety-index/artifacts/antv-chart-server.md +10 -10
  85. package/docs/safety-index/artifacts/browsermcp-server.json +17 -17
  86. package/docs/safety-index/artifacts/browsermcp-server.md +10 -10
  87. package/docs/safety-index/artifacts/context7-server.json +17 -17
  88. package/docs/safety-index/artifacts/context7-server.md +10 -10
  89. package/docs/safety-index/artifacts/cyanheads-git-mcp-server.json +2014 -0
  90. package/docs/safety-index/artifacts/cyanheads-git-mcp-server.md +163 -0
  91. package/docs/safety-index/artifacts/everything-server.json +131 -56
  92. package/docs/safety-index/artifacts/everything-server.md +24 -24
  93. package/docs/safety-index/artifacts/executeautomation-playwright-server.json +26 -18
  94. package/docs/safety-index/artifacts/executeautomation-playwright-server.md +10 -10
  95. package/docs/safety-index/artifacts/filesystem-server.json +128 -20
  96. package/docs/safety-index/artifacts/filesystem-server.md +10 -10
  97. package/docs/safety-index/artifacts/kubernetes-server.attack.json +1559 -0
  98. package/docs/safety-index/artifacts/kubernetes-server.attack.md +43 -0
  99. package/docs/safety-index/artifacts/kubernetes-server.attack.sarif +2857 -0
  100. package/docs/safety-index/artifacts/kubernetes-server.json +1348 -0
  101. package/docs/safety-index/artifacts/kubernetes-server.md +150 -0
  102. package/docs/safety-index/artifacts/memory-server.json +75 -32
  103. package/docs/safety-index/artifacts/memory-server.md +35 -28
  104. package/docs/safety-index/artifacts/opentofu-server.json +25 -17
  105. package/docs/safety-index/artifacts/opentofu-server.md +11 -11
  106. package/docs/safety-index/artifacts/playwright-mcp-server.json +56 -20
  107. package/docs/safety-index/artifacts/playwright-mcp-server.md +12 -12
  108. package/docs/safety-index/artifacts/promptopia-server.json +28 -20
  109. package/docs/safety-index/artifacts/promptopia-server.md +11 -11
  110. package/docs/safety-index/artifacts/puppeteer-server.json +42 -30
  111. package/docs/safety-index/artifacts/puppeteer-server.md +28 -28
  112. package/docs/safety-index/artifacts/ref-tools-server.json +17 -17
  113. package/docs/safety-index/artifacts/ref-tools-server.md +9 -9
  114. package/docs/safety-index/artifacts/sequential-thinking-server.json +20 -21
  115. package/docs/safety-index/artifacts/sequential-thinking-server.md +10 -10
  116. package/docs/safety-index/targets.json +90 -14
  117. package/docs/setup-ci-doctor.md +2 -0
  118. package/docs/target-gallery.md +49 -0
  119. package/docs/target-registry.md +5 -1
  120. package/docs/tool-call-receipts.md +116 -0
  121. package/package.json +20 -2
  122. package/schemas/run-artifact.schema.json +1 -0
  123. package/scripts/postinstall.mjs +123 -0
package/COMMERCIAL.md CHANGED
@@ -4,12 +4,17 @@ MCP Observatory is the CI and security gate for MCP servers before agents depend
4
4
 
5
5
  The open source CLI and MCP server remain free for local OSS use under the MIT license. Paid pilots are for production use cases where a team needs hosted reporting, private repository CI, security reports, certification, support, or fleet visibility.
6
6
 
7
- ## Pilot Pricing
7
+ ## MCP Readiness Review
8
+
9
+ The primary paid offer is a fixed-scope MCP Readiness Review starting at `$2,500`.
10
+
11
+ It includes CI rollout, SARIF/GitHub Code Scanning setup, private readiness reporting, prioritized remediation notes, and maintainer PR support for selected MCP servers.
8
12
 
9
13
  These are starting points for current pilots, not permanent fixed plans. For public OSS users, the important part is simple: local CLI use remains free, and paid work is for private or production support needs.
10
14
 
11
15
  | Pilot | Starting Price | Best Fit |
12
16
  | --- | ---: | --- |
17
+ | MCP Readiness Review | $2,500 | CI rollout, Code Scanning, private readiness report, and prioritized fixes |
13
18
  | Team Pilot | $299/month | Small teams adding MCP regression checks to CI |
14
19
  | Business Pilot | $999/month | Private repos, recurring security reports, and shared reporting |
15
20
  | Enterprise Pilot | $3k/month | Private MCP readiness reports, support, and fleet visibility |
@@ -0,0 +1,39 @@
1
+ # Contributors
2
+
3
+ MCP Observatory uses the [All Contributors](https://allcontributors.org/) spec so code, docs, tests, target research, reviews, security findings, design, and maintainer feedback can all receive visible credit.
4
+
5
+ Official GitHub profile achievements are platform-controlled; this project does not award them. Instead, contributors get public proof: a role on the recognition page, an All Contributors entry, and a proof card or recognition link they can reference from a README or GitHub profile.
6
+
7
+ See the full recognition path in [MCP Observatory Contributors](./docs/contributor-recognition.md).
8
+
9
+ <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
10
+ [![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors-)
11
+ <!-- ALL-CONTRIBUTORS-BADGE:END -->
12
+
13
+ ## Contributors
14
+
15
+ <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
16
+ <!-- prettier-ignore-start -->
17
+ <!-- markdownlint-disable -->
18
+ <table>
19
+ <tbody>
20
+ <tr>
21
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/KryptosAI"><img src="https://avatars.githubusercontent.com/u/140749029?s=100" width="100px;" alt="William Weishuhn"/><br /><sub><b>William Weishuhn</b></sub></a><br /><a href="https://github.com/KryptosAI/mcp-observatory/commits?author=KryptosAI" title="Code">💻</a> <a href="https://github.com/KryptosAI/mcp-observatory/commits?author=KryptosAI" title="Documentation">📖</a> <a href="#ideas-KryptosAI" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-KryptosAI" title="Maintenance">🚧</a> <a href="https://github.com/KryptosAI/mcp-observatory/commits?author=KryptosAI" title="Tests">⚠️</a></td>
22
+ </tr>
23
+ </tbody>
24
+ </table>
25
+
26
+ <!-- markdownlint-restore -->
27
+ <!-- prettier-ignore-end -->
28
+
29
+ <!-- ALL-CONTRIBUTORS-LIST:END -->
30
+
31
+ ## Recognition Requests
32
+
33
+ After a useful contribution is merged or accepted, request credit in the PR or issue:
34
+
35
+ ```text
36
+ @all-contributors please add @username for code, doc, test, ideas, review
37
+ ```
38
+
39
+ If the bot is unavailable, open a small PR that updates `.all-contributorsrc`, this file, and any relevant proof card under `docs/contributor-proof-cards/`.
package/README.md CHANGED
@@ -11,41 +11,80 @@
11
11
  ```
12
12
 
13
13
  [![CI](https://github.com/KryptosAI/mcp-observatory/actions/workflows/ci.yml/badge.svg)](https://github.com/KryptosAI/mcp-observatory/actions/workflows/ci.yml)
14
+ [![CodeQL](https://github.com/KryptosAI/mcp-observatory/actions/workflows/codeql.yml/badge.svg)](https://github.com/KryptosAI/mcp-observatory/actions/workflows/codeql.yml)
15
+ [![Coverage](https://github.com/KryptosAI/mcp-observatory/actions/workflows/coverage.yml/badge.svg)](https://github.com/KryptosAI/mcp-observatory/actions/workflows/coverage.yml)
16
+ [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/KryptosAI/mcp-observatory/badge)](https://securityscorecards.dev/viewer/?uri=github.com/KryptosAI/mcp-observatory)
17
+ [![Dependabot](https://img.shields.io/badge/dependabot-enabled-025e8c?logo=dependabot)](./.github/dependabot.yml)
18
+ [![npm provenance workflow](https://img.shields.io/badge/npm%20provenance-workflow-blue)](./.github/workflows/release.yml)
14
19
  [![npm](https://img.shields.io/npm/v/@kryptosai/mcp-observatory)](https://www.npmjs.com/package/@kryptosai/mcp-observatory)
15
- [![npm downloads](https://img.shields.io/npm/dm/@kryptosai/mcp-observatory)](https://www.npmjs.com/package/@kryptosai/mcp-observatory)
20
+ [![npm weekly downloads](https://img.shields.io/npm/dw/@kryptosai/mcp-observatory)](https://www.npmjs.com/package/@kryptosai/mcp-observatory)
21
+ [![GitHub stars](https://img.shields.io/github/stars/KryptosAI/mcp-observatory?style=flat)](https://github.com/KryptosAI/mcp-observatory/stargazers)
16
22
  [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](./LICENSE)
17
23
  [![Node >= 20](https://img.shields.io/badge/node-%3E%3D20-339933)](./package.json)
18
24
  [![Smithery](https://smithery.ai/badge/@kryptosai/mcp-observatory)](https://smithery.ai/server/@kryptosai/mcp-observatory)
19
25
  [![mcp-observatory MCP server](https://glama.ai/mcp/servers/KryptosAI/mcp-observatory/badges/score.svg)](https://glama.ai/mcp/servers/KryptosAI/mcp-observatory)
26
+ [![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](./CONTRIBUTORS.md)
20
27
 
21
- **The GitHub-native CI and security gate for MCP servers before agents depend on them.**
28
+ **The GitHub-native CI, SARIF, and security-readiness gate for MCP servers before agents depend on them.**
22
29
 
23
- Agents should not depend on tools nobody tests. MCP Observatory gives MCP servers the production safety rails every dependency eventually needs: CI checks, security scans, schema drift detection, PR reports, score badges, agent-accessible diagnostics, and GitHub Code Scanning findings.
30
+ Agents should not depend on tools nobody tests. MCP Observatory turns a local MCP check into release-gate evidence maintainers already understand: GitHub Actions, security findings, schema drift detection, PR reports, score badges, agent-accessible diagnostics, and GitHub Code Scanning SARIF.
24
31
 
25
- Security launch path:
32
+ ## Trust Signals
33
+
34
+ | Signal | What it means |
35
+ |---|---|
36
+ | CI + coverage | Typecheck, lint, tests, build, packed install, artifact validation, smoke test, and measured coverage run in GitHub Actions. |
37
+ | CodeQL + OpenSSF Scorecard | Static analysis and supply-chain posture are visible in GitHub-native security surfaces. |
38
+ | Dependabot | npm and GitHub Actions dependency updates are monitored weekly. |
39
+ | npm provenance workflow | Release automation is prepared for npm provenance through GitHub OIDC. |
40
+ | Security policy | Vulnerability reports go through private disclosure; see [SECURITY.md](./SECURITY.md). |
41
+
42
+ ## Try It
43
+
44
+ Start with the homepage demo: safely simulate MCP attack-readiness for one server and emit SARIF evidence that maintainers can inspect in GitHub Code Scanning.
26
45
 
27
46
  ```bash
28
- npx @kryptosai/mcp-observatory test npx -y my-mcp-server --sarif mcp-observatory.sarif
47
+ npx @kryptosai/mcp-observatory attack-sim npx -y my-mcp-server --sarif attack-results.sarif
29
48
  ```
30
49
 
31
- Or install the GitHub Action with Code Scanning upload:
50
+ Then make the evidence repeatable in CI:
32
51
 
33
52
  ```bash
34
53
  npx @kryptosai/mcp-observatory setup-ci --all --command "npx -y my-mcp-server" --sarif
35
54
  ```
36
55
 
37
- See [GitHub Code Scanning for MCP servers](./docs/github-code-scanning-for-mcp.md).
56
+ See the [MCP Attack Simulator](./docs/mcp-attack-simulator.md), [Tool-call receipts](./docs/tool-call-receipts.md), [MCP Receipt Graph](./docs/receipt-graph.md), [launch page](./docs/launch.md), [GitHub Code Scanning demo](./docs/code-scanning-demo.md), [GitHub Code Scanning for MCP servers](./docs/github-code-scanning-for-mcp.md), [sample safety reports](./docs/mcp-server-safety-index.md), and [reference evaluations](./docs/reference-evaluations.md).
57
+
58
+ Want a receipt for a server your agent depends on? Comment on [Drop an MCP server, get a receipt #146](https://github.com/KryptosAI/mcp-observatory/issues/146) or use the [structured receipt request form](https://github.com/KryptosAI/mcp-observatory/issues/new?template=tool-call-receipt-request.yml). Public requests can become Safety Index entries, delta receipts, SARIF evidence, and maintainer CI conversations.
59
+
60
+ ## Evidence You Can Inspect
61
+
62
+ | Evidence | Where |
63
+ |---|---|
64
+ | Example GitHub Actions adoption | [`setup-ci --all`](./docs/setup-ci-doctor.md) and the generated workflow docs |
65
+ | Attack simulation output | [MCP Attack Simulator](./docs/mcp-attack-simulator.md) |
66
+ | Tool-call receipts | [Receipt standard](./docs/tool-call-receipts.md) for reproducible MCP evidence |
67
+ | Receipt graph | [Server-to-evidence map](./docs/receipt-graph.md) for agent trust decisions |
68
+ | SARIF / Code Scanning output | [GitHub Code Scanning demo](./docs/code-scanning-demo.md) |
69
+ | Real MCP server evaluations | [MCP Server Safety Index](./docs/mcp-server-safety-index.md) |
70
+ | Reference reports | [Reference evaluations](./docs/reference-evaluations.md) |
71
+ | Maintainer and contributor proof | [MCP Observatory Contributors](./docs/contributor-recognition.md) |
72
+ | Security disclosure path | [SECURITY.md](./SECURITY.md) |
38
73
 
39
74
  Two more fast paths:
40
75
 
41
- Cloned this repo? Start here: [`CLONED_THIS.md`](./CLONED_THIS.md). Want to contribute? Add one server to the [MCP Target Registry](./docs/target-registry.md).
76
+ Cloned this repo? Start here: [`CLONED_THIS.md`](./CLONED_THIS.md). Want to contribute? Add one server to the [MCP Target Registry](./docs/target-registry.md), use the [Agent Task Pack](./docs/agent-tasks.md), and get public credit through [MCP Observatory Contributors](./docs/contributor-recognition.md).
42
77
 
43
- Add MCP CI in one command:
78
+ AI coding agents, agentic workflows, and rough PRs are welcome. Use the [10x Agentic Growth Sprint](./docs/10x-agentic-growth-sprint.md), [Agentic Contributor Outreach](./docs/agentic-contributor-outreach.md), or open a `Contributor quest`, `Agentic contribution idea`, or [`Drop an MCP server, get a receipt`](./docs/drop-server-get-receipt.md) issue to suggest a target, prompt, docs fix, receipt, or `setup-ci --sarif` integration.
79
+
80
+ Add MCP CI and Code Scanning in one command:
44
81
 
45
82
  ```bash
46
- npx @kryptosai/mcp-observatory setup-ci --all --command "npx -y my-mcp-server"
83
+ npx @kryptosai/mcp-observatory setup-ci --all --command "npx -y my-mcp-server" --sarif
47
84
  ```
48
85
 
86
+ Installing MCP Observatory in an MCP server project also prints the exact CI setup command. Projects can opt into automatic workflow creation during install with [`mcpObservatory.autoSetupCi`](./docs/automatic-ci-integration.md).
87
+
49
88
  Upload normalized MCP findings to GitHub Code Scanning when you want a security-native release gate:
50
89
 
51
90
  ```bash
@@ -74,6 +113,8 @@ Use it as a CLI, a GitHub Action, or an MCP server that lets your AI agent scan,
74
113
 
75
114
  [![Observatory MCP server](https://glama.ai/mcp/servers/KryptosAI/mcp-observatory/badges/card.svg)](https://glama.ai/mcp/servers/KryptosAI/mcp-observatory)
76
115
 
116
+ The Glama card is an external MCP directory scorecard. Treat it as directory-level social proof; click through for the underlying category details before using it as a production approval signal.
117
+
77
118
  ## Why MCP Observatory
78
119
 
79
120
  MCP servers are becoming production dependencies. If agents rely on them, teams need a way to catch broken tools, unsafe schemas, schema drift, slow responses, and security footguns before those failures reach users.
@@ -88,19 +129,19 @@ Observatory gives maintainers and teams:
88
129
  - **MCP server mode** so agents can inspect other MCP servers directly
89
130
  - **Production support path** for hosted history, private repo reporting, certification, support, and fleet visibility
90
131
 
91
- See [GitHub Code Scanning for MCP servers](./docs/github-code-scanning-for-mcp.md), the [target registry](./docs/target-registry.md), [target contribution guide](./docs/target-contribution-guide.md), [`setup-ci --doctor`](./docs/setup-ci-doctor.md), [MCP server security field guide](./docs/mcp-security-field-guide.md), [Safety Methodology](./docs/methodology.md), [MCP Server Safety Index](./docs/mcp-server-safety-index.md), [June 2026 safety field report](./docs/mcp-safety-field-report-2026-06.md), [reference evaluations](./docs/reference-evaluations.md), [MCP lock files](./docs/mcp-lock-files.md), [public proof](./docs/proof.md), [local metrics dashboard](./docs/metrics-dashboard.md), and [commercial support](./COMMERCIAL.md).
132
+ See the [launch page](./docs/launch.md), [GitHub Code Scanning for MCP servers](./docs/github-code-scanning-for-mcp.md), [Code Scanning demo](./docs/code-scanning-demo.md), [target gallery](./docs/target-gallery.md), [target registry](./docs/target-registry.md), [target contribution guide](./docs/target-contribution-guide.md), [MCP Observatory Contributors](./docs/contributor-recognition.md), [Agent Task Pack](./docs/agent-tasks.md), [Tool-call receipts](./docs/tool-call-receipts.md), [MCP Receipt Graph](./docs/receipt-graph.md), [`setup-ci --doctor`](./docs/setup-ci-doctor.md), [MCP server security field guide](./docs/mcp-security-field-guide.md), [Safety Methodology](./docs/methodology.md), [MCP Server Safety Index](./docs/mcp-server-safety-index.md), [June 2026 safety field report](./docs/mcp-safety-field-report-2026-06.md), [reference evaluations](./docs/reference-evaluations.md), [MCP lock files](./docs/mcp-lock-files.md), [public proof](./docs/proof.md), [campaign attribution](./docs/campaign-attribution.md), [local metrics dashboard](./docs/metrics-dashboard.md), and [commercial support](./COMMERCIAL.md).
92
133
 
93
134
  ## For Security And Platform Teams
94
135
 
95
136
  MCP servers are becoming part of the AI software supply chain. Agents need reliable, testable, auditable tools before those tools become dependencies in mission-critical workflows.
96
137
 
97
- MCP Observatory gives security and platform teams MCP server CI, schema drift detection, security findings, SARIF/HTML/Markdown reports, GitHub Code Scanning upload, and a path toward certification or fleet visibility. Local OSS use stays free; production, private repo, and fleet usage can move through a paid pilot.
138
+ MCP Observatory gives security and platform teams MCP server CI, schema drift detection, security findings, SARIF/HTML/Markdown reports, GitHub Code Scanning upload, and a path toward certification or fleet visibility. Local OSS use stays free; production, private repo, and fleet usage can move through a paid MCP Readiness Review.
98
139
 
99
140
  ## Production Support
100
141
 
101
- Local OSS use stays free under MIT. Teams running MCP in production can use [commercial support](./COMMERCIAL.md) for hosted reporting, private repo CI, recurring security reports, certification review, support, and fleet visibility.
142
+ Local OSS use stays free under MIT. Teams running MCP in production can use the [MCP Readiness Review](./docs/paid-pilot-offer.md) for CI rollout, SARIF/Code Scanning setup, private repo review, recurring security reports, certification review, support, and fleet visibility. The default package starts at `$2,500`.
102
143
 
103
- Run `npx @kryptosai/mcp-observatory cloud`, open a pilot request from the issue chooser, or see [COMMERCIAL.md](./COMMERCIAL.md). Also see [privacy and telemetry](./PRIVACY.md) and [terms for production use](./TERMS.md).
144
+ Run `npx @kryptosai/mcp-observatory cloud`, open a pilot request from the issue chooser, or see [COMMERCIAL.md](./COMMERCIAL.md). Also see [privacy and telemetry](./PRIVACY.md), [campaign attribution](./docs/campaign-attribution.md), and [terms for production use](./TERMS.md).
104
145
 
105
146
  ## Quick Start
106
147
 
@@ -256,7 +297,7 @@ jobs:
256
297
  runs-on: ubuntu-latest
257
298
  steps:
258
299
  - uses: actions/checkout@v4
259
- - uses: KryptosAI/mcp-observatory/action@v0.26.1
300
+ - uses: KryptosAI/mcp-observatory/action@v0.27.0
260
301
  with:
261
302
  command: npx -y my-mcp-server
262
303
  deep: true
@@ -362,9 +403,7 @@ Your agent gets 10 tools:
362
403
  | `get_last_run` | Retrieve previous check results for a server |
363
404
  | `suggest_servers` | Discover MCP servers that match your project stack |
364
405
 
365
- An AI tool that checks other AI tools. It's a tool testing tools that serve tools.*
366
-
367
- <sub>* I'm a dude playing a dude disguised as another dude.</sub>
406
+ An AI tool that checks other AI tools. It is a tool testing tools that serve tools.
368
407
 
369
408
  ### Security
370
409
 
@@ -18,8 +18,6 @@ export class HttpAdapter {
18
18
  throw new Error(`Unsupported protocol "${url.protocol}" — only http: and https: are allowed.`);
19
19
  }
20
20
  const timeoutMs = target.timeoutMs ?? 15_000;
21
- // Try streamable-http first, fall back to SSE
22
- let connected = false;
23
21
  let activeTransport;
24
22
  try {
25
23
  let transport = new StreamableHTTPClientTransport(url, { requestInit: { headers } });
@@ -27,19 +25,17 @@ export class HttpAdapter {
27
25
  transport = new RecordingTransport(transport);
28
26
  await client.connect(transport, { timeout: timeoutMs });
29
27
  activeTransport = transport;
30
- connected = true;
31
28
  }
32
29
  catch {
33
30
  stderrLines.push("Streamable HTTP failed, falling back to SSE.");
34
31
  }
35
- if (!connected) {
32
+ if (!activeTransport) {
36
33
  try {
37
34
  let transport = new SSEClientTransport(url, { requestInit: { headers } });
38
35
  if (options?.record)
39
36
  transport = new RecordingTransport(transport);
40
37
  await client.connect(transport, { timeout: timeoutMs });
41
38
  activeTransport = transport;
42
- connected = true;
43
39
  }
44
40
  catch (error) {
45
41
  const rawMessage = errorMessage(error);
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/adapters/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AAInG,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAGzD,MAAM,OAAO,WAAW;IACtB,KAAK,CAAC,OAAO,CAAC,MAAwB,EAAE,OAA+B;QACrE,MAAM,OAAO,GAA2B,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,CAAC;QACtE,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACrB,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,MAAM,CAAC,SAAS,EAAE,CAAC;QAC1D,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,YAAY,EAAE,EAClD,EAAE,YAAY,EAAE,EAAE,EAAE,CACrB,CAAC;QAEF,MAAM,WAAW,GAAa,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC1D,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,CAAC,QAAQ,wCAAwC,CAAC,CAAC;QACjG,CAAC;QACD,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC;QAE7C,8CAA8C;QAC9C,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,IAAI,eAAsC,CAAC;QAC3C,IAAI,CAAC;YACH,IAAI,SAAS,GAAc,IAAI,6BAA6B,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;YAChG,IAAI,OAAO,EAAE,MAAM;gBAAE,SAAS,GAAG,IAAI,kBAAkB,CAAC,SAAS,CAAC,CAAC;YACnE,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;YACxD,eAAe,GAAG,SAAS,CAAC;YAC5B,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC;QAAC,MAAM,CAAC;YACP,WAAW,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;QACnE,CAAC;QAED,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,IAAI,CAAC;gBACH,IAAI,SAAS,GAAc,IAAI,kBAAkB,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;gBACrF,IAAI,OAAO,EAAE,MAAM;oBAAE,SAAS,GAAG,IAAI,kBAAkB,CAAC,SAAS,CAAC,CAAC;gBACnE,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;gBACxD,eAAe,GAAG,SAAS,CAAC;gBAC5B,SAAS,GAAG,IAAI,CAAC;YACnB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;gBACvC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,+BAA+B;gBAC5E,MAAM,IAAI,mBAAmB,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAEhD,OAAO;YACL,MAAM;YACN,kBAAkB,EAAE,MAAM,CAAC,qBAAqB,EAAE;YAClD,UAAU,EAAE,aAAa,EAAE,IAAI;YAC/B,aAAa,EAAE,aAAa,EAAE,OAAO;YACrC,WAAW;YACX,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS;YACxD,KAAK,EAAE,KAAK,IAAI,EAAE;gBAChB,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACvB,CAAC;SACF,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/adapters/http.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
- import { readFile, writeFile } from "node:fs/promises";
1
+ import { readFile } from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { ensureDirectory } from "./storage.js";
4
+ import { writeTextFileAtomic } from "./utils/files.js";
4
5
  import { slugify } from "./utils/ids.js";
5
6
  // ── I/O ──────────────────────────────────────────────────────────────────────
6
7
  export function defaultCassettesDirectory(cwd = process.cwd()) {
@@ -11,7 +12,7 @@ export async function saveCassette(cassette, outDir) {
11
12
  const timestamp = new Date().toISOString().replaceAll(":", "-");
12
13
  const fileName = `${timestamp}--${slugify(cassette.targetId)}.cassette.json`;
13
14
  const filePath = path.join(outDir, fileName);
14
- await writeFile(filePath, JSON.stringify(cassette, null, 2) + "\n", "utf8");
15
+ await writeTextFileAtomic(filePath, JSON.stringify(cassette, null, 2) + "\n");
15
16
  return filePath;
16
17
  }
17
18
  export async function loadCassette(filePath) {
@@ -1 +1 @@
1
- {"version":3,"file":"cassette.js","sourceRoot":"","sources":["../../src/cassette.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAqBzC,gFAAgF;AAEhF,MAAM,UAAU,yBAAyB,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC3D,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,kBAAkB,EAAE,WAAW,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,QAAkB,EAClB,MAAc;IAEd,MAAM,eAAe,CAAC,MAAM,CAAC,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,GAAG,SAAS,KAAK,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IAC7E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC7C,MAAM,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;IAC5E,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB;IACjD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACjD,MAAM,IAAI,GAAY,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAE1C,IACE,OAAO,IAAI,KAAK,QAAQ;QACxB,IAAI,KAAK,IAAI;QACZ,IAAgC,CAAC,SAAS,CAAC,KAAK,CAAC;QAClD,CAAC,KAAK,CAAC,OAAO,CAAE,IAAgC,CAAC,SAAS,CAAC,CAAC,EAC5D,CAAC;QACD,MAAM,IAAI,KAAK,CACb,0BAA0B,QAAQ,4CAA4C,CAC/E,CAAC;IACJ,CAAC;IAED,OAAO,IAAgB,CAAC;AAC1B,CAAC"}
1
+ {"version":3,"file":"cassette.js","sourceRoot":"","sources":["../../src/cassette.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAqBzC,gFAAgF;AAEhF,MAAM,UAAU,yBAAyB,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC3D,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,kBAAkB,EAAE,WAAW,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,QAAkB,EAClB,MAAc;IAEd,MAAM,eAAe,CAAC,MAAM,CAAC,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,GAAG,SAAS,KAAK,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IAC7E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC7C,MAAM,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC9E,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB;IACjD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACjD,MAAM,IAAI,GAAY,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAE1C,IACE,OAAO,IAAI,KAAK,QAAQ;QACxB,IAAI,KAAK,IAAI;QACZ,IAAgC,CAAC,SAAS,CAAC,KAAK,CAAC;QAClD,CAAC,KAAK,CAAC,OAAO,CAAE,IAAgC,CAAC,SAAS,CAAC,CAAC,EAC5D,CAAC;QACD,MAAM,IAAI,KAAK,CACb,0BAA0B,QAAQ,4CAA4C,CAC/E,CAAC;IACJ,CAAC;IAED,OAAO,IAAgB,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { CheckResult, RunArtifact } from "../types.js";
2
+ import { type CheckContext, type ObservedCheck } from "./base.js";
3
+ export type AttackClass = "tool-poisoning" | "exfiltration-canary" | "permission-boundary" | "contract-drift";
4
+ export type AttackFindingSeverity = "high" | "medium" | "low";
5
+ export interface AttackSimulationFinding {
6
+ ruleId: string;
7
+ attackClass: AttackClass;
8
+ severity: AttackFindingSeverity;
9
+ itemType: "target" | "tool" | "prompt" | "resource" | "schema" | "response";
10
+ itemName: string;
11
+ message: string;
12
+ evidence: Record<string, unknown>;
13
+ recommendation: string;
14
+ }
15
+ export interface AttackSimulationOptions {
16
+ baseline?: RunArtifact;
17
+ }
18
+ export declare function runAttackSimulationCheck(context: CheckContext, previousChecks: CheckResult[], options?: AttackSimulationOptions): Promise<ObservedCheck>;
@@ -0,0 +1,304 @@
1
+ import { performance } from "node:perf_hooks";
2
+ import { CREDENTIAL_PATTERNS } from "./security-rules.js";
3
+ import { isCapabilityAdvertised, makeCheckResult } from "./base.js";
4
+ const POISONING_PATTERNS = [
5
+ { id: "hidden-instruction", severity: "high", pattern: /\b(ignore|override|bypass)\b.{0,80}\b(previous|system|developer|user)\b.{0,80}\b(instruction|prompt|message|policy)s?\b/i, label: "hidden instruction override" },
6
+ { id: "secret-exfiltration-instruction", severity: "high", pattern: /\b(send|post|upload|exfiltrate|leak|copy)\b.{0,80}\b(secret|token|api[_ -]?key|credential|password|env|environment)\b/i, label: "secret exfiltration instruction" },
7
+ { id: "stealth-instruction", severity: "high", pattern: /\b(do not|don't)\b.{0,60}\b(tell|reveal|mention|disclose)\b.{0,80}\b(user|operator|developer|maintainer)\b/i, label: "stealth instruction" },
8
+ { id: "agent-behavior-control", severity: "medium", pattern: /\b(always|must|before answering|when called)\b.{0,80}\b(call|invoke|use|execute)\b.{0,80}\btool\b/i, label: "agent behavior control" },
9
+ { id: "remote-fetch-instruction", severity: "medium", pattern: /\b(fetch|download|curl|wget|open url|visit)\b.{0,80}\b(http:\/\/|https:\/\/)\S+/i, label: "remote fetch instruction" },
10
+ ];
11
+ const CANARY_PATTERNS = [
12
+ { name: "MCP Observatory canary", pattern: /MCP_OBSERVATORY_CANARY_[A-Z0-9_-]+/i },
13
+ { name: "safe exfiltration canary", pattern: /OBSERVATORY_SAFE_CANARY_[A-Z0-9_-]+/i },
14
+ { name: "fake GitHub token canary", pattern: /ghp_OBSERVATORY_CANARY_[A-Za-z0-9_]+/ },
15
+ ];
16
+ const BROAD_PARAM_NAMES = new Set([
17
+ "command", "cmd", "exec", "shell", "script", "code", "query", "url", "uri",
18
+ "endpoint", "host", "path", "file", "filepath", "filename", "directory",
19
+ "dir", "glob", "pattern", "headers", "body", "method",
20
+ ]);
21
+ const DESTRUCTIVE_WORDS = /\b(write|delete|remove|overwrite|create|modify|update|execute|run|post|put|patch|mutate|send|upload)\b/i;
22
+ function stringifyForScan(value) {
23
+ if (typeof value === "string")
24
+ return value;
25
+ if (value === undefined || value === null)
26
+ return "";
27
+ try {
28
+ return JSON.stringify(value);
29
+ }
30
+ catch {
31
+ return "";
32
+ }
33
+ }
34
+ function walkText(value, path = []) {
35
+ if (typeof value === "string") {
36
+ return [{ path: path.join(".") || "(root)", text: value }];
37
+ }
38
+ if (Array.isArray(value)) {
39
+ return value.flatMap((entry, index) => walkText(entry, [...path, String(index)]));
40
+ }
41
+ if (typeof value === "object" && value !== null) {
42
+ return Object.entries(value).flatMap(([key, entry]) => walkText(entry, [...path, key]));
43
+ }
44
+ return [];
45
+ }
46
+ function propertyNames(schema) {
47
+ if (typeof schema !== "object" || schema === null || Array.isArray(schema))
48
+ return [];
49
+ const props = schema["properties"];
50
+ if (typeof props !== "object" || props === null || Array.isArray(props))
51
+ return [];
52
+ return Object.keys(props);
53
+ }
54
+ function requiredFields(schema) {
55
+ if (typeof schema !== "object" || schema === null || Array.isArray(schema))
56
+ return [];
57
+ const required = schema["required"];
58
+ return Array.isArray(required) ? required.filter((entry) => typeof entry === "string") : [];
59
+ }
60
+ function additionalProperties(schema) {
61
+ if (typeof schema !== "object" || schema === null || Array.isArray(schema))
62
+ return undefined;
63
+ return schema["additionalProperties"];
64
+ }
65
+ function isDestructiveTool(tool) {
66
+ const annotations = tool.annotations;
67
+ return annotations?.["destructiveHint"] === true ||
68
+ annotations?.["readOnlyHint"] === false ||
69
+ DESTRUCTIVE_WORDS.test(tool.name) ||
70
+ DESTRUCTIVE_WORDS.test(tool.description ?? "");
71
+ }
72
+ function addPoisoningFindings(findings, itemType, itemName, value) {
73
+ const texts = walkText(value);
74
+ for (const { path, text } of texts) {
75
+ for (const pattern of POISONING_PATTERNS) {
76
+ const match = text.match(pattern.pattern);
77
+ if (!match)
78
+ continue;
79
+ findings.push({
80
+ ruleId: `attack-sim/tool-poisoning/${pattern.id}`,
81
+ attackClass: "tool-poisoning",
82
+ severity: pattern.severity,
83
+ itemType,
84
+ itemName,
85
+ message: `${itemType} "${itemName}" contains ${pattern.label} text that could steer an agent.`,
86
+ evidence: { path, excerpt: text.slice(0, 240), match: match[0] },
87
+ recommendation: "Remove hidden or behavioral instructions from MCP metadata; keep descriptions factual and user-visible.",
88
+ });
89
+ }
90
+ }
91
+ }
92
+ function addPermissionBoundaryFindings(findings, tool) {
93
+ const params = propertyNames(tool.inputSchema);
94
+ const broadParams = params.filter((name) => BROAD_PARAM_NAMES.has(name.toLowerCase()));
95
+ if (broadParams.length === 0 || !isDestructiveTool(tool))
96
+ return;
97
+ findings.push({
98
+ ruleId: "attack-sim/permission-boundary/broad-destructive-tool",
99
+ attackClass: "permission-boundary",
100
+ severity: broadParams.some((name) => ["command", "cmd", "exec", "shell", "script", "code"].includes(name.toLowerCase())) ? "high" : "medium",
101
+ itemType: "tool",
102
+ itemName: tool.name,
103
+ message: `Tool "${tool.name}" combines broad parameters (${broadParams.join(", ")}) with destructive or non-read-only behavior.`,
104
+ evidence: { broadParams, annotations: tool.annotations, description: tool.description },
105
+ recommendation: "Constrain this tool with typed inputs, allowlists, explicit read-only/destructive annotations, and a harmless CI fixture.",
106
+ });
107
+ }
108
+ function addCanaryFindings(findings, source, value) {
109
+ const text = stringifyForScan(value);
110
+ if (!text)
111
+ return;
112
+ for (const canary of CANARY_PATTERNS) {
113
+ const match = text.match(canary.pattern);
114
+ if (match) {
115
+ findings.push({
116
+ ruleId: "attack-sim/exfiltration-canary/canary-exposed",
117
+ attackClass: "exfiltration-canary",
118
+ severity: "high",
119
+ itemType: "response",
120
+ itemName: source,
121
+ message: `${canary.name} appeared in captured MCP evidence for "${source}".`,
122
+ evidence: { source, match: match[0] },
123
+ recommendation: "Redact canary-like or secret-like values from tool responses before exposing them to agents or logs.",
124
+ });
125
+ }
126
+ }
127
+ for (const credential of CREDENTIAL_PATTERNS) {
128
+ const match = text.match(credential.pattern);
129
+ if (match) {
130
+ findings.push({
131
+ ruleId: "attack-sim/exfiltration-canary/credential-like-output",
132
+ attackClass: "exfiltration-canary",
133
+ severity: "high",
134
+ itemType: "response",
135
+ itemName: source,
136
+ message: `Captured MCP evidence for "${source}" contains credential-like text (${credential.name}).`,
137
+ evidence: { source, credentialPattern: credential.name },
138
+ recommendation: "Redact credentials from MCP responses and move secrets into environment or secret storage.",
139
+ });
140
+ }
141
+ }
142
+ }
143
+ function toolSchemasFromArtifact(artifact) {
144
+ const toolsCheck = artifact?.checks.find((check) => check.id === "tools");
145
+ const schemas = toolsCheck?.evidence.flatMap((entry) => entry.schemas ? [entry.schemas] : []) ?? [];
146
+ return Object.assign({}, ...schemas);
147
+ }
148
+ function toolNamesFromArtifact(artifact) {
149
+ const toolsCheck = artifact?.checks.find((check) => check.id === "tools");
150
+ return new Set(toolsCheck?.evidence.flatMap((entry) => entry.identifiers ?? []) ?? []);
151
+ }
152
+ function addDriftFindings(findings, tools, baseline) {
153
+ if (!baseline)
154
+ return;
155
+ const baselineNames = toolNamesFromArtifact(baseline);
156
+ const baselineSchemas = toolSchemasFromArtifact(baseline);
157
+ for (const tool of tools) {
158
+ const currentSchema = tool.inputSchema;
159
+ const baselineSchema = baselineSchemas[tool.name];
160
+ if (!baselineNames.has(tool.name) && isDestructiveTool(tool)) {
161
+ findings.push({
162
+ ruleId: "attack-sim/contract-drift/new-destructive-tool",
163
+ attackClass: "contract-drift",
164
+ severity: "high",
165
+ itemType: "tool",
166
+ itemName: tool.name,
167
+ message: `New destructive-looking tool "${tool.name}" appeared after the baseline.`,
168
+ evidence: { toolName: tool.name, description: tool.description, annotations: tool.annotations },
169
+ recommendation: "Review and approve new destructive tool surfaces before agents can depend on this server update.",
170
+ });
171
+ }
172
+ if (!baselineSchema || !currentSchema)
173
+ continue;
174
+ const oldRequired = new Set(requiredFields(baselineSchema));
175
+ const newRequired = new Set(requiredFields(currentSchema));
176
+ const removedRequired = [...oldRequired].filter((field) => !newRequired.has(field));
177
+ if (removedRequired.length > 0) {
178
+ findings.push({
179
+ ruleId: "attack-sim/contract-drift/required-fields-removed",
180
+ attackClass: "contract-drift",
181
+ severity: "medium",
182
+ itemType: "schema",
183
+ itemName: tool.name,
184
+ message: `Tool "${tool.name}" removed required fields from its schema: ${removedRequired.join(", ")}.`,
185
+ evidence: { removedRequired },
186
+ recommendation: "Treat required-field removals as agent contract drift and require maintainer review.",
187
+ });
188
+ }
189
+ const oldAdditional = additionalProperties(baselineSchema);
190
+ const newAdditional = additionalProperties(currentSchema);
191
+ if (oldAdditional === false && newAdditional !== false) {
192
+ findings.push({
193
+ ruleId: "attack-sim/contract-drift/schema-broadened",
194
+ attackClass: "contract-drift",
195
+ severity: "medium",
196
+ itemType: "schema",
197
+ itemName: tool.name,
198
+ message: `Tool "${tool.name}" broadened its schema by allowing additional properties.`,
199
+ evidence: { previousAdditionalProperties: oldAdditional, currentAdditionalProperties: newAdditional },
200
+ recommendation: "Keep agent-facing schemas strict or document why additional properties are safe.",
201
+ });
202
+ }
203
+ }
204
+ }
205
+ function scanPreviousSnapshots(findings, previousChecks) {
206
+ for (const check of previousChecks) {
207
+ for (const evidence of check.evidence) {
208
+ if (evidence.responseSnapshots) {
209
+ for (const [name, snapshot] of Object.entries(evidence.responseSnapshots)) {
210
+ addCanaryFindings(findings, `${check.id}:${name}`, snapshot);
211
+ }
212
+ }
213
+ addCanaryFindings(findings, check.id, evidence.findings);
214
+ }
215
+ }
216
+ }
217
+ async function listSurfaces(context) {
218
+ const surfaces = { tools: [], prompts: [], resources: [], resourceTemplates: [] };
219
+ if (isCapabilityAdvertised(context.serverCapabilities, "tools")) {
220
+ try {
221
+ surfaces.tools = (await context.client.listTools(undefined, { timeout: context.timeoutMs })).tools;
222
+ }
223
+ catch {
224
+ // Existing capability checks already report list failures.
225
+ }
226
+ }
227
+ if (isCapabilityAdvertised(context.serverCapabilities, "prompts")) {
228
+ try {
229
+ surfaces.prompts = (await context.client.listPrompts(undefined, { timeout: context.timeoutMs })).prompts;
230
+ }
231
+ catch {
232
+ // Existing capability checks already report list failures.
233
+ }
234
+ }
235
+ if (isCapabilityAdvertised(context.serverCapabilities, "resources")) {
236
+ try {
237
+ surfaces.resources = (await context.client.listResources(undefined, { timeout: context.timeoutMs })).resources;
238
+ }
239
+ catch {
240
+ // Existing capability checks already report list failures.
241
+ }
242
+ try {
243
+ surfaces.resourceTemplates = (await context.client.listResourceTemplates(undefined, { timeout: context.timeoutMs })).resourceTemplates;
244
+ }
245
+ catch {
246
+ // Existing capability checks already report list failures.
247
+ }
248
+ }
249
+ return surfaces;
250
+ }
251
+ function statusForFindings(findings) {
252
+ if (findings.some((finding) => finding.severity === "high"))
253
+ return "fail";
254
+ if (findings.some((finding) => finding.severity === "medium"))
255
+ return "partial";
256
+ return "pass";
257
+ }
258
+ export async function runAttackSimulationCheck(context, previousChecks, options = {}) {
259
+ const startedAt = performance.now();
260
+ const surfaces = await listSurfaces(context);
261
+ const findings = [];
262
+ for (const tool of surfaces.tools) {
263
+ addPoisoningFindings(findings, "tool", tool.name, {
264
+ name: tool.name,
265
+ description: tool.description,
266
+ inputSchema: tool.inputSchema,
267
+ annotations: tool.annotations,
268
+ });
269
+ addPermissionBoundaryFindings(findings, tool);
270
+ }
271
+ for (const prompt of surfaces.prompts) {
272
+ addPoisoningFindings(findings, "prompt", prompt.name, prompt);
273
+ }
274
+ for (const resource of surfaces.resources) {
275
+ addPoisoningFindings(findings, "resource", resource.uri, resource);
276
+ }
277
+ for (const template of surfaces.resourceTemplates) {
278
+ addPoisoningFindings(findings, "resource", template.uriTemplate, template);
279
+ }
280
+ scanPreviousSnapshots(findings, previousChecks);
281
+ addDriftFindings(findings, surfaces.tools, options.baseline);
282
+ const status = statusForFindings(findings);
283
+ const high = findings.filter((finding) => finding.severity === "high").length;
284
+ const medium = findings.filter((finding) => finding.severity === "medium").length;
285
+ const low = findings.filter((finding) => finding.severity === "low").length;
286
+ const message = findings.length === 0
287
+ ? "Safe attack simulation found no high-risk MCP attack-readiness findings."
288
+ : `Safe attack simulation found ${findings.length} finding(s): ${high} high, ${medium} medium, ${low} low.`;
289
+ const diagnostics = findings.map((finding) => `[${finding.severity}] ${finding.message}`);
290
+ const evidence = {
291
+ endpoint: options.baseline ? "attack-sim/safe+baseline" : "attack-sim/safe",
292
+ advertised: true,
293
+ responded: true,
294
+ minimalShapePresent: true,
295
+ itemCount: findings.length,
296
+ identifiers: [...new Set(findings.map((finding) => finding.itemName))],
297
+ diagnostics: diagnostics.length > 0 ? diagnostics : undefined,
298
+ findings: findings.length > 0 ? findings.map((finding) => ({ ...finding })) : undefined,
299
+ };
300
+ return {
301
+ result: makeCheckResult("attack-sim", status, performance.now() - startedAt, message, [evidence]),
302
+ };
303
+ }
304
+ //# sourceMappingURL=attack-sim.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attack-sim.js","sourceRoot":"","sources":["../../../src/checks/attack-sim.ts"],"names":[],"mappings":"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"}