youmightnotneed-mcp 0.1.1
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/LICENSE +21 -0
- package/README.md +36 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +42 -0
- package/dist/bin.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +82 -0
- package/dist/server.js.map +1 -0
- package/dist/tools.d.ts +45 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +40 -0
- package/dist/tools.js.map +1 -0
- package/package.json +51 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Johannes Maendle
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# youmightnotneed-mcp
|
|
2
|
+
|
|
3
|
+
An MCP server that gives an agent direct access to the youmightnotneed rule
|
|
4
|
+
catalog: whether a dependency already has a native replacement, and what
|
|
5
|
+
that replacement looks like.
|
|
6
|
+
|
|
7
|
+
Add it to an MCP client's config:
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"mcpServers": {
|
|
12
|
+
"youmightnotneed": {
|
|
13
|
+
"command": "npx",
|
|
14
|
+
"args": ["youmightnotneed-mcp"]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Tools
|
|
21
|
+
|
|
22
|
+
- `analyze_dependencies`: matches a package.json's `dependencies`,
|
|
23
|
+
`devDependencies` and `peerDependencies` against the catalog. Returns
|
|
24
|
+
findings, a summary, and provenance for when the underlying data was
|
|
25
|
+
captured.
|
|
26
|
+
- `list_rules`: every rule's id, title, the npm packages it replaces, and
|
|
27
|
+
the native approach, in one line each.
|
|
28
|
+
- `get_rule`: full detail on one rule, looked up by id or by an npm
|
|
29
|
+
package name it replaces. Returns `{ found: false }` rather than an
|
|
30
|
+
error when nothing matches.
|
|
31
|
+
|
|
32
|
+
Data is a static snapshot, the same one `npx youmightnotneed` and
|
|
33
|
+
youmightnotneed.dev use. No network calls happen at tool-call time.
|
|
34
|
+
|
|
35
|
+
Powered by [`@jomae/catalog`](https://www.npmjs.com/package/@jomae/catalog).
|
|
36
|
+
MIT.
|
package/dist/bin.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":""}
|
package/dist/bin.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* npx youmightnotneed-mcp
|
|
4
|
+
*
|
|
5
|
+
* Starts the MCP server over stdio. All process-level I/O (the stdio
|
|
6
|
+
* transport) lives here; server.ts additionally reads this package's own
|
|
7
|
+
* version from package.json. Tool logic in tools.ts stays pure and
|
|
8
|
+
* server.ts's tool registration stays a thin adapter.
|
|
9
|
+
*/
|
|
10
|
+
import { realpathSync } from "node:fs";
|
|
11
|
+
import { pathToFileURL } from "node:url";
|
|
12
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
13
|
+
import { createServer } from "./server.js";
|
|
14
|
+
async function main() {
|
|
15
|
+
const server = createServer();
|
|
16
|
+
const transport = new StdioServerTransport();
|
|
17
|
+
await server.connect(transport);
|
|
18
|
+
}
|
|
19
|
+
// Only run as a side effect when this file is the process entry point, not
|
|
20
|
+
// when a test imports createServer() from server.ts directly. npm/npx
|
|
21
|
+
// invoke a package's bin through a node_modules/.bin symlink, and
|
|
22
|
+
// import.meta.url reports that symlink dereferenced while argv[1] does not.
|
|
23
|
+
// packages/cli/src/bin.ts had this same bug this session, fixed here from
|
|
24
|
+
// the start with the same realpathSync() + pathToFileURL() approach.
|
|
25
|
+
function isEntryPoint() {
|
|
26
|
+
const argv1 = process.argv[1];
|
|
27
|
+
if (argv1 === undefined)
|
|
28
|
+
return false;
|
|
29
|
+
try {
|
|
30
|
+
return import.meta.url === pathToFileURL(realpathSync(argv1)).href;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (isEntryPoint()) {
|
|
37
|
+
main().catch((error) => {
|
|
38
|
+
console.error(error);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=bin.js.map
|
package/dist/bin.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,2EAA2E;AAC3E,sEAAsE;AACtE,kEAAkE;AAClE,4EAA4E;AAC5E,0EAA0E;AAC1E,qEAAqE;AACrE,SAAS,YAAY;IACnB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACtC,IAAI,CAAC;QACH,OAAO,OAAO,IAAI,CAAC,GAAG,KAAK,aAAa,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,IAAI,YAAY,EAAE,EAAE,CAAC;IACnB,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QAC9B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA4BpE,wBAAgB,YAAY,IAAI,SAAS,CA+ExC"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { analyzeDependencies, getRule, listRules, } from "./tools.js";
|
|
5
|
+
/** Wraps a getRule() result in the { content, structuredContent } shape every tool handler returns. */
|
|
6
|
+
function toolResponse(result) {
|
|
7
|
+
return {
|
|
8
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
9
|
+
structuredContent: result,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function readOwnVersion() {
|
|
13
|
+
try {
|
|
14
|
+
const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
15
|
+
return pkg.version ?? "0.0.0";
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return "0.0.0";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function createServer() {
|
|
22
|
+
const server = new McpServer({
|
|
23
|
+
name: "youmightnotneed-mcp",
|
|
24
|
+
version: readOwnVersion(),
|
|
25
|
+
});
|
|
26
|
+
server.registerTool("analyze_dependencies", {
|
|
27
|
+
title: "Analyze dependencies",
|
|
28
|
+
description: "Matches a package.json's dependencies against the youmightnotneed catalog. Returns findings (a matched rule per dependency with a native replacement), a summary, and provenance for when the underlying data was captured. Every finding is conditional: read the rule's agent.unless conditions before suggesting a removal.",
|
|
29
|
+
inputSchema: {
|
|
30
|
+
dependencies: z.record(z.string(), z.string()).optional(),
|
|
31
|
+
devDependencies: z.record(z.string(), z.string()).optional(),
|
|
32
|
+
peerDependencies: z.record(z.string(), z.string()).optional(),
|
|
33
|
+
},
|
|
34
|
+
}, (input) => {
|
|
35
|
+
const result = analyzeDependencies(input);
|
|
36
|
+
return {
|
|
37
|
+
content: [
|
|
38
|
+
{ type: "text", text: JSON.stringify(result, null, 2) },
|
|
39
|
+
],
|
|
40
|
+
structuredContent: result,
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
server.registerTool("list_rules", {
|
|
44
|
+
title: "List rules",
|
|
45
|
+
description: "Lists every rule in the youmightnotneed catalog: id, title, the npm packages it replaces, and the native approach in one line. Use get_rule for full detail on one rule.",
|
|
46
|
+
inputSchema: {},
|
|
47
|
+
}, () => {
|
|
48
|
+
const result = listRules();
|
|
49
|
+
return {
|
|
50
|
+
content: [
|
|
51
|
+
{ type: "text", text: JSON.stringify(result, null, 2) },
|
|
52
|
+
],
|
|
53
|
+
structuredContent: result,
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
server.registerTool("get_rule", {
|
|
57
|
+
title: "Get rule",
|
|
58
|
+
description: "Looks up one catalog rule by its id or by an npm package name it replaces. Returns the full explainer, code snippet, agent.unless conditions, and resolved Baseline support status. Returns { found: false } rather than an error when nothing matches. If both id and package are given, id wins.",
|
|
59
|
+
inputSchema: {
|
|
60
|
+
id: z.string().optional(),
|
|
61
|
+
package: z.string().optional(),
|
|
62
|
+
},
|
|
63
|
+
}, (input) => {
|
|
64
|
+
if (input.id !== undefined) {
|
|
65
|
+
return toolResponse(getRule({ id: input.id }));
|
|
66
|
+
}
|
|
67
|
+
if (input.package !== undefined) {
|
|
68
|
+
return toolResponse(getRule({ package: input.package }));
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
content: [
|
|
72
|
+
{
|
|
73
|
+
type: "text",
|
|
74
|
+
text: "Provide either id or package.",
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
isError: true,
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
return server;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,mBAAmB,EAEnB,OAAO,EACP,SAAS,GACV,MAAM,YAAY,CAAC;AAEpB,uGAAuG;AACvG,SAAS,YAAY,CAAC,MAAqB;IACzC,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QAC3E,iBAAiB,EAAE,MAA4C;KAChE,CAAC;AACJ,CAAC;AAED,SAAS,cAAc;IACrB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CACpB,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAC1C,CAAC;QAC1B,OAAO,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,qBAAqB;QAC3B,OAAO,EAAE,cAAc,EAAE;KAC1B,CAAC,CAAC;IAEH,MAAM,CAAC,YAAY,CACjB,sBAAsB,EACtB;QACE,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EACT,gUAAgU;QAClU,WAAW,EAAE;YACX,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;YACzD,eAAe,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;YAC5D,gBAAgB,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;SAC9D;KACF,EACD,CAAC,KAAsB,EAAE,EAAE;QACzB,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;QAC1C,OAAO;YACL,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;aACjE;YACD,iBAAiB,EAAE,MAA4C;SAChE,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,YAAY,EACZ;QACE,KAAK,EAAE,YAAY;QACnB,WAAW,EACT,0KAA0K;QAC5K,WAAW,EAAE,EAAE;KAChB,EACD,GAAG,EAAE;QACH,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAC3B,OAAO;YACL,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;aACjE;YACD,iBAAiB,EAAE,MAA4C;SAChE,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,UAAU,EACV;QACE,KAAK,EAAE,UAAU;QACjB,WAAW,EACT,oSAAoS;QACtS,WAAW,EAAE;YACX,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YACzB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;SAC/B;KACF,EACD,CAAC,KAAwC,EAAE,EAAE;QAC3C,IAAI,KAAK,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;YAC3B,OAAO,YAAY,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACjD,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAChC,OAAO,YAAY,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC3D,CAAC;QACD,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,+BAA+B;iBACtC;aACF;YACD,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/tools.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type BaselineInfo, type PackageJsonLike, type Report, type Rule } from "@jomae/catalog";
|
|
2
|
+
interface Provenance {
|
|
3
|
+
baselineOn: string;
|
|
4
|
+
webFeaturesVersion: string;
|
|
5
|
+
sizesOn: string;
|
|
6
|
+
}
|
|
7
|
+
export interface AnalyzeDependenciesResult extends Report {
|
|
8
|
+
provenance: Provenance;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Matches a package.json's dependency fields against the catalog. Pure:
|
|
12
|
+
* calls straight into @jomae/catalog's analyze(), no filesystem or network.
|
|
13
|
+
*/
|
|
14
|
+
export declare function analyzeDependencies(input: PackageJsonLike): AnalyzeDependenciesResult;
|
|
15
|
+
export interface RuleSummary {
|
|
16
|
+
id: string;
|
|
17
|
+
title: string;
|
|
18
|
+
replaces: string[];
|
|
19
|
+
native: string;
|
|
20
|
+
}
|
|
21
|
+
/** Every rule, four fields each. Pure. Use getRule() for full detail. */
|
|
22
|
+
export declare function listRules(): {
|
|
23
|
+
rules: RuleSummary[];
|
|
24
|
+
};
|
|
25
|
+
export type GetRuleInput = {
|
|
26
|
+
id: string;
|
|
27
|
+
} | {
|
|
28
|
+
package: string;
|
|
29
|
+
};
|
|
30
|
+
export type GetRuleResult = {
|
|
31
|
+
found: true;
|
|
32
|
+
rule: Rule;
|
|
33
|
+
baseline: BaselineInfo;
|
|
34
|
+
} | {
|
|
35
|
+
found: false;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Looks up one rule by its id or by an npm package name it replaces. Pure.
|
|
39
|
+
* Returns { found: false } rather than throwing, matching
|
|
40
|
+
* resolveFeature()'s no-throw-on-unknown-input behavior elsewhere in the
|
|
41
|
+
* catalog.
|
|
42
|
+
*/
|
|
43
|
+
export declare function getRule(input: GetRuleInput): GetRuleResult;
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,eAAe,EAEpB,KAAK,MAAM,EACX,KAAK,IAAI,EAMV,MAAM,gBAAgB,CAAC;AAExB,UAAU,UAAU;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,yBAA0B,SAAQ,MAAM;IACvD,UAAU,EAAE,UAAU,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,eAAe,GACrB,yBAAyB,CAU3B;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,yEAAyE;AACzE,wBAAgB,SAAS,IAAI;IAAE,KAAK,EAAE,WAAW,EAAE,CAAA;CAAE,CASpD;AAED,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhE,MAAM,MAAM,aAAa,GACrB;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAA;CAAE,GACnD;IAAE,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC;AAErB;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,aAAa,CAM1D"}
|
package/dist/tools.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { analyze, BASELINE_DATA_DATE, packageSizes, resolveBaseline, rules, rulesById, rulesByPackage, WEB_FEATURES_VERSION, } from "@jomae/catalog";
|
|
2
|
+
/**
|
|
3
|
+
* Matches a package.json's dependency fields against the catalog. Pure:
|
|
4
|
+
* calls straight into @jomae/catalog's analyze(), no filesystem or network.
|
|
5
|
+
*/
|
|
6
|
+
export function analyzeDependencies(input) {
|
|
7
|
+
const report = analyze(input);
|
|
8
|
+
return {
|
|
9
|
+
...report,
|
|
10
|
+
provenance: {
|
|
11
|
+
baselineOn: BASELINE_DATA_DATE,
|
|
12
|
+
webFeaturesVersion: WEB_FEATURES_VERSION,
|
|
13
|
+
sizesOn: packageSizes.fetchedOn,
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** Every rule, four fields each. Pure. Use getRule() for full detail. */
|
|
18
|
+
export function listRules() {
|
|
19
|
+
return {
|
|
20
|
+
rules: rules.map((rule) => ({
|
|
21
|
+
id: rule.id,
|
|
22
|
+
title: rule.title,
|
|
23
|
+
replaces: rule.replaces,
|
|
24
|
+
native: rule.native,
|
|
25
|
+
})),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Looks up one rule by its id or by an npm package name it replaces. Pure.
|
|
30
|
+
* Returns { found: false } rather than throwing, matching
|
|
31
|
+
* resolveFeature()'s no-throw-on-unknown-input behavior elsewhere in the
|
|
32
|
+
* catalog.
|
|
33
|
+
*/
|
|
34
|
+
export function getRule(input) {
|
|
35
|
+
const rule = "id" in input ? rulesById.get(input.id) : rulesByPackage.get(input.package);
|
|
36
|
+
if (!rule)
|
|
37
|
+
return { found: false };
|
|
38
|
+
return { found: true, rule, baseline: resolveBaseline(rule) };
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,kBAAkB,EAGlB,YAAY,EAGZ,eAAe,EACf,KAAK,EACL,SAAS,EACT,cAAc,EACd,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAYxB;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAAsB;IAEtB,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9B,OAAO;QACL,GAAG,MAAM;QACT,UAAU,EAAE;YACV,UAAU,EAAE,kBAAkB;YAC9B,kBAAkB,EAAE,oBAAoB;YACxC,OAAO,EAAE,YAAY,CAAC,SAAS;SAChC;KACF,CAAC;AACJ,CAAC;AASD,yEAAyE;AACzE,MAAM,UAAU,SAAS;IACvB,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC1B,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC;AAQD;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,KAAmB;IACzC,MAAM,IAAI,GACR,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAE9E,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IACnC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;AAChE,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "youmightnotneed-mcp",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "MCP server exposing the youmightnotneed rule catalog to AI agents.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Johannes Maendle",
|
|
8
|
+
"homepage": "https://youmightnotneed-web.vercel.app",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/jomaendle/youmightnotneed.git",
|
|
12
|
+
"directory": "packages/mcp"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"mcp",
|
|
16
|
+
"model-context-protocol",
|
|
17
|
+
"css",
|
|
18
|
+
"baseline",
|
|
19
|
+
"agent"
|
|
20
|
+
],
|
|
21
|
+
"bin": {
|
|
22
|
+
"youmightnotneed-mcp": "./dist/bin.js"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"README.md"
|
|
27
|
+
],
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
33
|
+
"zod": "^4.5.4",
|
|
34
|
+
"@jomae/catalog": "0.3.0"
|
|
35
|
+
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=22.18.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"vitest": "^4.1.11",
|
|
41
|
+
"@types/node": "^24.13.3",
|
|
42
|
+
"@vitest/coverage-v8": "^4.1.11"
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "tsc -p tsconfig.build.json",
|
|
46
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
47
|
+
"start": "node src/bin.ts",
|
|
48
|
+
"test": "vitest run",
|
|
49
|
+
"test:coverage": "vitest run --coverage"
|
|
50
|
+
}
|
|
51
|
+
}
|