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 CHANGED
@@ -4,11 +4,23 @@
4
4
  [![npm downloads](https://img.shields.io/npm/dm/mcp-multitool)](https://www.npmjs.com/package/mcp-multitool)
5
5
  [![license](https://img.shields.io/npm/l/mcp-multitool)](./LICENSE)
6
6
 
7
- A minimal [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server with utility tools.
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 — pausing for rate limits, deleting temp files, etc. `mcp-multitool` gives any MCP-compatible client a small set of reliable tools.
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 | Default | Description |
118
- | ------------------- | -------- | --------------------------------------------------------------------------------------------------------- |
119
- | `waitMaxDurationMs` | `300000` | Override the maximum allowed `durationMs`. Must be a positive number. Server refuses to start if invalid. |
120
- | `deleteFile` | _(on)_ | Set to `"false"` to disable the `deleteFile` tool at startup. |
121
- | `moveFile` | _(on)_ | Set to `"false"` to disable the `moveFile` tool at startup. |
122
- | `wait` | _(on)_ | Set to `"false"` to disable the `wait` tool at startup. |
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: "0.1.0" });
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,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function register(server: McpServer): void;
@@ -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,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function register(server: McpServer): void;
@@ -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,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function register(server: McpServer): void;
@@ -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,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function register(server: McpServer): void;
@@ -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.1",
4
- "description": "Minimal MCP server wait tool and more.",
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": {