nodebench-mcp 3.0.2 → 3.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.
@@ -1,11 +1,9 @@
1
1
  #!/usr/bin/env bash
2
- # NodeBench MCP — One-liner installer
2
+ # NodeBench MCP installer
3
3
  # Usage: curl -sL https://nodebenchai.com/install.sh | bash
4
- # or: bash packages/mcp-local/scripts/install.sh
5
4
 
6
5
  set -euo pipefail
7
6
 
8
- # ── Colors ──────────────────────────────────────────────────────────────
9
7
  if [ -t 1 ]; then
10
8
  B="\033[1m"
11
9
  G="\033[32m"
@@ -17,199 +15,157 @@ else
17
15
  B="" G="" Y="" C="" R="" X=""
18
16
  fi
19
17
 
20
- echo -e "${B}NodeBench MCP Installer${X}"
18
+ echo -e "${B}NodeBench MCP Installer${X}"
21
19
  echo ""
22
20
 
23
- # ── Prerequisites ───────────────────────────────────────────────────────
24
- # Check Node.js
25
- if ! command -v node &>/dev/null; then
26
- echo -e "${R}ERROR${X}: Node.js not found. Install Node.js >= 18: https://nodejs.org"
21
+ if ! command -v node >/dev/null 2>&1; then
22
+ echo -e "${R}ERROR${X}: Node.js not found. Install Node.js >= 18 from https://nodejs.org"
27
23
  exit 1
28
24
  fi
29
25
 
30
- NODE_VERSION=$(node -v | sed 's/v//' | cut -d. -f1)
31
- if [ "$NODE_VERSION" -lt 18 ]; then
32
- echo -e "${R}ERROR${X}: Node.js >= 18 required (found v$(node -v))"
26
+ NODE_MAJOR=$(node -v | sed 's/^v//' | cut -d. -f1)
27
+ if [ "$NODE_MAJOR" -lt 18 ]; then
28
+ echo -e "${R}ERROR${X}: Node.js >= 18 required (found $(node -v))"
33
29
  exit 1
34
30
  fi
35
31
  echo -e " ${G}OK${X} Node.js $(node -v)"
36
32
 
37
- # Check npm
38
- if ! command -v npm &>/dev/null; then
33
+ if ! command -v npm >/dev/null 2>&1; then
39
34
  echo -e "${R}ERROR${X}: npm not found"
40
35
  exit 1
41
36
  fi
42
37
  echo -e " ${G}OK${X} npm $(npm -v)"
43
38
 
44
- # ── Detect user info ────────────────────────────────────────────────────
45
- USER_EMAIL=$(git config user.email 2>/dev/null || echo "")
46
- if [ -n "$USER_EMAIL" ]; then
47
- echo -e " ${G}OK${X} Git email: ${C}${USER_EMAIL}${X}"
48
- fi
39
+ PACKAGE_NAME="nodebench-mcp"
40
+ SERVER_KEY="nodebench"
41
+ PACKAGE_ARGS=(" -y")
49
42
 
50
- # ── Install nodebench-mcp globally ──────────────────────────────────────
51
43
  echo ""
52
- echo -e "${B}Installing nodebench-mcp...${X}"
53
- npm install -g nodebench-mcp@latest 2>/dev/null || {
54
- echo -e "${Y}WARN${X}: Global install failed, will use npx instead"
55
- }
44
+ echo -e "${B}Choose an install lane:${X}"
45
+ echo " 1) core - nodebench-mcp (9 visible tools, workflow-first lane)"
46
+ echo " 2) power - nodebench-mcp-power (founder + recon + packets)"
47
+ echo " 3) admin - nodebench-mcp-admin (profiling + dashboards + eval)"
48
+ echo " 4) founder - nodebench-mcp --preset founder (compatibility preset)"
49
+ echo " 5) full - nodebench-mcp --preset full (warehouse mode)"
50
+ echo ""
51
+ read -r -p "Choose [1-5, default=1]: " CHOICE </dev/tty 2>/dev/null || CHOICE="1"
52
+
53
+ PACKAGE_ARGS=("-y")
54
+ EXTRA_ARGS=()
56
55
 
57
- # ── Determine nodebench-mcp location ────────────────────────────────────
58
- NODEBENCH_PATH=""
59
- if command -v nodebench-mcp &>/dev/null; then
60
- NODEBENCH_PATH=$(which nodebench-mcp)
61
- echo -e " ${G}OK${X} Installed: ${NODEBENCH_PATH}"
56
+ case "${CHOICE:-1}" in
57
+ 2)
58
+ PACKAGE_NAME="nodebench-mcp-power"
59
+ SERVER_KEY="nodebench-power"
60
+ ;;
61
+ 3)
62
+ PACKAGE_NAME="nodebench-mcp-admin"
63
+ SERVER_KEY="nodebench-admin"
64
+ ;;
65
+ 4)
66
+ PACKAGE_NAME="nodebench-mcp"
67
+ SERVER_KEY="nodebench-founder"
68
+ EXTRA_ARGS=("--preset" "founder")
69
+ ;;
70
+ 5)
71
+ PACKAGE_NAME="nodebench-mcp"
72
+ SERVER_KEY="nodebench-full"
73
+ EXTRA_ARGS=("--preset" "full")
74
+ ;;
75
+ *)
76
+ PACKAGE_NAME="nodebench-mcp"
77
+ SERVER_KEY="nodebench"
78
+ ;;
79
+ esac
80
+
81
+ echo ""
82
+ echo -e "${B}Installing ${PACKAGE_NAME}@latest...${X}"
83
+ if npm install -g "${PACKAGE_NAME}@latest" >/dev/null 2>&1; then
84
+ echo -e " ${G}OK${X} Installed globally"
62
85
  else
63
- echo -e " ${G}OK${X} Will use: npx -y nodebench-mcp"
86
+ echo -e " ${Y}WARN${X} Global install failed. The config will still use npx."
64
87
  fi
65
88
 
66
- # ── Find rules directory ────────────────────────────────────────────────
89
+ NPM_ROOT=$(npm root -g 2>/dev/null || echo "")
67
90
  RULES_SOURCE=""
68
- if [ -n "$NODEBENCH_PATH" ]; then
69
- # Global install rules are in the package
70
- PKG_DIR=$(dirname "$(dirname "$NODEBENCH_PATH")")/lib/node_modules/nodebench-mcp
71
- if [ -d "$PKG_DIR/rules" ]; then
72
- RULES_SOURCE="$PKG_DIR/rules"
73
- fi
74
- fi
75
-
76
- # Fallback: try npm root
77
- if [ -z "$RULES_SOURCE" ]; then
78
- NPM_ROOT=$(npm root -g 2>/dev/null || echo "")
79
- if [ -d "$NPM_ROOT/nodebench-mcp/rules" ]; then
91
+ if [ -n "$NPM_ROOT" ]; then
92
+ if [ -d "$NPM_ROOT/$PACKAGE_NAME/rules" ]; then
93
+ RULES_SOURCE="$NPM_ROOT/$PACKAGE_NAME/rules"
94
+ elif [ -d "$NPM_ROOT/$PACKAGE_NAME/node_modules/nodebench-mcp/rules" ]; then
95
+ RULES_SOURCE="$NPM_ROOT/$PACKAGE_NAME/node_modules/nodebench-mcp/rules"
96
+ elif [ -d "$NPM_ROOT/nodebench-mcp/rules" ]; then
80
97
  RULES_SOURCE="$NPM_ROOT/nodebench-mcp/rules"
81
98
  fi
82
99
  fi
83
100
 
84
- # Fallback: npx cache
85
- if [ -z "$RULES_SOURCE" ]; then
86
- # Run npx once to ensure package is cached, then find it
87
- npx -y nodebench-mcp --help >/dev/null 2>&1 || true
88
- NPX_CACHE=$(find "$HOME/.npm/_npx" -name "nodebench-mcp" -type d 2>/dev/null | head -1)
89
- if [ -n "$NPX_CACHE" ] && [ -d "$NPX_CACHE/rules" ]; then
90
- RULES_SOURCE="$NPX_CACHE/rules"
91
- fi
92
- fi
93
-
94
- # ── Install rules to ~/.claude/rules/ ───────────────────────────────────
95
- echo ""
96
101
  CLAUDE_RULES_DIR="$HOME/.claude/rules"
97
102
  mkdir -p "$CLAUDE_RULES_DIR"
98
-
99
- RULES_INSTALLED=0
103
+ echo ""
100
104
  if [ -n "$RULES_SOURCE" ] && [ -d "$RULES_SOURCE" ]; then
101
- echo -e "${B}Installing rules to ${CLAUDE_RULES_DIR}/${X}"
105
+ echo -e "${B}Installing Claude rules...${X}"
106
+ INSTALLED=0
102
107
  for rule in "$RULES_SOURCE"/nodebench-*.md; do
103
108
  [ -f "$rule" ] || continue
104
- BASENAME=$(basename "$rule")
105
- TARGET="$CLAUDE_RULES_DIR/$BASENAME"
106
- # Don't overwrite if user's version is newer
107
- if [ -f "$TARGET" ] && [ "$TARGET" -nt "$rule" ]; then
108
- echo -e " ${Y}SKIP${X} $BASENAME (user version is newer)"
109
- else
110
- cp "$rule" "$TARGET"
111
- echo -e " ${G}OK${X} $BASENAME"
112
- RULES_INSTALLED=$((RULES_INSTALLED + 1))
113
- fi
109
+ cp "$rule" "$CLAUDE_RULES_DIR/$(basename "$rule")"
110
+ INSTALLED=$((INSTALLED + 1))
114
111
  done
115
- echo -e " Installed ${G}${RULES_INSTALLED}${X} rules"
112
+ echo -e " ${G}OK${X} Installed ${INSTALLED} rules into ${CLAUDE_RULES_DIR}"
116
113
  else
117
- echo -e "${Y}WARN${X}: Could not find rules directory. Run ${C}nodebench-mcp --sync-configs${X} after install to copy rules."
118
- fi
119
-
120
- # ── Write .mcp.json ─────────────────────────────────────────────────────
121
- echo ""
122
- MCP_CONFIG=".mcp.json"
123
-
124
- # Collect preset preference
125
- PRESET="default"
126
- echo -e "${B}Select a preset:${X}"
127
- echo " 1) default — 9 visible tools (workflow-first lane)"
128
- echo " 2) power — expanded workflow surface"
129
- echo " 3) founder — compatibility preset"
130
- echo " 4) cursor — constrained preset for Cursor"
131
- echo " 5) full — all loaded domains"
132
- echo ""
133
- read -r -p "Choose [1-5, default=1]: " CHOICE </dev/tty 2>/dev/null || CHOICE="1"
134
- case "${CHOICE:-1}" in
135
- 2) PRESET="power" ;;
136
- 3) PRESET="founder" ;;
137
- 4) PRESET="cursor" ;;
138
- 5) PRESET="full" ;;
139
- *) PRESET="default" ;;
140
- esac
141
-
142
- # Build MCP config
143
- if [ -n "$NODEBENCH_PATH" ]; then
144
- MCP_CMD="nodebench-mcp"
145
- MCP_ARGS="[\"--preset\", \"$PRESET\"]"
146
- else
147
- MCP_CMD="npx"
148
- MCP_ARGS="[\"-y\", \"nodebench-mcp\", \"--preset\", \"$PRESET\"]"
149
- fi
150
-
151
- # Collect env vars
152
- ENV_BLOCK=""
153
- if [ -n "${GEMINI_API_KEY:-}" ]; then
154
- ENV_BLOCK="\"GEMINI_API_KEY\": \"$GEMINI_API_KEY\""
155
- fi
156
- if [ -n "${OPENAI_API_KEY:-}" ]; then
157
- [ -n "$ENV_BLOCK" ] && ENV_BLOCK="$ENV_BLOCK, "
158
- ENV_BLOCK="${ENV_BLOCK}\"OPENAI_API_KEY\": \"$OPENAI_API_KEY\""
159
- fi
160
- if [ -n "${GITHUB_TOKEN:-}" ]; then
161
- [ -n "$ENV_BLOCK" ] && ENV_BLOCK="$ENV_BLOCK, "
162
- ENV_BLOCK="${ENV_BLOCK}\"GITHUB_TOKEN\": \"$GITHUB_TOKEN\""
114
+ echo -e "${Y}WARN${X} Could not find packaged rules. Run sync-configs from the MCP after install if needed."
163
115
  fi
164
116
 
165
117
  ENV_JSON="{}"
166
- if [ -n "$ENV_BLOCK" ]; then
167
- ENV_JSON="{$ENV_BLOCK}"
118
+ ENV_PAIRS=()
119
+ for key in GEMINI_API_KEY OPENAI_API_KEY GITHUB_TOKEN; do
120
+ if [ -n "${!key:-}" ]; then
121
+ ENV_PAIRS+=("\"$key\": \"${!key}\"")
122
+ fi
123
+ done
124
+ if [ "${#ENV_PAIRS[@]}" -gt 0 ]; then
125
+ ENV_JSON="{ $(IFS=', '; echo "${ENV_PAIRS[*]}") }"
168
126
  fi
169
127
 
170
- # Write or merge .mcp.json
171
- if [ -f "$MCP_CONFIG" ]; then
172
- echo -e "${Y}NOTE${X}: $MCP_CONFIG already exists. Adding nodebench entry."
173
- fi
128
+ ARGS_JSON=$(node -e "console.log(JSON.stringify(process.argv.slice(1)))" "${PACKAGE_ARGS[@]}" "$PACKAGE_NAME" "${EXTRA_ARGS[@]}")
174
129
 
175
- cat > "$MCP_CONFIG" <<MCPEOF
130
+ cat > .mcp.json <<MCPEOF
176
131
  {
177
132
  "mcpServers": {
178
- "nodebench": {
179
- "command": "$MCP_CMD",
180
- "args": $MCP_ARGS,
181
- "env": $ENV_JSON
133
+ "${SERVER_KEY}": {
134
+ "command": "npx",
135
+ "args": ${ARGS_JSON},
136
+ "env": ${ENV_JSON}
182
137
  }
183
138
  }
184
139
  }
185
140
  MCPEOF
186
- echo -e " ${G}OK${X} Written: ${C}${MCP_CONFIG}${X} (preset: $PRESET)"
187
-
188
- # ── Add .mcp.json to .gitignore ─────────────────────────────────────────
189
- if [ -f ".gitignore" ]; then
190
- if ! grep -qF ".mcp.json" .gitignore; then
191
- echo "" >> .gitignore
192
- echo "# NodeBench MCP config (contains API keys)" >> .gitignore
193
- echo ".mcp.json" >> .gitignore
194
- echo -e " ${G}OK${X} Added .mcp.json to .gitignore"
195
- fi
141
+
142
+ if [ -f ".gitignore" ] && ! grep -qF ".mcp.json" .gitignore; then
143
+ {
144
+ echo ""
145
+ echo "# NodeBench MCP config"
146
+ echo ".mcp.json"
147
+ } >> .gitignore
196
148
  fi
197
149
 
198
- # ── Run health check ────────────────────────────────────────────────────
199
150
  echo ""
200
151
  echo -e "${B}Running health check...${X}"
201
- npx -y nodebench-mcp --health 2>/dev/null || echo -e "${Y}WARN${X}: Health check skipped (will run on first use)"
152
+ if npx "${PACKAGE_ARGS[@]}" "$PACKAGE_NAME" "${EXTRA_ARGS[@]}" --health >/dev/null 2>&1; then
153
+ echo -e " ${G}OK${X} Health check passed"
154
+ else
155
+ echo -e " ${Y}WARN${X} Health check skipped or failed. Run it manually after install."
156
+ fi
202
157
 
203
- # ── Summary ─────────────────────────────────────────────────────────────
204
158
  echo ""
205
- echo -e "${B}${G}NodeBench MCP installed successfully!${X}"
159
+ echo -e "${B}${G}Installed.${X}"
160
+ echo -e " Package: ${C}${PACKAGE_NAME}${X}"
161
+ if [ "${#EXTRA_ARGS[@]}" -gt 0 ]; then
162
+ echo -e " Args: ${C}${EXTRA_ARGS[*]}${X}"
163
+ fi
164
+ echo -e " Server: ${C}${SERVER_KEY}${X}"
206
165
  echo ""
207
166
  echo -e "${B}Try these first:${X}"
208
- echo -e " ${C}investigate({ topic: 'Anthropic' })${X} — generate a sourced report"
209
- echo -e " ${C}compare({ entities: ['Anthropic', 'OpenAI'] })${X} — compare 2 entities"
210
- echo -e " ${C}discover_tools({ query: 'visual QA for a Vite app' })${X} — find a deeper lane"
211
- echo -e " ${C}load_toolset({ toolset: 'ui_ux_dive' })${X} — expand only when needed"
212
- echo ""
213
- echo -e " Run ${C}nodebench-mcp --health${X} anytime to check system status."
214
- echo -e " Run ${C}nodebench-mcp --sync-configs${X} to write configs to Claude/Cursor/Windsurf."
167
+ echo -e " ${C}investigate({ topic: 'Anthropic' })${X}"
168
+ echo -e " ${C}compare({ entities: ['Anthropic', 'OpenAI'] })${X}"
169
+ echo -e " ${C}discover_tools({ query: 'visual QA for a Vite app' })${X}"
170
+ echo -e " ${C}load_toolset({ toolset: 'ui_ux_dive' })${X}"
215
171
  echo ""
package/server.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.homenshum/nodebench",
4
+ "title": "NodeBench MCP",
5
+ "description": "Turn messy input into a sourced report. NodeBench MCP starts with a 9-tool workflow lane, expands via discover_tools and load_toolset, and keeps heavier power/admin domains off the default hot path.",
6
+ "repository": {
7
+ "url": "https://github.com/HomenShum/nodebench-ai",
8
+ "source": "github",
9
+ "subfolder": "packages/mcp-local"
10
+ },
11
+ "version": "3.1.1",
12
+ "packages": [
13
+ {
14
+ "registryType": "npm",
15
+ "identifier": "nodebench-mcp",
16
+ "version": "3.1.1",
17
+ "transport": {
18
+ "type": "stdio"
19
+ },
20
+ "arguments": ["--preset", "default"],
21
+ "environmentVariables": [
22
+ {
23
+ "description": "Gemini API key for web search and entity enrichment",
24
+ "isRequired": false,
25
+ "format": "string",
26
+ "isSecret": true,
27
+ "name": "GEMINI_API_KEY"
28
+ },
29
+ {
30
+ "description": "OpenAI API key for embeddings and LLM tools",
31
+ "isRequired": false,
32
+ "format": "string",
33
+ "isSecret": true,
34
+ "name": "OPENAI_API_KEY"
35
+ },
36
+ {
37
+ "description": "GitHub token for repository tools",
38
+ "isRequired": false,
39
+ "format": "string",
40
+ "isSecret": true,
41
+ "name": "GITHUB_TOKEN"
42
+ }
43
+ ]
44
+ }
45
+ ]
46
+ }