@rawwee/interactive-mcp 1.4.2 → 1.5.0
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 +6 -2
- package/dist/commands/intensive-chat/ui.js +1 -1
- package/dist/components/MarkdownText.js +31 -5
- package/dist/components/interactive-input/keyboard.js +8 -1
- package/dist/components/interactive-input/sections.js +4 -4
- package/dist/index.js +36 -30
- package/dist/utils/logger.js +3 -3
- package/package.json +35 -27
package/README.md
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@rawwee/interactive-mcp) [](https://www.npmjs.com/package/@rawwee/interactive-mcp) [](https://github.com/josippapez/interactive-mcp-server/blob/main/LICENSE) [](https://github.com/prettier/prettier) [](https://github.com/josippapez/interactive-mcp-server) [](https://github.com/josippapez/interactive-mcp-server/commits/main)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Repository
|
|
6
|
+
|
|
7
|
+
- GitHub: https://github.com/josippapez/interactive-mcp-server
|
|
8
|
+
|
|
9
|
+

|
|
6
10
|
|
|
7
11
|
A MCP Server implemented in Node.js/TypeScript, facilitating interactive communication between LLMs and users. **Note:** This server is designed to run locally alongside the MCP client (e.g., Claude Desktop, VS Code), as it needs direct access to the user's operating system to display notifications and command-line prompts.
|
|
8
12
|
|
|
@@ -19,7 +23,7 @@ This server exposes the following tools via the Model Context Protocol (MCP):
|
|
|
19
23
|
- `stop_intensive_chat`: Closes an active intensive chat session.
|
|
20
24
|
|
|
21
25
|
Prompt UIs support markdown-friendly question text (including multiline prompts, fenced code blocks, and diff snippets). When useful, you can also include VS Code-style file links in prompt text (for example, `vscode://file/<absolute-path>:<line>:<column>`).
|
|
22
|
-
In TUI input mode, `Cmd/Ctrl+V` supports clipboard text plus file/image includes from pasted paths, copied file objects, and copied images (platform support varies). Files are sent as path references rather than full contents to optimize token usage—the AI can then read files directly using its available tools.
|
|
26
|
+
In TUI input mode, `Cmd/Ctrl+C` copies current input, `Cmd/Ctrl+V` supports clipboard text plus file/image includes from pasted paths, copied file objects, and copied images (platform support varies), and `Cmd/Ctrl+Z` / `Cmd/Ctrl+Shift+Z` provide undo/redo. Files are sent as path references rather than full contents to optimize token usage—the AI can then read files directly using its available tools.
|
|
23
27
|
|
|
24
28
|
## Usage Scenarios
|
|
25
29
|
|
|
@@ -278,7 +278,7 @@ const App = ({ sessionId, title, outputDir, searchRoot, timeoutSeconds, onCloseS
|
|
|
278
278
|
: 0;
|
|
279
279
|
return (_jsxs("box", { flexDirection: "column", width: "100%", height: "100%", backgroundColor: "black", paddingLeft: isNarrow ? 0 : 1, paddingRight: isNarrow ? 0 : 1, children: [_jsxs("box", { marginBottom: 1, flexDirection: "column", width: "100%", paddingLeft: 1, paddingRight: 1, gap: 0, children: [_jsx("text", { fg: "magenta", children: _jsx("strong", { children: title }) }), _jsxs("text", { fg: "gray", wrapMode: "word", children: ["Session ", sessionId] }), !isNarrow && _jsx("text", { fg: "gray", children: "Waiting for prompts\u2026" })] }), _jsx("scrollbox", { ref: scrollRef, flexGrow: 1, width: "100%", scrollY: true, stickyScroll: followInput, stickyStart: followInput ? 'bottom' : undefined, viewportCulling: false, scrollbarOptions: {
|
|
280
280
|
showArrows: false,
|
|
281
|
-
}, children: _jsxs("box", { flexDirection: "column", width: "100%", paddingBottom: 1, children: [_jsx("box", { flexDirection: "column", width: "100%", gap: 2, children: chatHistory.map((msg, i) => (_jsxs("box", { flexDirection: "column", width: "100%", paddingLeft: 1, paddingRight: 1, gap: 1, children: [msg.isQuestion ? (_jsxs("box", { flexDirection: "column", width: "100%", gap: 0, children: [_jsx("text", { fg: "cyan", children: _jsx("strong", { children: "QUESTION" }) }), _jsx("box", { paddingLeft: isNarrow ? 1 : 2, children: _jsx(MarkdownText, { content: msg.text, showCodeCopyControls: true }) })] })) : null, msg.answer ? (_jsxs("box", { flexDirection: "column", width: "100%", marginTop: 0, children: [_jsx("text", { fg: "green", children: _jsx("strong", { children: "ANSWER" }) }), _jsx("box", { paddingLeft: isNarrow ? 1 : 2, children: _jsx(MarkdownText, { content: msg.answer, showCodeCopyControls: true }) })] })) : null] }, `msg-${i}`))) }), currentQuestionId && (_jsx("box", { flexDirection: "column", marginTop: 1, paddingLeft: 1, paddingRight: 1, gap: 1, children: _jsx(InteractiveInput, { question: chatHistory
|
|
281
|
+
}, children: _jsxs("box", { flexDirection: "column", width: "100%", paddingBottom: 1, children: [_jsx("box", { flexDirection: "column", width: "100%", gap: 2, children: chatHistory.map((msg, i) => (_jsxs("box", { flexDirection: "column", width: "100%", paddingLeft: 1, paddingRight: 1, gap: 1, children: [msg.isQuestion ? (_jsxs("box", { flexDirection: "column", width: "100%", gap: 0, children: [_jsx("text", { fg: "cyan", children: _jsx("strong", { children: "QUESTION" }) }), _jsx("box", { paddingLeft: isNarrow ? 1 : 2, children: _jsx(MarkdownText, { content: msg.text, showContentCopyControl: true, contentCopyLabel: "Copy question", showCodeCopyControls: true }) })] })) : null, msg.answer ? (_jsxs("box", { flexDirection: "column", width: "100%", marginTop: 0, children: [_jsx("text", { fg: "green", children: _jsx("strong", { children: "ANSWER" }) }), _jsx("box", { paddingLeft: isNarrow ? 1 : 2, children: _jsx(MarkdownText, { content: msg.answer, showContentCopyControl: true, contentCopyLabel: "Copy answer", showCodeCopyControls: true }) })] })) : null] }, `msg-${i}`))) }), currentQuestionId && (_jsx("box", { flexDirection: "column", marginTop: 1, paddingLeft: 1, paddingRight: 1, gap: 1, children: _jsx(InteractiveInput, { question: chatHistory
|
|
282
282
|
.slice()
|
|
283
283
|
.reverse()
|
|
284
284
|
.find((m) => m.isQuestion && !m.answer)
|
|
@@ -233,18 +233,41 @@ export function MarkdownText({ content, streaming = false, showContentCopyContro
|
|
|
233
233
|
const segments = useMemo(() => splitMarkdownSegments(content), [content]);
|
|
234
234
|
const [clipboardHint, setClipboardHint] = useState(null);
|
|
235
235
|
const [copiedSnippetIndex, setCopiedSnippetIndex] = useState(null);
|
|
236
|
+
const clipboardHintTimeoutRef = useRef(null);
|
|
236
237
|
const copiedSnippetTimeoutRef = useRef(null);
|
|
237
238
|
useEffect(() => {
|
|
238
239
|
return () => {
|
|
240
|
+
if (clipboardHintTimeoutRef.current) {
|
|
241
|
+
clearTimeout(clipboardHintTimeoutRef.current);
|
|
242
|
+
}
|
|
239
243
|
if (copiedSnippetTimeoutRef.current) {
|
|
240
244
|
clearTimeout(copiedSnippetTimeoutRef.current);
|
|
241
245
|
}
|
|
242
246
|
};
|
|
243
247
|
}, []);
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
+
useEffect(() => {
|
|
249
|
+
if (!clipboardHint) {
|
|
250
|
+
if (clipboardHintTimeoutRef.current) {
|
|
251
|
+
clearTimeout(clipboardHintTimeoutRef.current);
|
|
252
|
+
clipboardHintTimeoutRef.current = null;
|
|
253
|
+
}
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
if (clipboardHintTimeoutRef.current) {
|
|
257
|
+
clearTimeout(clipboardHintTimeoutRef.current);
|
|
258
|
+
}
|
|
259
|
+
clipboardHintTimeoutRef.current = setTimeout(() => {
|
|
260
|
+
setClipboardHint(null);
|
|
261
|
+
clipboardHintTimeoutRef.current = null;
|
|
262
|
+
}, 2000);
|
|
263
|
+
return () => {
|
|
264
|
+
if (clipboardHintTimeoutRef.current) {
|
|
265
|
+
clearTimeout(clipboardHintTimeoutRef.current);
|
|
266
|
+
clipboardHintTimeoutRef.current = null;
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
}, [clipboardHint]);
|
|
270
|
+
const copyWithHint = useCallback(async (value, successMessage) => {
|
|
248
271
|
if (!value) {
|
|
249
272
|
setClipboardHint('Nothing to copy.');
|
|
250
273
|
return;
|
|
@@ -256,7 +279,7 @@ export function MarkdownText({ content, streaming = false, showContentCopyContro
|
|
|
256
279
|
catch (error) {
|
|
257
280
|
setClipboardHint(`Copy failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
258
281
|
}
|
|
259
|
-
};
|
|
282
|
+
}, []);
|
|
260
283
|
const openLinkWithHint = useCallback(async (href, target) => {
|
|
261
284
|
try {
|
|
262
285
|
await openExternalLink(href, target);
|
|
@@ -266,6 +289,9 @@ export function MarkdownText({ content, streaming = false, showContentCopyContro
|
|
|
266
289
|
setClipboardHint(`Open link failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
267
290
|
}
|
|
268
291
|
}, []);
|
|
292
|
+
if (!content) {
|
|
293
|
+
return null;
|
|
294
|
+
}
|
|
269
295
|
return (_jsxs("box", { flexDirection: "column", width: "100%", gap: 1, children: [showContentCopyControl && (_jsx("box", { width: "100%", justifyContent: "flex-end", children: _jsxs("text", { fg: "cyan", onMouseUp: () => {
|
|
270
296
|
void copyWithHint(content, 'Prompt copied to clipboard.');
|
|
271
297
|
}, children: ["[", contentCopyLabel, "]"] }) })), segments.map((segment, index) => {
|
|
@@ -23,7 +23,7 @@ export const isControlKeyShortcut = (key, letter) => {
|
|
|
23
23
|
};
|
|
24
24
|
export const isSubmitShortcut = (key) => isControlKeyShortcut(key, 's');
|
|
25
25
|
export const isCopyShortcut = (key) => isControlKeyShortcut(key, 'c') ||
|
|
26
|
-
(key.ctrl && key.shift && key.name.toLowerCase() === 'c');
|
|
26
|
+
((key.ctrl || key.meta) && key.shift && key.name.toLowerCase() === 'c');
|
|
27
27
|
export const isPasteShortcut = (key) => isControlKeyShortcut(key, 'v') ||
|
|
28
28
|
(key.ctrl && key.shift && key.name.toLowerCase() === 'v');
|
|
29
29
|
export const isReverseTabShortcut = (key) => key.name === 'backtab' ||
|
|
@@ -64,5 +64,12 @@ export const textareaKeyBindings = [
|
|
|
64
64
|
{ name: 'a', ctrl: true, action: 'select-all' },
|
|
65
65
|
{ name: 'a', meta: true, action: 'select-all' },
|
|
66
66
|
{ name: 'a', super: true, action: 'select-all' },
|
|
67
|
+
{ name: 'z', ctrl: true, action: 'undo' },
|
|
68
|
+
{ name: 'z', meta: true, action: 'undo' },
|
|
69
|
+
{ name: 'z', super: true, action: 'undo' },
|
|
70
|
+
{ name: 'z', ctrl: true, shift: true, action: 'redo' },
|
|
71
|
+
{ name: 'z', meta: true, shift: true, action: 'redo' },
|
|
72
|
+
{ name: 'z', super: true, shift: true, action: 'redo' },
|
|
73
|
+
{ name: 'y', ctrl: true, action: 'redo' },
|
|
67
74
|
{ name: 'j', ctrl: true, action: 'newline' },
|
|
68
75
|
];
|
|
@@ -10,7 +10,7 @@ export const OptionList = ({ mode, options, selectedIndex, onSelectOption, onAct
|
|
|
10
10
|
onActivateOptionMode();
|
|
11
11
|
}, children: _jsxs("text", { wrapMode: "char", fg: index === selectedIndex && mode === 'option' ? 'cyan' : 'gray', children: [index === selectedIndex && mode === 'option' ? '› ' : ' ', opt] }) }, `${opt}-${index}`))) })] }));
|
|
12
12
|
};
|
|
13
|
-
export const InputEditor = ({ questionId, textareaRenderVersion, textareaRef, textareaContainerHeight, textareaRows, hasSuggestions, keyBindings, onFocusRequest, onContentSync, onSubmitFromTextarea, }) => (_jsxs("box", { flexDirection: "column", marginBottom: 0, width: "100%", children: [_jsx("text", { fg: "gray", children: "Input" }), _jsx("box", { border: true, borderStyle: "single", borderColor: hasSuggestions ? 'cyan' : 'gray', backgroundColor: "#1f1f1f",
|
|
13
|
+
export const InputEditor = ({ questionId, textareaRenderVersion, textareaRef, textareaContainerHeight, textareaRows, hasSuggestions, keyBindings, onFocusRequest, onContentSync, onSubmitFromTextarea, }) => (_jsxs("box", { flexDirection: "column", marginBottom: 0, width: "100%", children: [_jsx("text", { fg: "gray", children: "Input" }), _jsx("box", { border: true, borderStyle: "single", borderColor: hasSuggestions ? 'cyan' : 'gray', backgroundColor: "#1f1f1f", height: textareaContainerHeight, paddingLeft: 1, paddingRight: 1, onClick: onFocusRequest, children: _jsx("textarea", { ref: textareaRef, focused: true, height: textareaRows, wrapMode: "word", backgroundColor: "#1f1f1f", focusedBackgroundColor: "#1f1f1f", textColor: "white", focusedTextColor: "white", placeholderColor: "gray", placeholder: "Type your answer...", keyBindings: keyBindings, onContentChange: onContentSync, onCursorChange: onContentSync, onSubmit: onSubmitFromTextarea }, `textarea-${questionId}-${textareaRenderVersion}`) })] }));
|
|
14
14
|
export const SuggestionsPanel = ({ hasOptions, isIndexingFiles, fileSuggestions, selectedSuggestionIndex, selectedSuggestionVscodeLink, hasSearchRoot, }) => (_jsxs("box", { flexDirection: "column", marginBottom: 0, width: "100%", gap: 0, children: [_jsx("text", { fg: "gray", children: hasOptions
|
|
15
15
|
? 'File suggestions • ↑/↓ or Ctrl+N/P navigate • Enter apply'
|
|
16
16
|
: 'File suggestions • ↑/↓ or Ctrl+N/P navigate • Enter/Tab apply' }), isIndexingFiles ? (_jsx("text", { fg: "gray", children: "Indexing files..." })) : fileSuggestions.length > 0 ? (_jsxs("box", { flexDirection: "column", width: "100%", children: [fileSuggestions.map((suggestion, index) => (_jsx("box", { paddingLeft: 0, paddingRight: 1, gap: 0, children: _jsxs("text", { fg: index === selectedSuggestionIndex ? 'cyan' : 'gray', wrapMode: "char", children: [index === selectedSuggestionIndex ? '› ' : ' ', suggestion] }) }, suggestion))), selectedSuggestionVscodeLink && (_jsxs("box", { flexDirection: "column", width: "100%", children: [_jsx("text", { fg: "gray", wrapMode: "word", children: "open file with:" }), _jsx("text", { fg: "cyan", wrapMode: "word", onMouseUp: () => {
|
|
@@ -20,7 +20,7 @@ export const SuggestionsPanel = ({ hasOptions, isIndexingFiles, fileSuggestions,
|
|
|
20
20
|
}, children: "\u2022 VS Code Insiders" })] }))] })) : (_jsx("text", { fg: "gray", children: hasSearchRoot
|
|
21
21
|
? '#search: no matches'
|
|
22
22
|
: '#search: no search root configured' }))] }));
|
|
23
|
-
export const QuestionBox = ({ question, MarkdownTextComponent, }) => (_jsxs("box", { flexDirection: "column", marginBottom: 0,
|
|
23
|
+
export const QuestionBox = ({ question, MarkdownTextComponent, }) => (_jsxs("box", { flexDirection: "column", marginBottom: 0, gap: 0, border: true, borderStyle: "single", borderColor: "cyan", backgroundColor: "#121212", paddingLeft: 1, paddingRight: 1, paddingTop: 1, paddingBottom: 1, children: [_jsx("text", { fg: "cyan", children: _jsx("strong", { children: "PROMPT" }) }), _jsx(MarkdownTextComponent, { content: question, showContentCopyControl: true, showCodeCopyControls: true })] }));
|
|
24
24
|
export const SearchStatus = ({ isIndexingFiles, repositoryFiles, searchRoot, hasSearchRoot, }) => (_jsxs("box", { flexDirection: "column", marginBottom: 0, width: "100%", children: [_jsx("text", { fg: "gray", wrapMode: "char", children: hasSearchRoot
|
|
25
25
|
? `#search root: ${searchRoot}`
|
|
26
26
|
: '#search root: no search root' }), _jsx("text", { fg: "gray", children: isIndexingFiles
|
|
@@ -33,5 +33,5 @@ export const ClipboardStatus = ({ status }) => (_jsx("text", { fg: status.starts
|
|
|
33
33
|
export const AttachmentsDisplay = ({ queuedAttachments, }) => (_jsxs("box", { flexDirection: "column", width: "100%", gap: 0, children: [_jsxs("text", { fg: "yellow", children: [_jsx("strong", { children: "QUEUED ATTACHMENTS" }), " (Delete placeholder text to remove)"] }), queuedAttachments.map((attachment, index) => (_jsxs("text", { fg: "gray", wrapMode: "word", children: ["[File ", index + 1, "] ", attachment.label] }, attachment.id)))] }));
|
|
34
34
|
export const SendButton = () => (_jsx("box", { backgroundColor: "cyan", paddingLeft: 1, paddingRight: 1, alignSelf: "flex-start", marginBottom: 0, children: _jsxs("text", { fg: "black", children: [_jsx("strong", { children: "Send" }), " \u2303S"] }) }));
|
|
35
35
|
export const HelpText = ({ hasOptions }) => (_jsx("text", { fg: "gray", wrapMode: "word", children: hasOptions
|
|
36
|
-
? 'Enter/Ctrl+J newline (or #search apply) • #search nav: ↑/↓ or Ctrl+N/P • Tab mode switch • #path for repo file autocomplete • Cmd/Ctrl+C copy • Cmd/Ctrl+V paste/attach'
|
|
37
|
-
: 'Enter/Ctrl+J newline • #search nav: ↑/↓ or Ctrl+N/P • Enter/Tab #search apply • #path for repo file autocomplete • Cmd/Ctrl+C copy • Cmd/Ctrl+V paste/attach' }));
|
|
36
|
+
? 'Enter/Ctrl+J newline (or #search apply) • #search nav: ↑/↓ or Ctrl+N/P • Tab mode switch • #path for repo file autocomplete • Cmd/Ctrl+C copy input • Cmd/Ctrl+V paste/attach • Cmd/Ctrl+Z undo • Cmd/Ctrl+Shift+Z redo'
|
|
37
|
+
: 'Enter/Ctrl+J newline • #search nav: ↑/↓ or Ctrl+N/P • Enter/Tab #search apply • #path for repo file autocomplete • Cmd/Ctrl+C copy input • Cmd/Ctrl+V paste/attach • Cmd/Ctrl+Z undo • Cmd/Ctrl+Shift+Z redo' }));
|
package/dist/index.js
CHANGED
|
@@ -78,6 +78,7 @@ const isToolEnabled = (toolName) => {
|
|
|
78
78
|
const server = new McpServer({
|
|
79
79
|
name: 'Interactive MCP',
|
|
80
80
|
version: '1.0.0',
|
|
81
|
+
}, {
|
|
81
82
|
capabilities: {
|
|
82
83
|
tools: enabledToolCapabilities, // Use the filtered capabilities
|
|
83
84
|
},
|
|
@@ -85,12 +86,13 @@ const server = new McpServer({
|
|
|
85
86
|
// Conditionally register tools based on command-line arguments
|
|
86
87
|
if (isToolEnabled('request_user_input')) {
|
|
87
88
|
// Use properties from the imported tool object
|
|
88
|
-
server.
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
server.registerTool('request_user_input', {
|
|
90
|
+
// Need to handle description potentially being a function
|
|
91
|
+
description: typeof requestUserInputTool.description === 'function'
|
|
92
|
+
? requestUserInputTool.description(globalTimeoutSeconds)
|
|
93
|
+
: requestUserInputTool.description,
|
|
94
|
+
inputSchema: requestUserInputTool.schema, // Use schema property
|
|
95
|
+
}, async (args) => {
|
|
94
96
|
// Use inferred args type
|
|
95
97
|
const { projectName, message, predefinedOptions, baseDirectory } = args;
|
|
96
98
|
try {
|
|
@@ -125,12 +127,13 @@ if (isToolEnabled('request_user_input')) {
|
|
|
125
127
|
}
|
|
126
128
|
if (isToolEnabled('message_complete_notification')) {
|
|
127
129
|
// Use properties from the imported tool object
|
|
128
|
-
server.
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
130
|
+
server.registerTool('message_complete_notification', {
|
|
131
|
+
// Description is a string here, but handle consistently
|
|
132
|
+
description: typeof messageCompleteNotificationTool.description === 'function'
|
|
133
|
+
? messageCompleteNotificationTool.description(globalTimeoutSeconds) // Should not happen based on definition, but safe
|
|
134
|
+
: messageCompleteNotificationTool.description,
|
|
135
|
+
inputSchema: messageCompleteNotificationTool.schema, // Use schema property
|
|
136
|
+
}, (args) => {
|
|
134
137
|
// Use inferred args type
|
|
135
138
|
const { projectName, message } = args;
|
|
136
139
|
notifier.notify({ title: projectName, message });
|
|
@@ -148,12 +151,13 @@ if (isToolEnabled('message_complete_notification')) {
|
|
|
148
151
|
// Each tool must be checked individually based on filtered capabilities
|
|
149
152
|
if (isToolEnabled('start_intensive_chat')) {
|
|
150
153
|
// Use properties from the imported intensiveChatTools object
|
|
151
|
-
server.
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
154
|
+
server.registerTool('start_intensive_chat', {
|
|
155
|
+
// Description is a function here
|
|
156
|
+
description: typeof intensiveChatTools.start.description === 'function'
|
|
157
|
+
? intensiveChatTools.start.description(globalTimeoutSeconds)
|
|
158
|
+
: intensiveChatTools.start.description,
|
|
159
|
+
inputSchema: intensiveChatTools.start.schema, // Use schema property
|
|
160
|
+
}, async (args) => {
|
|
157
161
|
// Use inferred args type
|
|
158
162
|
const { sessionTitle, baseDirectory } = args;
|
|
159
163
|
try {
|
|
@@ -193,12 +197,13 @@ if (isToolEnabled('start_intensive_chat')) {
|
|
|
193
197
|
}
|
|
194
198
|
if (isToolEnabled('ask_intensive_chat')) {
|
|
195
199
|
// Use properties from the imported intensiveChatTools object
|
|
196
|
-
server.
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
200
|
+
server.registerTool('ask_intensive_chat', {
|
|
201
|
+
// Description is a string here
|
|
202
|
+
description: typeof intensiveChatTools.ask.description === 'function'
|
|
203
|
+
? intensiveChatTools.ask.description(globalTimeoutSeconds) // Should not happen, but safe
|
|
204
|
+
: intensiveChatTools.ask.description,
|
|
205
|
+
inputSchema: intensiveChatTools.ask.schema, // Use schema property
|
|
206
|
+
}, async (args) => {
|
|
202
207
|
// Use inferred args type
|
|
203
208
|
const { sessionId, question, predefinedOptions, baseDirectory } = args;
|
|
204
209
|
const activeSession = activeChatSessions.get(sessionId);
|
|
@@ -271,12 +276,13 @@ if (isToolEnabled('ask_intensive_chat')) {
|
|
|
271
276
|
}
|
|
272
277
|
if (isToolEnabled('stop_intensive_chat')) {
|
|
273
278
|
// Use properties from the imported intensiveChatTools object
|
|
274
|
-
server.
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
279
|
+
server.registerTool('stop_intensive_chat', {
|
|
280
|
+
// Description is a string here
|
|
281
|
+
description: typeof intensiveChatTools.stop.description === 'function'
|
|
282
|
+
? intensiveChatTools.stop.description(globalTimeoutSeconds) // Should not happen, but safe
|
|
283
|
+
: intensiveChatTools.stop.description,
|
|
284
|
+
inputSchema: intensiveChatTools.stop.schema, // Use schema property
|
|
285
|
+
}, async (args) => {
|
|
280
286
|
// Use inferred args type
|
|
281
287
|
const { sessionId } = args;
|
|
282
288
|
const activeSession = activeChatSessions.get(sessionId);
|
package/dist/utils/logger.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { pino, } from 'pino';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import fs from 'fs';
|
|
4
|
-
import os from 'os';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import os from 'node:os';
|
|
5
5
|
const logDir = path.resolve(os.tmpdir(), 'interactive-mcp-logs');
|
|
6
6
|
const logFile = path.join(logDir, 'dev.log');
|
|
7
7
|
// Ensure log directory exists
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rawwee/interactive-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -30,43 +30,51 @@
|
|
|
30
30
|
"author": "",
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"description": "",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/josippapez/interactive-mcp-server.git"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://github.com/josippapez/interactive-mcp-server#readme",
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/josippapez/interactive-mcp-server/issues"
|
|
40
|
+
},
|
|
33
41
|
"devDependencies": {
|
|
34
|
-
"@eslint/js": "^
|
|
42
|
+
"@eslint/js": "^10.0.1",
|
|
35
43
|
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
36
44
|
"@semantic-release/git": "^10.0.1",
|
|
37
|
-
"@semantic-release/github": "^
|
|
45
|
+
"@semantic-release/github": "^12.0.6",
|
|
38
46
|
"@semantic-release/npm": "^13.1.5",
|
|
39
|
-
"@semantic-release/release-notes-generator": "^14.0
|
|
47
|
+
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
40
48
|
"@types/bun": "^1.3.10",
|
|
41
|
-
"@types/node": "^
|
|
49
|
+
"@types/node": "^25.3.5",
|
|
42
50
|
"@types/node-notifier": "^8.0.5",
|
|
43
51
|
"@types/pino": "^7.0.5",
|
|
44
|
-
"@types/react": "^19.
|
|
45
|
-
"conventional-changelog-conventionalcommits": "^
|
|
46
|
-
"eslint": "^
|
|
47
|
-
"eslint-config-prettier": "^10.1.
|
|
48
|
-
"eslint-plugin-prettier": "^5.
|
|
49
|
-
"globals": "^
|
|
52
|
+
"@types/react": "^19.2.14",
|
|
53
|
+
"conventional-changelog-conventionalcommits": "^9.3.0",
|
|
54
|
+
"eslint": "^10.0.3",
|
|
55
|
+
"eslint-config-prettier": "^10.1.8",
|
|
56
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
57
|
+
"globals": "^17.4.0",
|
|
50
58
|
"husky": "^9.1.7",
|
|
51
|
-
"jiti": "^2.
|
|
52
|
-
"lint-staged": "^
|
|
53
|
-
"pino-pretty": "^13.
|
|
54
|
-
"prettier": "^3.
|
|
55
|
-
"semantic-release": "^
|
|
56
|
-
"tsc-alias": "^1.8.
|
|
57
|
-
"typescript": "^5.
|
|
58
|
-
"typescript-eslint": "^8.
|
|
59
|
+
"jiti": "^2.6.1",
|
|
60
|
+
"lint-staged": "^16.3.2",
|
|
61
|
+
"pino-pretty": "^13.1.3",
|
|
62
|
+
"prettier": "^3.8.1",
|
|
63
|
+
"semantic-release": "^25.0.3",
|
|
64
|
+
"tsc-alias": "^1.8.16",
|
|
65
|
+
"typescript": "^5.9.3",
|
|
66
|
+
"typescript-eslint": "^8.56.1"
|
|
59
67
|
},
|
|
60
68
|
"dependencies": {
|
|
61
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
62
|
-
"@opentui/core": "
|
|
63
|
-
"@opentui/react": "
|
|
64
|
-
"@types/yargs": "^17.0.
|
|
69
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
70
|
+
"@opentui/core": "0.1.87",
|
|
71
|
+
"@opentui/react": "0.1.87",
|
|
72
|
+
"@types/yargs": "^17.0.35",
|
|
65
73
|
"node-notifier": "^10.0.1",
|
|
66
|
-
"pino": "^
|
|
67
|
-
"react": "^19.2.
|
|
68
|
-
"yargs": "^
|
|
69
|
-
"zod": "^3.
|
|
74
|
+
"pino": "^10.3.1",
|
|
75
|
+
"react": "^19.2.4",
|
|
76
|
+
"yargs": "^18.0.0",
|
|
77
|
+
"zod": "^4.3.6"
|
|
70
78
|
},
|
|
71
79
|
"lint-staged": {
|
|
72
80
|
"*.{js,ts,jsx,tsx}": [
|