@mcp-use/cli 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/InputPrompt.d.ts +13 -0
  2. package/dist/InputPrompt.js +188 -0
  3. package/dist/MultilineInput.d.ts +13 -0
  4. package/dist/MultilineInput.js +154 -0
  5. package/dist/MultilineTextInput.d.ts +11 -0
  6. package/dist/MultilineTextInput.js +97 -0
  7. package/dist/PasteAwareInput.d.ts +13 -0
  8. package/dist/PasteAwareInput.js +183 -0
  9. package/dist/SimpleMultilineInput.d.ts +11 -0
  10. package/dist/SimpleMultilineInput.js +125 -0
  11. package/dist/app.d.ts +1 -5
  12. package/dist/app.js +291 -186
  13. package/dist/cli.js +2 -5
  14. package/dist/commands.d.ts +15 -30
  15. package/dist/commands.js +308 -568
  16. package/dist/components/AsciiLogo.d.ts +2 -0
  17. package/dist/components/AsciiLogo.js +7 -0
  18. package/dist/components/Footer.d.ts +5 -0
  19. package/dist/components/Footer.js +19 -0
  20. package/dist/components/InputPrompt.d.ts +13 -0
  21. package/dist/components/InputPrompt.js +188 -0
  22. package/dist/components/Messages.d.ts +21 -0
  23. package/dist/components/Messages.js +80 -0
  24. package/dist/components/ServerStatus.d.ts +7 -0
  25. package/dist/components/ServerStatus.js +36 -0
  26. package/dist/components/Spinner.d.ts +16 -0
  27. package/dist/components/Spinner.js +63 -0
  28. package/dist/components/ToolStatus.d.ts +8 -0
  29. package/dist/components/ToolStatus.js +33 -0
  30. package/dist/components/textInput.d.ts +1 -0
  31. package/dist/components/textInput.js +1 -0
  32. package/dist/logger.d.ts +10 -0
  33. package/dist/logger.js +48 -0
  34. package/dist/mcp-service.d.ts +5 -4
  35. package/dist/mcp-service.js +98 -207
  36. package/dist/services/agent-service.d.ts +56 -0
  37. package/dist/services/agent-service.js +203 -0
  38. package/dist/services/cli-service.d.ts +132 -0
  39. package/dist/services/cli-service.js +591 -0
  40. package/dist/services/index.d.ts +4 -0
  41. package/dist/services/index.js +4 -0
  42. package/dist/services/llm-service.d.ts +174 -0
  43. package/dist/services/llm-service.js +567 -0
  44. package/dist/services/mcp-config-service.d.ts +69 -0
  45. package/dist/services/mcp-config-service.js +426 -0
  46. package/dist/services/mcp-service.d.ts +1 -0
  47. package/dist/services/mcp-service.js +1 -0
  48. package/dist/services/utility-service.d.ts +47 -0
  49. package/dist/services/utility-service.js +208 -0
  50. package/dist/storage.js +4 -4
  51. package/dist/types.d.ts +30 -0
  52. package/dist/types.js +1 -0
  53. package/package.json +22 -8
  54. package/readme.md +68 -39
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export default function AsciiLogo(): React.JSX.Element;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { Text } from 'ink';
3
+ import BigText from 'ink-big-text';
4
+ export default function AsciiLogo() {
5
+ return (React.createElement(Text, null,
6
+ React.createElement(BigText, { colors: ['white'], text: "mcp use cli" })));
7
+ }
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ export declare const Footer: ({ servers, modelSlug }: {
3
+ servers: any;
4
+ modelSlug: string;
5
+ }) => React.JSX.Element;
@@ -0,0 +1,19 @@
1
+ import { Box, Text } from 'ink';
2
+ import React from 'react';
3
+ export const Footer = ({ servers, modelSlug }) => {
4
+ return (React.createElement(Box, { flexDirection: "row", justifyContent: "space-between", paddingX: 1, minWidth: 25 },
5
+ React.createElement(Box, { justifyContent: 'flex-start', paddingX: 1, minWidth: 25 }, servers.length > 0 ? (React.createElement(React.Fragment, null,
6
+ React.createElement(Text, { color: "green" },
7
+ "\u25CF ",
8
+ ' '),
9
+ React.createElement(Text, null,
10
+ servers.length,
11
+ " Server",
12
+ servers.length > 1 ? 's' : '',
13
+ " Connected"))) : (React.createElement(Text, null, "No servers connected"))),
14
+ React.createElement(Box, { justifyContent: 'flex-end', paddingX: 1, minWidth: 25 },
15
+ React.createElement(Text, { color: "blue", bold: true }, "Model:"),
16
+ React.createElement(Text, { color: "white" },
17
+ ' ',
18
+ modelSlug.replace('/', ' ')))));
19
+ };
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ interface InputPromptProps {
3
+ value: string;
4
+ onChange: (value: string) => void;
5
+ onSubmit: (value: string) => void;
6
+ onHistoryUp?: () => void;
7
+ onHistoryDown?: () => void;
8
+ placeholder?: string;
9
+ mask?: string;
10
+ focus?: boolean;
11
+ }
12
+ export declare const InputPrompt: React.FC<InputPromptProps>;
13
+ export {};
@@ -0,0 +1,188 @@
1
+ import React, { useState, useEffect, useCallback, useRef } from 'react';
2
+ import { Box, Text, useInput } from 'ink';
3
+ export const InputPrompt = ({ value, onChange, onSubmit, onHistoryUp, onHistoryDown, placeholder = 'Type your message...', mask, focus = true, }) => {
4
+ const [cursorPosition, setCursorPosition] = useState(value.length);
5
+ const [isMultiline, setIsMultiline] = useState(false);
6
+ const pasteBufferRef = useRef('');
7
+ const pasteTimeoutRef = useRef(null);
8
+ const lastInputTimeRef = useRef(Date.now());
9
+ // Track if we should allow multiline
10
+ useEffect(() => {
11
+ setIsMultiline(value.includes('\n'));
12
+ }, [value]);
13
+ // Update cursor position when value changes externally
14
+ useEffect(() => {
15
+ setCursorPosition(value.length);
16
+ }, [value]);
17
+ const handleSubmit = useCallback(() => {
18
+ const trimmedValue = value.trim();
19
+ if (trimmedValue) {
20
+ onSubmit(trimmedValue);
21
+ onChange('');
22
+ setCursorPosition(0);
23
+ setIsMultiline(false);
24
+ }
25
+ }, [value, onSubmit, onChange]);
26
+ const processPasteBuffer = useCallback(() => {
27
+ if (pasteBufferRef.current) {
28
+ const beforeCursor = value.slice(0, cursorPosition);
29
+ const afterCursor = value.slice(cursorPosition);
30
+ // Process the paste buffer to handle carriage returns
31
+ let processedPaste = pasteBufferRef.current
32
+ .replace(/\r\n/g, '\n')
33
+ .replace(/\r/g, '\n');
34
+ const newValue = beforeCursor + processedPaste + afterCursor;
35
+ onChange(newValue);
36
+ setCursorPosition(cursorPosition + processedPaste.length);
37
+ if (processedPaste.includes('\n')) {
38
+ setIsMultiline(true);
39
+ }
40
+ pasteBufferRef.current = '';
41
+ }
42
+ }, [value, cursorPosition, onChange]);
43
+ useInput((input, key) => {
44
+ if (!focus)
45
+ return;
46
+ const now = Date.now();
47
+ const timeSinceLastInput = now - lastInputTimeRef.current;
48
+ lastInputTimeRef.current = now;
49
+ // Detect paste by checking if we're getting rapid inputs or multi-character input
50
+ const isProbablyPaste = input &&
51
+ (timeSinceLastInput < 50 || input.length > 1) &&
52
+ !key.ctrl &&
53
+ !key.meta;
54
+ if (isProbablyPaste) {
55
+ // Accumulate paste buffer
56
+ pasteBufferRef.current += input;
57
+ // Clear existing timeout
58
+ if (pasteTimeoutRef.current) {
59
+ clearTimeout(pasteTimeoutRef.current);
60
+ }
61
+ // Set new timeout to process paste
62
+ pasteTimeoutRef.current = setTimeout(() => {
63
+ processPasteBuffer();
64
+ pasteTimeoutRef.current = null;
65
+ }, 100);
66
+ return;
67
+ }
68
+ // Process any pending paste buffer first
69
+ if (pasteBufferRef.current) {
70
+ processPasteBuffer();
71
+ }
72
+ // Submit on Enter (without modifiers)
73
+ if (key.return && !key.ctrl && !key.meta && !key.shift) {
74
+ handleSubmit();
75
+ return;
76
+ }
77
+ // New line on Ctrl+Enter, Meta+Enter, or Shift+Enter
78
+ if (key.return && (key.ctrl || key.meta || key.shift)) {
79
+ const beforeCursor = value.slice(0, cursorPosition);
80
+ const afterCursor = value.slice(cursorPosition);
81
+ onChange(beforeCursor + '\n' + afterCursor);
82
+ setCursorPosition(cursorPosition + 1);
83
+ setIsMultiline(true);
84
+ return;
85
+ }
86
+ // History navigation with up/down arrows (only in single-line mode)
87
+ if (!isMultiline) {
88
+ if (key.upArrow && onHistoryUp) {
89
+ onHistoryUp();
90
+ return;
91
+ }
92
+ if (key.downArrow && onHistoryDown) {
93
+ onHistoryDown();
94
+ return;
95
+ }
96
+ }
97
+ // Backspace
98
+ if (key.backspace || key.delete) {
99
+ if (cursorPosition > 0) {
100
+ const beforeCursor = value.slice(0, cursorPosition - 1);
101
+ const afterCursor = value.slice(cursorPosition);
102
+ onChange(beforeCursor + afterCursor);
103
+ setCursorPosition(cursorPosition - 1);
104
+ }
105
+ return;
106
+ }
107
+ // Navigation keys
108
+ if (key.leftArrow) {
109
+ setCursorPosition(Math.max(0, cursorPosition - 1));
110
+ return;
111
+ }
112
+ if (key.rightArrow) {
113
+ setCursorPosition(Math.min(value.length, cursorPosition + 1));
114
+ return;
115
+ }
116
+ // Home/End keys
117
+ if (key.ctrl && input === 'a') {
118
+ setCursorPosition(0);
119
+ return;
120
+ }
121
+ if (key.ctrl && input === 'e') {
122
+ setCursorPosition(value.length);
123
+ return;
124
+ }
125
+ // Regular character input (not paste)
126
+ if (input && !key.ctrl && !key.meta) {
127
+ const beforeCursor = value.slice(0, cursorPosition);
128
+ const afterCursor = value.slice(cursorPosition);
129
+ // Process input to handle carriage returns
130
+ const processedInput = input.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
131
+ const newValue = beforeCursor + processedInput + afterCursor;
132
+ onChange(newValue);
133
+ setCursorPosition(cursorPosition + processedInput.length);
134
+ if (processedInput.includes('\n')) {
135
+ setIsMultiline(true);
136
+ }
137
+ }
138
+ });
139
+ // Render the input
140
+ const renderContent = () => {
141
+ if (!value && placeholder && !focus) {
142
+ return React.createElement(Text, { dimColor: true }, placeholder);
143
+ }
144
+ let displayValue = mask ? value.replace(/./g, mask) : value;
145
+ if (!isMultiline) {
146
+ // Single line rendering with cursor
147
+ const beforeCursor = displayValue.slice(0, cursorPosition);
148
+ const atCursor = displayValue[cursorPosition] || ' ';
149
+ const afterCursor = displayValue.slice(cursorPosition + 1);
150
+ return (React.createElement(Text, null,
151
+ beforeCursor,
152
+ focus && React.createElement(Text, { inverse: true }, atCursor),
153
+ afterCursor));
154
+ }
155
+ // Multiline rendering
156
+ const lines = displayValue.split('\n');
157
+ let pos = 0;
158
+ let cursorRow = 0;
159
+ let cursorCol = 0;
160
+ for (let row = 0; row < lines.length; row++) {
161
+ const lineLength = lines[row]?.length || 0;
162
+ if (pos + lineLength >= cursorPosition) {
163
+ cursorRow = row;
164
+ cursorCol = cursorPosition - pos;
165
+ break;
166
+ }
167
+ pos += lineLength + 1; // +1 for newline
168
+ }
169
+ return lines.map((line, row) => {
170
+ if (row === cursorRow && focus) {
171
+ const before = line.slice(0, cursorCol);
172
+ const at = line[cursorCol] || ' ';
173
+ const after = line.slice(cursorCol + 1);
174
+ return (React.createElement(Box, { key: row },
175
+ React.createElement(Text, null,
176
+ before,
177
+ React.createElement(Text, { inverse: true }, at),
178
+ after)));
179
+ }
180
+ return (React.createElement(Box, { key: row },
181
+ React.createElement(Text, null, line || ' ')));
182
+ });
183
+ };
184
+ return (React.createElement(Box, { flexDirection: "column", flexGrow: 1 },
185
+ renderContent(),
186
+ isMultiline && focus && (React.createElement(Box, null,
187
+ React.createElement(Text, { dimColor: true, italic: true }, "Enter to submit \u2022 Ctrl/Shift+Enter for new line")))));
188
+ };
@@ -0,0 +1,21 @@
1
+ import { CommandMessage, ToolCall } from '../types.js';
2
+ import { Message } from '../types.js';
3
+ import React from 'react';
4
+ export declare const UserMessageRenderer: ({ message }: {
5
+ message: Message;
6
+ }) => React.JSX.Element;
7
+ export declare const AssistantMessageRenerer: ({ message }: {
8
+ message: Message;
9
+ }) => React.JSX.Element;
10
+ export declare const ThoughtMessageRenderer: ({ message }: {
11
+ message: Message;
12
+ }) => React.JSX.Element;
13
+ export declare const ToolCallRenderer: ({ message }: {
14
+ message: ToolCall;
15
+ }) => React.JSX.Element;
16
+ export declare const CommandMessageRenderer: ({ message, }: {
17
+ message: CommandMessage;
18
+ }) => React.JSX.Element;
19
+ export declare const MessageRenderer: ({ message, }: {
20
+ message: Message | ToolCall | CommandMessage;
21
+ }) => React.JSX.Element | null;
@@ -0,0 +1,80 @@
1
+ import React from 'react';
2
+ import { Box, Text } from 'ink';
3
+ import { ServerStatus } from './ServerStatus.js';
4
+ import { ToolStatus } from './ToolStatus.js';
5
+ export const UserMessageRenderer = ({ message }) => {
6
+ return (React.createElement(Box, { key: message.id, marginBottom: 1, flexDirection: "row" },
7
+ React.createElement(Box, { marginRight: 1 },
8
+ React.createElement(Text, { color: "white", bold: true }, "\u25CF")),
9
+ React.createElement(Box, { flexDirection: "column", flexGrow: 1 },
10
+ React.createElement(Text, { wrap: "wrap" }, message.content))));
11
+ };
12
+ export const AssistantMessageRenerer = ({ message }) => {
13
+ return (React.createElement(Box, { key: message.id, marginBottom: 1, flexDirection: "row" },
14
+ React.createElement(Box, { marginRight: 1 },
15
+ React.createElement(Text, { color: "blue", bold: true }, "\u25CF")),
16
+ React.createElement(Box, { flexDirection: "column", flexGrow: 1 },
17
+ React.createElement(Text, { wrap: "wrap" }, message.content))));
18
+ };
19
+ export const ThoughtMessageRenderer = ({ message }) => {
20
+ return (React.createElement(Box, { key: message.id, flexDirection: "row" },
21
+ React.createElement(Box, { flexDirection: "column", marginRight: 1, flexGrow: 1 },
22
+ React.createElement(Text, { color: "gray", italic: true }, message.content))));
23
+ };
24
+ export const ToolCallRenderer = ({ message }) => {
25
+ const input = JSON.stringify(message.tool_input);
26
+ const output = JSON.stringify(message.tool_output);
27
+ return (React.createElement(Box, { key: message.id, flexDirection: "row" },
28
+ React.createElement(Box, { marginRight: 1 },
29
+ React.createElement(Text, { color: "white", bold: true }, "\u25CF")),
30
+ React.createElement(Box, { flexGrow: 1, paddingX: 1, borderStyle: "round", borderColor: "white", flexDirection: "column" },
31
+ React.createElement(Text, { color: "white", bold: true },
32
+ "Tool: ",
33
+ message.tool_name),
34
+ React.createElement(Text, null,
35
+ "Input: ",
36
+ input.length > 100 ? `${input.slice(0, 97)}...` : input),
37
+ React.createElement(Text, null,
38
+ "Output: ",
39
+ output.length > 100 ? `${output.slice(0, 97)}...` : output))));
40
+ };
41
+ export const CommandMessageRenderer = ({ message, }) => {
42
+ const { commandResult } = message;
43
+ let color = 'magenta'; // Default for info/system
44
+ if (commandResult.type === 'error')
45
+ color = 'red';
46
+ if (commandResult.type === 'success')
47
+ color = 'green';
48
+ if (commandResult.type === 'prompt_key' ||
49
+ commandResult.type === 'prompt_server_config') {
50
+ color = 'yellow';
51
+ }
52
+ if (commandResult.type === 'list_servers')
53
+ color = 'magenta';
54
+ if (commandResult.type === 'list_tools')
55
+ color = 'cyan';
56
+ return (React.createElement(Box, { key: message.id, marginBottom: 1, flexDirection: "row" },
57
+ React.createElement(Box, { marginRight: 1 },
58
+ React.createElement(Text, { color: color, bold: true }, "\u25CF")),
59
+ React.createElement(Box, { flexDirection: "column", flexGrow: 1 },
60
+ React.createElement(Text, null, message.content),
61
+ commandResult.type === 'list_servers' &&
62
+ commandResult.data?.servers && (React.createElement(ServerStatus, { servers: commandResult.data.servers })),
63
+ commandResult.type === 'list_tools' && commandResult.data && (React.createElement(ToolStatus, { tools: commandResult.data.tools, error: commandResult.data.error })))));
64
+ };
65
+ export const MessageRenderer = ({ message, }) => {
66
+ switch (message.role) {
67
+ case 'tool':
68
+ return React.createElement(ToolCallRenderer, { message: message });
69
+ case 'user':
70
+ return React.createElement(UserMessageRenderer, { message: message });
71
+ case 'assistant':
72
+ return React.createElement(AssistantMessageRenerer, { message: message });
73
+ case 'thought':
74
+ return React.createElement(ThoughtMessageRenderer, { message: message });
75
+ case 'command':
76
+ return React.createElement(CommandMessageRenderer, { message: message });
77
+ default:
78
+ return null;
79
+ }
80
+ };
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import type { ServerStatus as ServerStatusData } from '../types.js';
3
+ interface ServerStatusProps {
4
+ servers: ServerStatusData[];
5
+ }
6
+ export declare function ServerStatus({ servers }: ServerStatusProps): React.JSX.Element;
7
+ export {};
@@ -0,0 +1,36 @@
1
+ import { Box, Text } from 'ink';
2
+ import React from 'react';
3
+ export function ServerStatus({ servers }) {
4
+ return (React.createElement(Box, { flexDirection: "column" }, servers.map(server => (React.createElement(Box, { key: server.name, flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1 },
5
+ React.createElement(Box, null, server.isConnected ? (React.createElement(Text, { bold: true },
6
+ " \uD83D\uDD39",
7
+ server.name)) : (React.createElement(Text, { bold: true },
8
+ " \uD83D\uDD38 ",
9
+ server.name))),
10
+ React.createElement(Box, null,
11
+ React.createElement(Text, null,
12
+ "Status:",
13
+ ' ',
14
+ server.isConnected ? (React.createElement(Text, { color: "green" }, "Connected")) : (React.createElement(Text, { color: "red" }, "Disconnected")))),
15
+ React.createElement(Box, null,
16
+ React.createElement(Text, null,
17
+ "Command: ",
18
+ server.config.command)),
19
+ server.config.args && server.config.args.length > 0 && (React.createElement(Box, null,
20
+ React.createElement(Text, null,
21
+ "Args: ",
22
+ server.config.args.join(' ')))),
23
+ server.config.env && Object.keys(server.config.env).length > 0 && (React.createElement(Box, null,
24
+ React.createElement(Text, null,
25
+ "Env:",
26
+ ' ',
27
+ Object.entries(server.config.env)
28
+ .map(([k, v]) => `${k}=${v}`)
29
+ .join(', ')))),
30
+ React.createElement(Box, null,
31
+ React.createElement(Text, null,
32
+ "Action: /server ",
33
+ server.isConnected ? 'disconnect' : 'connect',
34
+ ' ',
35
+ server.name)))))));
36
+ }
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import type { SpinnerName } from 'cli-spinners';
3
+ type SpinnerProps = {
4
+ /**
5
+ * Type of a spinner.
6
+ * See [cli-spinners](https://github.com/sindresorhus/cli-spinners) for available spinners.
7
+ *
8
+ * @default dots
9
+ */
10
+ type?: SpinnerName | 'mcpuse';
11
+ };
12
+ /**
13
+ * Spinner.
14
+ */
15
+ declare function Spinner({ type }: SpinnerProps): React.JSX.Element;
16
+ export default Spinner;
@@ -0,0 +1,63 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { Text } from 'ink';
3
+ import spinners from 'cli-spinners';
4
+ const mcpuseSpinner = {
5
+ interval: 80,
6
+ frames: [
7
+ "⠋",
8
+ "⠙",
9
+ "⠹",
10
+ "⠸",
11
+ "m", // 5
12
+ "⠼",
13
+ "⠴",
14
+ "⠦",
15
+ "c", // 9
16
+ "⠧",
17
+ "⠇",
18
+ "⠏",
19
+ "p", // 13
20
+ "⠋",
21
+ "⠙",
22
+ "⠹",
23
+ "-", // 17
24
+ "⠸",
25
+ "⠼",
26
+ "⠴",
27
+ "u", // 21
28
+ "⠦",
29
+ "⠧",
30
+ "⠇",
31
+ "s", // 25
32
+ "⠏",
33
+ "⠋",
34
+ "⠙",
35
+ "e" // 29
36
+ ]
37
+ };
38
+ /**
39
+ * Spinner.
40
+ */
41
+ function Spinner({ type = 'mcpuse' }) {
42
+ const [frame, setFrame] = useState(0);
43
+ let spinner;
44
+ if (type === 'mcpuse') {
45
+ spinner = mcpuseSpinner;
46
+ }
47
+ else {
48
+ spinner = spinners[type];
49
+ }
50
+ useEffect(() => {
51
+ const timer = setInterval(() => {
52
+ setFrame(previousFrame => {
53
+ const isLastFrame = previousFrame === spinner.frames.length - 1;
54
+ return isLastFrame ? 0 : previousFrame + 1;
55
+ });
56
+ }, spinner.interval);
57
+ return () => {
58
+ clearInterval(timer);
59
+ };
60
+ }, [spinner]);
61
+ return React.createElement(Text, null, spinner.frames[frame]);
62
+ }
63
+ export default Spinner;
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import type { Tool } from '@modelcontextprotocol/sdk/types.js';
3
+ interface ToolStatusProps {
4
+ tools: Tool[];
5
+ error?: string;
6
+ }
7
+ export declare function ToolStatus({ tools, error }: ToolStatusProps): React.JSX.Element;
8
+ export {};
@@ -0,0 +1,33 @@
1
+ import { Box, Text } from 'ink';
2
+ import React from 'react';
3
+ export function ToolStatus({ tools, error }) {
4
+ if (error) {
5
+ return (React.createElement(Box, { flexDirection: "column", marginTop: 1 },
6
+ React.createElement(Text, { color: "red" },
7
+ "\u274C Error: ",
8
+ error),
9
+ React.createElement(Text, null, "\uD83D\uDCA1 This might indicate:"),
10
+ React.createElement(Box, { marginLeft: 2, flexDirection: "column" },
11
+ React.createElement(Text, null, "\u2022 MCP servers failed to start"),
12
+ React.createElement(Text, null, "\u2022 Connection issues with configured servers")),
13
+ React.createElement(Text, null, "Check console logs for more details.")));
14
+ }
15
+ if (tools.length === 0) {
16
+ return (React.createElement(Box, { flexDirection: "column", marginTop: 1 },
17
+ React.createElement(Text, { color: "white" }, " No MCP tools found"),
18
+ React.createElement(Text, null,
19
+ ' ',
20
+ "Add tools from a server by running /server connect <name>")));
21
+ }
22
+ return (React.createElement(Box, { flexDirection: "column", marginTop: 1 },
23
+ React.createElement(Text, { color: "green" },
24
+ "Found ",
25
+ tools.length,
26
+ " MCP tools:"),
27
+ tools.map((tool, index) => (React.createElement(Box, { key: tool.name, flexDirection: "column", marginTop: 1 },
28
+ React.createElement(Text, null,
29
+ index + 1,
30
+ ". ",
31
+ React.createElement(Text, { bold: true }, tool.name || 'Unknown'),
32
+ tool.description && `: ${tool.description}`))))));
33
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ export declare class Logger {
2
+ private static formatMessage;
3
+ private static writeToFile;
4
+ static debug(message: string, data?: any): void;
5
+ static info(message: string, data?: any): void;
6
+ static warn(message: string, data?: any): void;
7
+ static error(message: string, data?: any): void;
8
+ static getLogPath(): string;
9
+ static clearLogs(): void;
10
+ }
package/dist/logger.js ADDED
@@ -0,0 +1,48 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import os from 'os';
4
+ const LOG_DIR = path.join(os.homedir(), '.mcp-use-cli');
5
+ const LOG_FILE = path.join(LOG_DIR, 'debug.log');
6
+ // Ensure log directory exists
7
+ if (!fs.existsSync(LOG_DIR)) {
8
+ fs.mkdirSync(LOG_DIR, { recursive: true });
9
+ }
10
+ export class Logger {
11
+ static formatMessage(level, message, data) {
12
+ const timestamp = new Date().toISOString();
13
+ const dataStr = data ? ` | Data: ${JSON.stringify(data, null, 2)}` : '';
14
+ return `[${timestamp}] ${level.toUpperCase()}: ${message}${dataStr}\n`;
15
+ }
16
+ static writeToFile(content) {
17
+ try {
18
+ fs.appendFileSync(LOG_FILE, content);
19
+ }
20
+ catch (error) {
21
+ // Fallback to console if file write fails
22
+ console.error('Failed to write to log file:', error);
23
+ }
24
+ }
25
+ static debug(message, data) {
26
+ this.writeToFile(this.formatMessage('debug', message, data));
27
+ }
28
+ static info(message, data) {
29
+ this.writeToFile(this.formatMessage('info', message, data));
30
+ }
31
+ static warn(message, data) {
32
+ this.writeToFile(this.formatMessage('warn', message, data));
33
+ }
34
+ static error(message, data) {
35
+ this.writeToFile(this.formatMessage('error', message, data));
36
+ }
37
+ static getLogPath() {
38
+ return LOG_FILE;
39
+ }
40
+ static clearLogs() {
41
+ try {
42
+ fs.writeFileSync(LOG_FILE, '');
43
+ }
44
+ catch (error) {
45
+ console.error('Failed to clear log file:', error);
46
+ }
47
+ }
48
+ }
@@ -1,4 +1,5 @@
1
1
  import { CommandResult } from './commands.js';
2
+ import type { Tool } from '@modelcontextprotocol/sdk/types.js';
2
3
  export interface MCPMessage {
3
4
  id: string;
4
5
  role: 'user' | 'assistant';
@@ -17,9 +18,9 @@ export declare class MCPService {
17
18
  private isInitialized;
18
19
  private commandHandler;
19
20
  private client;
20
- initialize(config?: any): Promise<void>;
21
- private initializeAgent;
22
- private reinitializeWithNewServers;
21
+ initialize(): Promise<void>;
22
+ initializeAgent(): Promise<void>;
23
+ refreshAgent(): Promise<void>;
23
24
  sendMessage(message: string, isApiKeyInput?: boolean, pendingProvider?: string, pendingModel?: string, isServerConfigInput?: boolean, serverConfigStep?: string, serverConfig?: any): Promise<{
24
25
  response: string;
25
26
  toolCalls: MCPToolCall[];
@@ -37,7 +38,7 @@ export declare class MCPService {
37
38
  getConfiguredServers(): string[];
38
39
  getConnectedServers(): string[];
39
40
  getAvailableTools(): Promise<{
40
- tools: any[];
41
+ tools: Tool[];
41
42
  error?: string;
42
43
  }>;
43
44
  }