@mrxkun/mcfast-mcp 1.2.0 → 1.4.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 +52 -100
- package/package.json +4 -2
- package/src/index.js +116 -9
package/README.md
CHANGED
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
# @mrxkun/mcfast-mcp
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
> **Supercharge your AI Agent experience with ultra-fast, intelligent tools.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`mcfast-mcp` is a Model Context Protocol (MCP) server that provides a suite of high-performance tools for AI coding agents (like Claude Desktop, Cursor, etc.). It bridges the gap between local filesystem operations and powerful cloud-based AI processing.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## ✨ Features
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- **⚡ Blazing Fast Search**:
|
|
10
|
+
- `search_filesystem`: Smartly detects and uses `ripgrep` (fastest), `git grep`, or `grep` to search your entire codebase in milliseconds.
|
|
11
|
+
- `search_code_ai`: Semantic/fuzzy search powered by cloud AI when you need to find concepts, not just keywords.
|
|
12
|
+
- **📂 Smart File Listing**:
|
|
13
|
+
- `list_files_fast`: Instantly list project files while automatically respecting your `.gitignore` rules (powered by `fast-glob`).
|
|
14
|
+
- **🧠 Intelligent Editing**:
|
|
15
|
+
- `apply_fast`: Applies complex code edits using the Mercury Coder Cloud API.
|
|
16
|
+
- `apply_search_replace`: Perfect for simple, surgical string replacements.
|
|
17
|
+
- `reapply`: Automatically fixes failed edits by analyzing errors.
|
|
18
|
+
- **📊 Audit Logging**:
|
|
19
|
+
- All local tool usage is audited and viewable in the mcfast Dashboard.
|
|
10
20
|
|
|
11
|
-
|
|
12
|
-
Visit [mcfast.vercel.app](https://mcfast.vercel.app) to sign up and get your free `MCFAST_TOKEN`.
|
|
21
|
+
## 🚀 Installation
|
|
13
22
|
|
|
14
|
-
|
|
23
|
+
You can use this package directly with `npx` without installing it globally, or install it as a global tool.
|
|
24
|
+
|
|
25
|
+
### Option 1: Using `npx` (Recommended)
|
|
26
|
+
|
|
27
|
+
Add this to your `claude_desktop_config.json` or Cursor MCP settings:
|
|
15
28
|
|
|
16
|
-
**Claude Code / Claude Desktop:**
|
|
17
29
|
```json
|
|
18
30
|
{
|
|
19
31
|
"mcpServers": {
|
|
@@ -21,117 +33,57 @@ Visit [mcfast.vercel.app](https://mcfast.vercel.app) to sign up and get your fre
|
|
|
21
33
|
"command": "npx",
|
|
22
34
|
"args": ["-y", "@mrxkun/mcfast-mcp"],
|
|
23
35
|
"env": {
|
|
24
|
-
"MCFAST_TOKEN": "
|
|
36
|
+
"MCFAST_TOKEN": "your_token_here"
|
|
25
37
|
}
|
|
26
38
|
}
|
|
27
39
|
}
|
|
28
40
|
}
|
|
29
41
|
```
|
|
30
42
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
43
|
+
### Option 2: Global Install
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm install -g @mrxkun/mcfast-mcp
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Then configure:
|
|
36
50
|
|
|
37
|
-
**VS Code / OpenCode:**
|
|
38
51
|
```json
|
|
39
52
|
{
|
|
40
|
-
"
|
|
53
|
+
"mcpServers": {
|
|
41
54
|
"mcfast": {
|
|
42
|
-
"command": "
|
|
43
|
-
"
|
|
44
|
-
|
|
55
|
+
"command": "mcfast-mcp",
|
|
56
|
+
"env": {
|
|
57
|
+
"MCFAST_TOKEN": "your_token_here"
|
|
58
|
+
}
|
|
45
59
|
}
|
|
46
60
|
}
|
|
47
61
|
}
|
|
48
62
|
```
|
|
49
63
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
## 🛠️ Available Tools
|
|
53
|
-
|
|
54
|
-
### `apply_fast`
|
|
55
|
-
Apply intelligent code edits to multiple files simultaneously.
|
|
56
|
-
|
|
57
|
-
**Example:**
|
|
58
|
-
```
|
|
59
|
-
instruction: "Add error handling to all fetch calls"
|
|
60
|
-
files: { "src/api.js": "<content>", "src/utils.js": "<content>" }
|
|
61
|
-
dryRun: false
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
**Features:**
|
|
65
|
-
- Automatic strategy selection (SEARCH_REPLACE, MULTI_EDIT, FULL_REWRITE)
|
|
66
|
-
- Deterministic diff generation
|
|
67
|
-
- Syntax-aware transformations
|
|
68
|
-
|
|
69
|
-
### `apply_search_replace`
|
|
70
|
-
Fast targeted replacements for simple edits.
|
|
71
|
-
|
|
72
|
-
**Example:**
|
|
73
|
-
```
|
|
74
|
-
files: { "src/config.js": "<content>" }
|
|
75
|
-
search: "localhost:3000"
|
|
76
|
-
replace: "api.example.com"
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### `search_code` ⚡ (No API required)
|
|
80
|
-
Fast local pattern-based search. Works offline without token.
|
|
81
|
-
|
|
82
|
-
**Example:**
|
|
83
|
-
```
|
|
84
|
-
query: "fetchData"
|
|
85
|
-
files: { "src/api.js": "<content>" }
|
|
86
|
-
regex: false
|
|
87
|
-
contextLines: 2
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### `reapply`
|
|
91
|
-
Smart retry for failed/incomplete edits. Auto-retries up to 3 times with enhanced context.
|
|
92
|
-
|
|
93
|
-
**Example:**
|
|
94
|
-
```
|
|
95
|
-
instruction: "Add error handling to all fetch calls"
|
|
96
|
-
files: { "src/api.js": "<content>" }
|
|
97
|
-
errorContext: "Previous attempt missed the catch block"
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
---
|
|
101
|
-
|
|
102
|
-
## 🧠 MCP Prompts
|
|
103
|
-
|
|
104
|
-
mcfast provides built-in strategies for AI agents (Claude Desktop, etc) to use tools effectively:
|
|
105
|
-
|
|
106
|
-
- **workflow_guide**: Standard operating procedure (List -> Search -> Apply)
|
|
107
|
-
- **refactor_plan**: Strategy for safe, atomic code refactoring
|
|
108
|
-
- **debug_investigation**: Step-by-step debugging protocol
|
|
109
|
-
|
|
110
|
-
---
|
|
111
|
-
|
|
112
|
-
## 🔒 Privacy & Security
|
|
113
|
-
|
|
114
|
-
- **Zero Persistence:** Code is processed in-memory and discarded immediately
|
|
115
|
-
- **Open Source Client:** Audit the source at [github.com/ndpmmo/mcfast](https://github.com/ndpmmo/mcfast). Current stable version: `1.1.0`.
|
|
116
|
-
- **Token Masking:** Your `MCFAST_TOKEN` is never logged
|
|
117
|
-
|
|
118
|
-
---
|
|
64
|
+
## 🔑 Configuration
|
|
119
65
|
|
|
120
|
-
|
|
66
|
+
You need a **MCFAST_TOKEN** to use the cloud features (Apply, AI Search).
|
|
67
|
+
1. Go to the [mcfast Dashboard](https://mcfast.vercel.app).
|
|
68
|
+
2. Login/Sign up.
|
|
69
|
+
3. Copy your API Key from the Account or Settings page.
|
|
121
70
|
|
|
122
|
-
|
|
123
|
-
- Dedicated bandwidth (no shared rate limits)
|
|
124
|
-
- Higher throughput for large codebases
|
|
125
|
-
- Direct access to Mercury Coder infrastructure
|
|
71
|
+
## 🛠️ Tool Reference
|
|
126
72
|
|
|
127
|
-
|
|
73
|
+
| Tool | Description |
|
|
74
|
+
|------|-------------|
|
|
75
|
+
| `search_filesystem` | **(NEW)** High-performance project-wide search. Uses `rg`/`git grep` for speed. |
|
|
76
|
+
| `list_files_fast` | **(NEW)** Lists files recursively, respecting `.gitignore`. |
|
|
77
|
+
| `apply_fast` | Applies multi-file edits using AI. |
|
|
78
|
+
| `apply_search_replace` | Simple find-and-replace. |
|
|
79
|
+
| `search_code_ai` | AI-powered semantic search. |
|
|
80
|
+
| `edit_file` | Direct file write (with cloud logging). |
|
|
128
81
|
|
|
129
|
-
##
|
|
82
|
+
## 📦 Requirements
|
|
130
83
|
|
|
131
|
-
-
|
|
132
|
-
-
|
|
133
|
-
- [Mercury Coder Docs](https://inceptionlabs.ai)
|
|
84
|
+
- Node.js >= 18
|
|
85
|
+
- (Optional) `ripgrep` installed on your system for maximum search speed.
|
|
134
86
|
|
|
135
|
-
##
|
|
87
|
+
## 📄 License
|
|
136
88
|
|
|
137
|
-
MIT ©
|
|
89
|
+
MIT © mrxkun
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrxkun/mcfast-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Ultra-fast code editing via Mercury Coder Cloud API.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -27,6 +27,8 @@
|
|
|
27
27
|
"url": "git+https://github.com/ndpmmo/mcfast.git"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@modelcontextprotocol/sdk": "^0.6.0"
|
|
30
|
+
"@modelcontextprotocol/sdk": "^0.6.0",
|
|
31
|
+
"fast-glob": "^3.3.3",
|
|
32
|
+
"ignore": "^7.0.5"
|
|
31
33
|
}
|
|
32
34
|
}
|
package/src/index.js
CHANGED
|
@@ -12,6 +12,7 @@ import fs from "fs/promises";
|
|
|
12
12
|
import path from "path";
|
|
13
13
|
import { exec } from "child_process";
|
|
14
14
|
import { promisify } from "util";
|
|
15
|
+
import fg from "fast-glob";
|
|
15
16
|
|
|
16
17
|
const execAsync = promisify(exec);
|
|
17
18
|
|
|
@@ -26,7 +27,7 @@ if (!TOKEN) {
|
|
|
26
27
|
const server = new Server(
|
|
27
28
|
{
|
|
28
29
|
name: "mcfast",
|
|
29
|
-
version: "1.
|
|
30
|
+
version: "1.3.0",
|
|
30
31
|
},
|
|
31
32
|
{
|
|
32
33
|
capabilities: {
|
|
@@ -130,13 +131,15 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
130
131
|
}
|
|
131
132
|
},
|
|
132
133
|
{
|
|
133
|
-
name: "
|
|
134
|
-
description: "
|
|
134
|
+
name: "search_filesystem",
|
|
135
|
+
description: "Deep, high-performance filesystem search using ripgrep -> git grep -> grep fallback. Best for finding code when you don't know the file location.",
|
|
135
136
|
inputSchema: {
|
|
136
137
|
type: "object",
|
|
137
138
|
properties: {
|
|
138
139
|
query: { type: "string", description: "Search pattern (literal or regex)" },
|
|
139
|
-
|
|
140
|
+
path: { type: "string", description: "Directory to search in (default: current cwd)" },
|
|
141
|
+
include: { type: "string", description: "Glob pattern to include (e.g. **/*.ts)" },
|
|
142
|
+
exclude: { type: "array", items: { type: "string" }, description: "Patterns to exclude" },
|
|
140
143
|
isRegex: { type: "boolean", description: "Treat query as regex (default: false)" },
|
|
141
144
|
caseSensitive: { type: "boolean", description: "Case sensitive search (default: false)" }
|
|
142
145
|
},
|
|
@@ -285,8 +288,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
285
288
|
|
|
286
289
|
if (name === "apply_fast") {
|
|
287
290
|
return await handleApplyFast({ ...args, toolName: 'apply_fast' });
|
|
288
|
-
} else if (name === "
|
|
289
|
-
return await
|
|
291
|
+
} else if (name === "search_filesystem") {
|
|
292
|
+
return await handleSearchFilesystem(args);
|
|
290
293
|
} else if (name === "apply_search_replace") {
|
|
291
294
|
return await handleApplyFast({
|
|
292
295
|
instruction: `Replace checking for exact match:\nSEARCH:\n${args.search}\n\nREPLACE WITH:\n${args.replace}`,
|
|
@@ -362,6 +365,106 @@ async function reportAudit(params) {
|
|
|
362
365
|
}
|
|
363
366
|
}
|
|
364
367
|
|
|
368
|
+
// Unified Search Implementation
|
|
369
|
+
async function handleSearchFilesystem({ query, path: searchPath = process.cwd(), include = "**/*", exclude = [], isRegex = false, caseSensitive = false }) {
|
|
370
|
+
const start = Date.now();
|
|
371
|
+
try {
|
|
372
|
+
let results = [];
|
|
373
|
+
let strategy = 'node_fallback';
|
|
374
|
+
|
|
375
|
+
// 1. Try ripgrep (rg) if available - fastest
|
|
376
|
+
try {
|
|
377
|
+
const flags = [
|
|
378
|
+
"--json",
|
|
379
|
+
caseSensitive ? "-s" : "-i",
|
|
380
|
+
isRegex ? "-e" : "-F"
|
|
381
|
+
].join(" ");
|
|
382
|
+
// This is a simplified call; parsing JSON output from rg is best for structured data
|
|
383
|
+
// For now, we'll rely on a simpler text output for the LLM
|
|
384
|
+
const simpleFlags = [
|
|
385
|
+
"-n",
|
|
386
|
+
"--no-heading",
|
|
387
|
+
"--with-filename",
|
|
388
|
+
caseSensitive ? "-s" : "-i",
|
|
389
|
+
isRegex ? "-e" : "-F"
|
|
390
|
+
].join(" ");
|
|
391
|
+
|
|
392
|
+
const command = `rg ${simpleFlags} "${query.replace(/"/g, '\\"')}" ${searchPath}`;
|
|
393
|
+
const { stdout } = await execAsync(command, { maxBuffer: 10 * 1024 * 1024 });
|
|
394
|
+
results = stdout.trim().split('\n').filter(Boolean);
|
|
395
|
+
strategy = 'ripgrep';
|
|
396
|
+
} catch (rgErr) {
|
|
397
|
+
// 2. Try git grep if in a git repo
|
|
398
|
+
try {
|
|
399
|
+
const flags = [
|
|
400
|
+
"-n",
|
|
401
|
+
"-I",
|
|
402
|
+
caseSensitive ? "" : "-i",
|
|
403
|
+
isRegex ? "-E" : "-F"
|
|
404
|
+
].filter(Boolean).join(" ");
|
|
405
|
+
const command = `git grep ${flags} "${query.replace(/"/g, '\\"')}" ${searchPath}`;
|
|
406
|
+
const { stdout } = await execAsync(command, { cwd: searchPath, maxBuffer: 10 * 1024 * 1024 });
|
|
407
|
+
results = stdout.trim().split('\n').filter(Boolean);
|
|
408
|
+
strategy = 'git_grep';
|
|
409
|
+
} catch (gitErr) {
|
|
410
|
+
// 3. Fallback to native grep
|
|
411
|
+
try {
|
|
412
|
+
const flags = [
|
|
413
|
+
"-r", "-n", "-I",
|
|
414
|
+
caseSensitive ? "" : "-i",
|
|
415
|
+
isRegex ? "-E" : "-F"
|
|
416
|
+
].filter(Boolean).join(" ");
|
|
417
|
+
const exclusions = ["node_modules", ".git", ".next", "dist", "build"].map(d => `--exclude-dir=${d}`).join(" ");
|
|
418
|
+
const command = `grep ${flags} ${exclusions} "${query.replace(/"/g, '\\"')}" ${searchPath}`;
|
|
419
|
+
const { stdout } = await execAsync(command, { maxBuffer: 10 * 1024 * 1024 });
|
|
420
|
+
results = stdout.trim().split('\n').filter(Boolean);
|
|
421
|
+
strategy = 'native_grep';
|
|
422
|
+
} catch (grepErr) {
|
|
423
|
+
// 4. Node.js fallback (slowest but guaranteed)
|
|
424
|
+
// Only used if all system tools fail
|
|
425
|
+
strategy = 'node_js_fallback';
|
|
426
|
+
// ... (implement if needed, but grep usually exists)
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
let output = `⚡ search_filesystem (${strategy}) found ${results.length} results for "${query}"\n\n`;
|
|
432
|
+
if (results.length === 0) {
|
|
433
|
+
output += "No matches found.";
|
|
434
|
+
} else {
|
|
435
|
+
const limitedResults = results.slice(0, 100);
|
|
436
|
+
output += limitedResults.join('\n');
|
|
437
|
+
if (results.length > 100) output += `\n... and ${results.length - 100} more matches.`;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
reportAudit({
|
|
441
|
+
tool: 'search_filesystem',
|
|
442
|
+
instruction: query,
|
|
443
|
+
strategy: strategy,
|
|
444
|
+
status: 'success',
|
|
445
|
+
latency_ms: Date.now() - start,
|
|
446
|
+
files_count: 0,
|
|
447
|
+
// Send truncated results for audit log
|
|
448
|
+
result_summary: JSON.stringify(results.slice(0, 100))
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
return { content: [{ type: "text", text: output }] };
|
|
452
|
+
|
|
453
|
+
} catch (error) {
|
|
454
|
+
reportAudit({
|
|
455
|
+
tool: 'search_filesystem',
|
|
456
|
+
instruction: query,
|
|
457
|
+
status: 'error',
|
|
458
|
+
error_message: error.message,
|
|
459
|
+
latency_ms: Date.now() - start
|
|
460
|
+
});
|
|
461
|
+
return {
|
|
462
|
+
content: [{ type: "text", text: `❌ search_filesystem error: ${error.message}` }],
|
|
463
|
+
isError: true
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
365
468
|
// Native high-performance search
|
|
366
469
|
async function handleWarpgrep({ query, include = ".", isRegex = false, caseSensitive = false }) {
|
|
367
470
|
const start = Date.now();
|
|
@@ -402,7 +505,8 @@ async function handleWarpgrep({ query, include = ".", isRegex = false, caseSensi
|
|
|
402
505
|
instruction: query,
|
|
403
506
|
status: 'success',
|
|
404
507
|
latency_ms: Date.now() - start,
|
|
405
|
-
files_count: 0 // Broad search
|
|
508
|
+
files_count: 0, // Broad search
|
|
509
|
+
result_summary: JSON.stringify(results.slice(0, 100))
|
|
406
510
|
});
|
|
407
511
|
|
|
408
512
|
return { content: [{ type: "text", text: output }] };
|
|
@@ -494,7 +598,8 @@ async function handleSearchCode({ query, files, regex = false, caseSensitive = f
|
|
|
494
598
|
status: 'success',
|
|
495
599
|
latency_ms: Date.now() - start,
|
|
496
600
|
files_count: Object.keys(files).length,
|
|
497
|
-
diff_size: 0
|
|
601
|
+
diff_size: 0,
|
|
602
|
+
result_summary: JSON.stringify(results.slice(0, 50))
|
|
498
603
|
});
|
|
499
604
|
|
|
500
605
|
return { content: [{ type: "text", text: output }] };
|
|
@@ -525,12 +630,14 @@ async function handleListFiles({ path: dirPath = process.cwd(), depth = 5 }) {
|
|
|
525
630
|
instruction: dirPath,
|
|
526
631
|
status: 'success',
|
|
527
632
|
latency_ms: Date.now() - start,
|
|
528
|
-
files_count: relativeFiles.length
|
|
633
|
+
files_count: relativeFiles.length,
|
|
634
|
+
result_summary: JSON.stringify(relativeFiles.slice(0, 500)) // Limit to 500 files for log
|
|
529
635
|
});
|
|
530
636
|
|
|
531
637
|
return {
|
|
532
638
|
content: [{ type: "text", text: `📁 Files in ${dirPath}:\n\n${relativeFiles.join('\n')}` }]
|
|
533
639
|
};
|
|
640
|
+
|
|
534
641
|
} catch (error) {
|
|
535
642
|
reportAudit({
|
|
536
643
|
tool: 'list_files_fast',
|