@baitong-dev/mcp-helpers 0.0.3 → 0.0.5

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.
@@ -4,7 +4,7 @@ export * as Ripgrep from './ripgrep';
4
4
  * @param path The path to check
5
5
  * @returns Whether the path is a directory
6
6
  */
7
- export declare function isDir(path: string): Promise<boolean>;
7
+ export declare function isDirectory(path: string): boolean;
8
8
  /**
9
9
  * 检查一个目录是否是另一个目录的子目录
10
10
  * @param parent - 父目录路径
@@ -37,18 +37,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.Ripgrep = void 0;
40
- exports.isDir = isDir;
40
+ exports.isDirectory = isDirectory;
41
41
  exports.isSubdirectory = isSubdirectory;
42
42
  const path_1 = __importDefault(require("path"));
43
+ const fs_1 = __importDefault(require("fs"));
43
44
  exports.Ripgrep = __importStar(require("./ripgrep"));
44
45
  /**
45
46
  * Check if a path is a directory.
46
47
  * @param path The path to check
47
48
  * @returns Whether the path is a directory
48
49
  */
49
- async function isDir(path) {
50
+ function isDirectory(path) {
50
51
  try {
51
- const stat = await Bun.file(path).stat();
52
+ const stat = fs_1.default.statSync(path);
52
53
  return stat.isDirectory();
53
54
  }
54
55
  catch {
package/dist/index.d.ts CHANGED
@@ -4,3 +4,4 @@ export * from './file';
4
4
  export * from './process';
5
5
  export * from './util';
6
6
  export * from './wasm';
7
+ export * from './tools';
package/dist/index.js CHANGED
@@ -20,3 +20,4 @@ __exportStar(require("./file"), exports);
20
20
  __exportStar(require("./process"), exports);
21
21
  __exportStar(require("./util"), exports);
22
22
  __exportStar(require("./wasm"), exports);
23
+ __exportStar(require("./tools"), exports);
@@ -0,0 +1,2 @@
1
+ export * as Tool from './tool';
2
+ export * from './question';
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
36
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.Tool = void 0;
40
+ exports.Tool = __importStar(require("./tool"));
41
+ __exportStar(require("./question"), exports);
@@ -0,0 +1,91 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import z from 'zod';
3
+ import { Info as ToolInfo } from './tool';
4
+ import { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';
5
+ import { ServerRequest } from '@modelcontextprotocol/sdk/types.js';
6
+ import { ServerNotification } from '@modelcontextprotocol/sdk/types.js';
7
+ declare const Questions: z.ZodArray<z.ZodObject<{
8
+ header: z.ZodString;
9
+ multiple: z.ZodOptional<z.ZodBoolean>;
10
+ options: z.ZodArray<z.ZodObject<{
11
+ label: z.ZodString;
12
+ description: z.ZodString;
13
+ }, z.core.$strip>>;
14
+ question: z.ZodString;
15
+ }, z.core.$strip>>;
16
+ type Questions = z.infer<typeof Questions>;
17
+ export declare class Question {
18
+ static Option: z.ZodObject<{
19
+ label: z.ZodString;
20
+ description: z.ZodString;
21
+ }, z.core.$strip>;
22
+ static Info: z.ZodObject<{
23
+ question: z.ZodString;
24
+ header: z.ZodString;
25
+ options: z.ZodArray<z.ZodObject<{
26
+ label: z.ZodString;
27
+ description: z.ZodString;
28
+ }, z.core.$strip>>;
29
+ multiple: z.ZodOptional<z.ZodBoolean>;
30
+ custom: z.ZodOptional<z.ZodBoolean>;
31
+ }, z.core.$strip>;
32
+ static Questions: z.ZodArray<z.ZodObject<{
33
+ header: z.ZodString;
34
+ multiple: z.ZodOptional<z.ZodBoolean>;
35
+ options: z.ZodArray<z.ZodObject<{
36
+ label: z.ZodString;
37
+ description: z.ZodString;
38
+ }, z.core.$strip>>;
39
+ question: z.ZodString;
40
+ }, z.core.$strip>>;
41
+ static Answer: z.ZodArray<z.ZodString>;
42
+ static Answers: z.ZodArray<z.ZodArray<z.ZodString>>;
43
+ static InfoSchema: z.ZodObject<{
44
+ method: z.ZodLiteral<"question:ask">;
45
+ params: z.ZodObject<{
46
+ requestId: z.ZodString;
47
+ toolInfo: z.ZodObject<{
48
+ sessionId: z.ZodString;
49
+ messageId: z.ZodString;
50
+ callId: z.ZodString;
51
+ }, z.core.$strip>;
52
+ questions: z.ZodArray<z.ZodObject<{
53
+ header: z.ZodString;
54
+ multiple: z.ZodOptional<z.ZodBoolean>;
55
+ options: z.ZodArray<z.ZodObject<{
56
+ label: z.ZodString;
57
+ description: z.ZodString;
58
+ }, z.core.$strip>>;
59
+ question: z.ZodString;
60
+ }, z.core.$strip>>;
61
+ }, z.core.$strip>;
62
+ }, z.core.$strip>;
63
+ static AnswerSchema: z.ZodObject<{
64
+ method: z.ZodLiteral<"question:answer">;
65
+ params: z.ZodObject<{
66
+ requestId: z.ZodString;
67
+ toolInfo: z.ZodObject<{
68
+ sessionId: z.ZodString;
69
+ messageId: z.ZodString;
70
+ callId: z.ZodString;
71
+ }, z.core.$strip>;
72
+ answers: z.ZodArray<z.ZodArray<z.ZodString>>;
73
+ }, z.core.$strip>;
74
+ }, z.core.$strip>;
75
+ private _server;
76
+ constructor(server: McpServer);
77
+ /**
78
+ * Ask questions to the user and wait for the answers.
79
+ * @param questions Questions to ask
80
+ * @param toolInfo ToolInfo
81
+ * @returns Answers
82
+ */
83
+ ask(questions: Questions, toolInfo: ToolInfo, extra: RequestHandlerExtra<ServerRequest, ServerNotification>): Promise<{
84
+ title: string;
85
+ output: string;
86
+ metadata: {
87
+ answers: string[][];
88
+ };
89
+ }>;
90
+ }
91
+ export {};
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Question = void 0;
7
+ const zod_1 = __importDefault(require("zod"));
8
+ const tool_1 = require("./tool");
9
+ const Option = zod_1.default
10
+ .object({
11
+ label: zod_1.default.string().describe('Display text (1-5 words, concise)'),
12
+ description: zod_1.default.string().describe('Explanation of choice')
13
+ })
14
+ .meta({
15
+ ref: 'QuestionOption'
16
+ });
17
+ const Info = zod_1.default
18
+ .object({
19
+ question: zod_1.default.string().describe('Complete question'),
20
+ header: zod_1.default.string().describe('Very short label (max 30 chars)'),
21
+ options: zod_1.default.array(Option).describe('Available choices'),
22
+ multiple: zod_1.default.boolean().optional().describe('Allow selecting multiple choices'),
23
+ custom: zod_1.default.boolean().optional().describe('Allow typing a custom answer (default: true)')
24
+ })
25
+ .meta({
26
+ ref: 'QuestionInfo'
27
+ });
28
+ const Questions = zod_1.default.array(Info.omit({ custom: true })).describe('Questions to ask');
29
+ const Answer = zod_1.default.array(zod_1.default.string()).meta({
30
+ ref: 'QuestionAnswer'
31
+ });
32
+ const Answers = zod_1.default
33
+ .array(Answer)
34
+ .describe('User answers in order of questions (each answer is an array of selected labels)');
35
+ const InfoSchema = zod_1.default.object({
36
+ method: zod_1.default.literal('question:ask'),
37
+ params: zod_1.default.object({
38
+ requestId: zod_1.default.string().describe('Request ID'),
39
+ toolInfo: tool_1.Info,
40
+ questions: Questions
41
+ })
42
+ });
43
+ const AnswerSchema = zod_1.default.object({
44
+ method: zod_1.default.literal('question:answer'),
45
+ params: zod_1.default.object({
46
+ requestId: zod_1.default.string().describe('Request ID'),
47
+ toolInfo: tool_1.Info,
48
+ answers: Answers
49
+ })
50
+ });
51
+ class Question {
52
+ constructor(server) {
53
+ this._server = server;
54
+ }
55
+ /**
56
+ * Ask questions to the user and wait for the answers.
57
+ * @param questions Questions to ask
58
+ * @param toolInfo ToolInfo
59
+ * @returns Answers
60
+ */
61
+ async ask(questions, toolInfo, extra) {
62
+ if (questions.length === 0) {
63
+ throw new Error('At least one question is required');
64
+ }
65
+ for (const question of questions) {
66
+ if (question.options.length === 0) {
67
+ throw new Error('At least one option is required for each question');
68
+ }
69
+ }
70
+ const requestId = (0, tool_1.createRequestId)(extra.requestId);
71
+ // 开始询问问题
72
+ let progressTimer;
73
+ try {
74
+ const startTime = Date.now();
75
+ const maxWaitTime = 10 * 60 * 1000;
76
+ const progressToken = extra._meta?.progressToken;
77
+ // 不断重置超时时间,防止用户长时间不回答
78
+ const heartbeat = () => {
79
+ if (!progressToken)
80
+ return;
81
+ progressTimer = setTimeout(() => {
82
+ const waitTime = Date.now() - startTime;
83
+ this._server.server.notification({
84
+ method: 'notifications/progress',
85
+ params: {
86
+ total: maxWaitTime,
87
+ progress: waitTime,
88
+ progressToken
89
+ }
90
+ }, { relatedRequestId: extra.requestId });
91
+ if (waitTime <= maxWaitTime) {
92
+ heartbeat();
93
+ }
94
+ }, 10 * 1000);
95
+ };
96
+ heartbeat();
97
+ // 发送问题请求并等待回答
98
+ const response = await this._server.server.request({
99
+ method: 'question:ask',
100
+ params: {
101
+ questions,
102
+ requestId,
103
+ toolInfo
104
+ }
105
+ }, AnswerSchema, {
106
+ timeout: maxWaitTime, // 10分钟超时
107
+ maxTotalTimeout: maxWaitTime,
108
+ relatedRequestId: extra.requestId
109
+ });
110
+ const answers = response.params.answers;
111
+ function format(answer) {
112
+ if (!answer?.length)
113
+ return 'Unanswered';
114
+ return answer.join(', ');
115
+ }
116
+ const formatted = questions
117
+ .map((q, i) => `"${q.question}"="${format(answers[i])}"`)
118
+ .join(', ');
119
+ const output = `User has answered your questions: ${formatted}. You can now continue with the user's answers in mind.`;
120
+ return {
121
+ title: `Asked ${questions.length} question${questions.length > 1 ? 's' : ''}`,
122
+ output,
123
+ metadata: {
124
+ answers
125
+ }
126
+ };
127
+ }
128
+ finally {
129
+ clearTimeout(progressTimer);
130
+ }
131
+ }
132
+ }
133
+ exports.Question = Question;
134
+ Question.Option = Option;
135
+ Question.Info = Info;
136
+ Question.Questions = Questions;
137
+ Question.Answer = Answer;
138
+ Question.Answers = Answers;
139
+ Question.InfoSchema = InfoSchema;
140
+ Question.AnswerSchema = AnswerSchema;
@@ -0,0 +1,9 @@
1
+ import z from 'zod';
2
+ import { RequestId } from '@modelcontextprotocol/sdk/types.js';
3
+ export declare const Info: z.ZodObject<{
4
+ sessionId: z.ZodString;
5
+ messageId: z.ZodString;
6
+ callId: z.ZodString;
7
+ }, z.core.$strip>;
8
+ export type Info = z.infer<typeof Info>;
9
+ export declare function createRequestId(requestId: RequestId): string;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Info = void 0;
7
+ exports.createRequestId = createRequestId;
8
+ const zod_1 = __importDefault(require("zod"));
9
+ const uuid_1 = require("uuid");
10
+ exports.Info = zod_1.default
11
+ .object({
12
+ sessionId: zod_1.default.string().describe('Session ID'),
13
+ messageId: zod_1.default.string().describe('Message ID'),
14
+ callId: zod_1.default.string().describe('Tool Call ID')
15
+ })
16
+ .meta({ ref: 'ToolInfo' });
17
+ function createRequestId(requestId) {
18
+ return (0, uuid_1.v5)(`${requestId}-${Date.now()}`, uuid_1.v5.DNS);
19
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@baitong-dev/mcp-helpers",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "main": "./dist/index.js",
5
5
  "files": [
6
6
  "dist",
@@ -12,7 +12,8 @@
12
12
  ],
13
13
  "description": "mcp-helpers",
14
14
  "dependencies": {
15
- "@modelcontextprotocol/sdk": "^1.25.1"
15
+ "@modelcontextprotocol/sdk": "^1.25.1",
16
+ "uuid": "^11.0.5"
16
17
  },
17
18
  "devDependencies": {
18
19
  "typescript": "^5.9.2"