mcp-multitool 0.1.1 → 0.1.4
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 +110 -8
- package/dist/index.js +16 -1
- package/dist/tools/analyzePatterns.d.ts +2 -0
- package/dist/tools/analyzePatterns.js +47 -0
- package/dist/tools/compressLogs.d.ts +2 -0
- package/dist/tools/compressLogs.js +60 -0
- package/dist/tools/compressText.d.ts +2 -0
- package/dist/tools/compressText.js +60 -0
- package/dist/tools/estimateCompression.d.ts +2 -0
- package/dist/tools/estimateCompression.js +47 -0
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -4,11 +4,23 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/mcp-multitool)
|
|
5
5
|
[](./LICENSE)
|
|
6
6
|
|
|
7
|
-
A
|
|
7
|
+
A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server with **file operations**, **log compression**, and **timing utilities**.
|
|
8
|
+
|
|
9
|
+
## Tools
|
|
10
|
+
|
|
11
|
+
| Tool | Description |
|
|
12
|
+
| --------------------- | ----------------------------------------------- |
|
|
13
|
+
| `deleteFile` | Delete files or directories (single or batch) |
|
|
14
|
+
| `moveFile` | Move/rename files or directories |
|
|
15
|
+
| `compressLogs` | Compress log arrays with 60-90% token reduction |
|
|
16
|
+
| `compressText` | Compress multi-line log text |
|
|
17
|
+
| `analyzePatterns` | Quick pattern extraction from logs |
|
|
18
|
+
| `estimateCompression` | Estimate compression ratio before processing |
|
|
19
|
+
| `wait` | Pause execution for rate limits or timing |
|
|
8
20
|
|
|
9
21
|
## Why
|
|
10
22
|
|
|
11
|
-
Some tasks need simple utilities that don't warrant a larger server —
|
|
23
|
+
Some tasks need simple utilities that don't warrant a larger server — cleaning up temp files, compressing verbose logs before analysis, pausing for rate limits. `mcp-multitool` gives any MCP-compatible client a small set of reliable tools.
|
|
12
24
|
|
|
13
25
|
## Quick Start
|
|
14
26
|
|
|
@@ -50,6 +62,72 @@ npx mcp-multitool
|
|
|
50
62
|
|
|
51
63
|
## Tool Reference
|
|
52
64
|
|
|
65
|
+
### `analyzePatterns`
|
|
66
|
+
|
|
67
|
+
Quick pattern analysis without full compression. Returns top N patterns found in logs, useful for rapid log triage.
|
|
68
|
+
|
|
69
|
+
| Parameter | Type | Required | Default | Description |
|
|
70
|
+
| ------------- | ---------- | -------- | ------- | --------------------------- |
|
|
71
|
+
| `lines` | `string[]` | ✅ | — | Log lines to analyze. |
|
|
72
|
+
| `maxPatterns` | `integer` | — | `20` | Maximum patterns to return. |
|
|
73
|
+
|
|
74
|
+
**Response:** JSON object with `patterns` array and `total` line count.
|
|
75
|
+
|
|
76
|
+
**Examples:**
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
analyzePatterns lines=["INFO Starting server", "INFO Starting server", "ERROR Failed"]
|
|
80
|
+
analyzePatterns lines=[...logs] maxPatterns=10
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
### `compressLogs`
|
|
86
|
+
|
|
87
|
+
Compress an array of log lines using semantic pattern extraction. Achieves 60-90% token reduction while preserving diagnostic context.
|
|
88
|
+
|
|
89
|
+
| Parameter | Type | Required | Default | Description |
|
|
90
|
+
| -------------- | ---------- | -------- | --------- | ----------------------------------------------------------------------- |
|
|
91
|
+
| `lines` | `string[]` | ✅ | — | Log lines to compress. |
|
|
92
|
+
| `format` | `string` | — | `summary` | Output format: `summary` (compact), `detailed` (full metadata), `json`. |
|
|
93
|
+
| `depth` | `integer` | — | `4` | Parse tree depth for pattern matching (2-8). |
|
|
94
|
+
| `simThreshold` | `number` | — | `0.4` | Similarity threshold for template matching (0.0-1.0). |
|
|
95
|
+
| `maxTemplates` | `integer` | — | `50` | Maximum templates to include in output. |
|
|
96
|
+
|
|
97
|
+
**Response:** Compressed log summary showing unique templates and occurrence counts.
|
|
98
|
+
|
|
99
|
+
**Examples:**
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
compressLogs lines=["2026-04-07 INFO Starting on port 3000", "2026-04-07 INFO Starting on port 3001"]
|
|
103
|
+
compressLogs lines=[...logs] format="json" maxTemplates=20
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
### `compressText`
|
|
109
|
+
|
|
110
|
+
Compress a multi-line log text string. Automatically splits on newlines and processes as individual log lines.
|
|
111
|
+
|
|
112
|
+
| Parameter | Type | Required | Default | Description |
|
|
113
|
+
| -------------- | --------- | -------- | --------- | ----------------------------------------------------------------------- |
|
|
114
|
+
| `text` | `string` | ✅ | — | Multi-line log text to compress. |
|
|
115
|
+
| `format` | `string` | — | `summary` | Output format: `summary` (compact), `detailed` (full metadata), `json`. |
|
|
116
|
+
| `depth` | `integer` | — | `4` | Parse tree depth for pattern matching (2-8). |
|
|
117
|
+
| `simThreshold` | `number` | — | `0.4` | Similarity threshold for template matching (0.0-1.0). |
|
|
118
|
+
| `maxTemplates` | `integer` | — | `50` | Maximum templates to include in output. |
|
|
119
|
+
|
|
120
|
+
**Response:** Compressed log summary showing unique templates and occurrence counts.
|
|
121
|
+
|
|
122
|
+
**Examples:**
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
compressText text="INFO Starting server\nINFO Starting server\nERROR Failed"
|
|
126
|
+
compressText text="<paste logs here>" format="detailed"
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
53
131
|
### `deleteFile`
|
|
54
132
|
|
|
55
133
|
Delete one or more files or directories.
|
|
@@ -71,6 +149,26 @@ deleteFile paths="build/" recursive=true
|
|
|
71
149
|
|
|
72
150
|
---
|
|
73
151
|
|
|
152
|
+
### `estimateCompression`
|
|
153
|
+
|
|
154
|
+
Estimate compression ratio without full processing. Samples a subset of logs to predict compression effectiveness.
|
|
155
|
+
|
|
156
|
+
| Parameter | Type | Required | Default | Description |
|
|
157
|
+
| ------------ | ---------- | -------- | ------- | ----------------------------------------- |
|
|
158
|
+
| `lines` | `string[]` | ✅ | — | Log lines to sample. |
|
|
159
|
+
| `sampleSize` | `integer` | — | `1000` | Number of lines to sample for estimation. |
|
|
160
|
+
|
|
161
|
+
**Response:** JSON object with estimated compression ratio, token reduction, and recommendation.
|
|
162
|
+
|
|
163
|
+
**Examples:**
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
estimateCompression lines=[...largeLogs]
|
|
167
|
+
estimateCompression lines=[...logs] sampleSize=500
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
74
172
|
### `moveFile`
|
|
75
173
|
|
|
76
174
|
Move one or more files or directories to a destination directory.
|
|
@@ -114,12 +212,16 @@ wait durationMs=500 reason="animation to complete"
|
|
|
114
212
|
|
|
115
213
|
## Environment Variables
|
|
116
214
|
|
|
117
|
-
| Variable
|
|
118
|
-
|
|
|
119
|
-
| `waitMaxDurationMs`
|
|
120
|
-
| `
|
|
121
|
-
| `
|
|
122
|
-
| `
|
|
215
|
+
| Variable | Default | Description |
|
|
216
|
+
| --------------------- | -------- | --------------------------------------------------------------------------------------------------------- |
|
|
217
|
+
| `waitMaxDurationMs` | `300000` | Override the maximum allowed `durationMs`. Must be a positive number. Server refuses to start if invalid. |
|
|
218
|
+
| `analyzePatterns` | _(on)_ | Set to `"false"` to disable the `analyzePatterns` tool at startup. |
|
|
219
|
+
| `compressLogs` | _(on)_ | Set to `"false"` to disable the `compressLogs` tool at startup. |
|
|
220
|
+
| `compressText` | _(on)_ | Set to `"false"` to disable the `compressText` tool at startup. |
|
|
221
|
+
| `deleteFile` | _(on)_ | Set to `"false"` to disable the `deleteFile` tool at startup. |
|
|
222
|
+
| `estimateCompression` | _(on)_ | Set to `"false"` to disable the `estimateCompression` tool at startup. |
|
|
223
|
+
| `moveFile` | _(on)_ | Set to `"false"` to disable the `moveFile` tool at startup. |
|
|
224
|
+
| `wait` | _(on)_ | Set to `"false"` to disable the `wait` tool at startup. |
|
|
123
225
|
|
|
124
226
|
### Disabling Individual Tools
|
|
125
227
|
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from "node:module";
|
|
2
3
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
import { register as registerAnalyzePatterns } from "./tools/analyzePatterns.js";
|
|
6
|
+
import { register as registerCompressLogs } from "./tools/compressLogs.js";
|
|
7
|
+
import { register as registerCompressText } from "./tools/compressText.js";
|
|
4
8
|
import { register as registerDeleteFile } from "./tools/deleteFile.js";
|
|
9
|
+
import { register as registerEstimateCompression } from "./tools/estimateCompression.js";
|
|
5
10
|
import { register as registerMoveFile } from "./tools/moveFile.js";
|
|
6
11
|
import { register as registerWait } from "./tools/wait.js";
|
|
12
|
+
const require = createRequire(import.meta.url);
|
|
13
|
+
const { version } = require("./package.json");
|
|
7
14
|
const isEnabled = (name) => process.env[name] !== "false";
|
|
8
|
-
const server = new McpServer({ name: "mcp-multitool", version
|
|
15
|
+
const server = new McpServer({ name: "mcp-multitool", version });
|
|
16
|
+
if (isEnabled("analyzePatterns"))
|
|
17
|
+
registerAnalyzePatterns(server);
|
|
18
|
+
if (isEnabled("compressLogs"))
|
|
19
|
+
registerCompressLogs(server);
|
|
20
|
+
if (isEnabled("compressText"))
|
|
21
|
+
registerCompressText(server);
|
|
9
22
|
if (isEnabled("deleteFile"))
|
|
10
23
|
registerDeleteFile(server);
|
|
24
|
+
if (isEnabled("estimateCompression"))
|
|
25
|
+
registerEstimateCompression(server);
|
|
11
26
|
if (isEnabled("moveFile"))
|
|
12
27
|
registerMoveFile(server);
|
|
13
28
|
if (isEnabled("wait"))
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { compress } from "logpare";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
const schema = z.object({
|
|
4
|
+
lines: z.array(z.string()).min(1).describe("Log lines to analyze."),
|
|
5
|
+
maxPatterns: z
|
|
6
|
+
.number()
|
|
7
|
+
.int()
|
|
8
|
+
.min(1)
|
|
9
|
+
.max(100)
|
|
10
|
+
.default(20)
|
|
11
|
+
.describe("Maximum patterns to return."),
|
|
12
|
+
});
|
|
13
|
+
export function register(server) {
|
|
14
|
+
server.registerTool("analyzePatterns", {
|
|
15
|
+
description: "Quick pattern analysis without full compression. Returns top N patterns " +
|
|
16
|
+
"found in logs, useful for rapid log triage.",
|
|
17
|
+
inputSchema: schema,
|
|
18
|
+
annotations: {
|
|
19
|
+
readOnlyHint: true,
|
|
20
|
+
},
|
|
21
|
+
}, async (input) => {
|
|
22
|
+
try {
|
|
23
|
+
const result = compress(input.lines, {
|
|
24
|
+
format: "json",
|
|
25
|
+
maxTemplates: input.maxPatterns,
|
|
26
|
+
});
|
|
27
|
+
const patterns = result.templates.map((t) => ({
|
|
28
|
+
pattern: t.pattern,
|
|
29
|
+
count: t.occurrences,
|
|
30
|
+
severity: t.severity,
|
|
31
|
+
}));
|
|
32
|
+
const output = {
|
|
33
|
+
patterns,
|
|
34
|
+
total: result.stats.inputLines,
|
|
35
|
+
};
|
|
36
|
+
return {
|
|
37
|
+
content: [{ type: "text", text: JSON.stringify(output, null, 2) }],
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
return {
|
|
42
|
+
isError: true,
|
|
43
|
+
content: [{ type: "text", text: String(err) }],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { compress } from "logpare";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
const schema = z.object({
|
|
4
|
+
lines: z.array(z.string()).min(1).describe("Log lines to compress."),
|
|
5
|
+
format: z
|
|
6
|
+
.enum(["summary", "detailed", "json"])
|
|
7
|
+
.default("summary")
|
|
8
|
+
.describe("Output format: summary (compact), detailed (full metadata), json (machine-readable)."),
|
|
9
|
+
depth: z
|
|
10
|
+
.number()
|
|
11
|
+
.int()
|
|
12
|
+
.min(2)
|
|
13
|
+
.max(8)
|
|
14
|
+
.default(4)
|
|
15
|
+
.describe("Parse tree depth for pattern matching (2-8)."),
|
|
16
|
+
simThreshold: z
|
|
17
|
+
.number()
|
|
18
|
+
.min(0)
|
|
19
|
+
.max(1)
|
|
20
|
+
.default(0.4)
|
|
21
|
+
.describe("Similarity threshold for template matching (0.0-1.0)."),
|
|
22
|
+
maxTemplates: z
|
|
23
|
+
.number()
|
|
24
|
+
.int()
|
|
25
|
+
.min(1)
|
|
26
|
+
.max(500)
|
|
27
|
+
.default(50)
|
|
28
|
+
.describe("Maximum templates to include in output."),
|
|
29
|
+
});
|
|
30
|
+
export function register(server) {
|
|
31
|
+
server.registerTool("compressLogs", {
|
|
32
|
+
description: "Compress an array of log lines using semantic pattern extraction. " +
|
|
33
|
+
"Achieves 60-90% token reduction while preserving diagnostic context.",
|
|
34
|
+
inputSchema: schema,
|
|
35
|
+
annotations: {
|
|
36
|
+
readOnlyHint: true,
|
|
37
|
+
},
|
|
38
|
+
}, async (input) => {
|
|
39
|
+
try {
|
|
40
|
+
const options = {
|
|
41
|
+
format: input.format,
|
|
42
|
+
maxTemplates: input.maxTemplates,
|
|
43
|
+
drain: {
|
|
44
|
+
depth: input.depth,
|
|
45
|
+
simThreshold: input.simThreshold,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
const result = compress(input.lines, options);
|
|
49
|
+
return {
|
|
50
|
+
content: [{ type: "text", text: result.formatted }],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
return {
|
|
55
|
+
isError: true,
|
|
56
|
+
content: [{ type: "text", text: String(err) }],
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { compressText as logpareCompressText, } from "logpare";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
const schema = z.object({
|
|
4
|
+
text: z.string().min(1).describe("Multi-line log text to compress."),
|
|
5
|
+
format: z
|
|
6
|
+
.enum(["summary", "detailed", "json"])
|
|
7
|
+
.default("summary")
|
|
8
|
+
.describe("Output format: summary (compact), detailed (full metadata), json (machine-readable)."),
|
|
9
|
+
depth: z
|
|
10
|
+
.number()
|
|
11
|
+
.int()
|
|
12
|
+
.min(2)
|
|
13
|
+
.max(8)
|
|
14
|
+
.default(4)
|
|
15
|
+
.describe("Parse tree depth for pattern matching (2-8)."),
|
|
16
|
+
simThreshold: z
|
|
17
|
+
.number()
|
|
18
|
+
.min(0)
|
|
19
|
+
.max(1)
|
|
20
|
+
.default(0.4)
|
|
21
|
+
.describe("Similarity threshold for template matching (0.0-1.0)."),
|
|
22
|
+
maxTemplates: z
|
|
23
|
+
.number()
|
|
24
|
+
.int()
|
|
25
|
+
.min(1)
|
|
26
|
+
.max(500)
|
|
27
|
+
.default(50)
|
|
28
|
+
.describe("Maximum templates to include in output."),
|
|
29
|
+
});
|
|
30
|
+
export function register(server) {
|
|
31
|
+
server.registerTool("compressText", {
|
|
32
|
+
description: "Compress a multi-line log text string. Automatically splits on newlines " +
|
|
33
|
+
"and processes as individual log lines.",
|
|
34
|
+
inputSchema: schema,
|
|
35
|
+
annotations: {
|
|
36
|
+
readOnlyHint: true,
|
|
37
|
+
},
|
|
38
|
+
}, async (input) => {
|
|
39
|
+
try {
|
|
40
|
+
const options = {
|
|
41
|
+
format: input.format,
|
|
42
|
+
maxTemplates: input.maxTemplates,
|
|
43
|
+
drain: {
|
|
44
|
+
depth: input.depth,
|
|
45
|
+
simThreshold: input.simThreshold,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
const result = logpareCompressText(input.text, options);
|
|
49
|
+
return {
|
|
50
|
+
content: [{ type: "text", text: result.formatted }],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
return {
|
|
55
|
+
isError: true,
|
|
56
|
+
content: [{ type: "text", text: String(err) }],
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { compress } from "logpare";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
const schema = z.object({
|
|
4
|
+
lines: z.array(z.string()).min(1).describe("Log lines to sample."),
|
|
5
|
+
sampleSize: z
|
|
6
|
+
.number()
|
|
7
|
+
.int()
|
|
8
|
+
.min(100)
|
|
9
|
+
.max(10000)
|
|
10
|
+
.default(1000)
|
|
11
|
+
.describe("Number of lines to sample for estimation."),
|
|
12
|
+
});
|
|
13
|
+
export function register(server) {
|
|
14
|
+
server.registerTool("estimateCompression", {
|
|
15
|
+
description: "Estimate compression ratio without full processing. Samples a subset of " +
|
|
16
|
+
"logs to predict compression effectiveness.",
|
|
17
|
+
inputSchema: schema,
|
|
18
|
+
annotations: {
|
|
19
|
+
readOnlyHint: true,
|
|
20
|
+
},
|
|
21
|
+
}, async (input) => {
|
|
22
|
+
try {
|
|
23
|
+
const sampleSize = Math.min(input.sampleSize, input.lines.length);
|
|
24
|
+
const sample = input.lines.slice(0, sampleSize);
|
|
25
|
+
const result = compress(sample, { format: "json" });
|
|
26
|
+
const output = {
|
|
27
|
+
sampleSize,
|
|
28
|
+
totalLines: input.lines.length,
|
|
29
|
+
estimatedTemplates: Math.round(result.stats.uniqueTemplates * (input.lines.length / sampleSize)),
|
|
30
|
+
estimatedCompressionRatio: result.stats.compressionRatio,
|
|
31
|
+
estimatedTokenReduction: result.stats.estimatedTokenReduction,
|
|
32
|
+
recommendation: result.stats.compressionRatio > 0.5 ?
|
|
33
|
+
"Good compression expected"
|
|
34
|
+
: "Limited compression - logs may be highly variable",
|
|
35
|
+
};
|
|
36
|
+
return {
|
|
37
|
+
content: [{ type: "text", text: JSON.stringify(output, null, 2) }],
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
return {
|
|
42
|
+
isError: true,
|
|
43
|
+
content: [{ type: "text", text: String(err) }],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-multitool",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "MCP server with file operations (delete, move), log compression (60-90% token reduction), and timing utilities.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|
|
@@ -14,7 +14,12 @@
|
|
|
14
14
|
"keywords": [
|
|
15
15
|
"mcp",
|
|
16
16
|
"model-context-protocol",
|
|
17
|
+
"log-compression",
|
|
18
|
+
"file-operations",
|
|
19
|
+
"delete-file",
|
|
20
|
+
"move-file",
|
|
17
21
|
"wait",
|
|
22
|
+
"logpare",
|
|
18
23
|
"tool"
|
|
19
24
|
],
|
|
20
25
|
"scripts": {
|
|
@@ -27,6 +32,7 @@
|
|
|
27
32
|
},
|
|
28
33
|
"dependencies": {
|
|
29
34
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
35
|
+
"logpare": "^0.1.0",
|
|
30
36
|
"zod": "^3.24.0"
|
|
31
37
|
},
|
|
32
38
|
"devDependencies": {
|