@visulima/vis-mcp 0.0.1 → 1.0.0-alpha.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.
- package/CHANGELOG.md +16 -0
- package/LICENSE.md +27 -0
- package/README.md +122 -29
- package/dist/bin.js +3 -0
- package/dist/index.d.ts +109 -0
- package/dist/index.js +1 -0
- package/dist/packem_shared/execVis-BzS_F-9x.js +4 -0
- package/dist/packem_shared/isValidRunId-BKsKMWQf.js +1 -0
- package/dist/packem_shared/okResponse-DdzqnveW.js +1 -0
- package/dist/packem_shared/registerAllTools-BOmyhKCR.js +3 -0
- package/dist/packem_shared/registerCacheHash-CVckSIVO.js +1 -0
- package/dist/packem_shared/registerCacheWhy-BfIjli7n.js +1 -0
- package/dist/packem_shared/registerDescribeProject-Dhuzun-I.js +1 -0
- package/dist/packem_shared/registerGetRunLogs-BxkRfYZU.js +1 -0
- package/dist/packem_shared/registerListProjects-C-AZj8RT.js +1 -0
- package/dist/packem_shared/registerListTargets-Cq6bkF7O.js +1 -0
- package/package.json +71 -7
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
## @visulima/vis-mcp 1.0.0-alpha.1 (2026-05-04)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* **vis-mcp:** add list_templates and describe_template tools ([549ea7e](https://github.com/visulima/visulima/commit/549ea7edbe88e3dde40e09cf5f5eaea80bb8fd58))
|
|
6
|
+
* **vis-mcp:** add MCP server package for AI-agent integration ([a8d5022](https://github.com/visulima/visulima/commit/a8d5022ba905481985378c0ac01e7f654608ec2b))
|
|
7
|
+
|
|
8
|
+
### Miscellaneous Chores
|
|
9
|
+
|
|
10
|
+
* **vis-mcp:** adopt zod v4 catalog and bump @modelcontextprotocol/sdk ([a84ceb1](https://github.com/visulima/visulima/commit/a84ceb1efcfb368c361eb738006f2e7f113ac4c7))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Dependencies
|
|
14
|
+
|
|
15
|
+
* **@visulima/fs:** upgraded to 5.0.0-alpha.13
|
|
16
|
+
* **@visulima/vis:** upgraded to 1.0.0-alpha.11
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 visulima
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
<!-- DEPENDENCIES -->
|
|
24
|
+
<!-- /DEPENDENCIES -->
|
|
25
|
+
|
|
26
|
+
<!-- TYPE_DEPENDENCIES -->
|
|
27
|
+
<!-- /TYPE_DEPENDENCIES -->
|
package/README.md
CHANGED
|
@@ -1,45 +1,138 @@
|
|
|
1
|
-
|
|
1
|
+
<!-- START_PACKAGE_OG_IMAGE_PLACEHOLDER -->
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<a href="https://www.anolilab.com/open-source" align="center">
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<img src="__assets__/package-og.svg" alt="vis-mcp" />
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
</a>
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
<h3 align="center">MCP (Model Context Protocol) server for @visulima/vis — exposes vis tooling to AI agents over stdio</h3>
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
1. Configure OIDC trusted publishing for the package name `@visulima/vis-mcp`
|
|
13
|
-
2. Enable secure, token-less publishing from CI/CD workflows
|
|
14
|
-
3. Establish provenance for packages published under this name
|
|
11
|
+
<!-- END_PACKAGE_OG_IMAGE_PLACEHOLDER -->
|
|
15
12
|
|
|
16
|
-
|
|
13
|
+
<br />
|
|
17
14
|
|
|
18
|
-
|
|
15
|
+
<div align="center">
|
|
19
16
|
|
|
20
|
-
|
|
17
|
+
[![typescript-image][typescript-badge]][typescript-url]
|
|
18
|
+
[![mit licence][license-badge]][license]
|
|
19
|
+
[![npm downloads][npm-downloads-badge]][npm-downloads]
|
|
20
|
+
[![Chat][chat-badge]][chat]
|
|
21
|
+
[![PRs Welcome][prs-welcome-badge]][prs-welcome]
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
</div>
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
<div align="center">
|
|
28
|
+
<p>
|
|
29
|
+
<sup>
|
|
30
|
+
Daniel Bannert's open source work is supported by the community on <a href="https://github.com/sponsors/prisis">GitHub Sponsors</a>
|
|
31
|
+
</sup>
|
|
32
|
+
</p>
|
|
33
|
+
</div>
|
|
28
34
|
|
|
29
|
-
|
|
35
|
+
---
|
|
30
36
|
|
|
31
|
-
|
|
32
|
-
- Contains no executable code
|
|
33
|
-
- Provides no functionality
|
|
34
|
-
- Should not be installed as a dependency
|
|
35
|
-
- Exists only for administrative purposes
|
|
37
|
+
## Install
|
|
36
38
|
|
|
37
|
-
|
|
39
|
+
```sh
|
|
40
|
+
npm install @visulima/vis-mcp
|
|
41
|
+
```
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
43
|
+
```sh
|
|
44
|
+
yarn add @visulima/vis-mcp
|
|
45
|
+
```
|
|
42
46
|
|
|
43
|
-
|
|
47
|
+
```sh
|
|
48
|
+
pnpm add @visulima/vis-mcp
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Usage
|
|
52
|
+
|
|
53
|
+
`@visulima/vis-mcp` is an MCP (Model Context Protocol) server that exposes a read-only view of your `@visulima/vis` workspace to an LLM agent over stdio. It assumes `@visulima/vis` is installed in the workspace it operates against.
|
|
54
|
+
|
|
55
|
+
### Run
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
npx @visulima/vis-mcp
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The server speaks JSON-RPC on stdout and writes status to stderr. Wire it into any MCP-aware client (Claude Desktop, Cursor, Continue, etc.) by pointing the client at the `vis-mcp` command.
|
|
62
|
+
|
|
63
|
+
### Claude Desktop config
|
|
64
|
+
|
|
65
|
+
Add the server to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"mcpServers": {
|
|
70
|
+
"vis": {
|
|
71
|
+
"command": "npx",
|
|
72
|
+
"args": ["-y", "@visulima/vis-mcp"],
|
|
73
|
+
"env": {
|
|
74
|
+
"VIS_MCP_WORKSPACE_ROOT": "/absolute/path/to/your/workspace"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Environment
|
|
82
|
+
|
|
83
|
+
- `VIS_MCP_WORKSPACE_ROOT` — workspace to operate against. Defaults to `process.cwd()`.
|
|
84
|
+
- `VIS_MCP_VIS_BIN` — explicit path to the `vis` CLI. Defaults to resolving `@visulima/vis` from the workspace's `node_modules`.
|
|
85
|
+
|
|
86
|
+
### Tools
|
|
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. |
|
|
100
|
+
|
|
101
|
+
## Related
|
|
102
|
+
|
|
103
|
+
## Supported Node.js Versions
|
|
104
|
+
|
|
105
|
+
Libraries in this ecosystem make the best effort to track [Node.js’ release schedule](https://github.com/nodejs/release#release-schedule).
|
|
106
|
+
Here’s [a post on why we think this is important](https://medium.com/the-node-js-collection/maintainers-should-consider-following-node-js-release-schedule-ab08ed4de71a).
|
|
107
|
+
|
|
108
|
+
## Contributing
|
|
109
|
+
|
|
110
|
+
If you would like to help take a look at the [list of issues](https://github.com/visulima/visulima/issues) and check our [Contributing](.github/CONTRIBUTING.md) guidelines.
|
|
111
|
+
|
|
112
|
+
> **Note:** please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
|
|
113
|
+
|
|
114
|
+
## Credits
|
|
115
|
+
|
|
116
|
+
- [Daniel Bannert](https://github.com/prisis)
|
|
117
|
+
- [All Contributors](https://github.com/visulima/visulima/graphs/contributors)
|
|
118
|
+
|
|
119
|
+
## Made with ❤️ at Anolilab
|
|
120
|
+
|
|
121
|
+
This is an open source project and will always remain free to use. If you think it's cool, please star it 🌟. [Anolilab](https://www.anolilab.com/open-source) is a Development and AI Studio. Contact us at [hello@anolilab.com](mailto:hello@anolilab.com) if you need any help with these technologies or just want to say hi!
|
|
122
|
+
|
|
123
|
+
## License
|
|
124
|
+
|
|
125
|
+
The visulima vis-mcp is open-sourced software licensed under the [MIT][license]
|
|
126
|
+
|
|
127
|
+
<!-- badges -->
|
|
44
128
|
|
|
45
|
-
|
|
129
|
+
[license-badge]: https://img.shields.io/npm/l/@visulima/vis-mcp?style=for-the-badge
|
|
130
|
+
[license]: https://github.com/visulima/visulima/blob/main/LICENSE
|
|
131
|
+
[npm-downloads-badge]: https://img.shields.io/npm/dm/@visulima/vis-mcp?style=for-the-badge
|
|
132
|
+
[npm-downloads]: https://www.npmjs.com/package/@visulima/vis-mcp
|
|
133
|
+
[prs-welcome-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=for-the-badge
|
|
134
|
+
[prs-welcome]: https://github.com/visulima/visulima/blob/main/.github/CONTRIBUTING.md
|
|
135
|
+
[chat-badge]: https://img.shields.io/discord/932323359193186354.svg?style=for-the-badge
|
|
136
|
+
[chat]: https://discord.gg/TtFJY8xkFK
|
|
137
|
+
[typescript-badge]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript
|
|
138
|
+
[typescript-url]: https://www.typescriptlang.org/
|
package/dist/bin.js
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
/**
|
|
3
|
+
* Spawn a `vis` subprocess and capture stdout/stderr without piping to the
|
|
4
|
+
* parent's stdio. The MCP server must keep its own stdout pristine — anything
|
|
5
|
+
* other than JSON-RPC frames corrupts the protocol stream.
|
|
6
|
+
*
|
|
7
|
+
* `visBin` is the resolved path to the user's installed vis CLI; injected so
|
|
8
|
+
* tests can point at a fixture instead of the real CLI.
|
|
9
|
+
*/
|
|
10
|
+
declare const execVis: (visBin: string, args: ReadonlyArray<string>, options?: ExecOptions) => Promise<ExecResult>;
|
|
11
|
+
/**
|
|
12
|
+
* Run `vis` and parse stdout as JSON. Throws when the subprocess fails or
|
|
13
|
+
* stdout isn't valid JSON — callers map this into an `isError: true` MCP
|
|
14
|
+
* response.
|
|
15
|
+
*/
|
|
16
|
+
declare const execVisJson: <T>(visBin: string, args: ReadonlyArray<string>, options?: ExecOptions) => Promise<T>;
|
|
17
|
+
interface ExecResult {
|
|
18
|
+
exitCode: number;
|
|
19
|
+
stderr: string;
|
|
20
|
+
stdout: string;
|
|
21
|
+
timedOut: boolean;
|
|
22
|
+
}
|
|
23
|
+
interface ExecOptions {
|
|
24
|
+
cwd?: string;
|
|
25
|
+
env?: Record<string, string | undefined>;
|
|
26
|
+
/** Hard ceiling. The default 120s suits cache lookups and listings. */
|
|
27
|
+
timeoutMs?: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* MCP tool response shape used across all `vis` tools. Kept in one place so
|
|
31
|
+
* adding a new tool doesn't require re-deriving the type from the SDK.
|
|
32
|
+
*
|
|
33
|
+
* The index signature matches the SDK's `CallToolResult` shape — the SDK
|
|
34
|
+
* extends the JSON-RPC result with an open `_meta` bag and refuses anything
|
|
35
|
+
* stricter at the assignment site.
|
|
36
|
+
*/
|
|
37
|
+
interface McpToolResponse {
|
|
38
|
+
[key: string]: unknown;
|
|
39
|
+
content: {
|
|
40
|
+
text: string;
|
|
41
|
+
type: "text";
|
|
42
|
+
}[];
|
|
43
|
+
isError?: boolean;
|
|
44
|
+
}
|
|
45
|
+
declare const okResponse: (payload: unknown) => McpToolResponse;
|
|
46
|
+
declare const errorResponse: (error: unknown) => McpToolResponse;
|
|
47
|
+
interface ToolContext {
|
|
48
|
+
/** Absolute path to the resolved `vis` CLI bundle. */
|
|
49
|
+
visBin: string;
|
|
50
|
+
/** Workspace root the MCP server should operate against. */
|
|
51
|
+
workspaceRoot: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Dependencies a tool needs from the MCP SDK. Threaded through so each tool
|
|
55
|
+
* stays a plain registration function and tests can swap in a fake `server`
|
|
56
|
+
* without touching the real SDK.
|
|
57
|
+
*/
|
|
58
|
+
interface ToolDeps {
|
|
59
|
+
server: McpServer;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Register every tool against an already-built MCP server. Pure wiring — no
|
|
63
|
+
* I/O — so tests can drive it against an `InMemoryTransport` without forking
|
|
64
|
+
* a subprocess.
|
|
65
|
+
*/
|
|
66
|
+
declare const registerAllTools: (deps: ToolDeps, context: ToolContext) => void;
|
|
67
|
+
/**
|
|
68
|
+
* Build a fully-configured MCP server with all vis tools registered. Returns
|
|
69
|
+
* the server and deps so callers can connect any transport. Tests use this
|
|
70
|
+
* with `InMemoryTransport.createLinkedPair()`.
|
|
71
|
+
*/
|
|
72
|
+
declare const createMcpServer: (context: ToolContext) => Promise<{
|
|
73
|
+
deps: ToolDeps;
|
|
74
|
+
server: McpServer;
|
|
75
|
+
}>;
|
|
76
|
+
/**
|
|
77
|
+
* Boot the vis MCP server over stdio.
|
|
78
|
+
*
|
|
79
|
+
* Critical invariant: nothing in this process may write to stdout outside
|
|
80
|
+
* the MCP transport. Any console.log in tool handlers will frame-corrupt
|
|
81
|
+
* the JSON-RPC stream. Logs go to stderr only.
|
|
82
|
+
*/
|
|
83
|
+
declare const startMcpServer: () => Promise<void>;
|
|
84
|
+
declare const registerCacheHash: ({
|
|
85
|
+
server
|
|
86
|
+
}: ToolDeps, context: ToolContext) => void;
|
|
87
|
+
declare const registerCacheWhy: ({
|
|
88
|
+
server
|
|
89
|
+
}: ToolDeps, context: ToolContext) => void;
|
|
90
|
+
declare const registerDescribeProject: ({
|
|
91
|
+
server
|
|
92
|
+
}: ToolDeps, context: ToolContext) => void;
|
|
93
|
+
declare const registerGetRunLogs: ({
|
|
94
|
+
server
|
|
95
|
+
}: ToolDeps, context: ToolContext) => void;
|
|
96
|
+
declare const registerListProjects: ({
|
|
97
|
+
server
|
|
98
|
+
}: ToolDeps, context: ToolContext) => void;
|
|
99
|
+
declare const registerListTargets: ({
|
|
100
|
+
server
|
|
101
|
+
}: ToolDeps, context: ToolContext) => void;
|
|
102
|
+
declare const isValidRunId: (value: string) => boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Task IDs are `<project>:<target>`; both halves are package or npm-scope
|
|
105
|
+
* shaped. The exec layer uses argv-form spawn so shell metacharacters are
|
|
106
|
+
* inert, but a leading `-` would be parsed as a CLI flag by the vis CLI.
|
|
107
|
+
*/
|
|
108
|
+
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 };
|
package/dist/index.js
ADDED
|
@@ -0,0 +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};
|
|
@@ -0,0 +1,4 @@
|
|
|
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};
|
|
@@ -0,0 +1 @@
|
|
|
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};
|
|
@@ -0,0 +1 @@
|
|
|
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};
|
|
@@ -0,0 +1,3 @@
|
|
|
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};
|
|
@@ -0,0 +1 @@
|
|
|
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};
|
|
@@ -0,0 +1 @@
|
|
|
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};
|
|
@@ -0,0 +1 @@
|
|
|
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};
|
|
@@ -0,0 +1 @@
|
|
|
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};
|
|
@@ -0,0 +1 @@
|
|
|
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};
|
|
@@ -0,0 +1 @@
|
|
|
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};
|
package/package.json
CHANGED
|
@@ -1,10 +1,74 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@visulima/vis-mcp",
|
|
3
|
-
"version": "0.0.1",
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.0-alpha.1",
|
|
4
|
+
"description": "MCP (Model Context Protocol) server for @visulima/vis — exposes vis tooling to AI agents over stdio",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
"agent",
|
|
7
|
+
"ai",
|
|
8
|
+
"claude",
|
|
9
|
+
"cursor",
|
|
10
|
+
"llm",
|
|
11
|
+
"mcp",
|
|
12
|
+
"model-context-protocol",
|
|
13
|
+
"vis",
|
|
14
|
+
"visulima"
|
|
15
|
+
],
|
|
16
|
+
"homepage": "https://visulima.com/packages/vis-mcp",
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/visulima/visulima/issues"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/visulima/visulima.git",
|
|
23
|
+
"directory": "packages/tooling/vis-mcp"
|
|
24
|
+
},
|
|
25
|
+
"funding": [
|
|
26
|
+
{
|
|
27
|
+
"type": "github",
|
|
28
|
+
"url": "https://github.com/sponsors/prisis"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"type": "consulting",
|
|
32
|
+
"url": "https://anolilab.com/support"
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"author": {
|
|
37
|
+
"name": "Daniel Bannert",
|
|
38
|
+
"email": "d.bannert@anolilab.de"
|
|
39
|
+
},
|
|
40
|
+
"sideEffects": false,
|
|
41
|
+
"type": "module",
|
|
42
|
+
"exports": {
|
|
43
|
+
".": {
|
|
44
|
+
"types": "./dist/index.d.ts",
|
|
45
|
+
"default": "./dist/index.js"
|
|
46
|
+
},
|
|
47
|
+
"./package.json": "./package.json"
|
|
48
|
+
},
|
|
49
|
+
"bin": {
|
|
50
|
+
"vis-mcp": "./dist/bin.js"
|
|
51
|
+
},
|
|
52
|
+
"files": [
|
|
53
|
+
"dist/**",
|
|
54
|
+
"README.md",
|
|
55
|
+
"CHANGELOG.md",
|
|
56
|
+
"LICENSE.md"
|
|
57
|
+
],
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
60
|
+
"@visulima/fs": "5.0.0-alpha.13",
|
|
61
|
+
"@visulima/path": "3.0.0-alpha.10",
|
|
62
|
+
"zod": "4.4.3"
|
|
63
|
+
},
|
|
64
|
+
"peerDependencies": {
|
|
65
|
+
"@visulima/vis": "1.0.0-alpha.11"
|
|
66
|
+
},
|
|
67
|
+
"engines": {
|
|
68
|
+
"node": "^22.14.0 || >=24.10.0"
|
|
69
|
+
},
|
|
70
|
+
"publishConfig": {
|
|
71
|
+
"access": "public",
|
|
72
|
+
"provenance": true
|
|
73
|
+
}
|
|
74
|
+
}
|