memorylens-mcp 1.5.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 +39 -0
- package/bin/memorylens-mcp.js +138 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# memorylens-mcp
|
|
2
|
+
|
|
3
|
+
npm launcher for [MemoryLens MCP](https://github.com/MarcelRoozekrans/memorylens-mcp) — on-demand
|
|
4
|
+
.NET memory profiling with concrete, AI-actionable code fix suggestions, wrapping JetBrains
|
|
5
|
+
dotMemory with a heuristic-based rule engine.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx -y memorylens-mcp
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
This package contains no server code. It is a thin shim that ensures the
|
|
12
|
+
[`MemoryLens.Mcp`](https://www.nuget.org/packages/MemoryLens.Mcp) .NET global tool is installed at
|
|
13
|
+
the matching version, then execs it. **The .NET 10 SDK must be on `PATH`.**
|
|
14
|
+
|
|
15
|
+
## MCP client config
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"mcpServers": {
|
|
20
|
+
"memorylens": {
|
|
21
|
+
"type": "stdio",
|
|
22
|
+
"command": "npx",
|
|
23
|
+
"args": ["-y", "memorylens-mcp"]
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The server downloads and caches `dotnet-dotmemory` on first use; see the
|
|
30
|
+
[main README](https://github.com/MarcelRoozekrans/memorylens-mcp#readme) for supported platforms,
|
|
31
|
+
cache locations, and manual fallback discovery.
|
|
32
|
+
|
|
33
|
+
If you already have the .NET SDK and prefer no npm indirection, install the tool directly:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
dotnet tool install -g MemoryLens.Mcp
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
MIT licensed.
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// Launcher for the MemoryLens.Mcp .NET global tool.
|
|
4
|
+
//
|
|
5
|
+
// This package ships no server code. It exists so the server can be started with
|
|
6
|
+
// `npx -y memorylens-mcp` by clients and directories that only know how to run
|
|
7
|
+
// npm-hosted MCP servers. Everything it does is: verify the .NET SDK is present,
|
|
8
|
+
// make sure the global tool matches this package's version, then exec it.
|
|
9
|
+
//
|
|
10
|
+
// stdout is the JSON-RPC channel, so every diagnostic and every byte of dotnet's
|
|
11
|
+
// install output goes to stderr.
|
|
12
|
+
|
|
13
|
+
const { execFileSync, spawn } = require("node:child_process");
|
|
14
|
+
const fs = require("node:fs");
|
|
15
|
+
const os = require("node:os");
|
|
16
|
+
const path = require("node:path");
|
|
17
|
+
|
|
18
|
+
const PACKAGE_ID = "MemoryLens.Mcp";
|
|
19
|
+
const COMMAND = "memorylens-mcp";
|
|
20
|
+
const { version } = require("../package.json");
|
|
21
|
+
|
|
22
|
+
function fail(message) {
|
|
23
|
+
process.stderr.write(`memorylens-mcp: ${message}\n`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function hasDotnet() {
|
|
28
|
+
try {
|
|
29
|
+
execFileSync("dotnet", ["--version"], { stdio: "ignore" });
|
|
30
|
+
return true;
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// The installed version of the global tool, or null when it is not installed.
|
|
37
|
+
// `dotnet tool list --global` lowercases the package id and prints it as
|
|
38
|
+
// `memorylens.mcp 1.5.1 memorylens-mcp`. Local lookup — no network.
|
|
39
|
+
function installedVersion() {
|
|
40
|
+
try {
|
|
41
|
+
const output = execFileSync("dotnet", ["tool", "list", "--global"], {
|
|
42
|
+
encoding: "utf8",
|
|
43
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
44
|
+
});
|
|
45
|
+
for (const line of output.split("\n")) {
|
|
46
|
+
const match = line.match(/^memorylens\.mcp\s+(\S+)/i);
|
|
47
|
+
if (match) {
|
|
48
|
+
return match[1];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
} catch {
|
|
52
|
+
// dotnet missing or the command failed — treat the tool as not installed.
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// `dotnet tool install` fails when a different version is already present, so the
|
|
58
|
+
// verb depends on what is there. Output is routed to stderr (fd 2) rather than
|
|
59
|
+
// captured so a slow first-run restore still shows progress.
|
|
60
|
+
function install(alreadyInstalled) {
|
|
61
|
+
const verb = alreadyInstalled ? "update" : "install";
|
|
62
|
+
process.stderr.write(
|
|
63
|
+
`memorylens-mcp: ${verb === "install" ? "installing" : "updating"} ${PACKAGE_ID} ${version}...\n`
|
|
64
|
+
);
|
|
65
|
+
execFileSync(
|
|
66
|
+
"dotnet",
|
|
67
|
+
["tool", verb, "--global", PACKAGE_ID, "--version", version],
|
|
68
|
+
{ stdio: ["ignore", 2, 2] }
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Global tools land in ~/.dotnet/tools, which is not necessarily on PATH — notably
|
|
73
|
+
// in the same process that just installed them. Resolve the executable directly and
|
|
74
|
+
// prepend the directory for the child so any tool-to-tool lookup also works.
|
|
75
|
+
function toolsDir() {
|
|
76
|
+
return (
|
|
77
|
+
process.env.DOTNET_TOOLS_PATH ||
|
|
78
|
+
path.join(process.env.DOTNET_CLI_HOME || os.homedir(), ".dotnet", "tools")
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function resolveExecutable() {
|
|
83
|
+
const dir = toolsDir();
|
|
84
|
+
const name = process.platform === "win32" ? `${COMMAND}.exe` : COMMAND;
|
|
85
|
+
const candidate = path.join(dir, name);
|
|
86
|
+
return fs.existsSync(candidate) ? candidate : COMMAND;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function launch() {
|
|
90
|
+
const dir = toolsDir();
|
|
91
|
+
const child = spawn(resolveExecutable(), process.argv.slice(2), {
|
|
92
|
+
stdio: "inherit",
|
|
93
|
+
env: {
|
|
94
|
+
...process.env,
|
|
95
|
+
PATH: `${dir}${path.delimiter}${process.env.PATH || ""}`,
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
100
|
+
process.on(signal, () => child.kill(signal));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
child.on("error", (err) => fail(`failed to start ${COMMAND}: ${err.message}`));
|
|
104
|
+
child.on("exit", (code, signal) => {
|
|
105
|
+
if (signal) {
|
|
106
|
+
process.kill(process.pid, signal);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
process.exit(code ?? 0);
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (!hasDotnet()) {
|
|
114
|
+
fail(
|
|
115
|
+
"the .NET SDK was not found on PATH. MemoryLens requires the .NET 10 SDK — https://dotnet.microsoft.com/download"
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const current = installedVersion();
|
|
120
|
+
|
|
121
|
+
// Already on the matching version — skip the install round-trip entirely so startup
|
|
122
|
+
// stays fast and works offline.
|
|
123
|
+
if (current !== version) {
|
|
124
|
+
try {
|
|
125
|
+
install(current !== null);
|
|
126
|
+
} catch (err) {
|
|
127
|
+
if (current === null) {
|
|
128
|
+
fail(`failed to install ${PACKAGE_ID} ${version}: ${err.message}`);
|
|
129
|
+
}
|
|
130
|
+
// A version mismatch is not fatal when a working tool is already present:
|
|
131
|
+
// an offline or rate-limited NuGet should not take the server down.
|
|
132
|
+
process.stderr.write(
|
|
133
|
+
`memorylens-mcp: could not update to ${version}, continuing with installed ${current}\n`
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
launch();
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "memorylens-mcp",
|
|
3
|
+
"version": "1.5.2",
|
|
4
|
+
"description": "MCP server for .NET memory profiling with AI-actionable code fix suggestions — wraps JetBrains dotMemory with a heuristic-based rule engine.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"memorylens-mcp": "./bin/memorylens-mcp.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"bin",
|
|
10
|
+
"README.md"
|
|
11
|
+
],
|
|
12
|
+
"keywords": [
|
|
13
|
+
"mcp",
|
|
14
|
+
"mcp-server",
|
|
15
|
+
"modelcontextprotocol",
|
|
16
|
+
"memory",
|
|
17
|
+
"profiling",
|
|
18
|
+
"dotmemory",
|
|
19
|
+
"diagnostics",
|
|
20
|
+
"dotnet",
|
|
21
|
+
"memory-leak"
|
|
22
|
+
],
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"author": "Marcel Roozekrans",
|
|
25
|
+
"homepage": "https://github.com/MarcelRoozekrans/memorylens-mcp#readme",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/MarcelRoozekrans/memorylens-mcp.git"
|
|
29
|
+
},
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/MarcelRoozekrans/memorylens-mcp/issues"
|
|
32
|
+
},
|
|
33
|
+
"mcpName": "io.github.MarcelRoozekrans/memorylens-mcp",
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=18"
|
|
36
|
+
}
|
|
37
|
+
}
|