@xiaou66/vite-plugin-vue-mcp-next 1.0.0 → 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 -9
- package/dist/index.cjs +71 -6
- 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 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -29,9 +29,9 @@ interface VueMcpNextOptions {
|
|
|
29
29
|
readonly host?: string;
|
|
30
30
|
/** 是否在 Vite 启动日志中打印 MCP 地址,默认开启方便开发者复制到 MCP 客户端。 */
|
|
31
31
|
readonly printUrl?: boolean;
|
|
32
|
-
/** 是否写入 Cursor MCP
|
|
32
|
+
/** 是否写入 Cursor MCP 配置;默认只在 `.cursor` 已存在时写入,显式 `true` 会创建配置。 */
|
|
33
33
|
readonly updateCursorMcpJson?: boolean | CursorMcpConfig;
|
|
34
|
-
/** 是否写入常见 AI 客户端的项目级 MCP
|
|
34
|
+
/** 是否写入常见 AI 客户端的项目级 MCP 配置;默认按项目已有客户端入口自动探测。 */
|
|
35
35
|
readonly mcpClients?: McpClientConfigOptions;
|
|
36
36
|
/** 非 HTML 入口的运行时脚本注入点,用于兼容不直接使用 `index.html` 的项目。 */
|
|
37
37
|
readonly appendTo?: string | RegExp;
|
|
@@ -54,7 +54,7 @@ interface VueMcpNextOptions {
|
|
|
54
54
|
* 该配置只负责本地开发体验,不应强行修改未启用 Cursor 的项目。
|
|
55
55
|
*/
|
|
56
56
|
interface CursorMcpConfig {
|
|
57
|
-
/** 是否启用 Cursor
|
|
57
|
+
/** 是否启用 Cursor 配置写入;显式启用会创建 `.cursor/mcp.json`,显式关闭会跳过。 */
|
|
58
58
|
readonly enabled: boolean;
|
|
59
59
|
/** Cursor 展示的 MCP 服务名,用于同一项目存在多个 MCP 服务时避免冲突。 */
|
|
60
60
|
readonly serverName?: string;
|
|
@@ -66,13 +66,13 @@ interface CursorMcpConfig {
|
|
|
66
66
|
* 集中配置可以避免为每个客户端暴露一组重复选项。
|
|
67
67
|
*/
|
|
68
68
|
interface McpClientConfigOptions {
|
|
69
|
-
/** 是否写入 Cursor 的 `.cursor/mcp.json
|
|
69
|
+
/** 是否写入 Cursor 的 `.cursor/mcp.json`;默认只在 `.cursor` 目录已存在时自动写入。 */
|
|
70
70
|
readonly cursor?: boolean;
|
|
71
|
-
/** 是否写入 Codex 的 `.codex/config.toml
|
|
71
|
+
/** 是否写入 Codex 的 `.codex/config.toml`;默认只在 `.codex` 目录已存在时自动写入。 */
|
|
72
72
|
readonly codex?: boolean;
|
|
73
|
-
/** 是否写入 Claude Code 的 `.mcp.json
|
|
73
|
+
/** 是否写入 Claude Code 的 `.mcp.json`;默认只在根目录 `.mcp.json` 已存在时自动写入。 */
|
|
74
74
|
readonly claudeCode?: boolean;
|
|
75
|
-
/** 是否写入 Trae 的 `.trae/mcp.json
|
|
75
|
+
/** 是否写入 Trae 的 `.trae/mcp.json`;默认只在 `.trae` 目录已存在时自动写入。 */
|
|
76
76
|
readonly trae?: boolean;
|
|
77
77
|
/** MCP 客户端中展示的服务名,同一项目存在多个 MCP 服务时用于避免冲突。 */
|
|
78
78
|
readonly serverName?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -29,9 +29,9 @@ interface VueMcpNextOptions {
|
|
|
29
29
|
readonly host?: string;
|
|
30
30
|
/** 是否在 Vite 启动日志中打印 MCP 地址,默认开启方便开发者复制到 MCP 客户端。 */
|
|
31
31
|
readonly printUrl?: boolean;
|
|
32
|
-
/** 是否写入 Cursor MCP
|
|
32
|
+
/** 是否写入 Cursor MCP 配置;默认只在 `.cursor` 已存在时写入,显式 `true` 会创建配置。 */
|
|
33
33
|
readonly updateCursorMcpJson?: boolean | CursorMcpConfig;
|
|
34
|
-
/** 是否写入常见 AI 客户端的项目级 MCP
|
|
34
|
+
/** 是否写入常见 AI 客户端的项目级 MCP 配置;默认按项目已有客户端入口自动探测。 */
|
|
35
35
|
readonly mcpClients?: McpClientConfigOptions;
|
|
36
36
|
/** 非 HTML 入口的运行时脚本注入点,用于兼容不直接使用 `index.html` 的项目。 */
|
|
37
37
|
readonly appendTo?: string | RegExp;
|
|
@@ -54,7 +54,7 @@ interface VueMcpNextOptions {
|
|
|
54
54
|
* 该配置只负责本地开发体验,不应强行修改未启用 Cursor 的项目。
|
|
55
55
|
*/
|
|
56
56
|
interface CursorMcpConfig {
|
|
57
|
-
/** 是否启用 Cursor
|
|
57
|
+
/** 是否启用 Cursor 配置写入;显式启用会创建 `.cursor/mcp.json`,显式关闭会跳过。 */
|
|
58
58
|
readonly enabled: boolean;
|
|
59
59
|
/** Cursor 展示的 MCP 服务名,用于同一项目存在多个 MCP 服务时避免冲突。 */
|
|
60
60
|
readonly serverName?: string;
|
|
@@ -66,13 +66,13 @@ interface CursorMcpConfig {
|
|
|
66
66
|
* 集中配置可以避免为每个客户端暴露一组重复选项。
|
|
67
67
|
*/
|
|
68
68
|
interface McpClientConfigOptions {
|
|
69
|
-
/** 是否写入 Cursor 的 `.cursor/mcp.json
|
|
69
|
+
/** 是否写入 Cursor 的 `.cursor/mcp.json`;默认只在 `.cursor` 目录已存在时自动写入。 */
|
|
70
70
|
readonly cursor?: boolean;
|
|
71
|
-
/** 是否写入 Codex 的 `.codex/config.toml
|
|
71
|
+
/** 是否写入 Codex 的 `.codex/config.toml`;默认只在 `.codex` 目录已存在时自动写入。 */
|
|
72
72
|
readonly codex?: boolean;
|
|
73
|
-
/** 是否写入 Claude Code 的 `.mcp.json
|
|
73
|
+
/** 是否写入 Claude Code 的 `.mcp.json`;默认只在根目录 `.mcp.json` 已存在时自动写入。 */
|
|
74
74
|
readonly claudeCode?: boolean;
|
|
75
|
-
/** 是否写入 Trae 的 `.trae/mcp.json
|
|
75
|
+
/** 是否写入 Trae 的 `.trae/mcp.json`;默认只在 `.trae` 目录已存在时自动写入。 */
|
|
76
76
|
readonly trae?: boolean;
|
|
77
77
|
/** MCP 客户端中展示的服务名,同一项目存在多个 MCP 服务时用于避免冲突。 */
|
|
78
78
|
readonly serverName?: string;
|
package/dist/index.js
CHANGED
|
@@ -1734,6 +1734,7 @@ function getPluginPath(plugin) {
|
|
|
1734
1734
|
}
|
|
1735
1735
|
|
|
1736
1736
|
// src/plugin/mcpClientConfig/index.ts
|
|
1737
|
+
import fs4 from "fs/promises";
|
|
1737
1738
|
import path5 from "path";
|
|
1738
1739
|
|
|
1739
1740
|
// src/plugin/mcpClientConfig/codexConfig.ts
|
|
@@ -1870,10 +1871,17 @@ function isNodeError2(error) {
|
|
|
1870
1871
|
}
|
|
1871
1872
|
|
|
1872
1873
|
// src/plugin/mcpClientConfig/index.ts
|
|
1873
|
-
async function updateMcpClientConfigs(root, sseUrl, streamableHttpUrl, options) {
|
|
1874
|
+
async function updateMcpClientConfigs(root, sseUrl, streamableHttpUrl, options, userOptions = {}) {
|
|
1874
1875
|
const serverName = options.serverName;
|
|
1875
1876
|
const jobs = [];
|
|
1876
|
-
if (
|
|
1877
|
+
if (await shouldUpdateClientConfig({
|
|
1878
|
+
root,
|
|
1879
|
+
clientName: "cursor",
|
|
1880
|
+
enabled: options.cursor,
|
|
1881
|
+
entryPath: path5.join(root, ".cursor"),
|
|
1882
|
+
entryKind: "directory",
|
|
1883
|
+
userOptions
|
|
1884
|
+
})) {
|
|
1877
1885
|
jobs.push(
|
|
1878
1886
|
updateJsonMcpClientConfig({
|
|
1879
1887
|
clientName: "Cursor",
|
|
@@ -1883,7 +1891,14 @@ async function updateMcpClientConfigs(root, sseUrl, streamableHttpUrl, options)
|
|
|
1883
1891
|
})
|
|
1884
1892
|
);
|
|
1885
1893
|
}
|
|
1886
|
-
if (
|
|
1894
|
+
if (await shouldUpdateClientConfig({
|
|
1895
|
+
root,
|
|
1896
|
+
clientName: "codex",
|
|
1897
|
+
enabled: options.codex,
|
|
1898
|
+
entryPath: path5.join(root, ".codex"),
|
|
1899
|
+
entryKind: "directory",
|
|
1900
|
+
userOptions
|
|
1901
|
+
})) {
|
|
1887
1902
|
jobs.push(
|
|
1888
1903
|
updateCodexMcpClientConfig({
|
|
1889
1904
|
configPath: path5.join(root, ".codex", "config.toml"),
|
|
@@ -1892,7 +1907,14 @@ async function updateMcpClientConfigs(root, sseUrl, streamableHttpUrl, options)
|
|
|
1892
1907
|
})
|
|
1893
1908
|
);
|
|
1894
1909
|
}
|
|
1895
|
-
if (
|
|
1910
|
+
if (await shouldUpdateClientConfig({
|
|
1911
|
+
root,
|
|
1912
|
+
clientName: "claudeCode",
|
|
1913
|
+
enabled: options.claudeCode,
|
|
1914
|
+
entryPath: path5.join(root, ".mcp.json"),
|
|
1915
|
+
entryKind: "file",
|
|
1916
|
+
userOptions
|
|
1917
|
+
})) {
|
|
1896
1918
|
jobs.push(
|
|
1897
1919
|
updateJsonMcpClientConfig({
|
|
1898
1920
|
clientName: "Claude Code",
|
|
@@ -1902,7 +1924,14 @@ async function updateMcpClientConfigs(root, sseUrl, streamableHttpUrl, options)
|
|
|
1902
1924
|
})
|
|
1903
1925
|
);
|
|
1904
1926
|
}
|
|
1905
|
-
if (
|
|
1927
|
+
if (await shouldUpdateClientConfig({
|
|
1928
|
+
root,
|
|
1929
|
+
clientName: "trae",
|
|
1930
|
+
enabled: options.trae,
|
|
1931
|
+
entryPath: path5.join(root, ".trae"),
|
|
1932
|
+
entryKind: "directory",
|
|
1933
|
+
userOptions
|
|
1934
|
+
})) {
|
|
1906
1935
|
jobs.push(
|
|
1907
1936
|
updateJsonMcpClientConfig({
|
|
1908
1937
|
clientName: "Trae",
|
|
@@ -1914,6 +1943,41 @@ async function updateMcpClientConfigs(root, sseUrl, streamableHttpUrl, options)
|
|
|
1914
1943
|
}
|
|
1915
1944
|
await Promise.all(jobs);
|
|
1916
1945
|
}
|
|
1946
|
+
async function shouldUpdateClientConfig(options) {
|
|
1947
|
+
if (!options.enabled) {
|
|
1948
|
+
return false;
|
|
1949
|
+
}
|
|
1950
|
+
if (isClientExplicitlyConfigured(options.clientName, options.userOptions)) {
|
|
1951
|
+
return true;
|
|
1952
|
+
}
|
|
1953
|
+
return hasExpectedEntry(options.entryPath, options.entryKind);
|
|
1954
|
+
}
|
|
1955
|
+
function isClientExplicitlyConfigured(clientName, userOptions) {
|
|
1956
|
+
if (Object.hasOwn(userOptions.mcpClients ?? {}, clientName)) {
|
|
1957
|
+
return true;
|
|
1958
|
+
}
|
|
1959
|
+
return clientName === "cursor" && userOptions.updateCursorMcpJson !== void 0;
|
|
1960
|
+
}
|
|
1961
|
+
async function hasExpectedEntry(entryPath, entryKind) {
|
|
1962
|
+
try {
|
|
1963
|
+
const stat = await fs4.stat(entryPath);
|
|
1964
|
+
return entryKind === "directory" ? stat.isDirectory() : stat.isFile();
|
|
1965
|
+
} catch (error) {
|
|
1966
|
+
if (isNodeError3(error) && error.code === "ENOENT") {
|
|
1967
|
+
return false;
|
|
1968
|
+
}
|
|
1969
|
+
console.warn(
|
|
1970
|
+
`[vite-plugin-vue-mcp-next] Failed to inspect MCP client entry at ${entryPath}: ${formatError3(error)}`
|
|
1971
|
+
);
|
|
1972
|
+
return false;
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
function formatError3(error) {
|
|
1976
|
+
return error instanceof Error ? error.message : String(error);
|
|
1977
|
+
}
|
|
1978
|
+
function isNodeError3(error) {
|
|
1979
|
+
return error instanceof Error && "code" in error;
|
|
1980
|
+
}
|
|
1917
1981
|
|
|
1918
1982
|
// src/plugin/createPlugin.ts
|
|
1919
1983
|
import { createRPCServer } from "vite-dev-rpc";
|
|
@@ -1983,7 +2047,8 @@ function vueMcpNext(userOptions = {}) {
|
|
|
1983
2047
|
root,
|
|
1984
2048
|
mcpSseUrl,
|
|
1985
2049
|
mcpStreamableHttpUrl,
|
|
1986
|
-
options.mcpClients
|
|
2050
|
+
options.mcpClients,
|
|
2051
|
+
userOptions
|
|
1987
2052
|
);
|
|
1988
2053
|
if (options.printUrl) {
|
|
1989
2054
|
setTimeout(() => {
|