@weapp-vite/mcp 1.0.1 → 1.1.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 CHANGED
@@ -2,42 +2,75 @@
2
2
 
3
3
  ## 简介
4
4
 
5
- `@weapp-vite/mcp` 是一个基于 Model Context Protocol (MCP) SDK 的示例服务包,展示如何通过 stdio 传输方式注册工具并响应调用。
5
+ `@weapp-vite/mcp` 是面向 `weapp-vite` / `wevu` monorepo MCP 服务端实现,目标是把核心研发能力暴露给 AI:
6
6
 
7
- > 该包目前以示例为主,适合用于学习/验证 MCP 工具服务的基本结构。
7
+ - 包目录与能力发现
8
+ - 源码读取、检索、按行裁剪
9
+ - 包级脚本执行
10
+ - `weapp-vite` CLI 执行
11
+ - 文档/变更记录资源暴露
12
+ - 调试/改造提示词模板
8
13
 
9
- ## 特性
14
+ 默认通过 `stdio` 运行,适合接入任意 MCP Client,也支持 `streamable-http`。
10
15
 
11
- - 使用 MCP SDK 创建服务
12
- - 基于 zod 的入参校验
13
- - 内置示例工具(`calculate-bmi`、`fetch-weather`)
14
- - stdio 传输,方便被 MCP Client 集成
15
-
16
- ## 安装
16
+ ## 启动
17
17
 
18
18
  ```bash
19
- pnpm add @weapp-vite/mcp
19
+ pnpm --filter @weapp-vite/mcp start
20
20
  ```
21
21
 
22
- ## 使用
22
+ 也可以在 Node 脚本里直接调用:
23
23
 
24
- 在仓库内启动示例服务:
24
+ ```ts
25
+ import { startWeappViteMcpServer } from '@weapp-vite/mcp'
25
26
 
26
- ```bash
27
- pnpm --filter @weapp-vite/mcp start
27
+ const handle = await startWeappViteMcpServer({
28
+ workspaceRoot: process.cwd(),
29
+ transport: 'streamable-http',
30
+ host: '127.0.0.1',
31
+ port: 3088,
32
+ endpoint: '/mcp',
33
+ })
34
+
35
+ await handle.close?.()
28
36
  ```
29
37
 
30
- 然后由 MCP Client 通过 stdio 连接并调用工具。
38
+ ## 主要 Tools
39
+
40
+ - `workspace_catalog`: 输出 `weapp-vite / wevu / wevu-compiler` 目录、版本、脚本
41
+ - `list_source_files`: 列出包内文件(默认 `src`)
42
+ - `read_source_file`: 读取包内文件,支持 `startLine/endLine/maxChars`
43
+ - `search_source_code`: 在包源码中检索关键词
44
+ - `run_package_script`: 在指定包目录执行 `pnpm run <script>`
45
+ - `run_weapp_vite_cli`: 执行 `node packages/weapp-vite/bin/weapp-vite.js ...`
46
+ - `run_repo_command`: 执行仓库级命令(`pnpm/node/git/rg`)
47
+
48
+ ## 主要 Resources
31
49
 
32
- ## 配置
50
+ - `weapp-vite://workspace/catalog`
51
+ - `weapp-vite://docs/{package}/README.md`
52
+ - `weapp-vite://docs/{package}/CHANGELOG.md`
53
+ - `weapp-vite://source/{package}?path={path}`
33
54
 
34
- 目前没有独立配置文件。请直接修改 `src/index.ts` 来:
55
+ 其中 `{package}` 支持:
35
56
 
36
- - 添加/移除工具
37
- - 调整工具参数与逻辑
38
- - 修改服务名称与版本
57
+ - `weapp-vite`
58
+ - `wevu`
59
+ - `wevu-compiler`
60
+
61
+ ## Prompts
62
+
63
+ - `plan-weapp-vite-change`: 生成 weapp-vite/wevu 改造计划提示词
64
+ - `debug-wevu-runtime`: 生成 wevu runtime 排查提示词
65
+
66
+ ## 开发
67
+
68
+ ```bash
69
+ pnpm --filter @weapp-vite/mcp test
70
+ pnpm --filter @weapp-vite/mcp build
71
+ ```
39
72
 
40
73
  ## 相关链接
41
74
 
42
- - MCP SDKhttps://github.com/modelcontextprotocol/sdk
43
- - 仓库:https://github.com/weapp-vite/weapp-vite
75
+ - MCP SDK: https://github.com/modelcontextprotocol/sdk
76
+ - 仓库: https://github.com/weapp-vite/weapp-vite
package/dist/index.d.mts CHANGED
@@ -1,2 +1,131 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
1
2
 
2
- export { };
3
+ declare const MCP_SERVER_NAME = "@weapp-vite/mcp";
4
+ declare const MCP_SERVER_VERSION = "2.0.0";
5
+ declare const EXPOSED_PACKAGES: {
6
+ readonly 'weapp-vite': {
7
+ readonly id: "weapp-vite";
8
+ readonly label: "weapp-vite";
9
+ readonly relativePath: string;
10
+ };
11
+ readonly wevu: {
12
+ readonly id: "wevu";
13
+ readonly label: "wevu";
14
+ readonly relativePath: string;
15
+ };
16
+ readonly 'wevu-compiler': {
17
+ readonly id: "wevu-compiler";
18
+ readonly label: "wevu-compiler";
19
+ readonly relativePath: string;
20
+ };
21
+ };
22
+ type ExposedPackageId = keyof typeof EXPOSED_PACKAGES;
23
+ declare const DEFAULT_TIMEOUT_MS = 120000;
24
+ declare const DEFAULT_MAX_OUTPUT_CHARS = 120000;
25
+ declare const DEFAULT_MAX_FILE_CHARS = 80000;
26
+ declare const DEFAULT_MAX_RESULTS = 200;
27
+ declare const SKIPPED_DIR_NAMES: Set<string>;
28
+
29
+ interface ExposedPackageSummary {
30
+ id: ExposedPackageId;
31
+ label: string;
32
+ packageName: string;
33
+ version: string;
34
+ absolutePath: string;
35
+ relativePath: string;
36
+ scripts: string[];
37
+ docs: {
38
+ readme?: string;
39
+ changelog?: string;
40
+ };
41
+ }
42
+ declare function loadPackageSummary(workspaceRoot: string, id: ExposedPackageId): Promise<ExposedPackageSummary>;
43
+ declare function loadExposedCatalog(workspaceRoot: string): Promise<ExposedPackageSummary[]>;
44
+
45
+ interface CommandResult {
46
+ command: string;
47
+ args: string[];
48
+ cwd: string;
49
+ exitCode: number;
50
+ stdout: string;
51
+ stderr: string;
52
+ timedOut: boolean;
53
+ }
54
+ declare function runCommand(workspaceRoot: string, command: string, args: string[], options?: {
55
+ cwdRelative?: string;
56
+ timeoutMs?: number;
57
+ maxOutputChars?: number;
58
+ }): Promise<CommandResult>;
59
+
60
+ interface SearchMatch {
61
+ filePath: string;
62
+ line: number;
63
+ column: number;
64
+ text: string;
65
+ }
66
+ declare function listFilesInDirectory(root: string, relativeDirectory?: string, maxResults?: number): Promise<string[]>;
67
+ declare function readFileContent(root: string, relativeFilePath: string, options?: {
68
+ startLine?: number;
69
+ endLine?: number;
70
+ maxChars?: number;
71
+ }): Promise<{
72
+ filePath: string;
73
+ content: string;
74
+ }>;
75
+ declare function searchTextInDirectory(root: string, query: string, options?: {
76
+ relativeDirectory?: string;
77
+ maxResults?: number;
78
+ }): Promise<SearchMatch[]>;
79
+
80
+ interface CreateServerOptions {
81
+ workspaceRoot?: string;
82
+ }
83
+ declare function createWeappViteMcpServer(options?: CreateServerOptions): Promise<{
84
+ server: McpServer;
85
+ workspaceRoot: string;
86
+ }>;
87
+
88
+ declare const DEFAULT_MCP_HOST = "127.0.0.1";
89
+ declare const DEFAULT_MCP_PORT = 3088;
90
+ declare const DEFAULT_MCP_ENDPOINT = "/mcp";
91
+ interface StartMcpServerOptions extends CreateServerOptions {
92
+ transport?: 'stdio' | 'streamable-http';
93
+ host?: string;
94
+ port?: number;
95
+ endpoint?: string;
96
+ unref?: boolean;
97
+ quiet?: boolean;
98
+ onReady?: (message: string) => void;
99
+ }
100
+ interface McpServerHandle {
101
+ transport: 'stdio' | 'streamable-http';
102
+ close?: () => Promise<void>;
103
+ }
104
+ declare function startStdioServer(options?: CreateServerOptions): Promise<void>;
105
+ declare function startWeappViteMcpServer(options?: StartMcpServerOptions): Promise<McpServerHandle>;
106
+
107
+ declare function formatJson(value: unknown): string;
108
+ declare function normalizeErrorMessage(error: unknown): string;
109
+ declare function toToolResult(data: unknown, text?: string): {
110
+ content: {
111
+ type: "text";
112
+ text: string;
113
+ }[];
114
+ structuredContent: {
115
+ result: unknown;
116
+ };
117
+ };
118
+ declare function toToolError(error: unknown): {
119
+ isError: boolean;
120
+ content: {
121
+ type: "text";
122
+ text: string;
123
+ }[];
124
+ };
125
+
126
+ declare function resolveWorkspaceRoot(start?: string): string;
127
+ declare function assertInsideRoot(root: string, targetPath: string): string;
128
+ declare function resolveSubPath(root: string, relativePath: string): string;
129
+
130
+ export { DEFAULT_MAX_FILE_CHARS, DEFAULT_MAX_OUTPUT_CHARS, DEFAULT_MAX_RESULTS, DEFAULT_MCP_ENDPOINT, DEFAULT_MCP_HOST, DEFAULT_MCP_PORT, DEFAULT_TIMEOUT_MS, EXPOSED_PACKAGES, MCP_SERVER_NAME, MCP_SERVER_VERSION, SKIPPED_DIR_NAMES, assertInsideRoot, createWeappViteMcpServer, formatJson, listFilesInDirectory, loadExposedCatalog, loadPackageSummary, normalizeErrorMessage, readFileContent, resolveSubPath, resolveWorkspaceRoot, runCommand, searchTextInDirectory, startStdioServer, startWeappViteMcpServer, toToolError, toToolResult };
131
+ export type { CommandResult, CreateServerOptions, ExposedPackageId, ExposedPackageSummary, McpServerHandle, SearchMatch, StartMcpServerOptions };
package/dist/index.d.ts CHANGED
@@ -1,2 +1,131 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
1
2
 
2
- export { };
3
+ declare const MCP_SERVER_NAME = "@weapp-vite/mcp";
4
+ declare const MCP_SERVER_VERSION = "2.0.0";
5
+ declare const EXPOSED_PACKAGES: {
6
+ readonly 'weapp-vite': {
7
+ readonly id: "weapp-vite";
8
+ readonly label: "weapp-vite";
9
+ readonly relativePath: string;
10
+ };
11
+ readonly wevu: {
12
+ readonly id: "wevu";
13
+ readonly label: "wevu";
14
+ readonly relativePath: string;
15
+ };
16
+ readonly 'wevu-compiler': {
17
+ readonly id: "wevu-compiler";
18
+ readonly label: "wevu-compiler";
19
+ readonly relativePath: string;
20
+ };
21
+ };
22
+ type ExposedPackageId = keyof typeof EXPOSED_PACKAGES;
23
+ declare const DEFAULT_TIMEOUT_MS = 120000;
24
+ declare const DEFAULT_MAX_OUTPUT_CHARS = 120000;
25
+ declare const DEFAULT_MAX_FILE_CHARS = 80000;
26
+ declare const DEFAULT_MAX_RESULTS = 200;
27
+ declare const SKIPPED_DIR_NAMES: Set<string>;
28
+
29
+ interface ExposedPackageSummary {
30
+ id: ExposedPackageId;
31
+ label: string;
32
+ packageName: string;
33
+ version: string;
34
+ absolutePath: string;
35
+ relativePath: string;
36
+ scripts: string[];
37
+ docs: {
38
+ readme?: string;
39
+ changelog?: string;
40
+ };
41
+ }
42
+ declare function loadPackageSummary(workspaceRoot: string, id: ExposedPackageId): Promise<ExposedPackageSummary>;
43
+ declare function loadExposedCatalog(workspaceRoot: string): Promise<ExposedPackageSummary[]>;
44
+
45
+ interface CommandResult {
46
+ command: string;
47
+ args: string[];
48
+ cwd: string;
49
+ exitCode: number;
50
+ stdout: string;
51
+ stderr: string;
52
+ timedOut: boolean;
53
+ }
54
+ declare function runCommand(workspaceRoot: string, command: string, args: string[], options?: {
55
+ cwdRelative?: string;
56
+ timeoutMs?: number;
57
+ maxOutputChars?: number;
58
+ }): Promise<CommandResult>;
59
+
60
+ interface SearchMatch {
61
+ filePath: string;
62
+ line: number;
63
+ column: number;
64
+ text: string;
65
+ }
66
+ declare function listFilesInDirectory(root: string, relativeDirectory?: string, maxResults?: number): Promise<string[]>;
67
+ declare function readFileContent(root: string, relativeFilePath: string, options?: {
68
+ startLine?: number;
69
+ endLine?: number;
70
+ maxChars?: number;
71
+ }): Promise<{
72
+ filePath: string;
73
+ content: string;
74
+ }>;
75
+ declare function searchTextInDirectory(root: string, query: string, options?: {
76
+ relativeDirectory?: string;
77
+ maxResults?: number;
78
+ }): Promise<SearchMatch[]>;
79
+
80
+ interface CreateServerOptions {
81
+ workspaceRoot?: string;
82
+ }
83
+ declare function createWeappViteMcpServer(options?: CreateServerOptions): Promise<{
84
+ server: McpServer;
85
+ workspaceRoot: string;
86
+ }>;
87
+
88
+ declare const DEFAULT_MCP_HOST = "127.0.0.1";
89
+ declare const DEFAULT_MCP_PORT = 3088;
90
+ declare const DEFAULT_MCP_ENDPOINT = "/mcp";
91
+ interface StartMcpServerOptions extends CreateServerOptions {
92
+ transport?: 'stdio' | 'streamable-http';
93
+ host?: string;
94
+ port?: number;
95
+ endpoint?: string;
96
+ unref?: boolean;
97
+ quiet?: boolean;
98
+ onReady?: (message: string) => void;
99
+ }
100
+ interface McpServerHandle {
101
+ transport: 'stdio' | 'streamable-http';
102
+ close?: () => Promise<void>;
103
+ }
104
+ declare function startStdioServer(options?: CreateServerOptions): Promise<void>;
105
+ declare function startWeappViteMcpServer(options?: StartMcpServerOptions): Promise<McpServerHandle>;
106
+
107
+ declare function formatJson(value: unknown): string;
108
+ declare function normalizeErrorMessage(error: unknown): string;
109
+ declare function toToolResult(data: unknown, text?: string): {
110
+ content: {
111
+ type: "text";
112
+ text: string;
113
+ }[];
114
+ structuredContent: {
115
+ result: unknown;
116
+ };
117
+ };
118
+ declare function toToolError(error: unknown): {
119
+ isError: boolean;
120
+ content: {
121
+ type: "text";
122
+ text: string;
123
+ }[];
124
+ };
125
+
126
+ declare function resolveWorkspaceRoot(start?: string): string;
127
+ declare function assertInsideRoot(root: string, targetPath: string): string;
128
+ declare function resolveSubPath(root: string, relativePath: string): string;
129
+
130
+ export { DEFAULT_MAX_FILE_CHARS, DEFAULT_MAX_OUTPUT_CHARS, DEFAULT_MAX_RESULTS, DEFAULT_MCP_ENDPOINT, DEFAULT_MCP_HOST, DEFAULT_MCP_PORT, DEFAULT_TIMEOUT_MS, EXPOSED_PACKAGES, MCP_SERVER_NAME, MCP_SERVER_VERSION, SKIPPED_DIR_NAMES, assertInsideRoot, createWeappViteMcpServer, formatJson, listFilesInDirectory, loadExposedCatalog, loadPackageSummary, normalizeErrorMessage, readFileContent, resolveSubPath, resolveWorkspaceRoot, runCommand, searchTextInDirectory, startStdioServer, startWeappViteMcpServer, toToolError, toToolResult };
131
+ export type { CommandResult, CreateServerOptions, ExposedPackageId, ExposedPackageSummary, McpServerHandle, SearchMatch, StartMcpServerOptions };
package/dist/index.mjs CHANGED
@@ -1,37 +1,818 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
1
+ import process from 'node:process';
2
+ import { fileURLToPath } from 'node:url';
3
+ import fs$1 from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ import fs from 'node:fs';
6
+ import { spawn } from 'node:child_process';
7
+ import { Buffer } from 'node:buffer';
8
+ import http from 'node:http';
2
9
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
10
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
11
+ import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
3
12
  import { z } from 'zod';
4
13
 
5
- const server = new McpServer({
6
- name: "Demo",
7
- version: "1.0.0"
8
- });
9
- server.tool(
10
- "calculate-bmi",
11
- {
12
- weightKg: z.number(),
13
- heightM: z.number()
14
+ const MCP_SERVER_NAME = "@weapp-vite/mcp";
15
+ const MCP_SERVER_VERSION = "2.0.0";
16
+ const EXPOSED_PACKAGES = {
17
+ "weapp-vite": {
18
+ id: "weapp-vite",
19
+ label: "weapp-vite",
20
+ relativePath: path.join("packages", "weapp-vite")
14
21
  },
15
- async ({ weightKg, heightM }) => ({
22
+ "wevu": {
23
+ id: "wevu",
24
+ label: "wevu",
25
+ relativePath: path.join("packages", "wevu")
26
+ },
27
+ "wevu-compiler": {
28
+ id: "wevu-compiler",
29
+ label: "wevu-compiler",
30
+ relativePath: path.join("packages", "wevu-compiler")
31
+ }
32
+ };
33
+ const DEFAULT_TIMEOUT_MS = 12e4;
34
+ const DEFAULT_MAX_OUTPUT_CHARS = 12e4;
35
+ const DEFAULT_MAX_FILE_CHARS = 8e4;
36
+ const DEFAULT_MAX_RESULTS = 200;
37
+ const SKIPPED_DIR_NAMES = /* @__PURE__ */ new Set([
38
+ "node_modules",
39
+ ".git",
40
+ ".turbo",
41
+ "dist",
42
+ "coverage"
43
+ ]);
44
+
45
+ function hasWorkspaceMarkers(dir) {
46
+ return fs.existsSync(path.join(dir, "pnpm-workspace.yaml")) && fs.existsSync(path.join(dir, "package.json"));
47
+ }
48
+ function resolveWorkspaceRoot(start = process.cwd()) {
49
+ let current = path.resolve(start);
50
+ while (true) {
51
+ if (hasWorkspaceMarkers(current)) {
52
+ return current;
53
+ }
54
+ const parent = path.dirname(current);
55
+ if (parent === current) {
56
+ return path.resolve(start);
57
+ }
58
+ current = parent;
59
+ }
60
+ }
61
+ function assertInsideRoot(root, targetPath) {
62
+ const resolvedRoot = path.resolve(root);
63
+ const resolvedTarget = path.resolve(targetPath);
64
+ const relative = path.relative(resolvedRoot, resolvedTarget);
65
+ if (relative === "" || relative === ".") {
66
+ return resolvedTarget;
67
+ }
68
+ if (relative.startsWith("..") || path.isAbsolute(relative)) {
69
+ throw new Error(`\u8DEF\u5F84\u8D8A\u754C\uFF1A${targetPath}`);
70
+ }
71
+ return resolvedTarget;
72
+ }
73
+ function resolveSubPath(root, relativePath) {
74
+ if (!relativePath || relativePath === ".") {
75
+ return path.resolve(root);
76
+ }
77
+ if (path.isAbsolute(relativePath)) {
78
+ throw new Error("\u4EC5\u652F\u6301\u76F8\u5BF9\u8DEF\u5F84");
79
+ }
80
+ return assertInsideRoot(root, path.resolve(root, relativePath));
81
+ }
82
+
83
+ async function readJsonFile(filePath) {
84
+ const content = await fs$1.readFile(filePath, "utf8");
85
+ return JSON.parse(content);
86
+ }
87
+ async function pathExists(filePath) {
88
+ try {
89
+ await fs$1.access(filePath);
90
+ return true;
91
+ } catch {
92
+ return false;
93
+ }
94
+ }
95
+ async function loadPackageSummary(workspaceRoot, id) {
96
+ const config = EXPOSED_PACKAGES[id];
97
+ const absolutePath = assertInsideRoot(workspaceRoot, path.join(workspaceRoot, config.relativePath));
98
+ const packageJsonPath = path.join(absolutePath, "package.json");
99
+ const packageJson = await readJsonFile(packageJsonPath);
100
+ const readmePath = path.join(absolutePath, "README.md");
101
+ const changelogPath = path.join(absolutePath, "CHANGELOG.md");
102
+ return {
103
+ id,
104
+ label: config.label,
105
+ packageName: packageJson.name ?? config.label,
106
+ version: packageJson.version ?? "0.0.0",
107
+ absolutePath,
108
+ relativePath: config.relativePath,
109
+ scripts: Object.keys(packageJson.scripts ?? {}),
110
+ docs: {
111
+ readme: await pathExists(readmePath) ? readmePath : void 0,
112
+ changelog: await pathExists(changelogPath) ? changelogPath : void 0
113
+ }
114
+ };
115
+ }
116
+ async function loadExposedCatalog(workspaceRoot) {
117
+ const summaries = await Promise.all(
118
+ Object.keys(EXPOSED_PACKAGES).map((id) => loadPackageSummary(workspaceRoot, id))
119
+ );
120
+ return summaries.sort((a, b) => a.id.localeCompare(b.id));
121
+ }
122
+
123
+ const ALLOWED_COMMANDS = /* @__PURE__ */ new Set([
124
+ "pnpm",
125
+ "node",
126
+ "git",
127
+ "rg"
128
+ ]);
129
+ function resolveExecutable(command) {
130
+ if (process.platform === "win32") {
131
+ if (command === "pnpm") {
132
+ return "pnpm.cmd";
133
+ }
134
+ if (command === "git") {
135
+ return "git.exe";
136
+ }
137
+ if (command === "rg") {
138
+ return "rg.exe";
139
+ }
140
+ }
141
+ return command;
142
+ }
143
+ function truncateOutput(text, maxChars) {
144
+ if (text.length <= maxChars) {
145
+ return text;
146
+ }
147
+ return `${text.slice(0, maxChars)}
148
+
149
+ [truncated: ${text.length - maxChars} chars omitted]`;
150
+ }
151
+ async function runCommand(workspaceRoot, command, args, options) {
152
+ if (!ALLOWED_COMMANDS.has(command)) {
153
+ throw new Error(`\u4E0D\u5141\u8BB8\u7684\u547D\u4EE4\uFF1A${command}`);
154
+ }
155
+ const cwd = resolveSubPath(workspaceRoot, options?.cwdRelative ?? ".");
156
+ const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
157
+ const maxOutputChars = options?.maxOutputChars ?? DEFAULT_MAX_OUTPUT_CHARS;
158
+ const executable = resolveExecutable(command);
159
+ const child = spawn(executable, args, {
160
+ cwd,
161
+ env: process.env,
162
+ stdio: ["ignore", "pipe", "pipe"],
163
+ shell: false
164
+ });
165
+ let stdout = "";
166
+ let stderr = "";
167
+ let timedOut = false;
168
+ const timer = setTimeout(() => {
169
+ timedOut = true;
170
+ child.kill("SIGTERM");
171
+ }, timeoutMs);
172
+ child.stdout.on("data", (chunk) => {
173
+ stdout += chunk.toString();
174
+ });
175
+ child.stderr.on("data", (chunk) => {
176
+ stderr += chunk.toString();
177
+ });
178
+ const exitCode = await new Promise((resolve, reject) => {
179
+ child.on("error", reject);
180
+ child.on("close", (code) => {
181
+ resolve(code ?? -1);
182
+ });
183
+ }).finally(() => {
184
+ clearTimeout(timer);
185
+ });
186
+ return {
187
+ command,
188
+ args,
189
+ cwd: path.resolve(cwd),
190
+ exitCode,
191
+ stdout: truncateOutput(stdout.trim(), maxOutputChars),
192
+ stderr: truncateOutput(stderr.trim(), maxOutputChars),
193
+ timedOut
194
+ };
195
+ }
196
+
197
+ async function walkFilesRecursive(root, current, output, maxResults) {
198
+ if (output.length >= maxResults) {
199
+ return;
200
+ }
201
+ const entries = await fs$1.readdir(current, { withFileTypes: true });
202
+ for (const entry of entries) {
203
+ if (output.length >= maxResults) {
204
+ return;
205
+ }
206
+ if (entry.isDirectory()) {
207
+ if (SKIPPED_DIR_NAMES.has(entry.name)) {
208
+ continue;
209
+ }
210
+ await walkFilesRecursive(root, path.join(current, entry.name), output, maxResults);
211
+ continue;
212
+ }
213
+ if (!entry.isFile()) {
214
+ continue;
215
+ }
216
+ const absolutePath = path.join(current, entry.name);
217
+ const relativePath = path.relative(root, absolutePath).split(path.sep).join("/");
218
+ output.push(relativePath);
219
+ }
220
+ }
221
+ async function listFilesInDirectory(root, relativeDirectory = ".", maxResults = DEFAULT_MAX_RESULTS) {
222
+ const dirPath = resolveSubPath(root, relativeDirectory);
223
+ const files = [];
224
+ await walkFilesRecursive(root, dirPath, files, maxResults);
225
+ return files;
226
+ }
227
+ function sliceLines(content, startLine, endLine) {
228
+ if (!startLine && !endLine) {
229
+ return content;
230
+ }
231
+ const lines = content.split("\n");
232
+ const safeStart = Math.max(1, startLine ?? 1);
233
+ const safeEnd = Math.max(safeStart, endLine ?? lines.length);
234
+ return lines.slice(safeStart - 1, safeEnd).join("\n");
235
+ }
236
+ async function readFileContent(root, relativeFilePath, options) {
237
+ const filePath = assertInsideRoot(root, path.join(root, relativeFilePath));
238
+ const content = await fs$1.readFile(filePath, "utf8");
239
+ const selected = sliceLines(content, options?.startLine, options?.endLine);
240
+ const maxChars = options?.maxChars ?? DEFAULT_MAX_FILE_CHARS;
241
+ const clipped = selected.length > maxChars ? `${selected.slice(0, maxChars)}
242
+
243
+ [truncated: ${selected.length - maxChars} chars omitted]` : selected;
244
+ return {
245
+ filePath,
246
+ content: clipped
247
+ };
248
+ }
249
+ function collectMatchesFromText(query, relativeFilePath, content, maxResults, output) {
250
+ const lines = content.split("\n");
251
+ for (let index = 0; index < lines.length; index += 1) {
252
+ if (output.length >= maxResults) {
253
+ return;
254
+ }
255
+ const lineText = lines[index] ?? "";
256
+ const column = lineText.toLowerCase().indexOf(query.toLowerCase());
257
+ if (column === -1) {
258
+ continue;
259
+ }
260
+ output.push({
261
+ filePath: relativeFilePath,
262
+ line: index + 1,
263
+ column: column + 1,
264
+ text: lineText.trim()
265
+ });
266
+ }
267
+ }
268
+ async function searchTextInDirectory(root, query, options) {
269
+ const maxResults = options?.maxResults ?? DEFAULT_MAX_RESULTS;
270
+ const files = await listFilesInDirectory(root, options?.relativeDirectory ?? ".", Math.max(400, maxResults));
271
+ const matches = [];
272
+ for (const file of files) {
273
+ if (matches.length >= maxResults) {
274
+ break;
275
+ }
276
+ const absolutePath = path.join(root, file);
277
+ let content = "";
278
+ try {
279
+ content = await fs$1.readFile(absolutePath, "utf8");
280
+ } catch {
281
+ continue;
282
+ }
283
+ collectMatchesFromText(query, file, content, maxResults, matches);
284
+ }
285
+ return matches;
286
+ }
287
+
288
+ function formatJson(value) {
289
+ return JSON.stringify(value, null, 2);
290
+ }
291
+ function normalizeErrorMessage(error) {
292
+ if (error instanceof Error) {
293
+ return error.message;
294
+ }
295
+ return String(error);
296
+ }
297
+ function toToolResult(data, text) {
298
+ return {
299
+ content: [{
300
+ type: "text",
301
+ text: text ?? formatJson(data)
302
+ }],
303
+ structuredContent: {
304
+ result: data
305
+ }
306
+ };
307
+ }
308
+ function toToolError(error) {
309
+ const message = normalizeErrorMessage(error);
310
+ return {
311
+ isError: true,
16
312
  content: [{
17
313
  type: "text",
18
- text: String(weightKg / (heightM * heightM))
314
+ text: message
19
315
  }]
20
- })
21
- );
22
- server.tool(
23
- "fetch-weather",
24
- { city: z.string() },
25
- async ({ city }) => {
26
- const response = await fetch(`https://api.weather.com/${city}`);
27
- const data = await response.text();
316
+ };
317
+ }
318
+
319
+ const packageIds = Object.keys(EXPOSED_PACKAGES);
320
+ const packageIdSchema = z.enum(packageIds);
321
+ function resolvePackageRoot(workspaceRoot, packageId) {
322
+ return assertInsideRoot(workspaceRoot, path.join(workspaceRoot, EXPOSED_PACKAGES[packageId].relativePath));
323
+ }
324
+ function toDocsUri(packageId, fileName) {
325
+ return `weapp-vite://docs/${packageId}/${fileName}`;
326
+ }
327
+ async function readTextFile(filePath) {
328
+ return fs$1.readFile(filePath, "utf8");
329
+ }
330
+ async function createWeappViteMcpServer(options) {
331
+ const workspaceRoot = resolveWorkspaceRoot(options?.workspaceRoot);
332
+ const server = new McpServer({
333
+ name: MCP_SERVER_NAME,
334
+ version: MCP_SERVER_VERSION
335
+ });
336
+ server.registerTool("workspace_catalog", {
337
+ title: "Workspace Catalog",
338
+ description: "\u8BFB\u53D6 weapp-vite / wevu \u76F8\u5173\u5305\u76EE\u5F55\u4E0E\u811A\u672C\u80FD\u529B\u6E05\u5355"
339
+ }, async () => {
340
+ try {
341
+ const catalog2 = await loadExposedCatalog(workspaceRoot);
342
+ return toToolResult({
343
+ workspaceRoot,
344
+ packages: catalog2
345
+ });
346
+ } catch (error) {
347
+ return toToolError(error);
348
+ }
349
+ });
350
+ server.registerTool("list_source_files", {
351
+ title: "List Source Files",
352
+ description: "\u5217\u51FA weapp-vite / wevu \u5305\u4E0B\u6307\u5B9A\u76EE\u5F55\u6587\u4EF6\u5217\u8868",
353
+ inputSchema: {
354
+ packageId: packageIdSchema,
355
+ directory: z.string().optional().describe("\u5305\u5185\u76F8\u5BF9\u76EE\u5F55\uFF0C\u9ED8\u8BA4 src"),
356
+ maxResults: z.number().int().positive().max(2e3).optional()
357
+ }
358
+ }, async ({ packageId, directory, maxResults }) => {
359
+ try {
360
+ const packageRoot = resolvePackageRoot(workspaceRoot, packageId);
361
+ const files = await listFilesInDirectory(packageRoot, directory ?? "src", maxResults ?? DEFAULT_MAX_RESULTS);
362
+ return toToolResult({
363
+ packageId,
364
+ directory: directory ?? "src",
365
+ count: files.length,
366
+ files
367
+ });
368
+ } catch (error) {
369
+ return toToolError(error);
370
+ }
371
+ });
372
+ server.registerTool("read_source_file", {
373
+ title: "Read Source File",
374
+ description: "\u8BFB\u53D6 weapp-vite / wevu \u5305\u5185\u6E90\u7801\u6587\u4EF6\uFF0C\u652F\u6301\u884C\u533A\u95F4\u88C1\u526A",
375
+ inputSchema: {
376
+ packageId: packageIdSchema,
377
+ filePath: z.string().describe("\u5305\u5185\u76F8\u5BF9\u6587\u4EF6\u8DEF\u5F84"),
378
+ startLine: z.number().int().positive().optional(),
379
+ endLine: z.number().int().positive().optional(),
380
+ maxChars: z.number().int().positive().max(2e5).optional()
381
+ }
382
+ }, async ({ packageId, filePath, startLine, endLine, maxChars }) => {
383
+ try {
384
+ const packageRoot = resolvePackageRoot(workspaceRoot, packageId);
385
+ const { filePath: absolutePath, content } = await readFileContent(packageRoot, filePath, {
386
+ startLine,
387
+ endLine,
388
+ maxChars: maxChars ?? DEFAULT_MAX_FILE_CHARS
389
+ });
390
+ return toToolResult({
391
+ packageId,
392
+ filePath,
393
+ absolutePath,
394
+ startLine: startLine ?? null,
395
+ endLine: endLine ?? null,
396
+ content
397
+ }, content);
398
+ } catch (error) {
399
+ return toToolError(error);
400
+ }
401
+ });
402
+ server.registerTool("search_source_code", {
403
+ title: "Search Source Code",
404
+ description: "\u5728 weapp-vite / wevu \u4EE3\u7801\u4E2D\u641C\u7D22\u5173\u952E\u8BCD",
405
+ inputSchema: {
406
+ query: z.string().min(1),
407
+ packageId: packageIdSchema.optional(),
408
+ directory: z.string().optional(),
409
+ maxResults: z.number().int().positive().max(2e3).optional()
410
+ }
411
+ }, async ({ query, packageId, directory, maxResults }) => {
412
+ try {
413
+ const targetPackageIds = packageId ? [packageId] : packageIds;
414
+ const allMatches = [];
415
+ const safeMax = maxResults ?? DEFAULT_MAX_RESULTS;
416
+ for (const id of targetPackageIds) {
417
+ if (allMatches.length >= safeMax) {
418
+ break;
419
+ }
420
+ const packageRoot = resolvePackageRoot(workspaceRoot, id);
421
+ const matches = await searchTextInDirectory(packageRoot, query, {
422
+ relativeDirectory: directory ?? "src",
423
+ maxResults: safeMax - allMatches.length
424
+ });
425
+ allMatches.push(...matches.map((match) => ({
426
+ packageId: id,
427
+ ...match
428
+ })));
429
+ }
430
+ return toToolResult({
431
+ query,
432
+ total: allMatches.length,
433
+ matches: allMatches
434
+ });
435
+ } catch (error) {
436
+ return toToolError(error);
437
+ }
438
+ });
439
+ server.registerTool("run_package_script", {
440
+ title: "Run Package Script",
441
+ description: "\u5728 weapp-vite / wevu \u5305\u76EE\u5F55\u6267\u884C pnpm script",
442
+ inputSchema: {
443
+ packageId: packageIdSchema,
444
+ script: z.string().min(1),
445
+ args: z.array(z.string()).optional(),
446
+ timeoutMs: z.number().int().positive().max(9e5).optional()
447
+ }
448
+ }, async ({ packageId, script, args, timeoutMs }) => {
449
+ try {
450
+ const cwdRelative = EXPOSED_PACKAGES[packageId].relativePath;
451
+ const result = await runCommand(workspaceRoot, "pnpm", ["run", script, ...args ?? []], {
452
+ cwdRelative,
453
+ timeoutMs: timeoutMs ?? DEFAULT_TIMEOUT_MS
454
+ });
455
+ return toToolResult(result);
456
+ } catch (error) {
457
+ return toToolError(error);
458
+ }
459
+ });
460
+ server.registerTool("run_weapp_vite_cli", {
461
+ title: "Run weapp-vite CLI",
462
+ description: "\u6267\u884C weapp-vite CLI\uFF08build/dev/open/analyze \u7B49\uFF09",
463
+ inputSchema: {
464
+ subCommand: z.string().min(1),
465
+ projectPath: z.string().optional().describe("\u76F8\u5BF9 workspace \u6839\u8DEF\u5F84\uFF0C\u5982 e2e-apps/auto-routes-define-app-json"),
466
+ platform: z.string().optional(),
467
+ args: z.array(z.string()).optional(),
468
+ timeoutMs: z.number().int().positive().max(9e5).optional()
469
+ }
470
+ }, async ({ subCommand, projectPath, platform, args, timeoutMs }) => {
471
+ try {
472
+ const cliPath = path.join("packages", "weapp-vite", "bin", "weapp-vite.js");
473
+ const finalArgs = [cliPath, subCommand];
474
+ if (projectPath) {
475
+ finalArgs.push(resolveSubPath(workspaceRoot, projectPath));
476
+ }
477
+ if (platform) {
478
+ finalArgs.push("--platform", platform);
479
+ }
480
+ if (Array.isArray(args) && args.length > 0) {
481
+ finalArgs.push(...args);
482
+ }
483
+ const result = await runCommand(workspaceRoot, "node", finalArgs, {
484
+ timeoutMs: timeoutMs ?? DEFAULT_TIMEOUT_MS
485
+ });
486
+ return toToolResult(result);
487
+ } catch (error) {
488
+ return toToolError(error);
489
+ }
490
+ });
491
+ server.registerTool("run_repo_command", {
492
+ title: "Run Repo Command",
493
+ description: "\u6267\u884C\u4ED3\u5E93\u7EA7\u547D\u4EE4\uFF08\u652F\u6301 pnpm/node/git/rg\uFF09",
494
+ inputSchema: {
495
+ command: z.enum(["pnpm", "node", "git", "rg"]),
496
+ args: z.array(z.string()).optional(),
497
+ cwdRelative: z.string().optional(),
498
+ timeoutMs: z.number().int().positive().max(9e5).optional()
499
+ }
500
+ }, async ({ command, args, cwdRelative, timeoutMs }) => {
501
+ try {
502
+ const result = await runCommand(workspaceRoot, command, args ?? [], {
503
+ cwdRelative,
504
+ timeoutMs: timeoutMs ?? DEFAULT_TIMEOUT_MS
505
+ });
506
+ return toToolResult(result);
507
+ } catch (error) {
508
+ return toToolError(error);
509
+ }
510
+ });
511
+ server.registerPrompt("plan-weapp-vite-change", {
512
+ title: "Plan weapp-vite Change",
513
+ description: "\u6839\u636E\u53D8\u66F4\u76EE\u6807\u751F\u6210 weapp-vite / wevu \u4FEE\u6539\u8BA1\u5212\u63D0\u793A\u8BCD",
514
+ argsSchema: {
515
+ objective: z.string().min(1),
516
+ focusPackage: packageIdSchema.optional()
517
+ }
518
+ }, async ({ objective, focusPackage }) => {
519
+ const targets = focusPackage ? [focusPackage] : packageIds;
520
+ return {
521
+ messages: [
522
+ {
523
+ role: "user",
524
+ content: {
525
+ type: "text",
526
+ text: [
527
+ "\u4F60\u662F weapp-vite monorepo \u7EF4\u62A4\u8005\uFF0C\u8BF7\u7ED9\u51FA\u53EF\u6267\u884C\u7684\u6539\u9020\u8BA1\u5212\u3002",
528
+ `\u76EE\u6807\uFF1A${objective}`,
529
+ `\u805A\u7126\u5305\uFF1A${targets.join(", ")}`,
530
+ "\u8BF7\u5305\u542B\uFF1A\u5F71\u54CD\u9762\u3001\u98CE\u9669\u70B9\u3001\u6D4B\u8BD5\u7B56\u7565\u3001\u56DE\u6EDA\u7B56\u7565\u3002"
531
+ ].join("\n")
532
+ }
533
+ }
534
+ ]
535
+ };
536
+ });
537
+ server.registerPrompt("debug-wevu-runtime", {
538
+ title: "Debug wevu Runtime",
539
+ description: "\u7528\u4E8E\u5B9A\u4F4D wevu runtime \u751F\u547D\u5468\u671F/\u54CD\u5E94\u5F0F\u95EE\u9898\u7684\u6807\u51C6\u63D0\u793A\u8BCD",
540
+ argsSchema: {
541
+ symptom: z.string().min(1)
542
+ }
543
+ }, async ({ symptom }) => {
544
+ return {
545
+ messages: [
546
+ {
547
+ role: "user",
548
+ content: {
549
+ type: "text",
550
+ text: [
551
+ "\u8BF7\u57FA\u4E8E wevu runtime \u4EE3\u7801\u8DEF\u5F84\u8FDB\u884C\u5206\u5C42\u6392\u67E5\uFF1A",
552
+ "1. \u590D\u73B0\u573A\u666F\u4E0E\u6700\u5C0F\u6837\u4F8B",
553
+ "2. \u751F\u547D\u5468\u671F\u94A9\u5B50\u89E6\u53D1\u94FE",
554
+ "3. \u54CD\u5E94\u5F0F\u4E0E setData \u5DEE\u91CF\u540C\u6B65\u94FE",
555
+ "4. \u5355\u6D4B\u4E0E e2e \u56DE\u5F52\u8865\u4E01",
556
+ `\u73B0\u8C61\uFF1A${symptom}`
557
+ ].join("\n")
558
+ }
559
+ }
560
+ ]
561
+ };
562
+ });
563
+ server.registerResource("workspace-catalog", "weapp-vite://workspace/catalog", {
564
+ title: "Workspace Catalog",
565
+ description: "weapp-vite / wevu \u5305\u76EE\u5F55\u3001\u7248\u672C\u548C\u811A\u672C\u5217\u8868",
566
+ mimeType: "application/json"
567
+ }, async () => {
568
+ const catalog2 = await loadExposedCatalog(workspaceRoot);
569
+ const text = JSON.stringify({ workspaceRoot, packages: catalog2 }, null, 2);
28
570
  return {
29
- content: [{ type: "text", text: data }]
571
+ contents: [{
572
+ uri: "weapp-vite://workspace/catalog",
573
+ mimeType: "application/json",
574
+ text
575
+ }]
30
576
  };
577
+ });
578
+ const catalog = await loadExposedCatalog(workspaceRoot);
579
+ for (const summary of catalog) {
580
+ if (summary.docs.readme) {
581
+ const uri = toDocsUri(summary.id, "README.md");
582
+ server.registerResource(`docs-${summary.id}-readme`, uri, {
583
+ title: `${summary.id} README`,
584
+ mimeType: "text/markdown"
585
+ }, async () => {
586
+ const text = await readTextFile(summary.docs.readme);
587
+ return {
588
+ contents: [{ uri, mimeType: "text/markdown", text }]
589
+ };
590
+ });
591
+ }
592
+ if (summary.docs.changelog) {
593
+ const uri = toDocsUri(summary.id, "CHANGELOG.md");
594
+ server.registerResource(`docs-${summary.id}-changelog`, uri, {
595
+ title: `${summary.id} CHANGELOG`,
596
+ mimeType: "text/markdown"
597
+ }, async () => {
598
+ const text = await readTextFile(summary.docs.changelog);
599
+ return {
600
+ contents: [{ uri, mimeType: "text/markdown", text }]
601
+ };
602
+ });
603
+ }
604
+ }
605
+ const sourceTemplate = new ResourceTemplate("weapp-vite://source/{package}?path={path}", {
606
+ list: void 0,
607
+ complete: {
608
+ package: () => packageIds
609
+ }
610
+ });
611
+ server.registerResource("source-template", sourceTemplate, {
612
+ title: "Source Template",
613
+ description: "\u8BFB\u53D6 weapp-vite / wevu \u4EFB\u610F\u6E90\u7801\u6587\u4EF6\uFF08\u901A\u8FC7 package + path \u53C2\u6570\uFF09",
614
+ mimeType: "text/plain"
615
+ }, async (uri, variables) => {
616
+ try {
617
+ const packageId = String(variables.package ?? "");
618
+ if (!packageIds.includes(packageId)) {
619
+ throw new Error(`\u672A\u77E5 package\uFF1A${packageId}`);
620
+ }
621
+ const relativePath = decodeURIComponent(String(variables.path ?? ""));
622
+ const packageRoot = resolvePackageRoot(workspaceRoot, packageId);
623
+ const { content } = await readFileContent(packageRoot, relativePath, {
624
+ maxChars: DEFAULT_MAX_FILE_CHARS
625
+ });
626
+ return {
627
+ contents: [{
628
+ uri: uri.toString(),
629
+ mimeType: "text/plain",
630
+ text: content
631
+ }]
632
+ };
633
+ } catch (error) {
634
+ return {
635
+ contents: [{
636
+ uri: uri.toString(),
637
+ mimeType: "text/plain",
638
+ text: `[resource-error] ${normalizeErrorMessage(error)}`
639
+ }]
640
+ };
641
+ }
642
+ });
643
+ return {
644
+ server,
645
+ workspaceRoot
646
+ };
647
+ }
648
+
649
+ const DEFAULT_MCP_HOST = "127.0.0.1";
650
+ const DEFAULT_MCP_PORT = 3088;
651
+ const DEFAULT_MCP_ENDPOINT = "/mcp";
652
+ function normalizeEndpoint(input) {
653
+ const value = typeof input === "string" ? input.trim() : "";
654
+ if (!value) {
655
+ return DEFAULT_MCP_ENDPOINT;
656
+ }
657
+ return value.startsWith("/") ? value : `/${value}`;
658
+ }
659
+ function normalizePort(input) {
660
+ if (typeof input === "number" && Number.isInteger(input) && input > 0 && input <= 65535) {
661
+ return input;
31
662
  }
32
- );
33
- const transport = new StdioServerTransport();
34
- async function main() {
35
- await server.connect(transport);
663
+ return DEFAULT_MCP_PORT;
36
664
  }
37
- main();
665
+ async function parseJsonBody(req) {
666
+ if (req.method !== "POST") {
667
+ return void 0;
668
+ }
669
+ const chunks = [];
670
+ for await (const chunk of req) {
671
+ chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
672
+ }
673
+ if (chunks.length === 0) {
674
+ return void 0;
675
+ }
676
+ const raw = Buffer.concat(chunks).toString("utf8").trim();
677
+ if (!raw) {
678
+ return void 0;
679
+ }
680
+ return JSON.parse(raw);
681
+ }
682
+ function writeJson(res, statusCode, payload) {
683
+ if (res.headersSent) {
684
+ return;
685
+ }
686
+ res.statusCode = statusCode;
687
+ res.setHeader("content-type", "application/json");
688
+ res.end(JSON.stringify(payload));
689
+ }
690
+ async function startStdioServer$1(options) {
691
+ const previousCwd = process.cwd();
692
+ if (options?.workspaceRoot) {
693
+ process.chdir(options.workspaceRoot);
694
+ }
695
+ try {
696
+ const { server } = await createWeappViteMcpServer(options);
697
+ const transport = new StdioServerTransport();
698
+ await server.connect(transport);
699
+ } finally {
700
+ if (options?.workspaceRoot) {
701
+ process.chdir(previousCwd);
702
+ }
703
+ }
704
+ }
705
+ async function startStreamableHttpServer(options) {
706
+ const {
707
+ endpoint = DEFAULT_MCP_ENDPOINT,
708
+ host = DEFAULT_MCP_HOST,
709
+ port = DEFAULT_MCP_PORT,
710
+ workspaceRoot,
711
+ unref = false,
712
+ quiet = false,
713
+ onReady
714
+ } = options;
715
+ const normalizedEndpoint = normalizeEndpoint(endpoint);
716
+ const normalizedPort = normalizePort(port);
717
+ const { server: mcpServer } = await createWeappViteMcpServer({ workspaceRoot });
718
+ const transport = new StreamableHTTPServerTransport({
719
+ sessionIdGenerator: void 0
720
+ });
721
+ await mcpServer.connect(transport);
722
+ const httpServer = http.createServer(async (req, res) => {
723
+ try {
724
+ const hostHeader = req.headers.host ?? `${host}:${normalizedPort}`;
725
+ const url = new URL(req.url ?? "/", `http://${hostHeader}`);
726
+ if (url.pathname !== normalizedEndpoint) {
727
+ writeJson(res, 404, {
728
+ jsonrpc: "2.0",
729
+ error: {
730
+ code: -32004,
731
+ message: `Not Found: ${url.pathname}`
732
+ },
733
+ id: null
734
+ });
735
+ return;
736
+ }
737
+ const method = req.method ?? "GET";
738
+ if (!["GET", "POST", "DELETE"].includes(method)) {
739
+ writeJson(res, 405, {
740
+ jsonrpc: "2.0",
741
+ error: {
742
+ code: -32005,
743
+ message: `Method Not Allowed: ${method}`
744
+ },
745
+ id: null
746
+ });
747
+ return;
748
+ }
749
+ const body = await parseJsonBody(req);
750
+ await transport.handleRequest(req, res, body);
751
+ } catch (error) {
752
+ writeJson(res, 500, {
753
+ jsonrpc: "2.0",
754
+ error: {
755
+ code: -32603,
756
+ message: error instanceof Error ? error.message : String(error)
757
+ },
758
+ id: null
759
+ });
760
+ }
761
+ });
762
+ await new Promise((resolve, reject) => {
763
+ httpServer.once("error", reject);
764
+ httpServer.listen(normalizedPort, host, () => {
765
+ resolve();
766
+ });
767
+ });
768
+ if (unref) {
769
+ httpServer.unref();
770
+ }
771
+ if (!quiet) {
772
+ onReady?.(`[mcp] streamable-http ready at http://${host}:${normalizedPort}${normalizedEndpoint}`);
773
+ }
774
+ return {
775
+ transport: "streamable-http",
776
+ close: async () => {
777
+ await transport.close();
778
+ await new Promise((resolve, reject) => {
779
+ httpServer.close((error) => {
780
+ if (error) {
781
+ reject(error);
782
+ return;
783
+ }
784
+ resolve();
785
+ });
786
+ });
787
+ }
788
+ };
789
+ }
790
+ async function startWeappViteMcpServer(options) {
791
+ const transport = options?.transport ?? "stdio";
792
+ if (transport === "streamable-http") {
793
+ return startStreamableHttpServer(options ?? {});
794
+ }
795
+ await startStdioServer$1(options);
796
+ return {
797
+ transport: "stdio"
798
+ };
799
+ }
800
+
801
+ function isDirectExecution() {
802
+ const entry = process.argv[1];
803
+ if (!entry) {
804
+ return false;
805
+ }
806
+ return fileURLToPath(import.meta.url) === entry;
807
+ }
808
+ if (isDirectExecution()) {
809
+ startStdioServer().catch((error) => {
810
+ const message = error instanceof Error ? error.stack ?? error.message : String(error);
811
+ process.stderr.write(`[mcp] server start failed
812
+ ${message}
813
+ `);
814
+ process.exitCode = 1;
815
+ });
816
+ }
817
+
818
+ export { DEFAULT_MAX_FILE_CHARS, DEFAULT_MAX_OUTPUT_CHARS, DEFAULT_MAX_RESULTS, DEFAULT_MCP_ENDPOINT, DEFAULT_MCP_HOST, DEFAULT_MCP_PORT, DEFAULT_TIMEOUT_MS, EXPOSED_PACKAGES, MCP_SERVER_NAME, MCP_SERVER_VERSION, SKIPPED_DIR_NAMES, assertInsideRoot, createWeappViteMcpServer, formatJson, listFilesInDirectory, loadExposedCatalog, loadPackageSummary, normalizeErrorMessage, readFileContent, resolveSubPath, resolveWorkspaceRoot, runCommand, searchTextInDirectory, startStdioServer$1 as startStdioServer, startWeappViteMcpServer, toToolError, toToolResult };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@weapp-vite/mcp",
3
3
  "type": "module",
4
- "version": "1.0.1",
4
+ "version": "1.1.1",
5
5
  "description": "mcp",
6
6
  "author": "ice breaker <1324318532@qq.com>",
7
7
  "license": "ISC",
@@ -31,7 +31,7 @@
31
31
  "node": "^20.19.0 || >=22.12.0"
32
32
  },
33
33
  "dependencies": {
34
- "@modelcontextprotocol/sdk": "^1.25.3",
34
+ "@modelcontextprotocol/sdk": "^1.27.1",
35
35
  "zod": "^4.3.6"
36
36
  },
37
37
  "scripts": {
@@ -40,6 +40,7 @@
40
40
  "build": "unbuild",
41
41
  "test": "vitest run",
42
42
  "test:dev": "vitest",
43
+ "typecheck": "tsc --noEmit",
43
44
  "release": "pnpm publish",
44
45
  "lint": "eslint .",
45
46
  "lint:fix": "eslint . --fix",