Skip to content

Commit ebd13f4

Browse files
authored
Merge pull request #95 from leadbay/fix/server-json-version-drift
fix(release): align server.json with package.json (0.18.2) + drift guard
2 parents ea52d94 + acdd599 commit ebd13f4

4 files changed

Lines changed: 67 additions & 5 deletions

File tree

packages/mcp/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog — @leadbay/mcp
22

3+
## 0.18.2 — 2026-06-09
4+
5+
- **Release-pipeline fix**: align `packages/mcp/server.json` with `package.json`. `server.json` had been stuck at `0.17.2` since the 0.17.2 release, so the MCP-Registry publish step (`Verify server.json version matches package.json`) failed on every release from 0.17.3 through 0.18.1 — npm and the GitHub `.mcpb` shipped, but the registry listing silently went stale. Both `server.json` version fields (top-level + `packages[0].version`) now track `package.json`, and a new audit test (`test/audit/server-json-version.test.ts`) fails the build on any future drift instead of letting it surface only at release time.
6+
37
## 0.18.1 — 2026-06-09
48

59
- **Quota rendering fix**: `leadbay_account_status` now renders the per-resource Daily / Weekly / Monthly **usage** table the API actually returns, instead of collapsing to "quota: null / no limits". Root cause: `quota_status` returns `count` (amount **used**) per resource per window with no cap field and a possibly-`null` `plan`; the old render hint tried to draw `used / cap` and gave up when there was no cap. The hint is now usage-only and explicitly warns that a missing cap / `null` plan is **not** "unlimited" or "no quota". `get-quota.ts` `outputSchema` corrected to the real `org` / `user.resources[]` shape (`{resource_type, count, window_type, resets_at}`, `count` = used), and a failed quota fetch is now distinguished from an empty quota.

packages/mcp/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@leadbay/mcp",
3-
"version": "0.18.1",
3+
"version": "0.18.2",
44
"mcpName": "io.github.leadbay/leadbay-mcp",
55
"description": "Model Context Protocol (MCP) server for Leadbay — AI lead discovery, qualification, and enrichment for Claude Desktop, Cursor, and Claude Code.",
66
"type": "module",

packages/mcp/server.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"name": "io.github.leadbay/leadbay-mcp",
44
"title": "Leadbay",
55
"description": "AI lead discovery, qualification, and outreach prep on your Leadbay account.",
6-
"version": "0.17.2",
6+
"version": "0.18.2",
77
"repository": {
88
"url": "https://github.com/leadbay/leadclaw",
99
"source": "github",
@@ -15,7 +15,7 @@
1515
"registryType": "npm",
1616
"registryBaseUrl": "https://registry.npmjs.org",
1717
"identifier": "@leadbay/mcp",
18-
"version": "0.17.2",
18+
"version": "0.18.2",
1919
"transport": {
2020
"type": "stdio"
2121
},
@@ -27,13 +27,13 @@
2727
},
2828
{
2929
"type": "positional",
30-
"value": "@leadbay/mcp@0.17"
30+
"value": "@leadbay/mcp@0.18"
3131
}
3232
],
3333
"environmentVariables": [
3434
{
3535
"name": "LEADBAY_TOKEN",
36-
"description": "Bearer token; mint with `npx -y @leadbay/mcp@0.17 login --email <you> --region <us|fr>`.",
36+
"description": "Bearer token; mint with `npx -y @leadbay/mcp@0.18 login --email <you> --region <us|fr>`.",
3737
"isRequired": true,
3838
"isSecret": true
3939
},
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* Audit: packages/mcp/server.json stays aligned with package.json.
3+
*
4+
* The release pipeline (.github/workflows/release.yml) refuses to publish to
5+
* the MCP Registry unless server.json.version === package.json.version and
6+
* server.json.name === package.json.mcpName. That guard only runs at release
7+
* time, so a drift (e.g. bumping package.json without server.json) ships to
8+
* npm + the GitHub .mcpb and only fails the registry step — silently, after
9+
* the fact. server.json sat at 0.17.2 across the 0.17.3 / 0.18.0 / 0.18.1
10+
* releases for exactly this reason. This test moves the check to PR time.
11+
*/
12+
import { readFileSync } from "node:fs";
13+
import { dirname, join } from "node:path";
14+
import { fileURLToPath } from "node:url";
15+
import { describe, it, expect } from "vitest";
16+
17+
const __dirname = dirname(fileURLToPath(import.meta.url));
18+
// packages/mcp/test/audit -> packages/mcp
19+
const MCP_DIR = join(__dirname, "..", "..");
20+
21+
const pkg = JSON.parse(readFileSync(join(MCP_DIR, "package.json"), "utf8"));
22+
const srv = JSON.parse(readFileSync(join(MCP_DIR, "server.json"), "utf8"));
23+
24+
describe("audit: server.json aligns with package.json", () => {
25+
it("top-level server.json.version matches package.json.version", () => {
26+
expect(srv.version).toBe(pkg.version);
27+
});
28+
29+
it("server.json.name matches package.json.mcpName", () => {
30+
expect(srv.name).toBe(pkg.mcpName);
31+
});
32+
33+
it("every server.json packages[].version matches package.json.version", () => {
34+
const versions = (srv.packages ?? []).map((p: { version?: string }) => p.version);
35+
for (const v of versions) {
36+
expect(v).toBe(pkg.version);
37+
}
38+
});
39+
40+
it("the npm package entry identifies @leadbay/mcp", () => {
41+
const npmPkg = (srv.packages ?? []).find(
42+
(p: { registryType?: string }) => p.registryType === "npm"
43+
);
44+
expect(npmPkg?.identifier).toBe(pkg.name);
45+
});
46+
47+
it("every @leadbay/mcp@<major.minor> npx pin tracks the current version line", () => {
48+
// Pins appear in packages[].runtimeArguments AND in env-var description
49+
// prose; scan the raw file so neither can silently lag (the registry would
50+
// otherwise install an older line — exactly the 0.17 staleness this fixes).
51+
const raw = readFileSync(join(MCP_DIR, "server.json"), "utf8");
52+
const [major, minor] = pkg.version.split(".");
53+
const line = `${major}.${minor}`;
54+
const pins = [...raw.matchAll(/@leadbay\/mcp@(\d+\.\d+)/g)].map((m) => m[1]);
55+
expect(pins.length).toBeGreaterThan(0);
56+
for (const p of pins) expect(p).toBe(line);
57+
});
58+
});

0 commit comments

Comments
 (0)