@rawwee/interactive-mcp 1.4.3 → 1.5.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,7 +2,11 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/%40rawwee%2Finteractive-mcp)](https://www.npmjs.com/package/@rawwee/interactive-mcp) [![npm downloads](https://img.shields.io/npm/dm/%40rawwee%2Finteractive-mcp)](https://www.npmjs.com/package/@rawwee/interactive-mcp) [![GitHub license](https://img.shields.io/github/license/josippapez/interactive-mcp-server)](https://github.com/josippapez/interactive-mcp-server/blob/main/LICENSE) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) [![Platforms](https://img.shields.io/badge/Platform-Windows%20%7C%20macOS%20%7C%20Linux-blue)](https://github.com/josippapez/interactive-mcp-server) [![GitHub last commit](https://img.shields.io/github/last-commit/josippapez/interactive-mcp-server)](https://github.com/josippapez/interactive-mcp-server/commits/main)
4
4
 
5
- ![Interactive MCP screenshot](docs/image.png)
5
+ ## Repository
6
+
7
+ - GitHub: https://github.com/josippapez/interactive-mcp-server
8
+
9
+ ![Interactive MCP screenshot](https://raw.githubusercontent.com/josippapez/interactive-mcp-server/main/docs/image.png)
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,14 +233,40 @@ 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
  }, []);
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]);
244
270
  const copyWithHint = useCallback(async (value, successMessage) => {
245
271
  if (!value) {
246
272
  setClipboardHint('Nothing to copy.');
@@ -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", width: "100%", height: textareaContainerHeight, paddingLeft: 0, paddingRight: 0, 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}`) })] }));
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, width: "100%", 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, showCodeCopyControls: true })] }));
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
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env bun
2
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
2
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
3
  import notifier from 'node-notifier';
@@ -86,12 +85,13 @@ const server = new McpServer({
86
85
  // Conditionally register tools based on command-line arguments
87
86
  if (isToolEnabled('request_user_input')) {
88
87
  // Use properties from the imported tool object
89
- server.tool('request_user_input',
90
- // Need to handle description potentially being a function
91
- typeof requestUserInputTool.description === 'function'
92
- ? requestUserInputTool.description(globalTimeoutSeconds)
93
- : requestUserInputTool.description, requestUserInputTool.schema, // Use schema property
94
- async (args) => {
88
+ server.registerTool('request_user_input', {
89
+ // Need to handle description potentially being a function
90
+ description: typeof requestUserInputTool.description === 'function'
91
+ ? requestUserInputTool.description(globalTimeoutSeconds)
92
+ : requestUserInputTool.description,
93
+ inputSchema: requestUserInputTool.schema, // Use schema property
94
+ }, async (args) => {
95
95
  // Use inferred args type
96
96
  const { projectName, message, predefinedOptions, baseDirectory } = args;
97
97
  try {
@@ -126,12 +126,13 @@ if (isToolEnabled('request_user_input')) {
126
126
  }
127
127
  if (isToolEnabled('message_complete_notification')) {
128
128
  // Use properties from the imported tool object
129
- server.tool('message_complete_notification',
130
- // Description is a string here, but handle consistently
131
- typeof messageCompleteNotificationTool.description === 'function'
132
- ? messageCompleteNotificationTool.description(globalTimeoutSeconds) // Should not happen based on definition, but safe
133
- : messageCompleteNotificationTool.description, messageCompleteNotificationTool.schema, // Use schema property
134
- (args) => {
129
+ server.registerTool('message_complete_notification', {
130
+ // Description is a string here, but handle consistently
131
+ description: typeof messageCompleteNotificationTool.description === 'function'
132
+ ? messageCompleteNotificationTool.description(globalTimeoutSeconds) // Should not happen based on definition, but safe
133
+ : messageCompleteNotificationTool.description,
134
+ inputSchema: messageCompleteNotificationTool.schema, // Use schema property
135
+ }, (args) => {
135
136
  // Use inferred args type
136
137
  const { projectName, message } = args;
137
138
  notifier.notify({ title: projectName, message });
@@ -149,12 +150,13 @@ if (isToolEnabled('message_complete_notification')) {
149
150
  // Each tool must be checked individually based on filtered capabilities
150
151
  if (isToolEnabled('start_intensive_chat')) {
151
152
  // Use properties from the imported intensiveChatTools object
152
- server.tool('start_intensive_chat',
153
- // Description is a function here
154
- typeof intensiveChatTools.start.description === 'function'
155
- ? intensiveChatTools.start.description(globalTimeoutSeconds)
156
- : intensiveChatTools.start.description, intensiveChatTools.start.schema, // Use schema property
157
- async (args) => {
153
+ server.registerTool('start_intensive_chat', {
154
+ // Description is a function here
155
+ description: typeof intensiveChatTools.start.description === 'function'
156
+ ? intensiveChatTools.start.description(globalTimeoutSeconds)
157
+ : intensiveChatTools.start.description,
158
+ inputSchema: intensiveChatTools.start.schema, // Use schema property
159
+ }, async (args) => {
158
160
  // Use inferred args type
159
161
  const { sessionTitle, baseDirectory } = args;
160
162
  try {
@@ -194,12 +196,13 @@ if (isToolEnabled('start_intensive_chat')) {
194
196
  }
195
197
  if (isToolEnabled('ask_intensive_chat')) {
196
198
  // Use properties from the imported intensiveChatTools object
197
- server.tool('ask_intensive_chat',
198
- // Description is a string here
199
- typeof intensiveChatTools.ask.description === 'function'
200
- ? intensiveChatTools.ask.description(globalTimeoutSeconds) // Should not happen, but safe
201
- : intensiveChatTools.ask.description, intensiveChatTools.ask.schema, // Use schema property
202
- async (args) => {
199
+ server.registerTool('ask_intensive_chat', {
200
+ // Description is a string here
201
+ description: typeof intensiveChatTools.ask.description === 'function'
202
+ ? intensiveChatTools.ask.description(globalTimeoutSeconds) // Should not happen, but safe
203
+ : intensiveChatTools.ask.description,
204
+ inputSchema: intensiveChatTools.ask.schema, // Use schema property
205
+ }, async (args) => {
203
206
  // Use inferred args type
204
207
  const { sessionId, question, predefinedOptions, baseDirectory } = args;
205
208
  const activeSession = activeChatSessions.get(sessionId);
@@ -272,12 +275,13 @@ if (isToolEnabled('ask_intensive_chat')) {
272
275
  }
273
276
  if (isToolEnabled('stop_intensive_chat')) {
274
277
  // Use properties from the imported intensiveChatTools object
275
- server.tool('stop_intensive_chat',
276
- // Description is a string here
277
- typeof intensiveChatTools.stop.description === 'function'
278
- ? intensiveChatTools.stop.description(globalTimeoutSeconds) // Should not happen, but safe
279
- : intensiveChatTools.stop.description, intensiveChatTools.stop.schema, // Use schema property
280
- async (args) => {
278
+ server.registerTool('stop_intensive_chat', {
279
+ // Description is a string here
280
+ description: typeof intensiveChatTools.stop.description === 'function'
281
+ ? intensiveChatTools.stop.description(globalTimeoutSeconds) // Should not happen, but safe
282
+ : intensiveChatTools.stop.description,
283
+ inputSchema: intensiveChatTools.stop.schema, // Use schema property
284
+ }, async (args) => {
281
285
  // Use inferred args type
282
286
  const { sessionId } = args;
283
287
  const activeSession = activeChatSessions.get(sessionId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rawwee/interactive-mcp",
3
- "version": "1.4.3",
3
+ "version": "1.5.1",
4
4
  "main": "dist/index.js",
5
5
  "type": "module",
6
6
  "bin": {
@@ -30,6 +30,14 @@
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
42
  "@eslint/js": "^10.0.1",
35
43
  "@semantic-release/commit-analyzer": "^13.0.1",