nicepick-mcp 1.0.0
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/index.mjs +119 -0
- package/package.json +27 -0
package/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# NicePick MCP — the verdict layer for AI agents
|
|
2
|
+
|
|
3
|
+
Your docs tool (Context7) tells an agent how to use the library it *already chose*.
|
|
4
|
+
**NicePick tells it which one to choose.**
|
|
5
|
+
|
|
6
|
+
900+ structured, opinionated tool/library/framework comparisons. No hedging — every
|
|
7
|
+
query returns a winner and a decisive reason. Backed by [nicepick.dev](https://nicepick.dev).
|
|
8
|
+
|
|
9
|
+
## Tools
|
|
10
|
+
|
|
11
|
+
- **`compare_tools(tool_a, tool_b)`** — head-to-head verdict. `postgresql` vs `mysql`,
|
|
12
|
+
`react` vs `svelte`, `vite` vs `webpack`. Returns the pick, why, and when to use each.
|
|
13
|
+
- **`recommend_tool(query)`** — best pick for a use-case. `"best vector database"`,
|
|
14
|
+
`"best python web framework"`.
|
|
15
|
+
|
|
16
|
+
## Install (Claude Desktop / Cursor / any MCP client)
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"mcpServers": {
|
|
21
|
+
"nicepick": {
|
|
22
|
+
"command": "npx",
|
|
23
|
+
"args": ["-y", "nicepick-mcp"]
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Or run directly: `node index.mjs` (talks MCP over stdio).
|
|
30
|
+
|
|
31
|
+
## Why
|
|
32
|
+
|
|
33
|
+
LLMs hallucinate non-existent packages in ~20% of generated code. Picking the *right*
|
|
34
|
+
real tool is a decision they're bad at and there's no current source for — registries
|
|
35
|
+
rank by popularity, docs assume you've chosen, and chat is un-opinionated. NicePick is
|
|
36
|
+
the structured, opinionated verdict — the one shape a model can't reliably produce from
|
|
37
|
+
training data.
|
|
38
|
+
|
|
39
|
+
MIT. No API key required.
|
package/index.mjs
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// NicePick MCP server — the opinionated "which tool should I pick?" decision layer
|
|
3
|
+
// for AI agents. Context7 (57.8k stars) owns docs-for-a-library-you-already-chose;
|
|
4
|
+
// NOBODY owns the verdict ("X vs Y — pick X because…"). NicePick has 900 structured
|
|
5
|
+
// opinionated comparisons + taxonomy — exactly the corpus an LLM can't reliably
|
|
6
|
+
// produce from training data (it hallucinates dead packages ~20% of the time).
|
|
7
|
+
//
|
|
8
|
+
// Tools exposed:
|
|
9
|
+
// compare_tools(a, b) → Nice Pick's verdict on a head-to-head
|
|
10
|
+
// recommend_tool(query) → best pick for a use-case / category
|
|
11
|
+
//
|
|
12
|
+
// Backed by the live public API at nicepick.dev/api/recommend (CORS, no key needed).
|
|
13
|
+
// Distribute via the MCP registry + Smithery/Glama/PulseMCP. Install:
|
|
14
|
+
// npx @nicepick/mcp (once published) or run this file directly with node.
|
|
15
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
16
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
17
|
+
import {
|
|
18
|
+
CallToolRequestSchema,
|
|
19
|
+
ListToolsRequestSchema,
|
|
20
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
21
|
+
|
|
22
|
+
const BASE = process.env.NICEPICK_API || "https://nicepick.dev";
|
|
23
|
+
|
|
24
|
+
async function api(path) {
|
|
25
|
+
const res = await fetch(`${BASE}${path}`, {
|
|
26
|
+
headers: { "user-agent": "nicepick-mcp/1.0" },
|
|
27
|
+
});
|
|
28
|
+
if (!res.ok) throw new Error(`NicePick API ${res.status}`);
|
|
29
|
+
return res.json();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const server = new Server(
|
|
33
|
+
{ name: "nicepick", version: "1.0.0" },
|
|
34
|
+
{ capabilities: { tools: {} } }
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
38
|
+
tools: [
|
|
39
|
+
{
|
|
40
|
+
name: "compare_tools",
|
|
41
|
+
description:
|
|
42
|
+
"Get Nice Pick's opinionated verdict on two tools/libraries/frameworks head-to-head (e.g. 'postgres' vs 'mysql', 'react' vs 'svelte'). Returns the winner, a decisive reason, and when to use each. Use this when an agent or user must choose between two specific options and wants a real verdict, not a hedge.",
|
|
43
|
+
inputSchema: {
|
|
44
|
+
type: "object",
|
|
45
|
+
properties: {
|
|
46
|
+
tool_a: { type: "string", description: "First tool/library/framework (e.g. 'postgresql')" },
|
|
47
|
+
tool_b: { type: "string", description: "Second tool/library/framework (e.g. 'mysql')" },
|
|
48
|
+
},
|
|
49
|
+
required: ["tool_a", "tool_b"],
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "recommend_tool",
|
|
54
|
+
description:
|
|
55
|
+
"Get Nice Pick's recommendation for a use-case or category (e.g. 'best react state management', 'best vector database', 'best python web framework'). Returns the top pick plus ranked alternatives with a decisive rationale.",
|
|
56
|
+
inputSchema: {
|
|
57
|
+
type: "object",
|
|
58
|
+
properties: {
|
|
59
|
+
query: { type: "string", description: "The use-case or 'best X' query" },
|
|
60
|
+
},
|
|
61
|
+
required: ["query"],
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
}));
|
|
66
|
+
|
|
67
|
+
function fmtComparison(d) {
|
|
68
|
+
let out = `## Nice Pick: ${d.pick} wins (${d.title})\n\n`;
|
|
69
|
+
if (d.nice_says) out += `**Verdict:** ${d.nice_says}\n\n`;
|
|
70
|
+
if (d.pick_reason) out += `${d.pick_reason}\n\n`;
|
|
71
|
+
if (d.verdict) {
|
|
72
|
+
if (d.verdict.useTool1If) out += `- Use **${d.tool1?.name || "the first"}** if: ${d.verdict.useTool1If}\n`;
|
|
73
|
+
if (d.verdict.useTool2If) out += `- Use **${d.tool2?.name || "the second"}** if: ${d.verdict.useTool2If}\n`;
|
|
74
|
+
}
|
|
75
|
+
out += `\n— ${BASE}/compare/${d.slug || ""}`;
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function fmtRecommendation(d) {
|
|
80
|
+
let out = `## Nice Pick: ${d.pick}\n\n`;
|
|
81
|
+
if (d.nice_says) out += `${d.nice_says}\n\n`;
|
|
82
|
+
if (Array.isArray(d.tools) && d.tools.length) {
|
|
83
|
+
out += `Ranked:\n`;
|
|
84
|
+
for (const t of d.tools.slice(0, 5)) {
|
|
85
|
+
out += `${t.rank}. **${t.name}**${t.tagline ? ` — ${t.tagline}` : ""}\n`;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return out;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
92
|
+
const { name, arguments: args } = req.params;
|
|
93
|
+
try {
|
|
94
|
+
if (name === "compare_tools") {
|
|
95
|
+
const a = encodeURIComponent(args.tool_a.toLowerCase().trim());
|
|
96
|
+
const b = encodeURIComponent(args.tool_b.toLowerCase().trim());
|
|
97
|
+
const d = await api(`/api/recommend?a=${a}&b=${b}`);
|
|
98
|
+
const text =
|
|
99
|
+
d.type === "comparison"
|
|
100
|
+
? fmtComparison(d)
|
|
101
|
+
: `Nice Pick doesn't have a head-to-head on those two yet. Closest: ${JSON.stringify(d).slice(0, 200)}`;
|
|
102
|
+
return { content: [{ type: "text", text }] };
|
|
103
|
+
}
|
|
104
|
+
if (name === "recommend_tool") {
|
|
105
|
+
const q = encodeURIComponent(args.query.trim());
|
|
106
|
+
const d = await api(`/api/recommend?q=${q}`);
|
|
107
|
+
const text =
|
|
108
|
+
d.type === "comparison" ? fmtComparison(d) : fmtRecommendation(d);
|
|
109
|
+
return { content: [{ type: "text", text }] };
|
|
110
|
+
}
|
|
111
|
+
return { content: [{ type: "text", text: `Unknown tool: ${name}` }], isError: true };
|
|
112
|
+
} catch (e) {
|
|
113
|
+
return { content: [{ type: "text", text: `NicePick error: ${e.message}` }], isError: true };
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
const transport = new StdioServerTransport();
|
|
118
|
+
await server.connect(transport);
|
|
119
|
+
console.error("NicePick MCP server running (stdio)");
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nicepick-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Opinionated 'which tool should I pick?' verdicts for AI agents — the decision layer next to your docs. 900+ structured tool/library/framework comparisons.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"nicepick-mcp": "index.mjs"
|
|
8
|
+
},
|
|
9
|
+
"main": "index.mjs",
|
|
10
|
+
"files": ["index.mjs", "README.md"],
|
|
11
|
+
"keywords": [
|
|
12
|
+
"mcp",
|
|
13
|
+
"model-context-protocol",
|
|
14
|
+
"ai-agents",
|
|
15
|
+
"tool-comparison",
|
|
16
|
+
"tech-stack",
|
|
17
|
+
"developer-tools",
|
|
18
|
+
"claude",
|
|
19
|
+
"cursor"
|
|
20
|
+
],
|
|
21
|
+
"engines": { "node": ">=18" },
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
24
|
+
},
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"homepage": "https://nicepick.dev"
|
|
27
|
+
}
|