+2
-2
| { | ||
| "name": "@laver/mcp", | ||
| "version": "0.1.0", | ||
| "description": "MCP server for Laver — drive kanban boards, tickets and the wiki from an agent.", | ||
| "version": "0.1.1", | ||
| "description": "MCP server for Laver \u2014 drive kanban boards, tickets and the wiki from an agent.", | ||
| "license": "MIT", | ||
@@ -6,0 +6,0 @@ "type": "module", |
+23
-3
@@ -233,6 +233,26 @@ # @laver/mcp | ||
| Not yet published. The package is ready to be; the publish itself is the | ||
| owner's to run, because it is public, permanent enough to matter, and takes a | ||
| name nobody else can then have. | ||
| **0.1.0 is published and is broken. Do not tell anyone to install it.** It | ||
| starts, registers all 20 tools, connects no transport, and exits 0 without | ||
| writing anything to stdout or stderr — so a client sees the process end and | ||
| nothing else. The entry-point guard compared the *basename* of `process.argv[1]` | ||
| against this file's name, which is true only for `node mcp/server.js`; npm's | ||
| shim for `bin` makes argv[1] `node_modules/.bin/laver-mcp`, so `npx -y | ||
| @laver/mcp` — the way this README tells everyone to run it — never matched. | ||
| Fixed in 0.1.1, and `tests/check-mcp-bin-entrypoint.mjs` now spawns the server | ||
| through a symlink and speaks MCP to it, so the same class of bug cannot ship | ||
| again. | ||
| When 0.1.1 goes out, mark the broken one so nobody lands on it: | ||
| ```bash | ||
| npm deprecate @laver/mcp@0.1.0 "Never connects its stdio transport when run via npx or the bin shim. Use 0.1.1 or later." | ||
| ``` | ||
| Unpublishing 0.1.0 is the other option and is worse: within 72 hours it removes | ||
| the version, but the number stays burned either way, and anything that already | ||
| pinned it breaks rather than being warned. | ||
| The publish itself is the owner's to run, because it is public, permanent enough | ||
| to matter, and takes a name nobody else can then have. | ||
| **The name.** `laver` on npm is taken — v1.0.0, published in 2021 by an | ||
@@ -239,0 +259,0 @@ unrelated maintainer — so the bare name is not available and never will be. |
+33
-8
@@ -15,3 +15,4 @@ #!/usr/bin/env node | ||
| import { readFileSync } from "node:fs"; | ||
| import { readFileSync, realpathSync } from "node:fs"; | ||
| import { pathToFileURL } from "node:url"; | ||
| import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; | ||
@@ -494,8 +495,32 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; | ||
| // Only connect stdio when actually run as the server. Imported by check.js, | ||
| // which would otherwise hang waiting on a transport nobody is speaking to. | ||
| if ( | ||
| process.argv[1] && | ||
| import.meta.url.endsWith(process.argv[1].split("/").pop()) | ||
| ) | ||
| await server.connect(new StdioServerTransport()); | ||
| /* Only connect stdio when this file is what was actually run. Imported by | ||
| * check.js, which would otherwise hang waiting on a transport nobody is | ||
| * speaking to. | ||
| * | ||
| * Compared as resolved paths, not as basenames. This used to test whether | ||
| * `import.meta.url` ended with the last segment of `process.argv[1]`, which is | ||
| * true for `node server.js` and false for every other way of starting it — | ||
| * because `bin` is `laver-mcp`, so npm's shim makes argv[1] | ||
| * `…/node_modules/.bin/laver-mcp` and the basenames never match. The server | ||
| * then registered its tools, connected nothing, and exited 0 in silence: no | ||
| * error, no output, a client that just sees the process end. That is the | ||
| * documented way to run this (`npx -y @laver/mcp`), and it shipped broken in | ||
| * 0.1.0 — the repo's own .mcp.json says `node mcp/server.js`, which took the | ||
| * one path that worked. | ||
| * | ||
| * realpathSync is what makes the bin shim resolve: it follows the symlink from | ||
| * .bin back to this file. pathToFileURL is what makes the two comparable — | ||
| * import.meta.url is a file:// URL and argv[1] is a plain path, so comparing | ||
| * them raw never matches on any platform. */ | ||
| const started_directly = (() => { | ||
| if (!process.argv[1]) return false; | ||
| try { | ||
| return import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href; | ||
| } catch { | ||
| // argv[1] can be something unresolvable — a deleted file, a odd embedder. | ||
| // Not being able to prove we are the entry point means not connecting. | ||
| return false; | ||
| } | ||
| })(); | ||
| if (started_directly) await server.connect(new StdioServerTransport()); |
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
48031
5.29%505
4.99%0
-100%339
6.27%