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 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
+ }