@xiaou66/vite-plugin-vue-mcp-next 0.0.8 → 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.
- package/README.md +15 -10
- package/dist/index.cjs +71 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +71 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -43,14 +43,18 @@ SSE: http://localhost:<vite-port>/__mcp/sse
|
|
|
43
43
|
Streamable HTTP: http://localhost:<vite-port>/__mcp/mcp
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
启动 Vite dev server
|
|
46
|
+
启动 Vite dev server 后,插件会按项目中已经存在的客户端入口自动写入项目级 MCP 配置,服务名默认是 `vue-mcp-next`。自动配置只会在缺少同名 server 条目时新增配置;如果用户已经配置了 `vue-mcp-next`,插件不会重复写入、覆盖原配置或改写用户自定义字段。
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
-
|
|
|
48
|
+
默认自动探测规则如下:
|
|
49
|
+
|
|
50
|
+
| 客户端 | 自动探测入口 | 自动配置文件 | 默认端点 |
|
|
51
|
+
| ----------- | ------------ | -------------------- | --------------- |
|
|
52
|
+
| Cursor | `.cursor/` | `.cursor/mcp.json` | SSE |
|
|
53
|
+
| Codex | `.codex/` | `.codex/config.toml` | Streamable HTTP |
|
|
54
|
+
| Claude Code | `.mcp.json` | `.mcp.json` | SSE |
|
|
55
|
+
| Trae | `.trae/` | `.trae/mcp.json` | SSE |
|
|
56
|
+
|
|
57
|
+
如果项目中没有对应入口,默认不会创建该客户端配置。需要强制创建时,可以在 `mcpClients` 中显式设置对应客户端为 `true`;需要禁用时显式设置为 `false`。
|
|
54
58
|
|
|
55
59
|
实际端口以启动日志中的 `MCP: SSE server is running at ...` 和 `MCP: Streamable HTTP server is running at ...` 为准。
|
|
56
60
|
|
|
@@ -82,6 +86,8 @@ url = "http://localhost:5173/__mcp/mcp"
|
|
|
82
86
|
|
|
83
87
|
## 完整配置
|
|
84
88
|
|
|
89
|
+
`mcpClients` 中的布尔值保留为开关语义:默认解析后为 `true`,但写入阶段会先做项目入口自动探测;用户在配置中显式写出 `true` 时表示强制创建对应客户端配置。
|
|
90
|
+
|
|
85
91
|
```ts
|
|
86
92
|
vueMcpNext({
|
|
87
93
|
mcpPath: '/__mcp',
|
|
@@ -147,8 +153,8 @@ vueMcpNext({
|
|
|
147
153
|
| `mcpPath` | `string` | `'/__mcp'` | MCP 服务挂载路径,实际 SSE 地址是 `${mcpPath}/sse`,Streamable HTTP 地址是 `${mcpPath}/mcp` |
|
|
148
154
|
| `host` | `string` | `'localhost'` | 打印 MCP 地址和写入 MCP 客户端配置时使用的 host |
|
|
149
155
|
| `printUrl` | `boolean` | `true` | 是否在 Vite 启动日志中打印 MCP SSE 地址 |
|
|
150
|
-
| `mcpClients` | `{ cursor?: boolean; codex?: boolean; claudeCode?: boolean; trae?: boolean; serverName?: string }` |
|
|
151
|
-
| `updateCursorMcpJson` | `boolean \| { enabled: boolean; serverName?: string }` |
|
|
156
|
+
| `mcpClients` | `{ cursor?: boolean; codex?: boolean; claudeCode?: boolean; trae?: boolean; serverName?: string }` | 自动探测 | 是否写入 Cursor、Codex、Claude Code、Trae 的项目级 MCP 配置;默认只处理项目中已有入口,显式 `true` 强制创建 |
|
|
157
|
+
| `updateCursorMcpJson` | `boolean \| { enabled: boolean; serverName?: string }` | 自动探测 | 兼容旧配置;默认只在 `.cursor` 已存在时写入,建议新项目使用 `mcpClients` |
|
|
152
158
|
| `appendTo` | `string \| RegExp` | `undefined` | 非 HTML 入口注入点。配置后会在匹配入口模块前追加 runtime import |
|
|
153
159
|
| `screenshot` | `ScreenshotOptions` | CDP 优先,snapdom 降级 | 页面截图配置,控制真截图、DOM 降级截图、体积上限和 snapdom 扩展 |
|
|
154
160
|
| `screenshot.type` | `'path' \| 'base64'` | `'path'` | 项目级控制截图返回文件路径还是 base64 数据 |
|
|
@@ -362,7 +368,6 @@ export function createMaskPlugin(options: { selectors: string[] }) {
|
|
|
362
368
|
| ---------------- | ------------------------- | ------------------------------- | ----------------------------------------------------------------- |
|
|
363
369
|
| `list_pages` | 无 | `entries`、`pages`、`cdpError?` | 返回 Vite HTML 入口、runtime 页面和 CDP target |
|
|
364
370
|
| `reload_page` | `pageId?`、`ignoreCache?` | `ok`、`source`、`ignoreCache?` | 刷新目标页面;CDP 可用时使用无缓存刷新,Runtime Hook 只能普通刷新 |
|
|
365
|
-
| `get_page_state` | `pageId?` | 页面状态 | 预留页面状态工具名 |
|
|
366
371
|
|
|
367
372
|
`list_pages` 的 `pages` 中可能出现两类页面:
|
|
368
373
|
|
package/dist/index.cjs
CHANGED
|
@@ -58,7 +58,6 @@ var DEFAULT_SCREENSHOT_SAVE_DIR = ".vite-mcp/screenshot";
|
|
|
58
58
|
var MCP_TOOL_NAMES = {
|
|
59
59
|
listPages: "list_pages",
|
|
60
60
|
reloadPage: "reload_page",
|
|
61
|
-
getPageState: "get_page_state",
|
|
62
61
|
getDomTree: "get_dom_tree",
|
|
63
62
|
queryDom: "query_dom",
|
|
64
63
|
takeScreenshot: "take_screenshot",
|
|
@@ -1772,6 +1771,7 @@ function getPluginPath(plugin) {
|
|
|
1772
1771
|
}
|
|
1773
1772
|
|
|
1774
1773
|
// src/plugin/mcpClientConfig/index.ts
|
|
1774
|
+
var import_promises4 = __toESM(require("fs/promises"), 1);
|
|
1775
1775
|
var import_node_path6 = __toESM(require("path"), 1);
|
|
1776
1776
|
|
|
1777
1777
|
// src/plugin/mcpClientConfig/codexConfig.ts
|
|
@@ -1908,10 +1908,17 @@ function isNodeError2(error) {
|
|
|
1908
1908
|
}
|
|
1909
1909
|
|
|
1910
1910
|
// src/plugin/mcpClientConfig/index.ts
|
|
1911
|
-
async function updateMcpClientConfigs(root, sseUrl, streamableHttpUrl, options) {
|
|
1911
|
+
async function updateMcpClientConfigs(root, sseUrl, streamableHttpUrl, options, userOptions = {}) {
|
|
1912
1912
|
const serverName = options.serverName;
|
|
1913
1913
|
const jobs = [];
|
|
1914
|
-
if (
|
|
1914
|
+
if (await shouldUpdateClientConfig({
|
|
1915
|
+
root,
|
|
1916
|
+
clientName: "cursor",
|
|
1917
|
+
enabled: options.cursor,
|
|
1918
|
+
entryPath: import_node_path6.default.join(root, ".cursor"),
|
|
1919
|
+
entryKind: "directory",
|
|
1920
|
+
userOptions
|
|
1921
|
+
})) {
|
|
1915
1922
|
jobs.push(
|
|
1916
1923
|
updateJsonMcpClientConfig({
|
|
1917
1924
|
clientName: "Cursor",
|
|
@@ -1921,7 +1928,14 @@ async function updateMcpClientConfigs(root, sseUrl, streamableHttpUrl, options)
|
|
|
1921
1928
|
})
|
|
1922
1929
|
);
|
|
1923
1930
|
}
|
|
1924
|
-
if (
|
|
1931
|
+
if (await shouldUpdateClientConfig({
|
|
1932
|
+
root,
|
|
1933
|
+
clientName: "codex",
|
|
1934
|
+
enabled: options.codex,
|
|
1935
|
+
entryPath: import_node_path6.default.join(root, ".codex"),
|
|
1936
|
+
entryKind: "directory",
|
|
1937
|
+
userOptions
|
|
1938
|
+
})) {
|
|
1925
1939
|
jobs.push(
|
|
1926
1940
|
updateCodexMcpClientConfig({
|
|
1927
1941
|
configPath: import_node_path6.default.join(root, ".codex", "config.toml"),
|
|
@@ -1930,7 +1944,14 @@ async function updateMcpClientConfigs(root, sseUrl, streamableHttpUrl, options)
|
|
|
1930
1944
|
})
|
|
1931
1945
|
);
|
|
1932
1946
|
}
|
|
1933
|
-
if (
|
|
1947
|
+
if (await shouldUpdateClientConfig({
|
|
1948
|
+
root,
|
|
1949
|
+
clientName: "claudeCode",
|
|
1950
|
+
enabled: options.claudeCode,
|
|
1951
|
+
entryPath: import_node_path6.default.join(root, ".mcp.json"),
|
|
1952
|
+
entryKind: "file",
|
|
1953
|
+
userOptions
|
|
1954
|
+
})) {
|
|
1934
1955
|
jobs.push(
|
|
1935
1956
|
updateJsonMcpClientConfig({
|
|
1936
1957
|
clientName: "Claude Code",
|
|
@@ -1940,7 +1961,14 @@ async function updateMcpClientConfigs(root, sseUrl, streamableHttpUrl, options)
|
|
|
1940
1961
|
})
|
|
1941
1962
|
);
|
|
1942
1963
|
}
|
|
1943
|
-
if (
|
|
1964
|
+
if (await shouldUpdateClientConfig({
|
|
1965
|
+
root,
|
|
1966
|
+
clientName: "trae",
|
|
1967
|
+
enabled: options.trae,
|
|
1968
|
+
entryPath: import_node_path6.default.join(root, ".trae"),
|
|
1969
|
+
entryKind: "directory",
|
|
1970
|
+
userOptions
|
|
1971
|
+
})) {
|
|
1944
1972
|
jobs.push(
|
|
1945
1973
|
updateJsonMcpClientConfig({
|
|
1946
1974
|
clientName: "Trae",
|
|
@@ -1952,6 +1980,41 @@ async function updateMcpClientConfigs(root, sseUrl, streamableHttpUrl, options)
|
|
|
1952
1980
|
}
|
|
1953
1981
|
await Promise.all(jobs);
|
|
1954
1982
|
}
|
|
1983
|
+
async function shouldUpdateClientConfig(options) {
|
|
1984
|
+
if (!options.enabled) {
|
|
1985
|
+
return false;
|
|
1986
|
+
}
|
|
1987
|
+
if (isClientExplicitlyConfigured(options.clientName, options.userOptions)) {
|
|
1988
|
+
return true;
|
|
1989
|
+
}
|
|
1990
|
+
return hasExpectedEntry(options.entryPath, options.entryKind);
|
|
1991
|
+
}
|
|
1992
|
+
function isClientExplicitlyConfigured(clientName, userOptions) {
|
|
1993
|
+
if (Object.hasOwn(userOptions.mcpClients ?? {}, clientName)) {
|
|
1994
|
+
return true;
|
|
1995
|
+
}
|
|
1996
|
+
return clientName === "cursor" && userOptions.updateCursorMcpJson !== void 0;
|
|
1997
|
+
}
|
|
1998
|
+
async function hasExpectedEntry(entryPath, entryKind) {
|
|
1999
|
+
try {
|
|
2000
|
+
const stat = await import_promises4.default.stat(entryPath);
|
|
2001
|
+
return entryKind === "directory" ? stat.isDirectory() : stat.isFile();
|
|
2002
|
+
} catch (error) {
|
|
2003
|
+
if (isNodeError3(error) && error.code === "ENOENT") {
|
|
2004
|
+
return false;
|
|
2005
|
+
}
|
|
2006
|
+
console.warn(
|
|
2007
|
+
`[vite-plugin-vue-mcp-next] Failed to inspect MCP client entry at ${entryPath}: ${formatError3(error)}`
|
|
2008
|
+
);
|
|
2009
|
+
return false;
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
function formatError3(error) {
|
|
2013
|
+
return error instanceof Error ? error.message : String(error);
|
|
2014
|
+
}
|
|
2015
|
+
function isNodeError3(error) {
|
|
2016
|
+
return error instanceof Error && "code" in error;
|
|
2017
|
+
}
|
|
1955
2018
|
|
|
1956
2019
|
// src/plugin/createPlugin.ts
|
|
1957
2020
|
var import_vite_dev_rpc = require("vite-dev-rpc");
|
|
@@ -2021,7 +2084,8 @@ function vueMcpNext(userOptions = {}) {
|
|
|
2021
2084
|
root,
|
|
2022
2085
|
mcpSseUrl,
|
|
2023
2086
|
mcpStreamableHttpUrl,
|
|
2024
|
-
options.mcpClients
|
|
2087
|
+
options.mcpClients,
|
|
2088
|
+
userOptions
|
|
2025
2089
|
);
|
|
2026
2090
|
if (options.printUrl) {
|
|
2027
2091
|
setTimeout(() => {
|