mcp-multitool 0.1.1 → 0.1.2

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
@@ -50,6 +50,72 @@ npx mcp-multitool
50
50
 
51
51
  ## Tool Reference
52
52
 
53
+ ### `analyzePatterns`
54
+
55
+ Quick pattern analysis without full compression. Returns top N patterns found in logs, useful for rapid log triage.
56
+
57
+ | Parameter | Type | Required | Default | Description |
58
+ | ------------- | ---------- | -------- | ------- | --------------------------- |
59
+ | `lines` | `string[]` | ✅ | — | Log lines to analyze. |
60
+ | `maxPatterns` | `integer` | — | `20` | Maximum patterns to return. |
61
+
62
+ **Response:** JSON object with `patterns` array and `total` line count.
63
+
64
+ **Examples:**
65
+
66
+ ```
67
+ analyzePatterns lines=["INFO Starting server", "INFO Starting server", "ERROR Failed"]
68
+ analyzePatterns lines=[...logs] maxPatterns=10
69
+ ```
70
+
71
+ ---
72
+
73
+ ### `compressLogs`
74
+
75
+ Compress an array of log lines using semantic pattern extraction. Achieves 60-90% token reduction while preserving diagnostic context.
76
+
77
+ | Parameter | Type | Required | Default | Description |
78
+ | -------------- | ---------- | -------- | --------- | ----------------------------------------------------------------------- |
79
+ | `lines` | `string[]` | ✅ | — | Log lines to compress. |
80
+ | `format` | `string` | — | `summary` | Output format: `summary` (compact), `detailed` (full metadata), `json`. |
81
+ | `depth` | `integer` | — | `4` | Parse tree depth for pattern matching (2-8). |
82
+ | `simThreshold` | `number` | — | `0.4` | Similarity threshold for template matching (0.0-1.0). |
83
+ | `maxTemplates` | `integer` | — | `50` | Maximum templates to include in output. |
84
+
85
+ **Response:** Compressed log summary showing unique templates and occurrence counts.
86
+
87
+ **Examples:**
88
+
89
+ ```
90
+ compressLogs lines=["2026-04-07 INFO Starting on port 3000", "2026-04-07 INFO Starting on port 3001"]
91
+ compressLogs lines=[...logs] format="json" maxTemplates=20
92
+ ```
93
+
94
+ ---
95
+
96
+ ### `compressText`
97
+
98
+ Compress a multi-line log text string. Automatically splits on newlines and processes as individual log lines.
99
+
100
+ | Parameter | Type | Required | Default | Description |
101
+ | -------------- | --------- | -------- | --------- | ----------------------------------------------------------------------- |
102
+ | `text` | `string` | ✅ | — | Multi-line log text to compress. |
103
+ | `format` | `string` | — | `summary` | Output format: `summary` (compact), `detailed` (full metadata), `json`. |
104
+ | `depth` | `integer` | — | `4` | Parse tree depth for pattern matching (2-8). |
105
+ | `simThreshold` | `number` | — | `0.4` | Similarity threshold for template matching (0.0-1.0). |
106
+ | `maxTemplates` | `integer` | — | `50` | Maximum templates to include in output. |
107
+
108
+ **Response:** Compressed log summary showing unique templates and occurrence counts.
109
+
110
+ **Examples:**
111
+
112
+ ```
113
+ compressText text="INFO Starting server\nINFO Starting server\nERROR Failed"
114
+ compressText text="<paste logs here>" format="detailed"
115
+ ```
116
+
117
+ ---
118
+
53
119
  ### `deleteFile`
54
120
 
55
121
  Delete one or more files or directories.
@@ -71,6 +137,26 @@ deleteFile paths="build/" recursive=true
71
137
 
72
138
  ---
73
139
 
140
+ ### `estimateCompression`
141
+
142
+ Estimate compression ratio without full processing. Samples a subset of logs to predict compression effectiveness.
143
+
144
+ | Parameter | Type | Required | Default | Description |
145
+ | ------------ | ---------- | -------- | ------- | ----------------------------------------- |
146
+ | `lines` | `string[]` | ✅ | — | Log lines to sample. |
147
+ | `sampleSize` | `integer` | — | `1000` | Number of lines to sample for estimation. |
148
+
149
+ **Response:** JSON object with estimated compression ratio, token reduction, and recommendation.
150
+
151
+ **Examples:**
152
+
153
+ ```
154
+ estimateCompression lines=[...largeLogs]
155
+ estimateCompression lines=[...logs] sampleSize=500
156
+ ```
157
+
158
+ ---
159
+
74
160
  ### `moveFile`
75
161
 
76
162
  Move one or more files or directories to a destination directory.
@@ -114,12 +200,16 @@ wait durationMs=500 reason="animation to complete"
114
200
 
115
201
  ## Environment Variables
116
202
 
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. |
203
+ | Variable | Default | Description |
204
+ | --------------------- | -------- | --------------------------------------------------------------------------------------------------------- |
205
+ | `waitMaxDurationMs` | `300000` | Override the maximum allowed `durationMs`. Must be a positive number. Server refuses to start if invalid. |
206
+ | `analyzePatterns` | _(on)_ | Set to `"false"` to disable the `analyzePatterns` tool at startup. |
207
+ | `compressLogs` | _(on)_ | Set to `"false"` to disable the `compressLogs` tool at startup. |
208
+ | `compressText` | _(on)_ | Set to `"false"` to disable the `compressText` tool at startup. |
209
+ | `deleteFile` | _(on)_ | Set to `"false"` to disable the `deleteFile` tool at startup. |
210
+ | `estimateCompression` | _(on)_ | Set to `"false"` to disable the `estimateCompression` tool at startup. |
211
+ | `moveFile` | _(on)_ | Set to `"false"` to disable the `moveFile` tool at startup. |
212
+ | `wait` | _(on)_ | Set to `"false"` to disable the `wait` tool at startup. |
123
213
 
124
214
  ### Disabling Individual Tools
125
215
 
package/dist/index.js CHANGED
@@ -1,13 +1,25 @@
1
1
  #!/usr/bin/env node
2
2
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { register as registerAnalyzePatterns } from "./tools/analyzePatterns.js";
5
+ import { register as registerCompressLogs } from "./tools/compressLogs.js";
6
+ import { register as registerCompressText } from "./tools/compressText.js";
4
7
  import { register as registerDeleteFile } from "./tools/deleteFile.js";
8
+ import { register as registerEstimateCompression } from "./tools/estimateCompression.js";
5
9
  import { register as registerMoveFile } from "./tools/moveFile.js";
6
10
  import { register as registerWait } from "./tools/wait.js";
7
11
  const isEnabled = (name) => process.env[name] !== "false";
8
12
  const server = new McpServer({ name: "mcp-multitool", version: "0.1.0" });
13
+ if (isEnabled("analyzePatterns"))
14
+ registerAnalyzePatterns(server);
15
+ if (isEnabled("compressLogs"))
16
+ registerCompressLogs(server);
17
+ if (isEnabled("compressText"))
18
+ registerCompressText(server);
9
19
  if (isEnabled("deleteFile"))
10
20
  registerDeleteFile(server);
21
+ if (isEnabled("estimateCompression"))
22
+ registerEstimateCompression(server);
11
23
  if (isEnabled("moveFile"))
12
24
  registerMoveFile(server);
13
25
  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,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-multitool",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Minimal MCP server — wait tool and more.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -27,6 +27,7 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@modelcontextprotocol/sdk": "1.29.0",
30
+ "logpare": "^0.1.0",
30
31
  "zod": "^3.24.0"
31
32
  },
32
33
  "devDependencies": {