@visulima/vis-mcp 1.0.0-alpha.9 → 1.0.1

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 (34) hide show
  1. package/CHANGELOG.md +614 -0
  2. package/README.md +21 -12
  3. package/dist/bin.js +2 -2
  4. package/dist/index.d.ts +60 -1
  5. package/dist/index.js +1 -1
  6. package/dist/packem_shared/clearListCache-4BxipCYS.js +1 -0
  7. package/dist/packem_shared/createMcpServer-DOAejOGe.js +4 -0
  8. package/dist/packem_shared/errorResponse-CVaJrOoB.js +1 -0
  9. package/dist/packem_shared/execVis-CMeUcwPz.js +4 -0
  10. package/dist/packem_shared/isSafePositional-CJq1jfAS.js +1 -0
  11. package/dist/packem_shared/registerAdvisoryStatus-BHihSIOB.js +1 -0
  12. package/dist/packem_shared/registerAudit-DTsSWedQ.js +1 -0
  13. package/dist/packem_shared/registerCacheHash-gEdqaBTi.js +1 -0
  14. package/dist/packem_shared/registerCacheWhy-DSj2LYlR.js +1 -0
  15. package/dist/packem_shared/registerDescribeProject-HYlvD0tm.js +1 -0
  16. package/dist/packem_shared/registerDescribeTemplate-6RCmmfQs.js +1 -0
  17. package/dist/packem_shared/registerFmt-Dh0z0vq3.js +4 -0
  18. package/dist/packem_shared/registerGetRunLogs-CNGR-EcE.js +1 -0
  19. package/dist/packem_shared/registerLint-kA0hcRUz.js +4 -0
  20. package/dist/packem_shared/registerListProjects-DYz2st87.js +1 -0
  21. package/dist/packem_shared/registerListRuns-BPqPwFUQ.js +1 -0
  22. package/dist/packem_shared/registerListTargets-IWnJkyzy.js +1 -0
  23. package/dist/packem_shared/registerListTemplates-CSsN3JAE.js +1 -0
  24. package/package.json +21 -23
  25. package/dist/packem_shared/execVis-BzS_F-9x.js +0 -4
  26. package/dist/packem_shared/isValidRunId-BKsKMWQf.js +0 -1
  27. package/dist/packem_shared/okResponse-DdzqnveW.js +0 -1
  28. package/dist/packem_shared/registerAllTools-BOmyhKCR.js +0 -3
  29. package/dist/packem_shared/registerCacheHash-CVckSIVO.js +0 -1
  30. package/dist/packem_shared/registerCacheWhy-BfIjli7n.js +0 -1
  31. package/dist/packem_shared/registerDescribeProject-Dhuzun-I.js +0 -1
  32. package/dist/packem_shared/registerGetRunLogs-BxkRfYZU.js +0 -1
  33. package/dist/packem_shared/registerListProjects-C-AZj8RT.js +0 -1
  34. package/dist/packem_shared/registerListTargets-Cq6bkF7O.js +0 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,617 @@
1
+ ## @visulima/vis-mcp [1.0.1](https://github.com/visulima/visulima/compare/%40visulima%2Fvis-mcp%401.0.0...%40visulima%2Fvis-mcp%401.0.1) (2026-07-15)
2
+
3
+
4
+ ### Dependencies
5
+
6
+ * **@visulima/fs:** upgraded to 5.0.1
7
+ * **@visulima/vis:** upgraded to 1.0.1
8
+
9
+ ## @visulima/vis-mcp 1.0.0 (2026-07-03)
10
+
11
+ ### ⚠ BREAKING CHANGES
12
+
13
+ * **vis:** the following security.* keys were renamed:
14
+ - security.minimumReleaseAge -> security.policies.first_seen.minutes
15
+ - security.minimumReleaseAgeExclude -> security.policies.first_seen.exclude
16
+ - security.trustPolicy -> security.policies.publisher_change.mode
17
+ - security.trustPolicyExclude -> security.policies.publisher_change.exclude
18
+ - security.trustPolicyIgnoreAfter -> security.policies.publisher_change.ignoreAfter
19
+ - security.allowBuilds -> security.policies.install_scripts.allow
20
+ - security.strictDepBuilds -> security.policies.install_scripts.strict
21
+ - security.socket.minimumScore -> security.policies.score.minimum
22
+ - security.socket.acceptedRisks -> security.acceptedRisks
23
+ - security.audit.failOn -> security.policies.vulnerability.failOn
24
+ - security.audit.usage -> security.policies.vulnerability.usage
25
+
26
+ AcceptedRisk now carries optional policies[] and expiresAt fields so
27
+ risks can be scoped per-policy and time-boxed. Native PM sync writers
28
+ keep emitting pnpm-native field names since pnpm owns that schema.
29
+
30
+ Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
31
+
32
+ * chore(vis): address coderabbit review feedback
33
+
34
+ - Add JSDoc to exported items across hook builtins, advisories, audit, docker
35
+ - Document OSV `last_affected` inclusive-upper semantics with a focused test
36
+ - Annotate NAPI u64→u32 truncations with JS Number range rationale
37
+ - Switch vis-mcp tool payloads to zod schemas with `.catchall(z.unknown())`
38
+ so unknown CLI fields stay forward-compatible
39
+ - Fence RFC code blocks with explicit languages and tidy hook-command
40
+ formatting (multi-line type, implicit-return arrows)
41
+
42
+ Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
43
+
44
+ * chore(vis): address second-round coderabbit feedback on policies rename
45
+
46
+ - Drift report labels now reference `security.policies.*` paths so the
47
+ hint matches the keys users edit
48
+ - `defineConfig` JSDoc examples use the new `security.policies` shape
49
+ - `mergeSecurityDefaults` deep-merges every defaulted sub-policy
50
+ generically; `mergeVisConfigs` deep-merges `policies` and
51
+ `acceptedRisks` so presets aren't clobbered
52
+ - Config-writer scopes its `allow:` match to follow an
53
+ `install_scripts:` opener
54
+ - JSDoc clarifications for `audit.advisories.source` default,
55
+ `acceptedRisks.expiresAt`/`acceptedScore` ranges, `malware.mode`
56
+ cross-field default, and the current `policies.score.minimum`
57
+ wiring gap
58
+
59
+ Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
60
+
61
+ * chore(vis): finish coderabbit round-2 fixes — camelCase policies + wire score.minimum
62
+
63
+ - Rename `PolicyName` union to camelCase (`firstSeen`, `installScripts`,
64
+ `publisherChange`, `unexpectedDeps`). Updates every consumer in src/,
65
+ test fixtures, schemas, and docs. JSON schema regenerated.
66
+ - Add `types` mapping to the `#native` package.json import so TypeScript
67
+ resolves `index.d.ts` when consumers import the alias.
68
+ - Thread `socketOptions.minimumScore` through `audit`, `doctor`, `check`,
69
+ `update`, `add`, `formatSecurityOverview`, `formatSummary`, and
70
+ `applyFilter`. `buildSocketOptions` now resolves the effective minimum
71
+ once (from `security.policies.score.minimum` or
72
+ `DEFAULT_LOW_SCORE_THRESHOLD`) so every consumer sees the same value
73
+ instead of comparing scores against the hard-coded constant.
74
+ - Update the JSDoc on `policies.score.minimum` to reflect the new wiring.
75
+
76
+ Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
77
+
78
+ * feat(vis): add Socket-style policy engine with 4 offline-clean policies
79
+
80
+ Introduce a unified `evaluatePolicies()` engine under `src/security/policies/`
81
+ with four offline-clean modules: license, install_scripts, vulnerability,
82
+ and unexpected_deps (baseline mode). Each policy emits PolicyDecisions
83
+ (block/warn/info) keyed by package, with per-policy accepted-risk scoping
84
+ and expiresAt support reused from the shared matcher.
85
+
86
+ Wires the engine into `vis audit`: a new `--policies <names>` flag
87
+ (comma-list, `all`, or `none`) narrows evaluation. Block-severity
88
+ decisions feed into `--exit-code` and `--fail-on`. JSON output gains
89
+ `policies[]` + `summary.policyBlocks`. SARIF and HTML formatters render
90
+ policy decisions alongside vulnerabilities; CSAF and CycloneDX-VEX are
91
+ intentionally left untouched (vuln-specific data models).
92
+
93
+ Adds `readNodeModulesManifests()` to walk `node_modules/` (including the
94
+ pnpm `.pnpm/` content-addressed store) and surface license + scripts +
95
+ maintainers metadata for the offline policies.
96
+
97
+ 33 new unit + integration tests; full vitest suite (3582/3582) green;
98
+ `tsc --noEmit` clean.
99
+
100
+ Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
101
+
102
+ * fix(vis): close three audit policy gating gaps surfaced by CodeRabbit
103
+
104
+ - applyExitGate's fallthrough call to applyFailOnGate was dropping the
105
+ policyDecisions argument, so `vis audit --format sarif --fail-on high`
106
+ exited 0 when the only signal was a block-severity policy decision.
107
+ Forward the argument.
108
+ - Unknown --policies tokens were silently swallowed when format was
109
+ json/sarif/csaf/cyclonedx-vex, so a typoed CI invocation reduced
110
+ enforcement with no log. Always emit the warning to stderr and
111
+ surface the tokens in JSON output as `warnings[]`.
112
+ - Vulnerability-policy block decisions whose advisory was masked by
113
+ --severity used to exit 1 with no visible reason. Surface those
114
+ decisions in the human-readable "Policy Decisions" section so the
115
+ gate is always traceable.
116
+
117
+ Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
118
+
119
+ * fix(vis): correct npm/yarn min-release-age native config writers
120
+
121
+ npm CLI types `min-release-age` as `Number` in days, not a duration string —
122
+ vis wrote `48h`/`15m`, which npm's parseInt would silently read as 48/15 days.
123
+ Write integer days rounded up so the native gate is never weaker than vis-config.
124
+
125
+ Yarn Berry silently treats day suffixes in `npmMinimalAgeGate` as minutes
126
+
127
+ ### Features
128
+
129
+ * **vis-mcp:** add audit/advisory/lint/fmt/list_runs tools and structured output ([4918e4b](https://github.com/visulima/visulima/commit/4918e4bb176508065bc8a578141beb79316c530d))
130
+ * **vis-mcp:** add list_templates and describe_template tools ([549ea7e](https://github.com/visulima/visulima/commit/549ea7edbe88e3dde40e09cf5f5eaea80bb8fd58))
131
+ * **vis-mcp:** add MCP server package for AI-agent integration ([a8d5022](https://github.com/visulima/visulima/commit/a8d5022ba905481985378c0ac01e7f654608ec2b))
132
+ * **vis:** lint + fmt orchestrator ([3a78ed7](https://github.com/visulima/visulima/commit/3a78ed709922e6a35648e0d0eb3f41cc49f89b7a))
133
+ * **vis:** offline OSV scanner + unified security.policies ([#632](https://github.com/visulima/visulima/issues/632)) ([6461902](https://github.com/visulima/visulima/commit/646190243bf51bb6df172665d70fd501644e7bc3)), closes [#631](https://github.com/visulima/visulima/issues/631) [#631](https://github.com/visulima/visulima/issues/631) [yarnpkg/berry#6991](https://github.com/yarnpkg/berry/issues/6991)
134
+
135
+ ### Bug Fixes
136
+
137
+ * **storage-client:** percent-encode user fields in defaultFingerprint ([7c78a0f](https://github.com/visulima/visulima/commit/7c78a0f9512e2a673b941d80839e9f1e86b7b5d0))
138
+ * **tests:** revert unsafe vitest autofixes from the lint sweep ([378f27c](https://github.com/visulima/visulima/commit/378f27caa370f1d3188aef2ed36d46839abc88c4))
139
+ * **vis-mcp:** 1 bug fix ([33cd25e](https://github.com/visulima/visulima/commit/33cd25ecbcea0185e4cab1e3d49ba0fd41206d67))
140
+ * **vis:** unbreak full build — exclude variable-import modules from dynamic-import-vars ([#712](https://github.com/visulima/visulima/issues/712)) ([29d46eb](https://github.com/visulima/visulima/commit/29d46eb719de11ab8f09e5303748264607b04fe3)), closes [#697](https://github.com/visulima/visulima/issues/697) [#697](https://github.com/visulima/visulima/issues/697) [#697](https://github.com/visulima/visulima/issues/697) [#697](https://github.com/visulima/visulima/issues/697)
141
+
142
+ ### Miscellaneous Chores
143
+
144
+ * add fallow code-intelligence across all packages ([a3b4821](https://github.com/visulima/visulima/commit/a3b48215002e86fed20f2973038b5d4a0aa1ce04))
145
+ * apply eslint + prettier autofixes across packages ([c1bb784](https://github.com/visulima/visulima/commit/c1bb7848a0d93d0dfe2960c77e3cda22239c79a0))
146
+ * **ci-stability:** green CI across vis, native, lint, tests, attw ([#651](https://github.com/visulima/visulima/issues/651)) ([d4eb684](https://github.com/visulima/visulima/commit/d4eb684b5f75c818c9251048c605a0ed54a268e3))
147
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.1 [skip ci]\n\n## @visulima/vis-mcp 1.0.0-alpha.1 (2026-05-04) ([4bea1b6](https://github.com/visulima/visulima/commit/4bea1b639140431c9fa25656d4a2225ddb1073d1))
148
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.10 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.10](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.9...@visulima/vis-mcp@1.0.0-alpha.10) (2026-05-14) ([aa118b9](https://github.com/visulima/visulima/commit/aa118b9acab23ace6523bc1b1b6ed2b5b5c4b69f))
149
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.11 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.11](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.10...@visulima/vis-mcp@1.0.0-alpha.11) (2026-05-16) ([e1c0f42](https://github.com/visulima/visulima/commit/e1c0f42676885a1ae0dbe867f2d3750ea2b60816))
150
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.12 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.12](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.11...@visulima/vis-mcp@1.0.0-alpha.12) (2026-05-19) ([df08589](https://github.com/visulima/visulima/commit/df085896065d7ee11b0ac48119cbc4d18542bce2))
151
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.13 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.13](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.12...@visulima/vis-mcp@1.0.0-alpha.13) (2026-05-20) ([6ac5046](https://github.com/visulima/visulima/commit/6ac50469ba4193756ce27e60010bf7725dd214e9))
152
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.14 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.14](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.13...@visulima/vis-mcp@1.0.0-alpha.14) (2026-05-26) ([a816f32](https://github.com/visulima/visulima/commit/a816f32ca84ad91e6a36fa852453dfdb095e218c))
153
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.15 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.15](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.14...@visulima/vis-mcp@1.0.0-alpha.15) (2026-05-27) ([8c626df](https://github.com/visulima/visulima/commit/8c626df8cfe37b190c7199446012be356b380dbb))
154
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.16 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.16](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.15...@visulima/vis-mcp@1.0.0-alpha.16) (2026-05-29) ([7f98d00](https://github.com/visulima/visulima/commit/7f98d002e55a7c70f70ef4648bc6622bb4bb2686))
155
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.17 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.17](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.16...@visulima/vis-mcp@1.0.0-alpha.17) (2026-06-02) ([5e112bb](https://github.com/visulima/visulima/commit/5e112bbcfc982bafa6a18d38916d172dbe209717))
156
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.18 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.18](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.17...@visulima/vis-mcp@1.0.0-alpha.18) (2026-06-03) ([8cb3d99](https://github.com/visulima/visulima/commit/8cb3d990a30e5765f52b2a558064c7e2cd29d759))
157
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.19 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.19](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.18...@visulima/vis-mcp@1.0.0-alpha.19) (2026-06-04) ([8210e8c](https://github.com/visulima/visulima/commit/8210e8cad57916e4b8736dcb95e640a40dda713f))
158
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.2 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.2](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.1...@visulima/vis-mcp@1.0.0-alpha.2) (2026-05-06) ([fcf91fa](https://github.com/visulima/visulima/commit/fcf91fa4c22cf3314b57bd45a28e67281351e65d))
159
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.20 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.20](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.19...@visulima/vis-mcp@1.0.0-alpha.20) (2026-06-04) ([7000c46](https://github.com/visulima/visulima/commit/7000c4608e54de019a93562c2255c96fca1afb7d))
160
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.21 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.21](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.20...@visulima/vis-mcp@1.0.0-alpha.21) (2026-06-06) ([3abc667](https://github.com/visulima/visulima/commit/3abc66722bea0d69730b60bec445cd1e2b9ae948))
161
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.22 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.22](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.21...@visulima/vis-mcp@1.0.0-alpha.22) (2026-06-07) ([3062334](https://github.com/visulima/visulima/commit/306233441335f5e36b6ffc386f9233c98b529631))
162
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.23 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.23](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.22...@visulima/vis-mcp@1.0.0-alpha.23) (2026-06-07) ([9262893](https://github.com/visulima/visulima/commit/92628936ed49da4277a06ffea13163f87278cbd2))
163
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.24 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.24](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.23...@visulima/vis-mcp@1.0.0-alpha.24) (2026-06-08) ([8f8c3dc](https://github.com/visulima/visulima/commit/8f8c3dcedab8d80818a07b35642f09b1791801ed))
164
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.25 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.25](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.24...@visulima/vis-mcp@1.0.0-alpha.25) (2026-06-09) ([fd66314](https://github.com/visulima/visulima/commit/fd6631451ed09ec1096800d06f09bd3d70e609f6))
165
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.26 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.26](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.25...@visulima/vis-mcp@1.0.0-alpha.26) (2026-06-13) ([9bcbaa2](https://github.com/visulima/visulima/commit/9bcbaa2ab0334786180881c36d85cad6782f715d))
166
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.27 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.27](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.26...@visulima/vis-mcp@1.0.0-alpha.27) (2026-06-15) ([13222ff](https://github.com/visulima/visulima/commit/13222ffedbc93110bc557e9574470d9d2076490b))
167
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.28 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.28](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.27...@visulima/vis-mcp@1.0.0-alpha.28) (2026-06-16) ([41bbb5f](https://github.com/visulima/visulima/commit/41bbb5f5aaf36382dfeb5dcf97565c23dfceb3ac))
168
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.29 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.29](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.28...@visulima/vis-mcp@1.0.0-alpha.29) (2026-06-16) ([6b911f6](https://github.com/visulima/visulima/commit/6b911f682352b8c3cea5f589f9e11c336c4192ce))
169
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.3 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.3](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.2...@visulima/vis-mcp@1.0.0-alpha.3) (2026-05-06) ([30cfcda](https://github.com/visulima/visulima/commit/30cfcdabff162902ed53e018420f53967c6d2d9a))
170
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.30 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.30](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.29...@visulima/vis-mcp@1.0.0-alpha.30) (2026-06-17) ([ba5f8d2](https://github.com/visulima/visulima/commit/ba5f8d261ab2f0907ae0a8e46f54c0217205bf0e))
171
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.31 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.31](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.30...@visulima/vis-mcp@1.0.0-alpha.31) (2026-06-19) ([ec79624](https://github.com/visulima/visulima/commit/ec7962425122ed9cbd534a159da1909fc290da0b))
172
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.32 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.32](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.31...@visulima/vis-mcp@1.0.0-alpha.32) (2026-06-19) ([581a6ef](https://github.com/visulima/visulima/commit/581a6ef35da1471486c6f8e1f63603a5b29d4e8e))
173
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.33 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.33](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.32...@visulima/vis-mcp@1.0.0-alpha.33) (2026-06-20) ([d23610f](https://github.com/visulima/visulima/commit/d23610f925906eae32512f8cece804d6d17e980c))
174
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.34 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.34](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.33...@visulima/vis-mcp@1.0.0-alpha.34) (2026-06-23) ([a90381f](https://github.com/visulima/visulima/commit/a90381f477ffb2638ac37a7cdfc6bb25a28d89be))
175
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.35 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.35](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.34...@visulima/vis-mcp@1.0.0-alpha.35) (2026-06-30) ([a4ccaf6](https://github.com/visulima/visulima/commit/a4ccaf66eba5dbd6e81567e369c2bed6902ad8ff))
176
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.36 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.36](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.35...@visulima/vis-mcp@1.0.0-alpha.36) (2026-07-01) ([beca008](https://github.com/visulima/visulima/commit/beca00876cd9282fb703063c3074e6ea8843af85))
177
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.37 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.37](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.36...@visulima/vis-mcp@1.0.0-alpha.37) (2026-07-03) ([105c996](https://github.com/visulima/visulima/commit/105c996f6433c5609bdbeb7b045508a8da5acda5))
178
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.4 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.4](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.3...@visulima/vis-mcp@1.0.0-alpha.4) (2026-05-07) ([1783ff4](https://github.com/visulima/visulima/commit/1783ff4dfcdfa2930876d1a21ebc4494fa25e26d))
179
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.5 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.5](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.4...@visulima/vis-mcp@1.0.0-alpha.5) (2026-05-07) ([11fdc83](https://github.com/visulima/visulima/commit/11fdc83848f17c272730dc8f4dc87270f78d434c))
180
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.6 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.6](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.5...@visulima/vis-mcp@1.0.0-alpha.6) (2026-05-10) ([94bb50c](https://github.com/visulima/visulima/commit/94bb50cb28bf9a4d0630d7da703f9c09de17b1f3))
181
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.7 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.7](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.6...@visulima/vis-mcp@1.0.0-alpha.7) (2026-05-10) ([299de51](https://github.com/visulima/visulima/commit/299de51d78febde7024b30ce8242703b75fb06b4))
182
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.8 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.8](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.7...@visulima/vis-mcp@1.0.0-alpha.8) (2026-05-11) ([de533a9](https://github.com/visulima/visulima/commit/de533a9dd9f32d2dc90d2f8a9f322fc950f1eaaf))
183
+ * **release:** @visulima/vis-mcp@1.0.0-alpha.9 [skip ci]\n\n## @visulima/vis-mcp [1.0.0-alpha.9](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.8...@visulima/vis-mcp@1.0.0-alpha.9) (2026-05-11) ([308df7f](https://github.com/visulima/visulima/commit/308df7f556442ff017635a31f4fc19326c7efec7))
184
+ * **repo:** apply eslint --fix and prettier --fix across packages ([#650](https://github.com/visulima/visulima/issues/650)) ([2e26a84](https://github.com/visulima/visulima/commit/2e26a84774f218f21345e9a8ecd68236b6542743)), closes [#620](https://github.com/visulima/visulima/issues/620)
185
+ * sorted package.json ([b47c545](https://github.com/visulima/visulima/commit/b47c545591600fdab17d5cd3a3fbc68b61e199da))
186
+ * **vis-mcp:** adopt zod v4 catalog and bump @modelcontextprotocol/sdk ([a84ceb1](https://github.com/visulima/visulima/commit/a84ceb1efcfb368c361eb738006f2e7f113ac4c7))
187
+ * **vis-mcp:** bump eslint-plugin-zod and sort package.json keys ([787abc4](https://github.com/visulima/visulima/commit/787abc46e1b637fdb8968a492cd923537e404fbe))
188
+ * **vis-mcp:** housekeeping cleanup ([947eff5](https://github.com/visulima/visulima/commit/947eff503b5e170194f7f8e21bea2ab82b0786bf))
189
+
190
+ ### Code Refactoring
191
+
192
+ * **vis-mcp:** reformat source and README for prettier line-length ([5b41e65](https://github.com/visulima/visulima/commit/5b41e65dceb622cecf554b938261fb7c550a47bd))
193
+
194
+ ### Tests
195
+
196
+ * improve coverage across packages ([91bd6d3](https://github.com/visulima/visulima/commit/91bd6d3b61736e3c8bd1fc59b0b5955f76a5d323))
197
+ * **repo:** cover bin entry points in dist integration suite ([7479ef1](https://github.com/visulima/visulima/commit/7479ef113cf5ccef25692619082afb1b6a0eecab))
198
+ * **vis-mcp:** assert error payloads are strings ([cf18663](https://github.com/visulima/visulima/commit/cf1866327423e77b6a99d6e6e41ebc9f10995dc2))
199
+ * **vis-mcp:** cover cli-failure catch paths, resolveVisBin fallback, and version/exec edge branches ([a46fa08](https://github.com/visulima/visulima/commit/a46fa08c991ceeab1e5d4ae575768581aba7bdec))
200
+
201
+ ### Build System
202
+
203
+ * **deps:** update vis-mcp dependencies ([5f27664](https://github.com/visulima/visulima/commit/5f2766405b74001dee44f90722e65608a71434ac))
204
+
205
+ ### Continuous Integration
206
+
207
+ * **fallow:** make fallow:health advisory (--report-only) ([d57148e](https://github.com/visulima/visulima/commit/d57148ea0e3556b4c24d8d336b9fa14987f5dc7d))
208
+
209
+
210
+ ### Dependencies
211
+
212
+ * **@visulima/fs:** upgraded to 5.0.0
213
+ * **@visulima/path:** upgraded to 3.0.0
214
+ * **@visulima/vis:** upgraded to 1.0.0
215
+
216
+ ## @visulima/vis-mcp [1.0.0-alpha.37](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.36...@visulima/vis-mcp@1.0.0-alpha.37) (2026-07-03)
217
+
218
+
219
+ ### Dependencies
220
+
221
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.47
222
+
223
+ ## @visulima/vis-mcp [1.0.0-alpha.36](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.35...@visulima/vis-mcp@1.0.0-alpha.36) (2026-07-01)
224
+
225
+
226
+ ### Dependencies
227
+
228
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.46
229
+
230
+ ## @visulima/vis-mcp [1.0.0-alpha.35](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.34...@visulima/vis-mcp@1.0.0-alpha.35) (2026-06-30)
231
+
232
+ ### Miscellaneous Chores
233
+
234
+ * add fallow code-intelligence across all packages ([a3b4821](https://github.com/visulima/visulima/commit/a3b48215002e86fed20f2973038b5d4a0aa1ce04))
235
+
236
+ ### Continuous Integration
237
+
238
+ * **fallow:** make fallow:health advisory (--report-only) ([d57148e](https://github.com/visulima/visulima/commit/d57148ea0e3556b4c24d8d336b9fa14987f5dc7d))
239
+
240
+
241
+ ### Dependencies
242
+
243
+ * **@visulima/fs:** upgraded to 5.0.0-alpha.33
244
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.45
245
+
246
+ ## @visulima/vis-mcp [1.0.0-alpha.34](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.33...@visulima/vis-mcp@1.0.0-alpha.34) (2026-06-23)
247
+
248
+ ### Bug Fixes
249
+
250
+ * **vis:** unbreak full build — exclude variable-import modules from dynamic-import-vars ([#712](https://github.com/visulima/visulima/issues/712)) ([29d46eb](https://github.com/visulima/visulima/commit/29d46eb719de11ab8f09e5303748264607b04fe3)), closes [#697](https://github.com/visulima/visulima/issues/697) [#697](https://github.com/visulima/visulima/issues/697) [#697](https://github.com/visulima/visulima/issues/697) [#697](https://github.com/visulima/visulima/issues/697)
251
+
252
+
253
+ ### Dependencies
254
+
255
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.44
256
+
257
+ ## @visulima/vis-mcp [1.0.0-alpha.33](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.32...@visulima/vis-mcp@1.0.0-alpha.33) (2026-06-20)
258
+
259
+
260
+ ### Dependencies
261
+
262
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.43
263
+
264
+ ## @visulima/vis-mcp [1.0.0-alpha.32](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.31...@visulima/vis-mcp@1.0.0-alpha.32) (2026-06-19)
265
+
266
+
267
+ ### Dependencies
268
+
269
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.42
270
+
271
+ ## @visulima/vis-mcp [1.0.0-alpha.31](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.30...@visulima/vis-mcp@1.0.0-alpha.31) (2026-06-19)
272
+
273
+
274
+ ### Dependencies
275
+
276
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.41
277
+
278
+ ## @visulima/vis-mcp [1.0.0-alpha.30](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.29...@visulima/vis-mcp@1.0.0-alpha.30) (2026-06-17)
279
+
280
+
281
+ ### Dependencies
282
+
283
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.40
284
+
285
+ ## @visulima/vis-mcp [1.0.0-alpha.29](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.28...@visulima/vis-mcp@1.0.0-alpha.29) (2026-06-16)
286
+
287
+
288
+ ### Dependencies
289
+
290
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.39
291
+
292
+ ## @visulima/vis-mcp [1.0.0-alpha.28](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.27...@visulima/vis-mcp@1.0.0-alpha.28) (2026-06-16)
293
+
294
+
295
+ ### Dependencies
296
+
297
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.38
298
+
299
+ ## @visulima/vis-mcp [1.0.0-alpha.27](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.26...@visulima/vis-mcp@1.0.0-alpha.27) (2026-06-15)
300
+
301
+
302
+ ### Dependencies
303
+
304
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.37
305
+
306
+ ## @visulima/vis-mcp [1.0.0-alpha.26](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.25...@visulima/vis-mcp@1.0.0-alpha.26) (2026-06-13)
307
+
308
+ ### Features
309
+
310
+ * **vis-mcp:** add audit/advisory/lint/fmt/list_runs tools and structured output ([4918e4b](https://github.com/visulima/visulima/commit/4918e4bb176508065bc8a578141beb79316c530d))
311
+
312
+ ### Code Refactoring
313
+
314
+ * **vis-mcp:** reformat source and README for prettier line-length ([5b41e65](https://github.com/visulima/visulima/commit/5b41e65dceb622cecf554b938261fb7c550a47bd))
315
+
316
+ ### Tests
317
+
318
+ * **vis-mcp:** assert error payloads are strings ([cf18663](https://github.com/visulima/visulima/commit/cf1866327423e77b6a99d6e6e41ebc9f10995dc2))
319
+
320
+ ### Build System
321
+
322
+ * **deps:** update vis-mcp dependencies ([5f27664](https://github.com/visulima/visulima/commit/5f2766405b74001dee44f90722e65608a71434ac))
323
+
324
+
325
+ ### Dependencies
326
+
327
+ * **@visulima/fs:** upgraded to 5.0.0-alpha.32
328
+ * **@visulima/path:** upgraded to 3.0.0-alpha.13
329
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.36
330
+
331
+ ## @visulima/vis-mcp [1.0.0-alpha.25](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.24...@visulima/vis-mcp@1.0.0-alpha.25) (2026-06-09)
332
+
333
+
334
+ ### Dependencies
335
+
336
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.35
337
+
338
+ ## @visulima/vis-mcp [1.0.0-alpha.24](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.23...@visulima/vis-mcp@1.0.0-alpha.24) (2026-06-08)
339
+
340
+
341
+ ### Dependencies
342
+
343
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.34
344
+
345
+ ## @visulima/vis-mcp [1.0.0-alpha.23](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.22...@visulima/vis-mcp@1.0.0-alpha.23) (2026-06-07)
346
+
347
+
348
+ ### Dependencies
349
+
350
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.33
351
+
352
+ ## @visulima/vis-mcp [1.0.0-alpha.22](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.21...@visulima/vis-mcp@1.0.0-alpha.22) (2026-06-07)
353
+
354
+
355
+ ### Dependencies
356
+
357
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.32
358
+
359
+ ## @visulima/vis-mcp [1.0.0-alpha.21](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.20...@visulima/vis-mcp@1.0.0-alpha.21) (2026-06-06)
360
+
361
+
362
+ ### Dependencies
363
+
364
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.31
365
+
366
+ ## @visulima/vis-mcp [1.0.0-alpha.20](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.19...@visulima/vis-mcp@1.0.0-alpha.20) (2026-06-04)
367
+
368
+
369
+ ### Dependencies
370
+
371
+ * **@visulima/fs:** upgraded to 5.0.0-alpha.31
372
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.30
373
+
374
+ ## @visulima/vis-mcp [1.0.0-alpha.19](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.18...@visulima/vis-mcp@1.0.0-alpha.19) (2026-06-04)
375
+
376
+ ### Bug Fixes
377
+
378
+ * **vis-mcp:** 1 bug fix ([33cd25e](https://github.com/visulima/visulima/commit/33cd25ecbcea0185e4cab1e3d49ba0fd41206d67))
379
+
380
+
381
+ ### Dependencies
382
+
383
+ * **@visulima/fs:** upgraded to 5.0.0-alpha.30
384
+ * **@visulima/path:** upgraded to 3.0.0-alpha.12
385
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.29
386
+
387
+ ## @visulima/vis-mcp [1.0.0-alpha.18](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.17...@visulima/vis-mcp@1.0.0-alpha.18) (2026-06-03)
388
+
389
+
390
+ ### Dependencies
391
+
392
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.28
393
+
394
+ ## @visulima/vis-mcp [1.0.0-alpha.17](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.16...@visulima/vis-mcp@1.0.0-alpha.17) (2026-06-02)
395
+
396
+ ### Features
397
+
398
+ * **vis:** lint + fmt orchestrator ([3a78ed7](https://github.com/visulima/visulima/commit/3a78ed709922e6a35648e0d0eb3f41cc49f89b7a))
399
+
400
+ ### Bug Fixes
401
+
402
+ * **tests:** revert unsafe vitest autofixes from the lint sweep ([378f27c](https://github.com/visulima/visulima/commit/378f27caa370f1d3188aef2ed36d46839abc88c4))
403
+
404
+ ### Miscellaneous Chores
405
+
406
+ * apply eslint + prettier autofixes across packages ([c1bb784](https://github.com/visulima/visulima/commit/c1bb7848a0d93d0dfe2960c77e3cda22239c79a0))
407
+
408
+ ### Tests
409
+
410
+ * **vis-mcp:** cover cli-failure catch paths, resolveVisBin fallback, and version/exec edge branches ([a46fa08](https://github.com/visulima/visulima/commit/a46fa08c991ceeab1e5d4ae575768581aba7bdec))
411
+
412
+
413
+ ### Dependencies
414
+
415
+ * **@visulima/fs:** upgraded to 5.0.0-alpha.29
416
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.27
417
+
418
+ ## @visulima/vis-mcp [1.0.0-alpha.16](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.15...@visulima/vis-mcp@1.0.0-alpha.16) (2026-05-29)
419
+
420
+ ### Tests
421
+
422
+ * improve coverage across packages ([91bd6d3](https://github.com/visulima/visulima/commit/91bd6d3b61736e3c8bd1fc59b0b5955f76a5d323))
423
+
424
+
425
+ ### Dependencies
426
+
427
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.26
428
+
429
+ ## @visulima/vis-mcp [1.0.0-alpha.15](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.14...@visulima/vis-mcp@1.0.0-alpha.15) (2026-05-27)
430
+
431
+ ### Bug Fixes
432
+
433
+ * **storage-client:** percent-encode user fields in defaultFingerprint ([7c78a0f](https://github.com/visulima/visulima/commit/7c78a0f9512e2a673b941d80839e9f1e86b7b5d0))
434
+
435
+ ### Miscellaneous Chores
436
+
437
+ * sorted package.json ([b47c545](https://github.com/visulima/visulima/commit/b47c545591600fdab17d5cd3a3fbc68b61e199da))
438
+
439
+
440
+ ### Dependencies
441
+
442
+ * **@visulima/fs:** upgraded to 5.0.0-alpha.28
443
+ * **@visulima/path:** upgraded to 3.0.0-alpha.11
444
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.25
445
+
446
+ ## @visulima/vis-mcp [1.0.0-alpha.14](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.13...@visulima/vis-mcp@1.0.0-alpha.14) (2026-05-26)
447
+
448
+ ### Miscellaneous Chores
449
+
450
+ * **ci-stability:** green CI across vis, native, lint, tests, attw ([#651](https://github.com/visulima/visulima/issues/651)) ([d4eb684](https://github.com/visulima/visulima/commit/d4eb684b5f75c818c9251048c605a0ed54a268e3))
451
+ * **repo:** apply eslint --fix and prettier --fix across packages ([#650](https://github.com/visulima/visulima/issues/650)) ([2e26a84](https://github.com/visulima/visulima/commit/2e26a84774f218f21345e9a8ecd68236b6542743)), closes [#620](https://github.com/visulima/visulima/issues/620)
452
+
453
+ ### Tests
454
+
455
+ * **repo:** cover bin entry points in dist integration suite ([7479ef1](https://github.com/visulima/visulima/commit/7479ef113cf5ccef25692619082afb1b6a0eecab))
456
+
457
+
458
+ ### Dependencies
459
+
460
+ * **@visulima/fs:** upgraded to 5.0.0-alpha.26
461
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.24
462
+
463
+ ## @visulima/vis-mcp [1.0.0-alpha.13](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.12...@visulima/vis-mcp@1.0.0-alpha.13) (2026-05-20)
464
+
465
+
466
+ ### Dependencies
467
+
468
+ * **@visulima/fs:** upgraded to 5.0.0-alpha.25
469
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.23
470
+
471
+ ## @visulima/vis-mcp [1.0.0-alpha.12](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.11...@visulima/vis-mcp@1.0.0-alpha.12) (2026-05-19)
472
+
473
+
474
+ ### Dependencies
475
+
476
+ * **@visulima/fs:** upgraded to 5.0.0-alpha.24
477
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.22
478
+
479
+ ## @visulima/vis-mcp [1.0.0-alpha.11](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.10...@visulima/vis-mcp@1.0.0-alpha.11) (2026-05-16)
480
+
481
+
482
+ ### Dependencies
483
+
484
+ * **@visulima/fs:** upgraded to 5.0.0-alpha.23
485
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.21
486
+
487
+ ## @visulima/vis-mcp [1.0.0-alpha.10](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.9...@visulima/vis-mcp@1.0.0-alpha.10) (2026-05-14)
488
+
489
+ ### ⚠ BREAKING CHANGES
490
+
491
+ * **vis:** the following security.* keys were renamed:
492
+ - security.minimumReleaseAge -> security.policies.first_seen.minutes
493
+ - security.minimumReleaseAgeExclude -> security.policies.first_seen.exclude
494
+ - security.trustPolicy -> security.policies.publisher_change.mode
495
+ - security.trustPolicyExclude -> security.policies.publisher_change.exclude
496
+ - security.trustPolicyIgnoreAfter -> security.policies.publisher_change.ignoreAfter
497
+ - security.allowBuilds -> security.policies.install_scripts.allow
498
+ - security.strictDepBuilds -> security.policies.install_scripts.strict
499
+ - security.socket.minimumScore -> security.policies.score.minimum
500
+ - security.socket.acceptedRisks -> security.acceptedRisks
501
+ - security.audit.failOn -> security.policies.vulnerability.failOn
502
+ - security.audit.usage -> security.policies.vulnerability.usage
503
+
504
+ AcceptedRisk now carries optional policies[] and expiresAt fields so
505
+ risks can be scoped per-policy and time-boxed. Native PM sync writers
506
+ keep emitting pnpm-native field names since pnpm owns that schema.
507
+
508
+ Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
509
+
510
+ * chore(vis): address coderabbit review feedback
511
+
512
+ - Add JSDoc to exported items across hook builtins, advisories, audit, docker
513
+ - Document OSV `last_affected` inclusive-upper semantics with a focused test
514
+ - Annotate NAPI u64→u32 truncations with JS Number range rationale
515
+ - Switch vis-mcp tool payloads to zod schemas with `.catchall(z.unknown())`
516
+ so unknown CLI fields stay forward-compatible
517
+ - Fence RFC code blocks with explicit languages and tidy hook-command
518
+ formatting (multi-line type, implicit-return arrows)
519
+
520
+ Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
521
+
522
+ * chore(vis): address second-round coderabbit feedback on policies rename
523
+
524
+ - Drift report labels now reference `security.policies.*` paths so the
525
+ hint matches the keys users edit
526
+ - `defineConfig` JSDoc examples use the new `security.policies` shape
527
+ - `mergeSecurityDefaults` deep-merges every defaulted sub-policy
528
+ generically; `mergeVisConfigs` deep-merges `policies` and
529
+ `acceptedRisks` so presets aren't clobbered
530
+ - Config-writer scopes its `allow:` match to follow an
531
+ `install_scripts:` opener
532
+ - JSDoc clarifications for `audit.advisories.source` default,
533
+ `acceptedRisks.expiresAt`/`acceptedScore` ranges, `malware.mode`
534
+ cross-field default, and the current `policies.score.minimum`
535
+ wiring gap
536
+
537
+ Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
538
+
539
+ * chore(vis): finish coderabbit round-2 fixes — camelCase policies + wire score.minimum
540
+
541
+ - Rename `PolicyName` union to camelCase (`firstSeen`, `installScripts`,
542
+ `publisherChange`, `unexpectedDeps`). Updates every consumer in src/,
543
+ test fixtures, schemas, and docs. JSON schema regenerated.
544
+ - Add `types` mapping to the `#native` package.json import so TypeScript
545
+ resolves `index.d.ts` when consumers import the alias.
546
+ - Thread `socketOptions.minimumScore` through `audit`, `doctor`, `check`,
547
+ `update`, `add`, `formatSecurityOverview`, `formatSummary`, and
548
+ `applyFilter`. `buildSocketOptions` now resolves the effective minimum
549
+ once (from `security.policies.score.minimum` or
550
+ `DEFAULT_LOW_SCORE_THRESHOLD`) so every consumer sees the same value
551
+ instead of comparing scores against the hard-coded constant.
552
+ - Update the JSDoc on `policies.score.minimum` to reflect the new wiring.
553
+
554
+ Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
555
+
556
+ * feat(vis): add Socket-style policy engine with 4 offline-clean policies
557
+
558
+ Introduce a unified `evaluatePolicies()` engine under `src/security/policies/`
559
+ with four offline-clean modules: license, install_scripts, vulnerability,
560
+ and unexpected_deps (baseline mode). Each policy emits PolicyDecisions
561
+ (block/warn/info) keyed by package, with per-policy accepted-risk scoping
562
+ and expiresAt support reused from the shared matcher.
563
+
564
+ Wires the engine into `vis audit`: a new `--policies <names>` flag
565
+ (comma-list, `all`, or `none`) narrows evaluation. Block-severity
566
+ decisions feed into `--exit-code` and `--fail-on`. JSON output gains
567
+ `policies[]` + `summary.policyBlocks`. SARIF and HTML formatters render
568
+ policy decisions alongside vulnerabilities; CSAF and CycloneDX-VEX are
569
+ intentionally left untouched (vuln-specific data models).
570
+
571
+ Adds `readNodeModulesManifests()` to walk `node_modules/` (including the
572
+ pnpm `.pnpm/` content-addressed store) and surface license + scripts +
573
+ maintainers metadata for the offline policies.
574
+
575
+ 33 new unit + integration tests; full vitest suite (3582/3582) green;
576
+ `tsc --noEmit` clean.
577
+
578
+ Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
579
+
580
+ * fix(vis): close three audit policy gating gaps surfaced by CodeRabbit
581
+
582
+ - applyExitGate's fallthrough call to applyFailOnGate was dropping the
583
+ policyDecisions argument, so `vis audit --format sarif --fail-on high`
584
+ exited 0 when the only signal was a block-severity policy decision.
585
+ Forward the argument.
586
+ - Unknown --policies tokens were silently swallowed when format was
587
+ json/sarif/csaf/cyclonedx-vex, so a typoed CI invocation reduced
588
+ enforcement with no log. Always emit the warning to stderr and
589
+ surface the tokens in JSON output as `warnings[]`.
590
+ - Vulnerability-policy block decisions whose advisory was masked by
591
+ --severity used to exit 1 with no visible reason. Surface those
592
+ decisions in the human-readable "Policy Decisions" section so the
593
+ gate is always traceable.
594
+
595
+ Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
596
+
597
+ * fix(vis): correct npm/yarn min-release-age native config writers
598
+
599
+ npm CLI types `min-release-age` as `Number` in days, not a duration string —
600
+ vis wrote `48h`/`15m`, which npm's parseInt would silently read as 48/15 days.
601
+ Write integer days rounded up so the native gate is never weaker than vis-config.
602
+
603
+ Yarn Berry silently treats day suffixes in `npmMinimalAgeGate` as minutes
604
+
605
+ ### Features
606
+
607
+ * **vis:** offline OSV scanner + unified security.policies ([#632](https://github.com/visulima/visulima/issues/632)) ([6461902](https://github.com/visulima/visulima/commit/646190243bf51bb6df172665d70fd501644e7bc3)), closes [#631](https://github.com/visulima/visulima/issues/631) [#631](https://github.com/visulima/visulima/issues/631) [yarnpkg/berry#6991](https://github.com/yarnpkg/berry/issues/6991)
608
+
609
+
610
+ ### Dependencies
611
+
612
+ * **@visulima/fs:** upgraded to 5.0.0-alpha.22
613
+ * **@visulima/vis:** upgraded to 1.0.0-alpha.20
614
+
1
615
  ## @visulima/vis-mcp [1.0.0-alpha.9](https://github.com/visulima/visulima/compare/@visulima/vis-mcp@1.0.0-alpha.8...@visulima/vis-mcp@1.0.0-alpha.9) (2026-05-11)
2
616
 
3
617
 
package/README.md CHANGED
@@ -85,21 +85,30 @@ Add the server to `~/Library/Application Support/Claude/claude_desktop_config.js
85
85
 
86
86
  ### Tools
87
87
 
88
- All eight tools are read-only. The agent prepares commands; a human runs them.
89
-
90
- | Tool | What it does |
91
- | ------------------- | ------------------------------------------------------------------------------------------------------- |
92
- | `list_projects` | List all workspace projects, optionally filtered by a vis query string. |
93
- | `describe_project` | Return full metadata for one project (language, layer, stack, targets). |
94
- | `list_targets` | Flatten projects into per-target rows; optionally narrow to one project. |
95
- | `list_templates` | List scaffolding templates discovered in the workspace, with source and one-line description. |
96
- | `describe_template` | Return template metadata: description, default destination, and the variable schema for `vis generate`. |
97
- | `get_run_logs` | Read a run summary from `.task-runner/`; optionally filter to one task. |
98
- | `cache_why` | Diff a task's hash inputs against the previous run to explain a rotation. |
99
- | `cache_hash` | Print the recorded hash and per-input hash details for a task. |
88
+ All tools are read-only (each is annotated `readOnlyHint: true`). The agent prepares commands; a human runs anything that writes. The `lint` and `fmt` tools always run in check-only mode and never apply fixes — invoke `vis lint --fix` / `vis fmt` directly for that.
89
+
90
+ | Tool | What it does |
91
+ | ------------------- | ------------------------------------------------------------------------------------------------------------ |
92
+ | `list_projects` | List all workspace projects, optionally filtered by a vis query string. |
93
+ | `describe_project` | Return full metadata for one project (language, layer, stack, targets). |
94
+ | `list_targets` | Flatten projects into per-target rows; optionally narrow to one project. |
95
+ | `list_templates` | List scaffolding templates discovered in the workspace, with source and one-line description. |
96
+ | `describe_template` | Return template metadata: description, default destination, and the variable schema for `vis generate`. |
97
+ | `get_run_logs` | Read a run summary from `.task-runner/`; optionally filter to one task. |
98
+ | `list_runs` | List recorded runs from `.task-runner/runs/` (newest first) with status and task counts to discover run IDs. |
99
+ | `cache_why` | Diff a task's hash inputs against the previous run to explain a rotation. |
100
+ | `cache_hash` | Print the recorded hash and per-input hash details for a task. |
101
+ | `audit` | Audit installed packages for known vulnerabilities and supply-chain risk (`vis audit`). |
102
+ | `advisory_status` | Report local OSV advisory DB freshness (path, schema version, per-ecosystem counts, last sync). |
103
+ | `lint` | Run the vis lint orchestrator in check-only mode (`vis lint --format json`) and return `{ findings, runs }`. |
104
+ | `fmt` | Run the vis fmt orchestrator in `--check` mode and return the files that would change. |
105
+
106
+ Tools backed by a typed CLI payload (`audit`, `advisory_status`, `lint`, `fmt`) also expose an `outputSchema` and return `structuredContent`, so MCP-aware clients can validate and render the result instead of re-parsing the JSON text block.
100
107
 
101
108
  ## Related
102
109
 
110
+ - [`@visulima/vis`](https://github.com/visulima/visulima/tree/main/packages/tooling/vis) — the workspace CLI this server exposes. vis-mcp is a thin RPC over `vis` subcommands and does not duplicate vis logic.
111
+
103
112
  ## Supported Node.js Versions
104
113
 
105
114
  Libraries in this ecosystem make the best effort to track [Node.js’ release schedule](https://github.com/nodejs/release#release-schedule).
package/dist/bin.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import{startMcpServer as t}from"./packem_shared/registerAllTools-BOmyhKCR.js";try{await t()}catch(r){process.stderr.write(`[vis-mcp] failed to start: ${r instanceof Error?r.message:String(r)}
3
- `),process.exit(1)}
2
+ import{argv as t}from"node:process";import{fileURLToPath as a}from"node:url";import{startMcpServer as o}from"./packem_shared/createMcpServer-DOAejOGe.js";const i=async()=>{try{await o()}catch(r){process.stderr.write(`[vis-mcp] failed to start: ${r instanceof Error?r.message:String(r)}
3
+ `),process.exit(1)}},e=t[1]!==void 0&&a(import.meta.url)===t[1];e&&await i();export{i as main};
package/dist/index.d.ts CHANGED
@@ -16,6 +16,8 @@ declare const execVis: (visBin: string, args: ReadonlyArray<string>, options?: E
16
16
  declare const execVisJson: <T>(visBin: string, args: ReadonlyArray<string>, options?: ExecOptions) => Promise<T>;
17
17
  interface ExecResult {
18
18
  exitCode: number;
19
+ /** True when captured output hit `maxBufferBytes` and the child was killed. */
20
+ overflowed: boolean;
19
21
  stderr: string;
20
22
  stdout: string;
21
23
  timedOut: boolean;
@@ -23,10 +25,23 @@ interface ExecResult {
23
25
  interface ExecOptions {
24
26
  cwd?: string;
25
27
  env?: Record<string, string | undefined>;
28
+ /**
29
+ * Maximum combined stdout+stderr (in code units, an over-approximation of
30
+ * bytes) before the child is killed. Defaults to 64 MiB.
31
+ */
32
+ maxBufferBytes?: number;
26
33
  /** Hard ceiling. The default 120s suits cache lookups and listings. */
27
34
  timeoutMs?: number;
28
35
  }
29
36
  /**
37
+ * Run `vis list ...` and parse stdout as JSON, served from a short-TTL memo
38
+ * keyed on `workspaceRoot` + `args`. A rejected lookup is never cached, so a
39
+ * transient CLI failure does not poison subsequent calls.
40
+ */
41
+ declare const listVisJson: <T>(visBin: string, workspaceRoot: string, args: ReadonlyArray<string>, ttlMs?: number) => Promise<T>;
42
+ /** Clear the memo. Exposed for tests and long-running embeds that need a reset. */
43
+ declare const clearListCache: () => void;
44
+ /**
30
45
  * MCP tool response shape used across all `vis` tools. Kept in one place so
31
46
  * adding a new tool doesn't require re-deriving the type from the SDK.
32
47
  *
@@ -41,8 +56,21 @@ interface McpToolResponse {
41
56
  type: "text";
42
57
  }[];
43
58
  isError?: boolean;
59
+ /**
60
+ * Typed payload mirrored from `content`. Present only for tools that declare
61
+ * an `outputSchema`; lets MCP clients validate and render the result instead
62
+ * of re-parsing the JSON string in the text block.
63
+ */
64
+ structuredContent?: Record<string, unknown>;
44
65
  }
45
66
  declare const okResponse: (payload: unknown) => McpToolResponse;
67
+ /**
68
+ * Like {@link okResponse} but also attaches `structuredContent` so clients of a
69
+ * tool that declared an `outputSchema` get a validated, typed payload alongside
70
+ * the JSON text block. Only object payloads are valid structured content per the
71
+ * MCP spec, so the caller must pass a record.
72
+ */
73
+ declare const okStructuredResponse: (payload: Record<string, unknown>) => McpToolResponse;
46
74
  declare const errorResponse: (error: unknown) => McpToolResponse;
47
75
  interface ToolContext {
48
76
  /** Absolute path to the resolved `vis` CLI bundle. */
@@ -81,6 +109,12 @@ declare const createMcpServer: (context: ToolContext) => Promise<{
81
109
  * the JSON-RPC stream. Logs go to stderr only.
82
110
  */
83
111
  declare const startMcpServer: () => Promise<void>;
112
+ declare const registerAdvisoryStatus: ({
113
+ server
114
+ }: ToolDeps, context: ToolContext) => void;
115
+ declare const registerAudit: ({
116
+ server
117
+ }: ToolDeps, context: ToolContext) => void;
84
118
  declare const registerCacheHash: ({
85
119
  server
86
120
  }: ToolDeps, context: ToolContext) => void;
@@ -90,15 +124,30 @@ declare const registerCacheWhy: ({
90
124
  declare const registerDescribeProject: ({
91
125
  server
92
126
  }: ToolDeps, context: ToolContext) => void;
127
+ declare const registerDescribeTemplate: ({
128
+ server
129
+ }: ToolDeps, context: ToolContext) => void;
130
+ declare const registerFmt: ({
131
+ server
132
+ }: ToolDeps, context: ToolContext) => void;
93
133
  declare const registerGetRunLogs: ({
94
134
  server
95
135
  }: ToolDeps, context: ToolContext) => void;
136
+ declare const registerLint: ({
137
+ server
138
+ }: ToolDeps, context: ToolContext) => void;
96
139
  declare const registerListProjects: ({
97
140
  server
98
141
  }: ToolDeps, context: ToolContext) => void;
142
+ declare const registerListRuns: ({
143
+ server
144
+ }: ToolDeps, context: ToolContext) => void;
99
145
  declare const registerListTargets: ({
100
146
  server
101
147
  }: ToolDeps, context: ToolContext) => void;
148
+ declare const registerListTemplates: ({
149
+ server
150
+ }: ToolDeps, context: ToolContext) => void;
102
151
  declare const isValidRunId: (value: string) => boolean;
103
152
  /**
104
153
  * Task IDs are `&lt;project>:&lt;target>`; both halves are package or npm-scope
@@ -106,4 +155,14 @@ declare const isValidRunId: (value: string) => boolean;
106
155
  * inert, but a leading `-` would be parsed as a CLI flag by the vis CLI.
107
156
  */
108
157
  declare const isValidTaskId: (value: string) => boolean;
109
- export { type ExecOptions, type ExecResult, type McpToolResponse, type ToolContext, type ToolDeps, createMcpServer, errorResponse, execVis, execVisJson, isValidRunId, isValidTaskId, okResponse, registerAllTools, registerCacheHash, registerCacheWhy, registerDescribeProject, registerGetRunLogs, registerListProjects, registerListTargets, startMcpServer };
158
+ /**
159
+ * Guard for free-form positional arguments forwarded to the vis CLI (template
160
+ * names, file paths). Spawn is argv-form so shell metacharacters are inert, but
161
+ * a leading `-` would be parsed as a CLI flag — turning an LLM-supplied
162
+ * `files: ["--fix"]` into a write operation that violates the `readOnlyHint`
163
+ * contract clients rely on for auto-approval. Callers must additionally insert
164
+ * a literal `--` separator before any positionals so a value that *becomes*
165
+ * flag-shaped through some other path can never be reinterpreted as an option.
166
+ */
167
+ declare const isSafePositional: (value: string) => boolean;
168
+ export { type ExecOptions, type ExecResult, type McpToolResponse, type ToolContext, type ToolDeps, clearListCache, createMcpServer, errorResponse, execVis, execVisJson, isSafePositional, isValidRunId, isValidTaskId, listVisJson, okResponse, okStructuredResponse, registerAdvisoryStatus, registerAllTools, registerAudit, registerCacheHash, registerCacheWhy, registerDescribeProject, registerDescribeTemplate, registerFmt, registerGetRunLogs, registerLint, registerListProjects, registerListRuns, registerListTargets, registerListTemplates, startMcpServer };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{execVis as o,execVisJson as s}from"./packem_shared/execVis-BzS_F-9x.js";import{errorResponse as i,okResponse as p}from"./packem_shared/okResponse-DdzqnveW.js";import{createMcpServer as c,registerAllTools as f,startMcpServer as m}from"./packem_shared/registerAllTools-BOmyhKCR.js";import{registerCacheHash as g}from"./packem_shared/registerCacheHash-CVckSIVO.js";import{registerCacheWhy as n}from"./packem_shared/registerCacheWhy-BfIjli7n.js";import{registerDescribeProject as h}from"./packem_shared/registerDescribeProject-Dhuzun-I.js";import{registerGetRunLogs as V}from"./packem_shared/registerGetRunLogs-BxkRfYZU.js";import{registerListProjects as T}from"./packem_shared/registerListProjects-C-AZj8RT.js";import{registerListTargets as k}from"./packem_shared/registerListTargets-Cq6bkF7O.js";import{isValidRunId as v,isValidTaskId as C}from"./packem_shared/isValidRunId-BKsKMWQf.js";export{c as createMcpServer,i as errorResponse,o as execVis,s as execVisJson,v as isValidRunId,C as isValidTaskId,p as okResponse,f as registerAllTools,g as registerCacheHash,n as registerCacheWhy,h as registerDescribeProject,V as registerGetRunLogs,T as registerListProjects,k as registerListTargets,m as startMcpServer};
1
+ import{execVis as t,execVisJson as o}from"./packem_shared/execVis-CMeUcwPz.js";import{clearListCache as i,listVisJson as p}from"./packem_shared/clearListCache-4BxipCYS.js";import{errorResponse as x,okResponse as f,okStructuredResponse as a}from"./packem_shared/errorResponse-CVaJrOoB.js";import{createMcpServer as c,registerAllTools as l,startMcpServer as n}from"./packem_shared/createMcpServer-DOAejOGe.js";import{registerAdvisoryStatus as u}from"./packem_shared/registerAdvisoryStatus-BHihSIOB.js";import{registerAudit as R}from"./packem_shared/registerAudit-DTsSWedQ.js";import{registerCacheHash as S}from"./packem_shared/registerCacheHash-gEdqaBTi.js";import{registerCacheWhy as V}from"./packem_shared/registerCacheWhy-DSj2LYlR.js";import{registerDescribeProject as v}from"./packem_shared/registerDescribeProject-HYlvD0tm.js";import{registerDescribeTemplate as C}from"./packem_shared/registerDescribeTemplate-6RCmmfQs.js";import{registerFmt as b}from"./packem_shared/registerFmt-Dh0z0vq3.js";import{registerGetRunLogs as y}from"./packem_shared/registerGetRunLogs-CNGR-EcE.js";import{registerLint as I}from"./packem_shared/registerLint-kA0hcRUz.js";import{registerListProjects as M}from"./packem_shared/registerListProjects-DYz2st87.js";import{registerListRuns as G}from"./packem_shared/registerListRuns-BPqPwFUQ.js";import{registerListTargets as W}from"./packem_shared/registerListTargets-IWnJkyzy.js";import{registerListTemplates as w}from"./packem_shared/registerListTemplates-CSsN3JAE.js";import{isSafePositional as B,isValidRunId as E,isValidTaskId as K}from"./packem_shared/isSafePositional-CJq1jfAS.js";export{i as clearListCache,c as createMcpServer,x as errorResponse,t as execVis,o as execVisJson,B as isSafePositional,E as isValidRunId,K as isValidTaskId,p as listVisJson,f as okResponse,a as okStructuredResponse,u as registerAdvisoryStatus,l as registerAllTools,R as registerAudit,S as registerCacheHash,V as registerCacheWhy,v as registerDescribeProject,C as registerDescribeTemplate,b as registerFmt,y as registerGetRunLogs,I as registerLint,M as registerListProjects,G as registerListRuns,W as registerListTargets,w as registerListTemplates,n as startMcpServer};
@@ -0,0 +1 @@
1
+ import{execVisJson as u}from"./execVis-CMeUcwPz.js";const p=5e3,e=new Map,w=(c,t)=>`${c}\0${t.join("\0")}`,g=async(c,t,a,o=p)=>{const s=w(t,a),i=Date.now(),n=e.get(s);if(n&&n.expiresAt>i)return n.value;const r=u(c,a,{cwd:t});e.set(s,{expiresAt:i+o,value:r});try{return await r}catch(l){throw e.get(s)?.value===r&&e.delete(s),l}},h=()=>{e.clear()};export{h as clearListCache,g as listVisJson};
@@ -0,0 +1,4 @@
1
+ import{readFile as g}from"node:fs/promises";import{createRequire as l}from"node:module";import{resolve as u,dirname as f}from"node:path";import{pathToFileURL as d,fileURLToPath as h}from"node:url";import{McpServer as w}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as b}from"@modelcontextprotocol/sdk/server/stdio.js";import{findUp as I}from"@visulima/fs";import{registerAdvisoryStatus as S}from"./registerAdvisoryStatus-BHihSIOB.js";import{registerAudit as N}from"./registerAudit-DTsSWedQ.js";import{registerCacheHash as y}from"./registerCacheHash-gEdqaBTi.js";import{registerCacheWhy as _}from"./registerCacheWhy-DSj2LYlR.js";import{registerDescribeProject as k}from"./registerDescribeProject-HYlvD0tm.js";import{registerDescribeTemplate as P}from"./registerDescribeTemplate-6RCmmfQs.js";import{registerFmt as R}from"./registerFmt-Dh0z0vq3.js";import{registerGetRunLogs as C}from"./registerGetRunLogs-CNGR-EcE.js";import{registerLint as L}from"./registerLint-kA0hcRUz.js";import{registerListProjects as T}from"./registerListProjects-DYz2st87.js";import{registerListRuns as V}from"./registerListRuns-BPqPwFUQ.js";import{registerListTargets as j}from"./registerListTargets-IWnJkyzy.js";import{registerListTemplates as M}from"./registerListTemplates-CSsN3JAE.js";const p="1.0.0-alpha.35",v=r=>{const[e,s=""]=r.split("-",2);return{core:(e??"").split(".").map(t=>Number.parseInt(t,10)||0),pre:s.length>0?s.split("."):[]}},$=(r,e)=>{if(r===void 0)return e===void 0?0:-1;if(e===void 0)return 1;const s=Number.parseInt(r,10),t=Number.parseInt(e,10);return!Number.isNaN(s)&&!Number.isNaN(t)?s-t:r.localeCompare(e)},O=(r,e)=>{if(r.length===0&&e.length>0)return 1;if(r.length>0&&e.length===0)return-1;const s=Math.max(r.length,e.length);for(let t=0;t<s;t+=1){const i=$(r[t],e[t]);if(i!==0)return i}return 0},q=(r,e)=>{const s=v(r),t=v(e);for(let i=0;i<3;i+=1){const o=(s.core[i]??0)-(t.core[i]??0);if(o!==0)return o}return O(s.pre,t.pre)},E=r=>{!r||q(r,p)>=0||process.stderr.write(`[vis-mcp] warning: @visulima/vis ${r} is older than the required ${p}; lint/fmt/audit tools may fail with opaque errors. Upgrade @visulima/vis to >= ${p}.
2
+ `)},A=r=>{const e=process.env.VIS_MCP_VIS_BIN;if(e)return{binPath:u(e)};const s=[{label:r,require:l(d(`${r}/package.json`))},{label:"vis-mcp install location",require:l(import.meta.url)}],t=[];let i,o;for(const{label:n,require:a}of s)try{i=a.resolve("@visulima/vis/package.json"),o=a("@visulima/vis/package.json");break}catch(m){t.push({error:m,label:n})}if(!i||!o){const n=t.at(-1)?.error,a=t.map(m=>m.label).join(", ");throw new Error(`Cannot resolve \`@visulima/vis\` (tried: ${a}). Install it as a workspace dependency, or set VIS_MCP_VIS_BIN to a vis CLI path.`,{cause:n})}const c=typeof o.bin=="string"?o.bin:o.bin?.vis;if(!c)throw new Error("`@visulima/vis` is installed but does not declare a `vis` bin entry — install a current version.");return{binPath:u(f(i),c),version:o.version}},U=async()=>{try{const r=await I("package.json",{cwd:f(h(import.meta.url))});return r?JSON.parse(await g(r,"utf8")).version??"0.0.0":"0.0.0"}catch(r){return process.stderr.write(`[vis-mcp] failed to read package.json: ${r instanceof Error?r.message:String(r)}
3
+ `),"0.0.0"}},B=(r,e)=>{T(r,e),k(r,e),j(r,e),M(r,e),P(r,e),C(r,e),V(r,e),_(r,e),y(r,e),N(r,e),S(r,e),L(r,e),R(r,e)},D=async r=>{const e=new w({name:"vis",version:await U()}),s={server:e};return B(s,r),{deps:s,server:e}},mr=async()=>{const r=process.env.VIS_MCP_WORKSPACE_ROOT??process.cwd(),{binPath:e,version:s}=A(r);E(s);const t={visBin:e,workspaceRoot:r},{server:i}=await D(t);await i.connect(new b),process.stderr.write(`[vis-mcp] ready (workspace: ${t.workspaceRoot})
4
+ `)};export{p as MIN_VIS_VERSION,q as compareVersions,D as createMcpServer,B as registerAllTools,mr as startMcpServer,E as warnIfVisTooOld};
@@ -0,0 +1 @@
1
+ const r=t=>({content:[{text:typeof t=="string"?t:JSON.stringify(t),type:"text"}]}),n=t=>({content:[{text:JSON.stringify(t),type:"text"}],structuredContent:t}),o=t=>{const e=t instanceof Error?t.message:String(t);return{content:[{text:JSON.stringify({error:e}),type:"text"}],isError:!0}};export{o as errorResponse,r as okResponse,n as okStructuredResponse};
@@ -0,0 +1,4 @@
1
+ import{spawn as E}from"node:child_process";const x=12e4,g=64*1024*1024,S=async(a,s,t={})=>{const r=t.timeoutMs??x,o=t.maxBufferBytes??g,u={};for(const[d,n]of Object.entries(process.env))n!==void 0&&(u[d]=n);if(t.env)for(const[d,n]of Object.entries(t.env))n!==void 0&&(u[d]=n);u.NO_COLOR="1";const h={cwd:t.cwd??process.cwd(),env:u,stdio:["ignore","pipe","pipe"],windowsHide:!0};return await new Promise((d,n)=>{const e=E(process.execPath,[a,...s],h);let l="",f="",w=!1,m=!1,i;const p=setTimeout(()=>{w=!0,e.kill("SIGTERM"),i=setTimeout(()=>e.kill("SIGKILL"),2e3),i.unref()},r),v=()=>{m||l.length+f.length<=o||(m=!0,e.kill("SIGTERM"),i??=setTimeout(()=>e.kill("SIGKILL"),2e3),i.unref())};e.stdout?.setEncoding("utf8"),e.stdout?.on("data",c=>{l+=c,v()}),e.stderr?.setEncoding("utf8"),e.stderr?.on("data",c=>{f+=c,v()}),e.once("error",c=>{clearTimeout(p),i&&clearTimeout(i),n(c)}),e.once("close",c=>{clearTimeout(p),i&&clearTimeout(i),d({exitCode:c??-1,overflowed:m,stderr:f,stdout:l,timedOut:w})})})},$=async(a,s,t={})=>{const r=await S(a,s,t);if(r.timedOut)throw new Error(`vis ${s.join(" ")} timed out after ${String(t.timeoutMs??x)}ms`);if(r.overflowed)throw new Error(`vis ${s.join(" ")} exceeded the ${String(t.maxBufferBytes??g)}-byte output limit and was killed`);if(r.exitCode!==0){const o=r.stderr.trim().split(`
2
+ `).slice(-5).join(`
3
+ `);throw new Error(`vis ${s.join(" ")} exited with code ${String(r.exitCode)}${o?`
4
+ ${o}`:""}`)}try{return JSON.parse(r.stdout)}catch(o){throw new Error(`vis ${s.join(" ")} did not emit valid JSON: ${o instanceof Error?o.message:String(o)}`,{cause:o})}};export{S as execVis,$ as execVisJson};
@@ -0,0 +1 @@
1
+ const e=/^[\w.-]+$/,n=i=>e.test(i),d=i=>i.length>0&&!i.startsWith("-")&&i.includes(":"),l=i=>i.length>0&&!i.startsWith("-"),o=(i,s)=>{if(!s||s.length===0)return;const t=s.find(a=>!l(a));if(t!==void 0)return`Invalid file path "${t}". A leading "-" would be parsed as a CLI flag.`;i.push("--",...s)};export{o as appendPositionalFiles,l as isSafePositional,n as isValidRunId,d as isValidTaskId};
@@ -0,0 +1 @@
1
+ import*as s from"zod";import{execVisJson as c}from"./execVis-CMeUcwPz.js";import{okStructuredResponse as d,errorResponse as u}from"./errorResponse-CVaJrOoB.js";const m=s.object({advisoryCount:s.number(),lastSyncIso:s.string(),manifestEtag:s.string().nullable(),name:s.string()}),o=s.object({dbPath:s.string(),ecosystems:s.array(m),exists:s.boolean(),schemaVersion:s.number(),sizeBytes:s.number()}).catchall(s.unknown()),h=o.shape,v=({server:a},t)=>{a.registerTool("advisory_status",{annotations:{readOnlyHint:!0},description:"Report the local OSV advisory DB freshness via `vis advisories status --format json`: DB path, schema version, per-ecosystem advisory counts, last sync timestamp, and ETag. Use this to detect whether the offline cache is stale before running an `audit` in offline mode.",inputSchema:{db:s.string().min(1).optional().describe("Override the cache DB path (default: <cache>/vis/advisories/db.sqlite).")},outputSchema:h},async r=>{try{const e=["advisories","status","--format","json"];r.db!==void 0&&e.push("--db",r.db);const i=await c(t.visBin,e,{cwd:t.workspaceRoot}),n=o.parse(i);return d(n)}catch(e){return u(e)}})};export{v as registerAdvisoryStatus};
@@ -0,0 +1 @@
1
+ import*as e from"zod";import{execVisJson as c}from"./execVis-CMeUcwPz.js";import{okStructuredResponse as l,errorResponse as p}from"./errorResponse-CVaJrOoB.js";const u=e.object({fixedVersions:e.array(e.string()).optional(),id:e.string(),severity:e.string(),summary:e.string().optional()}),d=e.object({acceptedRisk:e.unknown().optional(),name:e.string(),socketAlerts:e.array(e.unknown()).optional(),socketScore:e.number().nullable().optional(),version:e.string(),vulnerabilities:e.array(u)}),r=e.object({duplicates:e.array(e.object({name:e.string(),versionCount:e.number(),versions:e.array(e.string())})),packages:e.number(),results:e.array(d),summary:e.object({accepted:e.number(),duplicatePackages:e.number(),issues:e.number(),total:e.number()})}).catchall(e.unknown()),m=r.shape,y=["low","medium","high","critical"],f=({server:i},s)=>{i.registerTool("audit",{annotations:{readOnlyHint:!0},description:"Audit installed packages for known vulnerabilities and supply-chain risk via `vis audit --format json`. Defaults to the local offline OSV cache when one exists, otherwise falls back to the live OSV API. Returns the parsed audit payload (results, duplicates, summary).",inputSchema:{ecosystem:e.string().optional().describe("Comma-separated OSV ecosystems to scan. Defaults to 'npm' (the only matcher wired today)."),offline:e.boolean().optional().describe("Force the local OSV cache. Errors if the cache is missing — run `vis advisories sync` first."),prodOnly:e.boolean().optional().describe("Skip devDependencies — scan the production graph only."),severity:e.enum(y).optional().describe("Minimum severity to report. Defaults to 'low'."),showAccepted:e.boolean().optional().describe("Include findings already on the workspace's accepted-risk list."),usage:e.boolean().optional().describe("Apply the reachability filter — only report vulnerabilities in statically-imported packages.")},outputSchema:m},async o=>{try{const t=["audit","--format","json"];o.severity&&t.push("--severity",o.severity),o.offline&&t.push("--offline"),o.prodOnly&&t.push("--prod-only"),o.usage&&t.push("--usage"),o.ecosystem&&t.push("--ecosystem",o.ecosystem),o.showAccepted&&t.push("--show-accepted");const a=await c(s.visBin,t,{cwd:s.workspaceRoot}),n=r.parse(a);return l(n)}catch(t){return p(t)}})};export{f as registerAudit};
@@ -0,0 +1 @@
1
+ import*as n from"zod";import{execVisJson as d}from"./execVis-CMeUcwPz.js";import{errorResponse as s,okResponse as c}from"./errorResponse-CVaJrOoB.js";import{isValidTaskId as p,isValidRunId as u}from"./isSafePositional-CJq1jfAS.js";const I=({server:a},i)=>{a.registerTool("cache_hash",{annotations:{readOnlyHint:!0},description:"Print the recorded hash and per-input hash details for a task — the contributing inputs (command, nodes, runtime, implicitDeps) that produced it.",inputSchema:{runId:n.string().optional().describe("Run ID to inspect (default: latest)"),taskId:n.string().describe('Task ID like "@my/app:build"')}},async({runId:t,taskId:e})=>{if(!p(e))return s(new Error(`Invalid taskId "${e}". Expected "<project>:<target>".`));if(t!==void 0&&!u(t))return s(new Error(`Invalid runId "${t}". Expected filesystem-safe slug ([A-Za-z0-9_.-]).`));try{const r=["cache","hash",e,"--format=json"];t&&r.push("--run",t);const o=await d(i.visBin,r,{cwd:i.workspaceRoot});return c(o)}catch(r){return s(r)}})};export{I as registerCacheHash};
@@ -0,0 +1 @@
1
+ import*as n from"zod";import{execVisJson as c}from"./execVis-CMeUcwPz.js";import{errorResponse as s,okResponse as d}from"./errorResponse-CVaJrOoB.js";import{isValidTaskId as p,isValidRunId as u}from"./isSafePositional-CJq1jfAS.js";const f=({server:i},a)=>{i.registerTool("cache_why",{annotations:{readOnlyHint:!0},description:"Explain why a task's cache hash rotated between runs. Diffs the task's hashDetails (command, nodes, runtime, implicitDeps) against the previous run to pinpoint what changed.",inputSchema:{runId:n.string().optional().describe("Run ID to inspect (default: latest)"),taskId:n.string().describe('Task ID like "@my/app:build"')}},async({runId:t,taskId:r})=>{if(!p(r))return s(new Error(`Invalid taskId "${r}". Expected "<project>:<target>".`));if(t!==void 0&&!u(t))return s(new Error(`Invalid runId "${t}". Expected filesystem-safe slug ([A-Za-z0-9_.-]).`));try{const e=["cache","why",r,"--format=json"];t&&e.push("--run",t);const o=await c(a.visBin,e,{cwd:a.workspaceRoot});return d(o)}catch(e){return s(e)}})};export{f as registerCacheWhy};
@@ -0,0 +1 @@
1
+ import*as n from"zod";import{listVisJson as i}from"./clearListCache-4BxipCYS.js";import{okResponse as c,errorResponse as o}from"./errorResponse-CVaJrOoB.js";const m=({server:s},r)=>{s.registerTool("describe_project",{annotations:{readOnlyHint:!0},description:"Return full metadata for a single workspace project: language, layer, stack, type, tags, root path, and all targets.",inputSchema:{name:n.string().describe('Project name (e.g. "@visulima/cerebro")')}},async({name:t})=>{try{const e=(await i(r.visBin,r.workspaceRoot,["list","--json"])).find(a=>a.name===t);return e?c(e):o(new Error(`No project named "${t}". Use list_projects to see available names.`))}catch(e){return o(e)}})};export{m as registerDescribeProject};
@@ -0,0 +1 @@
1
+ import*as s from"zod";import{execVisJson as o}from"./execVis-CMeUcwPz.js";import{errorResponse as r,okResponse as i}from"./errorResponse-CVaJrOoB.js";import{isSafePositional as m}from"./isSafePositional-CJq1jfAS.js";const d=({server:n},a)=>{n.registerTool("describe_template",{annotations:{readOnlyHint:!0},description:"Return full metadata for a scaffolding template: description, default destination, and the variable schema (name, type, default, required, prompt, enum values). Use this before suggesting a `vis generate` command so option values can be filled correctly.",inputSchema:{name:s.string().describe('Template name (e.g. "package", "component"). Use list_templates to see available names.')}},async({name:e})=>{if(!m(e))return r(new Error(`Invalid template name "${e}". A leading "-" would be parsed as a CLI flag.`));try{const t=await o(a.visBin,["generate","--describe","--json","--",e],{cwd:a.workspaceRoot});return i(t)}catch(t){return r(t)}})};export{d as registerDescribeTemplate};
@@ -0,0 +1,4 @@
1
+ import*as e from"zod";import{execVis as f}from"./execVis-CMeUcwPz.js";import{errorResponse as n,okStructuredResponse as p}from"./errorResponse-CVaJrOoB.js";import{appendPositionalFiles as h}from"./isSafePositional-CJq1jfAS.js";const l=e.object({adapter:e.string(),column:e.number().optional(),file:e.string(),fixable:e.boolean().optional(),line:e.number().optional(),message:e.string(),ruleId:e.string().optional(),severity:e.enum(["error","info","warning"])}).catchall(e.unknown()),u=e.object({adapter:e.string(),durationMs:e.number(),exitCode:e.number(),findingCount:e.number()}).catchall(e.unknown()),g=e.object({findings:e.array(l),mode:e.enum(["check","fix"]).optional(),runs:e.array(u)}).catchall(e.unknown()),w={exitCode:e.number(),findings:e.array(l),mode:e.enum(["check","fix"]),runs:e.array(u)},y=({server:m},s)=>{m.registerTool("fmt",{annotations:{readOnlyHint:!0},description:"Run the vis fmt orchestrator in --check mode via `vis fmt --check --format json`. Auto-detects every installed formatter (oxfmt, biome, dprint, prettier, ruff-fmt, deno-fmt) and returns the merged { findings, runs } payload — each finding represents a file that would change. This tool never writes to disk; invoke `vis fmt` directly to apply the formatting.",inputSchema:{files:e.array(e.string()).optional().describe("Restrict the check to these files (relative to the workspace root). Empty/omitted = workspace-wide."),quiet:e.boolean().optional().describe("Suppress per-file logs (findings still flow through)."),since:e.string().optional().describe("Forward `--since <ref>` so only files changed vs `<ref>` are checked."),staged:e.boolean().optional().describe("Forward `--staged` so only files in the git index are checked.")},outputSchema:w},async i=>{try{const t=["fmt","--check","--format","json"];i.quiet&&t.push("--quiet"),i.staged?t.push("--staged"):i.since!==void 0&&i.since.length>0&&t.push("--since",i.since);const a=h(t,i.files);if(a!==void 0)return n(new Error(a));const r=await f(s.visBin,t,{cwd:s.workspaceRoot});if(r.timedOut)return n(new Error("vis fmt timed out"));if(r.overflowed)return n(new Error("vis fmt produced more output than the buffer ceiling allows and was killed"));if(r.stdout.trim().length===0){const o=r.stderr.trim().split(`
2
+ `).slice(-5).join(`
3
+ `);return n(new Error(`vis fmt exited with code ${String(r.exitCode)} and no JSON output${o?`
4
+ ${o}`:""}`))}let c;try{c=JSON.parse(r.stdout)}catch(o){return n(new Error(`vis ${t.join(" ")} did not emit valid JSON: ${o instanceof Error?o.message:String(o)}`,{cause:o}))}const d=g.parse(c);return p({...d,exitCode:r.exitCode,mode:d.mode??"check"})}catch(t){return n(t)}})};export{y as registerFmt};
@@ -0,0 +1 @@
1
+ import{readFile as c}from"node:fs/promises";import{join as u}from"@visulima/path";import*as d from"zod";import{errorResponse as e,okResponse as l}from"./errorResponse-CVaJrOoB.js";import{isValidRunId as f}from"./isSafePositional-CJq1jfAS.js";const R=({server:p},o)=>{p.registerTool("get_run_logs",{annotations:{readOnlyHint:!0},description:"Read a vis run summary from .task-runner/. Returns the most recent run by default, or a specific run when `runId` is set. Optionally filter to a single task with `taskId`.",inputSchema:{runId:d.string().optional().describe("Run ID (default: latest)"),taskId:d.string().optional().describe('Filter to a single task ID like "@my/app:build"')}},async({runId:r,taskId:s})=>{if(r!==void 0&&!f(r))return e(new Error(`Invalid runId "${r}". Expected filesystem-safe slug ([A-Za-z0-9_.-]).`));const a=r?u(o.workspaceRoot,".task-runner","runs",`${r}.json`):u(o.workspaceRoot,".task-runner","last-summary.json");try{const t=await c(a,"utf8"),n=JSON.parse(t);if(s){const i=n.tasks?.find(m=>m.taskId===s);return i?l({runId:n.runId,task:i}):e(new Error(`Task "${s}" not found in run "${n.runId??"(unknown)"}".`))}return l(n)}catch(t){return t.code==="ENOENT"?e(new Error(`No run summary at ${a}. Run a task first to populate it.`)):e(t)}})};export{R as registerGetRunLogs};
@@ -0,0 +1,4 @@
1
+ import*as e from"zod";import{execVis as m}from"./execVis-CMeUcwPz.js";import{errorResponse as o,okStructuredResponse as g}from"./errorResponse-CVaJrOoB.js";import{appendPositionalFiles as f}from"./isSafePositional-CJq1jfAS.js";const d=e.object({adapter:e.string(),column:e.number().optional(),endColumn:e.number().optional(),endLine:e.number().optional(),file:e.string(),fixable:e.boolean().optional(),line:e.number().optional(),message:e.string(),ruleId:e.string().optional(),severity:e.enum(["error","info","warning"])}).catchall(e.unknown()),u=e.object({adapter:e.string(),durationMs:e.number(),exitCode:e.number(),findingCount:e.number()}).catchall(e.unknown()),h=e.object({findings:e.array(d),runs:e.array(u)}).catchall(e.unknown()),w={exitCode:e.number(),findings:e.array(d),runs:e.array(u)},x=({server:c},s)=>{c.registerTool("lint",{annotations:{readOnlyHint:!0},description:"Run the vis lint orchestrator in check-only mode via `vis lint --format json`. Auto-detects every installed linter (oxlint, biome, eslint, stylelint, ruff, markdownlint, shellcheck, deno-lint) and returns the merged { findings, runs } payload. This tool never applies fixes — invoke `vis lint --fix` directly for that.",inputSchema:{files:e.array(e.string()).optional().describe("Restrict the run to these files (relative to the workspace root). Empty/omitted = workspace-wide."),maxWarnings:e.int().nonnegative().optional().describe("Forward `--max-warnings N` to every adapter that supports it."),quiet:e.boolean().optional().describe("Suppress warning-severity findings (errors still flow through)."),since:e.string().optional().describe("Forward `--since <ref>` so only files changed vs `<ref>` are linted."),staged:e.boolean().optional().describe("Forward `--staged` so only files in the git index are linted.")},outputSchema:w},async t=>{try{const n=["lint","--format","json"];t.quiet&&n.push("--quiet"),typeof t.maxWarnings=="number"&&n.push("--max-warnings",String(t.maxWarnings)),t.staged?n.push("--staged"):t.since!==void 0&&t.since.length>0&&n.push("--since",t.since);const a=f(n,t.files);if(a!==void 0)return o(new Error(a));const i=await m(s.visBin,n,{cwd:s.workspaceRoot});if(i.timedOut)return o(new Error("vis lint timed out"));if(i.overflowed)return o(new Error("vis lint produced more output than the buffer ceiling allows and was killed"));if(i.stdout.trim().length===0){const r=i.stderr.trim().split(`
2
+ `).slice(-5).join(`
3
+ `);return o(new Error(`vis lint exited with code ${String(i.exitCode)} and no JSON output${r?`
4
+ ${r}`:""}`))}let l;try{l=JSON.parse(i.stdout)}catch(r){return o(new Error(`vis ${n.join(" ")} did not emit valid JSON: ${r instanceof Error?r.message:String(r)}`,{cause:r}))}const p=h.parse(l);return g({...p,exitCode:i.exitCode})}catch(n){return o(n)}})};export{x as registerLint};
@@ -0,0 +1 @@
1
+ import*as i from"zod";import{execVisJson as n}from"./execVis-CMeUcwPz.js";import{okResponse as a,errorResponse as p}from"./errorResponse-CVaJrOoB.js";const g=({server:o},e)=>{o.registerTool("list_projects",{annotations:{readOnlyHint:!0},description:'List all workspace projects with their language, type, layer, tags, and target metadata. Optionally filter with a vis query string (e.g. "tag=frontend", "type=application").',inputSchema:{query:i.string().optional().describe('Filter projects by vis query string (e.g. "tag=frontend")')}},async({query:r})=>{try{const t=["list","--json"];r&&t.push("--query",r);const s=await n(e.visBin,t,{cwd:e.workspaceRoot});return a({count:s.length,projects:s})}catch(t){return p(t)}})};export{g as registerListProjects};
@@ -0,0 +1 @@
1
+ import{readdir as h,stat as k,readFile as g}from"node:fs/promises";import{join as l}from"@visulima/path";import*as y from"zod";import{okResponse as m,errorResponse as f}from"./errorResponse-CVaJrOoB.js";const v=/\.json$/,w=r=>{if(typeof r.status=="string")return r.status;if(r.tasks)return r.tasks.some(n=>n.status==="failure"||n.status==="failed")?"failure":"success"},R=({server:r},n)=>{r.registerTool("list_runs",{annotations:{readOnlyHint:!0},description:'List recorded vis runs from `.task-runner/runs/`, most recent first. Each entry includes the run ID, start timestamp, derived status, task count, and failed-task count — use it to discover run IDs for `get_run_logs`, `cache_hash`, or `cache_why` (e.g. "compare this run to the previous one").',inputSchema:{limit:y.int().positive().max(100).optional().describe("Maximum runs to return (default: 20, newest first).")}},async({limit:p})=>{const d=l(n.workspaceRoot,".task-runner","runs");let c;try{c=(await h(d)).filter(t=>t.endsWith(".json"))}catch(t){return t.code==="ENOENT"?m({count:0,runs:[]}):f(t)}try{const t=(await Promise.all(c.map(async s=>{const a=l(d,s);try{const[o,u]=await Promise.all([k(a),g(a,"utf8")]),e=JSON.parse(u);return{failedTasks:e.tasks?.filter(i=>i.status==="failure"||i.status==="failed").length,modifiedMs:o.mtimeMs,runId:e.runId??s.replace(v,""),startedAt:e.startedAt,status:w(e),taskCount:e.tasks?.length}}catch{return}}))).filter(s=>s!==void 0).toSorted((s,a)=>a.modifiedMs-s.modifiedMs).slice(0,p??20).map(s=>{const{failedTasks:a,runId:o,startedAt:u,status:e,taskCount:i}=s;return{failedTasks:a,runId:o,startedAt:u,status:e,taskCount:i}});return m({count:t.length,runs:t})}catch(t){return f(t)}})};export{R as registerListRuns};
@@ -0,0 +1 @@
1
+ import*as p from"zod";import{listVisJson as l}from"./clearListCache-4BxipCYS.js";import{errorResponse as i,okResponse as m}from"./errorResponse-CVaJrOoB.js";const j=({server:c},o)=>{c.registerTool("list_targets",{annotations:{readOnlyHint:!0},description:"List per-target rows across the workspace: which targets each project exposes, with type, command, and description. Optionally narrow to a single project.",inputSchema:{project:p.string().optional().describe('Limit to one project (e.g. "@visulima/cerebro")')}},async({project:e})=>{try{const t=await l(o.visBin,o.workspaceRoot,["list","--targets","--json"]),s=e?t.filter(r=>r.name===e):t;if(e&&s.length===0)return i(new Error(`No project named "${e}". Use list_projects to see available names.`));const a=s.flatMap(r=>(r.targets??[]).map(n=>({...n,project:r.name,target:n.name})));return m({count:a.length,targets:a})}catch(t){return i(t)}})};export{j as registerListTargets};
@@ -0,0 +1 @@
1
+ import{execVisJson as n}from"./execVis-CMeUcwPz.js";import{okResponse as o,errorResponse as r}from"./errorResponse-CVaJrOoB.js";const c=({server:s},t)=>{s.registerTool("list_templates",{annotations:{readOnlyHint:!0},description:"List scaffolding templates discovered in the workspace (`.vis/templates/`, `.moon/templates/`, and `vis.config.ts` `generator.templates`). Each entry includes name, source, on-disk path, and one-line description.",inputSchema:{}},async()=>{try{const e=await n(t.visBin,["generate","--list","--json"],{cwd:t.workspaceRoot});return o({count:e.length,templates:e})}catch(e){return r(e)}})};export{c as registerListTemplates};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@visulima/vis-mcp",
3
- "version": "1.0.0-alpha.9",
3
+ "version": "1.0.1",
4
4
  "description": "MCP (Model Context Protocol) server for @visulima/vis — exposes vis tooling to AI agents over stdio",
5
5
  "keywords": [
6
6
  "agent",
@@ -14,8 +14,11 @@
14
14
  "visulima"
15
15
  ],
16
16
  "homepage": "https://visulima.com/packages/vis-mcp",
17
- "bugs": {
18
- "url": "https://github.com/visulima/visulima/issues"
17
+ "bugs": "https://github.com/visulima/visulima/issues",
18
+ "license": "MIT",
19
+ "author": {
20
+ "name": "Daniel Bannert",
21
+ "email": "d.bannert@anolilab.de"
19
22
  },
20
23
  "repository": {
21
24
  "type": "git",
@@ -32,13 +35,17 @@
32
35
  "url": "https://anolilab.com/support"
33
36
  }
34
37
  ],
35
- "license": "MIT",
36
- "author": {
37
- "name": "Daniel Bannert",
38
- "email": "d.bannert@anolilab.de"
38
+ "bin": {
39
+ "vis-mcp": "./dist/bin.js"
39
40
  },
40
- "sideEffects": false,
41
+ "files": [
42
+ "dist/**",
43
+ "README.md",
44
+ "CHANGELOG.md",
45
+ "LICENSE.md"
46
+ ],
41
47
  "type": "module",
48
+ "sideEffects": false,
42
49
  "exports": {
43
50
  ".": {
44
51
  "types": "./dist/index.d.ts",
@@ -46,29 +53,20 @@
46
53
  },
47
54
  "./package.json": "./package.json"
48
55
  },
49
- "bin": {
50
- "vis-mcp": "./dist/bin.js"
56
+ "publishConfig": {
57
+ "access": "public",
58
+ "provenance": true
51
59
  },
52
- "files": [
53
- "dist/**",
54
- "README.md",
55
- "CHANGELOG.md",
56
- "LICENSE.md"
57
- ],
58
60
  "dependencies": {
59
61
  "@modelcontextprotocol/sdk": "^1.29.0",
60
- "@visulima/fs": "5.0.0-alpha.21",
61
- "@visulima/path": "3.0.0-alpha.10",
62
+ "@visulima/fs": "5.0.1",
63
+ "@visulima/path": "3.0.0",
62
64
  "zod": "4.4.3"
63
65
  },
64
66
  "peerDependencies": {
65
- "@visulima/vis": "1.0.0-alpha.19"
67
+ "@visulima/vis": "1.0.1"
66
68
  },
67
69
  "engines": {
68
70
  "node": "^22.14.0 || >=24.10.0"
69
- },
70
- "publishConfig": {
71
- "access": "public",
72
- "provenance": true
73
71
  }
74
72
  }
@@ -1,4 +0,0 @@
1
- var x=Object.defineProperty;var m=(i,e)=>x(i,"name",{value:e,configurable:!0});import{spawn as v}from"node:child_process";var g=Object.defineProperty,w=m((i,e)=>g(i,"name",{value:e,configurable:!0}),"c");const l=12e4,O=w(async(i,e,n={})=>{const o=n.timeoutMs??l,t={cwd:n.cwd??process.cwd(),env:{...process.env,...n.env,NO_COLOR:"1"},stdio:["ignore","pipe","pipe"],windowsHide:!0};return await new Promise((p,f)=>{const r=v(process.execPath,[i,...e],t);let c="",d="",a=!1;const u=setTimeout(()=>{a=!0,r.kill("SIGTERM"),setTimeout(()=>r.kill("SIGKILL"),2e3).unref()},o);r.stdout?.setEncoding("utf8"),r.stdout?.on("data",s=>{c+=s}),r.stderr?.setEncoding("utf8"),r.stderr?.on("data",s=>{d+=s}),r.once("error",s=>{clearTimeout(u),f(s)}),r.once("close",s=>{clearTimeout(u),p({exitCode:s??-1,stderr:d,stdout:c,timedOut:a})})})},"execVis"),S=w(async(i,e,n={})=>{const o=await O(i,e,n);if(o.timedOut)throw new Error(`vis ${e.join(" ")} timed out after ${String(n.timeoutMs??l)}ms`);if(o.exitCode!==0){const t=o.stderr.trim().split(`
2
- `).slice(-5).join(`
3
- `);throw new Error(`vis ${e.join(" ")} exited with code ${String(o.exitCode)}${t?`
4
- ${t}`:""}`)}try{return JSON.parse(o.stdout)}catch(t){throw new Error(`vis ${e.join(" ")} did not emit valid JSON: ${t instanceof Error?t.message:String(t)}`,{cause:t})}},"execVisJson");export{O as execVis,S as execVisJson};
@@ -1 +0,0 @@
1
- var d=Object.defineProperty;var a=(i,s)=>d(i,"name",{value:s,configurable:!0});var t=Object.defineProperty,e=a((i,s)=>t(i,"name",{value:s,configurable:!0}),"s");const n=/^[\w.-]+$/,r=e(i=>n.test(i),"isValidRunId"),o=e(i=>i.length>0&&!i.startsWith("-")&&i.includes(":"),"isValidTaskId");export{r as isValidRunId,o as isValidTaskId};
@@ -1 +0,0 @@
1
- var o=Object.defineProperty;var t=(e,r)=>o(e,"name",{value:r,configurable:!0});var s=Object.defineProperty,n=t((e,r)=>s(e,"name",{value:r,configurable:!0}),"o");const p=n(e=>({content:[{text:typeof e=="string"?e:JSON.stringify(e),type:"text"}]}),"okResponse"),a=n(e=>{const r=e instanceof Error?e.message:String(e);return{content:[{text:JSON.stringify({error:r}),type:"text"}],isError:!0}},"errorResponse");export{a as errorResponse,p as okResponse};
@@ -1,3 +0,0 @@
1
- var u=Object.defineProperty;var i=(e,r)=>u(e,"name",{value:r,configurable:!0});import{readFile as f}from"node:fs/promises";import{createRequire as g}from"node:module";import{resolve as c,dirname as p}from"node:path";import{pathToFileURL as w,fileURLToPath as h}from"node:url";import{McpServer as y}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as b}from"@modelcontextprotocol/sdk/server/stdio.js";import{findUp as S}from"@visulima/fs";import{registerCacheHash as k}from"./registerCacheHash-CVckSIVO.js";import{registerCacheWhy as T}from"./registerCacheWhy-BfIjli7n.js";import{registerDescribeProject as R}from"./registerDescribeProject-Dhuzun-I.js";import*as _ from"zod";import{execVisJson as m}from"./execVis-BzS_F-9x.js";import{okResponse as l,errorResponse as v}from"./okResponse-DdzqnveW.js";import{registerGetRunLogs as j}from"./registerGetRunLogs-BxkRfYZU.js";import{registerListProjects as I}from"./registerListProjects-C-AZj8RT.js";import{registerListTargets as P}from"./registerListTargets-Cq6bkF7O.js";var L=Object.defineProperty,O=i((e,r)=>L(e,"name",{value:r,configurable:!0}),"r");const C=O(({server:e},r)=>{e.registerTool("describe_template",{annotations:{readOnlyHint:!0},description:"Return full metadata for a scaffolding template: description, default destination, and the variable schema (name, type, default, required, prompt, enum values). Use this before suggesting a `vis generate` command so option values can be filled correctly.",inputSchema:{name:_.string().describe('Template name (e.g. "package", "component"). Use list_templates to see available names.')}},async({name:t})=>{try{const s=await m(r.visBin,["generate",t,"--describe","--json"],{cwd:r.workspaceRoot});return l(s)}catch(s){return v(s)}})},"registerDescribeTemplate");var M=Object.defineProperty,V=i((e,r)=>M(e,"name",{value:r,configurable:!0}),"n");const B=V(({server:e},r)=>{e.registerTool("list_templates",{annotations:{readOnlyHint:!0},description:"List scaffolding templates discovered in the workspace (`.vis/templates/`, `.moon/templates/`, and `vis.config.ts` `generator.templates`). Each entry includes name, source, on-disk path, and one-line description.",inputSchema:{}},async()=>{try{const t=await m(r.visBin,["generate","--list","--json"],{cwd:r.workspaceRoot});return l({count:t.length,templates:t})}catch(t){return v(t)}})},"registerListTemplates");var E=Object.defineProperty,o=i((e,r)=>E(e,"name",{value:r,configurable:!0}),"s");const U=o(e=>{const r=process.env.VIS_MCP_VIS_BIN;if(r)return c(r);const t=g(w(`${e}/package.json`));let s,a;try{s=t.resolve("@visulima/vis/package.json"),a=t("@visulima/vis/package.json")}catch(d){throw new Error(`Cannot resolve \`@visulima/vis\` from ${e}. Install it as a workspace dependency, or set VIS_MCP_VIS_BIN to a vis CLI path.`,{cause:d})}const n=typeof a.bin=="string"?a.bin:a.bin?.vis;if(!n)throw new Error("`@visulima/vis` is installed but does not declare a `vis` bin entry — install a current version.");return c(p(s),n)},"resolveVisBin"),$=o(async()=>{try{const e=await S("package.json",{cwd:p(h(import.meta.url))});return e?JSON.parse(await f(e,"utf8")).version??"0.0.0":"0.0.0"}catch(e){return process.stderr.write(`[vis-mcp] failed to read package.json: ${e instanceof Error?e.message:String(e)}
2
- `),"0.0.0"}},"loadVersion"),A=o((e,r)=>{I(e,r),R(e,r),P(e,r),B(e,r),C(e,r),j(e,r),T(e,r),k(e,r)},"registerAllTools"),D=o(async e=>{const r=new y({name:"vis",version:await $()}),t={server:r};return A(t,e),{deps:t,server:r}},"createMcpServer"),te=o(async()=>{const e=process.env.VIS_MCP_WORKSPACE_ROOT??process.cwd(),r={visBin:U(e),workspaceRoot:e},{server:t}=await D(r);await t.connect(new b),process.stderr.write(`[vis-mcp] ready (workspace: ${r.workspaceRoot})
3
- `)},"startMcpServer");export{D as createMcpServer,A as registerAllTools,te as startMcpServer};
@@ -1 +0,0 @@
1
- var d=Object.defineProperty;var s=(e,r)=>d(e,"name",{value:r,configurable:!0});import*as o from"zod";import{execVisJson as p}from"./execVis-BzS_F-9x.js";import{errorResponse as n,okResponse as u}from"./okResponse-DdzqnveW.js";import{isValidTaskId as h,isValidRunId as l}from"./isValidRunId-BKsKMWQf.js";var m=Object.defineProperty,f=s((e,r)=>m(e,"name",{value:r,configurable:!0}),"n");const b=f(({server:e},r)=>{e.registerTool("cache_hash",{annotations:{readOnlyHint:!0},description:"Print the recorded hash and per-input hash details for a task — the contributing inputs (command, nodes, runtime, implicitDeps) that produced it.",inputSchema:{runId:o.string().optional().describe("Run ID to inspect (default: latest)"),taskId:o.string().describe('Task ID like "@my/app:build"')}},async({runId:t,taskId:i})=>{if(!h(i))return n(new Error(`Invalid taskId "${i}". Expected "<project>:<target>".`));if(t!==void 0&&!l(t))return n(new Error(`Invalid runId "${t}". Expected filesystem-safe slug ([A-Za-z0-9_.-]).`));try{const a=["cache","hash",i,"--format=json"];t&&a.push("--run",t);const c=await p(r.visBin,a,{cwd:r.workspaceRoot});return u(c)}catch(a){return n(a)}})},"registerCacheHash");export{b as registerCacheHash};
@@ -1 +0,0 @@
1
- var d=Object.defineProperty;var n=(r,e)=>d(r,"name",{value:e,configurable:!0});import*as o from"zod";import{execVisJson as p}from"./execVis-BzS_F-9x.js";import{errorResponse as i,okResponse as u}from"./okResponse-DdzqnveW.js";import{isValidTaskId as h,isValidRunId as l}from"./isValidRunId-BKsKMWQf.js";var m=Object.defineProperty,f=n((r,e)=>m(r,"name",{value:e,configurable:!0}),"i");const w=f(({server:r},e)=>{r.registerTool("cache_why",{annotations:{readOnlyHint:!0},description:"Explain why a task's cache hash rotated between runs. Diffs the task's hashDetails (command, nodes, runtime, implicitDeps) against the previous run to pinpoint what changed.",inputSchema:{runId:o.string().optional().describe("Run ID to inspect (default: latest)"),taskId:o.string().describe('Task ID like "@my/app:build"')}},async({runId:t,taskId:s})=>{if(!h(s))return i(new Error(`Invalid taskId "${s}". Expected "<project>:<target>".`));if(t!==void 0&&!l(t))return i(new Error(`Invalid runId "${t}". Expected filesystem-safe slug ([A-Za-z0-9_.-]).`));try{const a=["cache","why",s,"--format=json"];t&&a.push("--run",t);const c=await p(e.visBin,a,{cwd:e.workspaceRoot});return u(c)}catch(a){return i(a)}})},"registerCacheWhy");export{w as registerCacheWhy};
@@ -1 +0,0 @@
1
- var i=Object.defineProperty;var a=(r,e)=>i(r,"name",{value:e,configurable:!0});import*as c from"zod";import{execVisJson as p}from"./execVis-BzS_F-9x.js";import{okResponse as l,errorResponse as s}from"./okResponse-DdzqnveW.js";var m=Object.defineProperty,g=a((r,e)=>m(r,"name",{value:e,configurable:!0}),"n");const b=g(({server:r},e)=>{r.registerTool("describe_project",{annotations:{readOnlyHint:!0},description:"Return full metadata for a single workspace project: language, layer, stack, type, tags, root path, and all targets.",inputSchema:{name:c.string().describe('Project name (e.g. "@visulima/cerebro")')}},async({name:o})=>{try{const t=(await p(e.visBin,["list","--json"],{cwd:e.workspaceRoot})).find(n=>n.name===o);return t?l(t):s(new Error(`No project named "${o}". Use list_projects to see available names.`))}catch(t){return s(t)}})},"registerDescribeProject");export{b as registerDescribeProject};
@@ -1 +0,0 @@
1
- var f=Object.defineProperty;var d=(t,r)=>f(t,"name",{value:r,configurable:!0});import{readFile as k}from"node:fs/promises";import{join as l}from"@visulima/path";import*as m from"zod";import{errorResponse as o,okResponse as p}from"./okResponse-DdzqnveW.js";import{isValidRunId as I}from"./isValidRunId-BKsKMWQf.js";var g=Object.defineProperty,y=d((t,r)=>g(t,"name",{value:r,configurable:!0}),"m");const h=y(({server:t},r)=>{t.registerTool("get_run_logs",{annotations:{readOnlyHint:!0},description:"Read a vis run summary from .task-runner/. Returns the most recent run by default, or a specific run when `runId` is set. Optionally filter to a single task with `taskId`.",inputSchema:{runId:m.string().optional().describe("Run ID (default: latest)"),taskId:m.string().optional().describe('Filter to a single task ID like "@my/app:build"')}},async({runId:e,taskId:a})=>{if(e!==void 0&&!I(e))return o(new Error(`Invalid runId "${e}". Expected filesystem-safe slug ([A-Za-z0-9_.-]).`));const i=e?l(r.workspaceRoot,".task-runner","runs",`${e}.json`):l(r.workspaceRoot,".task-runner","last-summary.json");try{const n=await k(i,"utf8"),s=JSON.parse(n);if(a){const u=s.tasks?.find(c=>c.taskId===a);return u?p({runId:s.runId,task:u}):o(new Error(`Task "${a}" not found in run "${s.runId??"(unknown)"}".`))}return p(s)}catch(n){return n.code==="ENOENT"?o(new Error(`No run summary at ${i}. Run a task first to populate it.`)):o(n)}})},"registerGetRunLogs");export{h as registerGetRunLogs};
@@ -1 +0,0 @@
1
- var n=Object.defineProperty;var i=(t,e)=>n(t,"name",{value:e,configurable:!0});import*as a from"zod";import{execVisJson as c}from"./execVis-BzS_F-9x.js";import{okResponse as p,errorResponse as l}from"./okResponse-DdzqnveW.js";var g=Object.defineProperty,u=i((t,e)=>g(t,"name",{value:e,configurable:!0}),"n");const f=u(({server:t},e)=>{t.registerTool("list_projects",{annotations:{readOnlyHint:!0},description:'List all workspace projects with their language, type, layer, tags, and target metadata. Optionally filter with a vis query string (e.g. "tag=frontend", "type=application").',inputSchema:{query:a.string().optional().describe('Filter projects by vis query string (e.g. "tag=frontend")')}},async({query:s})=>{try{const r=["list","--json"];s&&r.push("--query",s);const o=await c(e.visBin,r,{cwd:e.workspaceRoot});return p({count:o.length,projects:o})}catch(r){return l(r)}})},"registerListProjects");export{f as registerListProjects};
@@ -1 +0,0 @@
1
- var l=Object.defineProperty;var c=(t,e)=>l(t,"name",{value:e,configurable:!0});import*as g from"zod";import{execVisJson as m}from"./execVis-BzS_F-9x.js";import{errorResponse as p,okResponse as j}from"./okResponse-DdzqnveW.js";var u=Object.defineProperty,d=c((t,e)=>u(t,"name",{value:e,configurable:!0}),"c");const v=d(({server:t},e)=>{t.registerTool("list_targets",{annotations:{readOnlyHint:!0},description:"List per-target rows across the workspace: which targets each project exposes, with type, command, and description. Optionally narrow to a single project.",inputSchema:{project:g.string().optional().describe('Limit to one project (e.g. "@visulima/cerebro")')}},async({project:r})=>{try{const o=await m(e.visBin,["list","--targets","--json"],{cwd:e.workspaceRoot}),a=r?o.filter(s=>s.name===r):o;if(r&&a.length===0)return p(new Error(`No project named "${r}". Use list_projects to see available names.`));const n=a.flatMap(s=>(s.targets??[]).map(i=>({project:s.name,target:i.name,...i})));return j({count:n.length,targets:n})}catch(o){return p(o)}})},"registerListTargets");export{v as registerListTargets};