webtool-log-cleaner-mcp 1.0.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 +76 -0
- package/bin/webtool-log-cleaner-mcp.cjs +171 -0
- package/package.json +16 -0
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# webtool-log-cleaner
|
|
2
|
+
|
|
3
|
+
A Python MCP server that captures raw logs from clipboard, files, shell commands, Docker, and Docker Compose, then deduplicates and compresses noisy output for AI debugging sessions.
|
|
4
|
+
|
|
5
|
+
## Tools
|
|
6
|
+
|
|
7
|
+
- `clean_clipboard_logs`
|
|
8
|
+
- `clean_log_file`
|
|
9
|
+
- `clean_command_logs`
|
|
10
|
+
- `clean_docker_logs`
|
|
11
|
+
- `clean_compose_logs`
|
|
12
|
+
|
|
13
|
+
## Reliability guardrails
|
|
14
|
+
|
|
15
|
+
- Default timeout: 30 seconds
|
|
16
|
+
- Output capture cap: 8 MB
|
|
17
|
+
- Max processed lines: 50,000
|
|
18
|
+
- Timed out/truncated captures are returned as partial cleaned summaries with explicit notes
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
### 1) PyPI + pipx (recommended)
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pipx install webtool-log-cleaner
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
MCP config:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"command": "webtool-log-cleaner",
|
|
33
|
+
"args": []
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 2) Plain pip (no pipx required)
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
python3 -m pip install --user webtool-log-cleaner
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
MCP config:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"command": "python3",
|
|
48
|
+
"args": ["-m", "webtool_log_cleaner.server"]
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 3) npx wrapper
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npx -y webtool-log-cleaner-mcp
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
MCP config:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"command": "npx",
|
|
63
|
+
"args": ["-y", "webtool-log-cleaner-mcp"]
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Notes:
|
|
68
|
+
- The npm wrapper still needs Python 3.11+ installed.
|
|
69
|
+
- On first run, it bootstraps the Python package with `pip --user` if missing.
|
|
70
|
+
|
|
71
|
+
## Local development
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
uv run pytest -q
|
|
75
|
+
uv run webtool-log-cleaner
|
|
76
|
+
```
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawn, spawnSync } = require("node:child_process");
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
const path = require("node:path");
|
|
6
|
+
|
|
7
|
+
const PYTHON_PACKAGE = "webtool-log-cleaner";
|
|
8
|
+
const MODULE_ENTRYPOINT = "webtool_log_cleaner.server";
|
|
9
|
+
const args = process.argv.slice(2);
|
|
10
|
+
|
|
11
|
+
function fail(message, code = 1) {
|
|
12
|
+
console.error(`[webtool-log-cleaner-mcp] ${message}`);
|
|
13
|
+
process.exit(code);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function runSync(command, commandArgs, options = {}) {
|
|
17
|
+
return spawnSync(command, commandArgs, {
|
|
18
|
+
stdio: "inherit",
|
|
19
|
+
...options,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function resolveLocalSourcePath() {
|
|
24
|
+
const candidate = path.resolve(__dirname, "..", "src");
|
|
25
|
+
const packagePath = path.join(candidate, "webtool_log_cleaner");
|
|
26
|
+
if (fs.existsSync(packagePath)) {
|
|
27
|
+
return candidate;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function resolveLocalVenvPython() {
|
|
33
|
+
const venvPath = process.platform === "win32"
|
|
34
|
+
? path.resolve(__dirname, "..", ".venv", "Scripts", "python.exe")
|
|
35
|
+
: path.resolve(__dirname, "..", ".venv", "bin", "python");
|
|
36
|
+
return fs.existsSync(venvPath) ? venvPath : null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function withLocalPythonPath(localSrcPath) {
|
|
40
|
+
const delimiter = process.platform === "win32" ? ";" : ":";
|
|
41
|
+
const existing = process.env.PYTHONPATH;
|
|
42
|
+
return existing ? `${localSrcPath}${delimiter}${existing}` : localSrcPath;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function selectPython() {
|
|
46
|
+
const localVenvPython = resolveLocalVenvPython();
|
|
47
|
+
const candidates = process.platform === "win32"
|
|
48
|
+
? [
|
|
49
|
+
...(localVenvPython ? [{ command: localVenvPython, baseArgs: [] }] : []),
|
|
50
|
+
{ command: "py", baseArgs: ["-3"] },
|
|
51
|
+
{ command: "python", baseArgs: [] },
|
|
52
|
+
{ command: "python3", baseArgs: [] },
|
|
53
|
+
]
|
|
54
|
+
: [
|
|
55
|
+
...(localVenvPython ? [{ command: localVenvPython, baseArgs: [] }] : []),
|
|
56
|
+
{ command: "python3", baseArgs: [] },
|
|
57
|
+
{ command: "python", baseArgs: [] },
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
for (const candidate of candidates) {
|
|
61
|
+
const probe = spawnSync(candidate.command, [...candidate.baseArgs, "--version"], {
|
|
62
|
+
stdio: "ignore",
|
|
63
|
+
});
|
|
64
|
+
if (probe.status === 0) {
|
|
65
|
+
return candidate;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function ensurePythonPackageInstalled(python) {
|
|
73
|
+
const importProbe = spawnSync(
|
|
74
|
+
python.command,
|
|
75
|
+
[...python.baseArgs, "-c", `import ${MODULE_ENTRYPOINT.split(".")[0]}`],
|
|
76
|
+
{ stdio: "ignore" }
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
if (importProbe.status === 0) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const localSourcePath = resolveLocalSourcePath();
|
|
84
|
+
if (localSourcePath) {
|
|
85
|
+
const localProbe = spawnSync(
|
|
86
|
+
python.command,
|
|
87
|
+
[...python.baseArgs, "-c", `import ${MODULE_ENTRYPOINT.split(".")[0]}`],
|
|
88
|
+
{
|
|
89
|
+
stdio: "ignore",
|
|
90
|
+
env: {
|
|
91
|
+
...process.env,
|
|
92
|
+
PYTHONPATH: withLocalPythonPath(localSourcePath),
|
|
93
|
+
},
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
if (localProbe.status === 0) {
|
|
98
|
+
return {
|
|
99
|
+
PYTHONPATH: withLocalPythonPath(localSourcePath),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
console.error(`[webtool-log-cleaner-mcp] Installing ${PYTHON_PACKAGE} with pip --user...`);
|
|
105
|
+
const install = runSync(python.command, [
|
|
106
|
+
...python.baseArgs,
|
|
107
|
+
"-m",
|
|
108
|
+
"pip",
|
|
109
|
+
"install",
|
|
110
|
+
"--user",
|
|
111
|
+
"--upgrade",
|
|
112
|
+
PYTHON_PACKAGE,
|
|
113
|
+
], {
|
|
114
|
+
env: {
|
|
115
|
+
...process.env,
|
|
116
|
+
PIP_REQUIRE_VIRTUALENV: "0",
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
if (install.status !== 0) {
|
|
121
|
+
fail(
|
|
122
|
+
"Could not install Python package. Install manually with `pipx install webtool-log-cleaner` or `python3 -m pip install --user webtool-log-cleaner`."
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function launchServer(python, forwardedArgs, envOverrides) {
|
|
130
|
+
const child = spawn(
|
|
131
|
+
python.command,
|
|
132
|
+
[...python.baseArgs, "-m", MODULE_ENTRYPOINT, ...forwardedArgs],
|
|
133
|
+
{
|
|
134
|
+
stdio: "inherit",
|
|
135
|
+
env: {
|
|
136
|
+
...process.env,
|
|
137
|
+
...(envOverrides || {}),
|
|
138
|
+
},
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
child.on("error", (err) => {
|
|
143
|
+
fail(`Failed to start Python MCP server: ${err.message}`);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
child.on("exit", (code, signal) => {
|
|
147
|
+
if (signal) {
|
|
148
|
+
process.kill(process.pid, signal);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
process.exit(code ?? 1);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function main() {
|
|
156
|
+
const python = selectPython();
|
|
157
|
+
if (!python) {
|
|
158
|
+
fail("Python 3.11+ is required but was not found in PATH.");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const envOverrides = ensurePythonPackageInstalled(python);
|
|
162
|
+
|
|
163
|
+
if (args.includes("--bootstrap-check")) {
|
|
164
|
+
console.log("webtool-log-cleaner-mcp bootstrap check: OK");
|
|
165
|
+
process.exit(0);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
launchServer(python, args, envOverrides);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "webtool-log-cleaner-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "npx launcher for the Python webtool-log-cleaner MCP server",
|
|
5
|
+
"bin": {
|
|
6
|
+
"webtool-log-cleaner-mcp": "bin/webtool-log-cleaner-mcp.cjs"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"bin/webtool-log-cleaner-mcp.cjs",
|
|
10
|
+
"README.md"
|
|
11
|
+
],
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=18"
|
|
15
|
+
}
|
|
16
|
+
}
|