@indiccoder/mentis-cli 1.1.3 → 1.1.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.
- package/.claude/settings.local.json +8 -0
- package/.mentis/session.json +15 -0
- package/.mentis/sessions/1769189035730.json +23 -0
- package/.mentis/sessions/1769189569160.json +23 -0
- package/.mentis/sessions/1769767538672.json +23 -0
- package/.mentis/sessions/1769767785155.json +23 -0
- package/.mentis/sessions/1769768745802.json +23 -0
- package/.mentis/sessions/1769769600884.json +31 -0
- package/.mentis/sessions/1769770030160.json +31 -0
- package/.mentis/sessions/1769770606004.json +78 -0
- package/.mentis/sessions/1769771084515.json +141 -0
- package/.mentis/sessions/1769881926630.json +57 -0
- package/ARCHITECTURE.md +267 -0
- package/CONTRIBUTING.md +209 -0
- package/README.md +17 -0
- package/dist/checkpoint/CheckpointManager.js +92 -0
- package/dist/commands/Command.js +15 -1
- package/dist/commands/CommandManager.js +30 -5
- package/dist/commands/__tests__/CommandManager.test.js +70 -0
- package/dist/debug_google.js +61 -0
- package/dist/debug_lite.js +49 -0
- package/dist/debug_lite_headers.js +57 -0
- package/dist/debug_search.js +16 -0
- package/dist/index.js +33 -0
- package/dist/mcp/JsonRpcClient.js +16 -0
- package/dist/mcp/McpConfig.js +132 -0
- package/dist/mcp/McpManager.js +189 -0
- package/dist/repl/PersistentShell.js +20 -1
- package/dist/repl/ReplManager.js +410 -138
- package/dist/skills/Skill.js +17 -2
- package/dist/skills/SkillsManager.js +28 -3
- package/dist/skills/__tests__/SkillsManager.test.js +62 -0
- package/dist/tools/AskQuestionTool.js +172 -0
- package/dist/tools/EditFileTool.js +141 -0
- package/dist/tools/FileTools.js +7 -1
- package/dist/tools/PlanModeTool.js +53 -0
- package/dist/tools/WebSearchTool.js +190 -27
- package/dist/ui/DiffViewer.js +110 -0
- package/dist/ui/InputBox.js +16 -2
- package/dist/ui/MultiFileSelector.js +123 -0
- package/dist/ui/PlanModeUI.js +105 -0
- package/dist/ui/ToolExecutor.js +154 -0
- package/dist/ui/UIManager.js +12 -2
- package/dist/utils/__mocks__/chalk.js +20 -0
- package/dist/utils/__tests__/ContextVisualizer.test.js +95 -0
- package/docs/MCP_INTEGRATION.md +290 -0
- package/google_dump.html +18 -0
- package/lite_dump.html +176 -0
- package/lite_headers_dump.html +176 -0
- package/package.json +34 -2
- package/scripts/test_exa_mcp.ts +90 -0
- package/src/checkpoint/CheckpointManager.ts +102 -0
- package/src/commands/Command.ts +64 -13
- package/src/commands/CommandManager.ts +26 -5
- package/src/commands/__tests__/CommandManager.test.ts +83 -0
- package/src/debug_google.ts +30 -0
- package/src/debug_lite.ts +18 -0
- package/src/debug_lite_headers.ts +25 -0
- package/src/debug_search.ts +18 -0
- package/src/index.ts +45 -1
- package/src/mcp/JsonRpcClient.ts +19 -0
- package/src/mcp/McpConfig.ts +153 -0
- package/src/mcp/McpManager.ts +224 -0
- package/src/repl/PersistentShell.ts +24 -1
- package/src/repl/ReplManager.ts +1521 -1204
- package/src/skills/Skill.ts +91 -11
- package/src/skills/SkillsManager.ts +25 -3
- package/src/skills/__tests__/SkillsManager.test.ts +73 -0
- package/src/tools/AskQuestionTool.ts +197 -0
- package/src/tools/EditFileTool.ts +172 -0
- package/src/tools/FileTools.ts +3 -0
- package/src/tools/PlanModeTool.ts +50 -0
- package/src/tools/WebSearchTool.ts +235 -63
- package/src/ui/DiffViewer.ts +117 -0
- package/src/ui/InputBox.ts +17 -2
- package/src/ui/MultiFileSelector.ts +135 -0
- package/src/ui/PlanModeUI.ts +121 -0
- package/src/ui/ToolExecutor.ts +182 -0
- package/src/ui/UIManager.ts +15 -2
- package/src/utils/__mocks__/chalk.ts +19 -0
- package/src/utils/__tests__/ContextVisualizer.test.ts +118 -0
- package/console.log(tick) +0 -0
|
@@ -0,0 +1,154 @@
|
|
|
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.ToolExecutor = void 0;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const ora_1 = __importDefault(require("ora"));
|
|
9
|
+
/**
|
|
10
|
+
* Visual feedback for tool execution
|
|
11
|
+
* Shows colored icons, spinners, and grouped display
|
|
12
|
+
*/
|
|
13
|
+
class ToolExecutor {
|
|
14
|
+
/**
|
|
15
|
+
* Get colored text for a tool name
|
|
16
|
+
*/
|
|
17
|
+
static colorToolName(toolName, color) {
|
|
18
|
+
switch (color) {
|
|
19
|
+
case 'blue': return chalk_1.default.blue(toolName);
|
|
20
|
+
case 'yellow': return chalk_1.default.yellow(toolName);
|
|
21
|
+
case 'cyan': return chalk_1.default.cyan(toolName);
|
|
22
|
+
case 'magenta': return chalk_1.default.magenta(toolName);
|
|
23
|
+
case 'green': return chalk_1.default.green(toolName);
|
|
24
|
+
case 'red': return chalk_1.default.red(toolName);
|
|
25
|
+
case 'gray': return chalk_1.default.gray(toolName);
|
|
26
|
+
default: return toolName;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Start a tool execution with visual feedback
|
|
31
|
+
*/
|
|
32
|
+
static startExecution(toolName, args) {
|
|
33
|
+
const execution = {
|
|
34
|
+
toolName,
|
|
35
|
+
args,
|
|
36
|
+
status: 'running'
|
|
37
|
+
};
|
|
38
|
+
this.executions.push(execution);
|
|
39
|
+
// Get icon and color for tool type
|
|
40
|
+
const { icon, color } = this.getToolStyle(toolName);
|
|
41
|
+
// Format args for display (truncate long values)
|
|
42
|
+
const argsDisplay = this.formatArgs(args);
|
|
43
|
+
// Start spinner
|
|
44
|
+
const spinner = (0, ora_1.default)({
|
|
45
|
+
text: `${icon} ${this.colorToolName(toolName, color)} ${argsDisplay}`,
|
|
46
|
+
color: color
|
|
47
|
+
});
|
|
48
|
+
spinner.start();
|
|
49
|
+
this.spinners.set(toolName, spinner);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Complete a tool execution successfully
|
|
53
|
+
*/
|
|
54
|
+
static completeExecution(toolName, result) {
|
|
55
|
+
const execution = this.executions.find(e => e.toolName === toolName);
|
|
56
|
+
if (execution) {
|
|
57
|
+
execution.status = 'completed';
|
|
58
|
+
execution.result = result;
|
|
59
|
+
}
|
|
60
|
+
const spinner = this.spinners.get(toolName);
|
|
61
|
+
if (spinner) {
|
|
62
|
+
const { icon } = this.getToolStyle(toolName);
|
|
63
|
+
spinner.succeed(`${icon} ${chalk_1.default.green(toolName)} completed`);
|
|
64
|
+
this.spinners.delete(toolName);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Mark a tool execution as failed
|
|
69
|
+
*/
|
|
70
|
+
static failExecution(toolName, error) {
|
|
71
|
+
const execution = this.executions.find(e => e.toolName === toolName);
|
|
72
|
+
if (execution) {
|
|
73
|
+
execution.status = 'failed';
|
|
74
|
+
execution.error = error;
|
|
75
|
+
}
|
|
76
|
+
const spinner = this.spinners.get(toolName);
|
|
77
|
+
if (spinner) {
|
|
78
|
+
const { icon } = this.getToolStyle(toolName);
|
|
79
|
+
spinner.fail(`${icon} ${chalk_1.default.red(toolName)} failed: ${error}`);
|
|
80
|
+
this.spinners.delete(toolName);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Show grouped summary of all tool executions
|
|
85
|
+
*/
|
|
86
|
+
static showSummary() {
|
|
87
|
+
if (this.executions.length === 0) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
console.log('');
|
|
91
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
92
|
+
console.log(chalk_1.default.cyan('🔧 Tool Executions'));
|
|
93
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
94
|
+
for (const execution of this.executions) {
|
|
95
|
+
const { icon, color } = this.getToolStyle(execution.toolName);
|
|
96
|
+
const statusIcon = execution.status === 'completed' ? '✓' : execution.status === 'failed' ? '✗' : '…';
|
|
97
|
+
console.log(`${icon} ${this.colorToolName(execution.toolName, color)} ${chalk_1.default.dim(statusIcon)}`);
|
|
98
|
+
}
|
|
99
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
100
|
+
console.log('');
|
|
101
|
+
// Reset for next batch
|
|
102
|
+
this.executions = [];
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get visual style for a tool type
|
|
106
|
+
*/
|
|
107
|
+
static getToolStyle(toolName) {
|
|
108
|
+
const styles = {
|
|
109
|
+
'read_file': { icon: '📖', color: 'blue' },
|
|
110
|
+
'write_file': { icon: '📄', color: 'yellow' },
|
|
111
|
+
'edit_file': { icon: '✏️', color: 'yellow' },
|
|
112
|
+
'list_dir': { icon: '📁', color: 'cyan' },
|
|
113
|
+
'search_files': { icon: '🔍', color: 'magenta' },
|
|
114
|
+
'search_web': { icon: '🌐', color: 'blue' },
|
|
115
|
+
'run_command': { icon: '💻', color: 'green' },
|
|
116
|
+
'git_commit': { icon: '📝', color: 'green' }
|
|
117
|
+
};
|
|
118
|
+
return styles[toolName] || { icon: '🔧', color: 'gray' };
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Format arguments for display
|
|
122
|
+
*/
|
|
123
|
+
static formatArgs(args) {
|
|
124
|
+
const parts = [];
|
|
125
|
+
for (const [key, value] of Object.entries(args)) {
|
|
126
|
+
const strValue = String(value);
|
|
127
|
+
// Truncate long values
|
|
128
|
+
const display = strValue.length > 30 ? strValue.slice(0, 30) + '...' : strValue;
|
|
129
|
+
parts.push(`${key}=${chalk_1.default.dim(display)}`);
|
|
130
|
+
}
|
|
131
|
+
return parts.length > 0 ? chalk_1.default.dim(`(${parts.join(', ')})`) : '';
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Show a simple inline tool usage message
|
|
135
|
+
*/
|
|
136
|
+
static showInline(toolName, args) {
|
|
137
|
+
const { icon, color } = this.getToolStyle(toolName);
|
|
138
|
+
const argsDisplay = this.formatArgs(args);
|
|
139
|
+
console.log(chalk_1.default.dim(` ${icon} ${this.colorToolName(toolName, color)} ${argsDisplay}`));
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Clear all pending executions
|
|
143
|
+
*/
|
|
144
|
+
static clear() {
|
|
145
|
+
for (const spinner of this.spinners.values()) {
|
|
146
|
+
spinner.stop();
|
|
147
|
+
}
|
|
148
|
+
this.spinners.clear();
|
|
149
|
+
this.executions = [];
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
exports.ToolExecutor = ToolExecutor;
|
|
153
|
+
ToolExecutor.executions = [];
|
|
154
|
+
ToolExecutor.spinners = new Map();
|
package/dist/ui/UIManager.js
CHANGED
|
@@ -19,12 +19,12 @@ class UIManager {
|
|
|
19
19
|
whitespaceBreak: true,
|
|
20
20
|
});
|
|
21
21
|
console.log(gradient_string_1.default.pastel.multiline(logoText));
|
|
22
|
-
console.log(chalk_1.default.gray(' v1.1.
|
|
22
|
+
console.log(chalk_1.default.gray(' v1.1.6 - AI Coding Agent'));
|
|
23
23
|
console.log('');
|
|
24
24
|
}
|
|
25
25
|
static renderDashboard(config) {
|
|
26
26
|
const { model, cwd } = config;
|
|
27
|
-
const version = 'v1.1.
|
|
27
|
+
const version = 'v1.1.6';
|
|
28
28
|
// Layout: Left (Status/Welcome) | Right (Tips/Activity)
|
|
29
29
|
// Total width ~80 chars.
|
|
30
30
|
// Left ~45, Right ~30.
|
|
@@ -74,5 +74,15 @@ class UIManager {
|
|
|
74
74
|
static printSeparator() {
|
|
75
75
|
console.log(chalk_1.default.gray('──────────────────────────────────────────────────'));
|
|
76
76
|
}
|
|
77
|
+
static logBullet(text, color = 'white') {
|
|
78
|
+
const bullet = color === 'white' ? '●' : chalk_1.default[color]('●');
|
|
79
|
+
console.log(` ${bullet} ${text}`);
|
|
80
|
+
}
|
|
81
|
+
static logSystem(text) {
|
|
82
|
+
console.log(chalk_1.default.dim(` ${text}`));
|
|
83
|
+
}
|
|
84
|
+
static logTransition(text) {
|
|
85
|
+
console.log(` ${chalk_1.default.red('+')} ${chalk_1.default.red(text)}`);
|
|
86
|
+
}
|
|
77
87
|
}
|
|
78
88
|
exports.UIManager = UIManager;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Manual mock for chalk to avoid ESM issues in Jest
|
|
3
|
+
module.exports = {
|
|
4
|
+
dim: (str) => str,
|
|
5
|
+
green: (str) => str,
|
|
6
|
+
yellow: (str) => str,
|
|
7
|
+
red: (str) => str,
|
|
8
|
+
gray: (str) => str,
|
|
9
|
+
bold: (str) => str,
|
|
10
|
+
cyan: (str) => str,
|
|
11
|
+
default: {
|
|
12
|
+
dim: (str) => str,
|
|
13
|
+
green: (str) => str,
|
|
14
|
+
yellow: (str) => str,
|
|
15
|
+
red: (str) => str,
|
|
16
|
+
gray: (str) => str,
|
|
17
|
+
bold: (str) => str,
|
|
18
|
+
cyan: (str) => str
|
|
19
|
+
}
|
|
20
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Tests for ContextVisualizer
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const ContextVisualizer_1 = require("../ContextVisualizer");
|
|
7
|
+
describe('ContextVisualizer', () => {
|
|
8
|
+
let visualizer;
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
visualizer = new ContextVisualizer_1.ContextVisualizer();
|
|
11
|
+
});
|
|
12
|
+
describe('calculateUsage', () => {
|
|
13
|
+
it('should handle empty history', () => {
|
|
14
|
+
const history = [];
|
|
15
|
+
const usage = visualizer.calculateUsage(history);
|
|
16
|
+
// Includes 2000 char overhead = 500 tokens
|
|
17
|
+
expect(usage.tokens).toBe(500);
|
|
18
|
+
expect(usage.maxTokens).toBe(128000);
|
|
19
|
+
expect(usage).toHaveProperty('percentage');
|
|
20
|
+
expect(usage).toHaveProperty('tokens');
|
|
21
|
+
expect(usage).toHaveProperty('maxTokens');
|
|
22
|
+
});
|
|
23
|
+
it('should calculate tokens for messages', () => {
|
|
24
|
+
const history = [
|
|
25
|
+
{ role: 'system', content: 'You are a helpful assistant.' },
|
|
26
|
+
{ role: 'user', content: 'Hello' },
|
|
27
|
+
{ role: 'assistant', content: 'Hi there!' }
|
|
28
|
+
];
|
|
29
|
+
const usage = visualizer.calculateUsage(history);
|
|
30
|
+
expect(usage.tokens).toBeGreaterThan(500);
|
|
31
|
+
expect(usage.tokens).toBeLessThan(1000);
|
|
32
|
+
expect(usage.maxTokens).toBe(128000);
|
|
33
|
+
});
|
|
34
|
+
it('should handle large messages', () => {
|
|
35
|
+
const largeContent = 'x'.repeat(10000);
|
|
36
|
+
const history = [
|
|
37
|
+
{ role: 'user', content: largeContent }
|
|
38
|
+
];
|
|
39
|
+
const usage = visualizer.calculateUsage(history);
|
|
40
|
+
expect(usage.tokens).toBeGreaterThan(1500);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe('formatBar', () => {
|
|
44
|
+
it('should format bar at low usage', () => {
|
|
45
|
+
const usage = { tokens: 1000, percentage: 5, maxTokens: 128000 };
|
|
46
|
+
const bar = visualizer.formatBar(usage);
|
|
47
|
+
// Check that bar contains expected data (without chalk dependency)
|
|
48
|
+
expect(bar).toContain('5');
|
|
49
|
+
expect(bar).toContain('1k');
|
|
50
|
+
expect(bar).toContain('128');
|
|
51
|
+
});
|
|
52
|
+
it('should format bar at medium usage', () => {
|
|
53
|
+
const usage = { tokens: 50000, percentage: 40, maxTokens: 128000 };
|
|
54
|
+
const bar = visualizer.formatBar(usage);
|
|
55
|
+
expect(bar).toContain('40');
|
|
56
|
+
expect(bar).toContain('50k');
|
|
57
|
+
});
|
|
58
|
+
it('should format bar at high usage', () => {
|
|
59
|
+
const usage = { tokens: 100000, percentage: 80, maxTokens: 128000 };
|
|
60
|
+
const bar = visualizer.formatBar(usage);
|
|
61
|
+
expect(bar).toContain('80');
|
|
62
|
+
expect(bar).toContain('100k');
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
describe('shouldCompact', () => {
|
|
66
|
+
it('should return false for low percentage', () => {
|
|
67
|
+
const history = [
|
|
68
|
+
{ role: 'user', content: 'small message' }
|
|
69
|
+
];
|
|
70
|
+
const shouldCompact = visualizer.shouldCompact(history);
|
|
71
|
+
expect(shouldCompact).toBe(false);
|
|
72
|
+
});
|
|
73
|
+
it('should return true at 80% threshold', () => {
|
|
74
|
+
// Create enough content to exceed 80%
|
|
75
|
+
// 80% of 128000 tokens = 102400 tokens = ~409600 chars
|
|
76
|
+
// Subtract 2000 overhead = ~407400 chars needed
|
|
77
|
+
const largeContent = 'x'.repeat(410000);
|
|
78
|
+
const history = [
|
|
79
|
+
{ role: 'system', content: largeContent },
|
|
80
|
+
{ role: 'user', content: largeContent }
|
|
81
|
+
];
|
|
82
|
+
const shouldCompact = visualizer.shouldCompact(history);
|
|
83
|
+
expect(shouldCompact).toBe(true);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
describe('setMaxTokens', () => {
|
|
87
|
+
it('should update max tokens', () => {
|
|
88
|
+
visualizer.setMaxTokens(32000);
|
|
89
|
+
const history = [];
|
|
90
|
+
const usage = visualizer.calculateUsage(history);
|
|
91
|
+
expect(usage.maxTokens).toBe(32000);
|
|
92
|
+
expect(usage.percentage).toBeGreaterThan(1); // Should be higher percentage with smaller max
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
});
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# MCP (Model Context Protocol) Integration
|
|
2
|
+
|
|
3
|
+
Mentis CLI now supports MCP (Model Context Protocol) servers, allowing you to extend functionality with external tools and services.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
MCP allows you to:
|
|
8
|
+
- Connect to external services (search, databases, APIs, etc.)
|
|
9
|
+
- Use additional tools beyond the built-in ones
|
|
10
|
+
- Create a customizable toolkit for your AI assistant
|
|
11
|
+
|
|
12
|
+
## Preconfigured MCP Servers
|
|
13
|
+
|
|
14
|
+
The following MCP servers are pre-configured:
|
|
15
|
+
|
|
16
|
+
### 1. Exa Search
|
|
17
|
+
- **Purpose**: Web search via Exa API
|
|
18
|
+
- **Setup**: Requires `EXA_API_KEY` environment variable
|
|
19
|
+
- **Command**: `npx -y @exa-labs/mcp-server-exa`
|
|
20
|
+
|
|
21
|
+
### 2. Memory Server
|
|
22
|
+
- **Purpose**: Persistent memory storage for conversations
|
|
23
|
+
- **Setup**: No additional configuration required
|
|
24
|
+
- **Command**: `npx -y @modelcontextprotocol/server-memory`
|
|
25
|
+
|
|
26
|
+
### 3. Filesystem Server
|
|
27
|
+
- **Purpose**: Enhanced filesystem operations
|
|
28
|
+
- **Setup**: No additional configuration required
|
|
29
|
+
- **Command**: `npx -y @modelcontextprotocol/server-filesystem <directory>`
|
|
30
|
+
|
|
31
|
+
### 4. GitHub Server
|
|
32
|
+
- **Purpose**: GitHub repository management and operations
|
|
33
|
+
- **Setup**: Requires `GITHUB_PERSONAL_ACCESS_TOKEN` environment variable
|
|
34
|
+
- **Command**: `npx -y @modelcontextprotocol/server-github`
|
|
35
|
+
|
|
36
|
+
### 5. Puppeteer Server
|
|
37
|
+
- **Purpose**: Web browser automation and scraping
|
|
38
|
+
- **Setup**: No additional configuration required
|
|
39
|
+
- **Command**: `npx -y @modelcontextprotocol/server-puppeteer`
|
|
40
|
+
|
|
41
|
+
### 6. Brave Search Server
|
|
42
|
+
- **Purpose**: Web search via Brave Search API
|
|
43
|
+
- **Setup**: Requires `BRAVE_API_KEY` environment variable
|
|
44
|
+
- **Command**: `npx -y @modelcontextprotocol/server-brave-search`
|
|
45
|
+
|
|
46
|
+
### 7. Slack Server
|
|
47
|
+
- **Purpose**: Slack workspace integration
|
|
48
|
+
- **Setup**: Requires `SLACK_BOT_TOKEN` environment variable
|
|
49
|
+
- **Command**: `npx -y @modelcontextprotocol/server-slack`
|
|
50
|
+
|
|
51
|
+
## MCP Commands
|
|
52
|
+
|
|
53
|
+
### List Servers
|
|
54
|
+
```bash
|
|
55
|
+
/mcp list
|
|
56
|
+
```
|
|
57
|
+
Shows all configured MCP servers and their connection status.
|
|
58
|
+
|
|
59
|
+
### Connect to Server
|
|
60
|
+
```bash
|
|
61
|
+
# Interactive selection
|
|
62
|
+
/mcp connect
|
|
63
|
+
|
|
64
|
+
# Direct connection
|
|
65
|
+
/mcp connect "Exa Search"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Disconnect from Server
|
|
69
|
+
```bash
|
|
70
|
+
# Interactive selection
|
|
71
|
+
/mcp disconnect
|
|
72
|
+
|
|
73
|
+
# Disconnect specific server
|
|
74
|
+
/mcp disconnect "Exa Search"
|
|
75
|
+
|
|
76
|
+
# Disconnect all
|
|
77
|
+
/mcp disconnect all
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Add Custom Server
|
|
81
|
+
```bash
|
|
82
|
+
/mcp add "My Server" npx -y @my/mcp-server
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Remove Server
|
|
86
|
+
```bash
|
|
87
|
+
# Interactive selection
|
|
88
|
+
/mcp remove
|
|
89
|
+
|
|
90
|
+
# Remove specific server
|
|
91
|
+
/mcp remove "My Server"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Test Connection
|
|
95
|
+
```bash
|
|
96
|
+
# Interactive selection
|
|
97
|
+
/mcp test
|
|
98
|
+
|
|
99
|
+
# Test specific server
|
|
100
|
+
/mcp test "Exa Search"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### View Configuration
|
|
104
|
+
```bash
|
|
105
|
+
/mcp config
|
|
106
|
+
```
|
|
107
|
+
Shows the full MCP configuration file location and contents.
|
|
108
|
+
|
|
109
|
+
## Configuration
|
|
110
|
+
|
|
111
|
+
MCP servers are configured in `~/.mentis/mcp.json`. The configuration includes:
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"servers": [
|
|
116
|
+
{
|
|
117
|
+
"name": "Exa Search",
|
|
118
|
+
"command": "npx",
|
|
119
|
+
"args": ["-y", "@exa-labs/mcp-server-exa"],
|
|
120
|
+
"description": "Web search and information retrieval via Exa API",
|
|
121
|
+
"autoConnect": false,
|
|
122
|
+
"env": {
|
|
123
|
+
"EXA_API_KEY": ""
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Server Configuration Fields
|
|
131
|
+
|
|
132
|
+
- `name`: Display name for the server
|
|
133
|
+
- `command`: Command to run (e.g., `npx`, `node`)
|
|
134
|
+
- `args`: Array of arguments for the command
|
|
135
|
+
- `description`: Optional description of what the server does
|
|
136
|
+
- `autoConnect`: If `true`, automatically connects on startup
|
|
137
|
+
- `env`: Optional environment variables required by the server
|
|
138
|
+
|
|
139
|
+
## Environment Variables
|
|
140
|
+
|
|
141
|
+
Some MCP servers require API keys or other configuration:
|
|
142
|
+
|
|
143
|
+
### Exa Search
|
|
144
|
+
```bash
|
|
145
|
+
export EXA_API_KEY=your_exa_api_key
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### GitHub Server
|
|
149
|
+
```bash
|
|
150
|
+
export GITHUB_PERSONAL_ACCESS_TOKEN=your_github_token
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Brave Search
|
|
154
|
+
```bash
|
|
155
|
+
export BRAVE_API_KEY=your_brave_api_key
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Slack Server
|
|
159
|
+
```bash
|
|
160
|
+
export SLACK_BOT_TOKEN=your_slack_bot_token
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Usage Examples
|
|
164
|
+
|
|
165
|
+
### Exa Search Integration
|
|
166
|
+
|
|
167
|
+
1. Set up your Exa API key:
|
|
168
|
+
```bash
|
|
169
|
+
export EXA_API_KEY=your_api_key_here
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
2. Connect to the Exa Search server:
|
|
173
|
+
```bash
|
|
174
|
+
/mcp connect "Exa Search"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
3. Use the search functionality:
|
|
178
|
+
```
|
|
179
|
+
Search for recent developments in TypeScript
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The AI will now have access to the Exa search tools and can perform web searches.
|
|
183
|
+
|
|
184
|
+
### Memory Server
|
|
185
|
+
|
|
186
|
+
1. Connect to the memory server:
|
|
187
|
+
```bash
|
|
188
|
+
/mcp connect Memory
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
2. The AI can now store and retrieve information across sessions.
|
|
192
|
+
|
|
193
|
+
### GitHub Integration
|
|
194
|
+
|
|
195
|
+
1. Set up your GitHub token:
|
|
196
|
+
```bash
|
|
197
|
+
export GITHUB_PERSONAL_ACCESS_TOKEN=your_token_here
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
2. Connect to the GitHub server:
|
|
201
|
+
```bash
|
|
202
|
+
/mcp connect GitHub
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
3. Use GitHub functionality:
|
|
206
|
+
```
|
|
207
|
+
List the recent issues in the mentis-cli repository
|
|
208
|
+
Create a pull request for my changes
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Auto-Connect
|
|
212
|
+
|
|
213
|
+
To automatically connect to specific servers on startup, set `autoConnect: true` in the server configuration:
|
|
214
|
+
|
|
215
|
+
```json
|
|
216
|
+
{
|
|
217
|
+
"servers": [
|
|
218
|
+
{
|
|
219
|
+
"name": "Memory",
|
|
220
|
+
"command": "npx",
|
|
221
|
+
"args": ["-y", "@modelcontextprotocol/server-memory"],
|
|
222
|
+
"autoConnect": true
|
|
223
|
+
}
|
|
224
|
+
]
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Troubleshooting
|
|
229
|
+
|
|
230
|
+
### Connection Issues
|
|
231
|
+
|
|
232
|
+
1. **Missing API Keys**: Ensure all required environment variables are set
|
|
233
|
+
2. **Network Issues**: Check your internet connection
|
|
234
|
+
3. **Server Not Found**: Verify the MCP server package is correct
|
|
235
|
+
|
|
236
|
+
### Test Connection
|
|
237
|
+
|
|
238
|
+
Use the test command to verify connectivity:
|
|
239
|
+
```bash
|
|
240
|
+
/mcp test <server_name>
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### View Logs
|
|
244
|
+
|
|
245
|
+
MCP connection errors are logged with detailed information. Check the console output for specific error messages.
|
|
246
|
+
|
|
247
|
+
## Creating Custom MCP Servers
|
|
248
|
+
|
|
249
|
+
You can add any MCP server to your configuration:
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
/mcp add "My Custom Server" node /path/to/my-server.js
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Or manually edit `~/.mentis/mcp.json`:
|
|
256
|
+
|
|
257
|
+
```json
|
|
258
|
+
{
|
|
259
|
+
"servers": [
|
|
260
|
+
{
|
|
261
|
+
"name": "My Custom Server",
|
|
262
|
+
"command": "node",
|
|
263
|
+
"args": ["/path/to/my-server.js"],
|
|
264
|
+
"description": "My custom MCP server",
|
|
265
|
+
"autoConnect": false
|
|
266
|
+
}
|
|
267
|
+
]
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## Security Considerations
|
|
272
|
+
|
|
273
|
+
- **API Keys**: Store API keys securely using environment variables
|
|
274
|
+
- **Server Trust**: Only connect to MCP servers from trusted sources
|
|
275
|
+
- **File Access**: Be cautious with filesystem servers that have broad access
|
|
276
|
+
- **Network**: MCP servers may make network requests on your behalf
|
|
277
|
+
|
|
278
|
+
## Best Practices
|
|
279
|
+
|
|
280
|
+
1. **Environment Variables**: Always use environment variables for sensitive data
|
|
281
|
+
2. **Minimal Scope**: Configure servers with minimal required permissions
|
|
282
|
+
3. **Regular Updates**: Keep MCP server packages updated
|
|
283
|
+
4. **Monitor Usage**: Check which tools are being used and how frequently
|
|
284
|
+
|
|
285
|
+
## Resources
|
|
286
|
+
|
|
287
|
+
- [MCP Specification](https://modelcontextprotocol.io/)
|
|
288
|
+
- [Exa API Documentation](https://docs.exa.ai/)
|
|
289
|
+
- [Model Context Protocol GitHub](https://github.com/modelcontextprotocol)
|
|
290
|
+
- [Available MCP Servers](https://mcp-examples.now.sh/)
|