mcp-server-mcpindex 0.3.7 → 0.3.9

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/CHANGELOG.md CHANGED
@@ -4,6 +4,23 @@ All notable changes to `mcp-server-mcpindex` are recorded here.
4
4
 
5
5
  The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.3.9] - 2026-07-15
8
+
9
+ ### Changed
10
+
11
+ - **Tool descriptions now have a single source of truth (`src/tools-meta.json`).** The stdio CLI (`src/index.mjs`) and the hosted remote endpoint both import the shared name/title/description for the 6 tools, so their copy can no longer drift. Description text is byte-identical to 0.3.8; this is an internal refactor with no change to the advertised tool copy. Bumped so the refactored source is releasable to npm.
12
+
13
+ ## [0.3.8] - 2026-07-15
14
+
15
+ ### Fixed
16
+
17
+ - **Empty `MCPINDEX_API_BASE` no longer breaks every API call.** Some MCPB-bundle hosts substitute an empty string for an unset optional `user_config` field, so `MCPINDEX_API_BASE=""` was being used verbatim as the base URL, turning every request into a broken relative URL. The base now falls back to `https://mcpindex.ai` on an empty value (`||` instead of `??`), so those hosts work out of the box. Source change was already on `main` at 0.3.7 but had not reached npm; this release ships it.
18
+
19
+ ### Changed
20
+
21
+ - Swept em-dashes to hyphens in the `check_tool_trust` tool description and the update-check comments (house style).
22
+ - Removed a no-op template expression in the recommendation output (`${r.name}@${r.qualityScore ? '' : ''}` always rendered `${r.name}`).
23
+
7
24
  ## [0.3.5] - 2026-07-12
8
25
 
9
26
  ### Changed
package/README.md CHANGED
@@ -12,6 +12,16 @@ npm install -g mcp-server-mcpindex
12
12
 
13
13
  This is the **directory / advisory** client (recommend, search, trust). It does **not** install the in-path drift gate — that is `curl -fsSL https://mcpindex.ai/install.sh | sh`.
14
14
 
15
+ ### Or connect remotely (no install)
16
+
17
+ Prefer not to install anything? mcpindex is also a **hosted remote MCP server**. Point any client that supports remote MCP (Claude connectors, Cursor, etc.) at:
18
+
19
+ ```
20
+ https://mcpindex.ai/api/mcp
21
+ ```
22
+
23
+ Streamable HTTP, no credentials. Same six tools as the npm package.
24
+
15
25
  ### Claude Code
16
26
 
17
27
  ```bash
@@ -215,6 +225,10 @@ MIT.
215
225
 
216
226
  - Website: [mcpindex.ai](https://mcpindex.ai)
217
227
  - Methodology: [mcpindex.ai/methodology](https://mcpindex.ai/methodology)
228
+ - Screen a server: [mcpindex.ai/screen](https://mcpindex.ai/screen)
229
+ - Guide: [Find the right MCP server by task](https://mcpindex.ai/guides/find-mcp-server-by-task)
218
230
  - Source: [github.com/mcpindex-ai](https://github.com/mcpindex-ai)
219
231
 
232
+ [![mcp-server-mcpindex MCP server](https://glama.ai/mcp/servers/mcpindex-ai/mcp-server-mcpindex/badges/score.svg)](https://glama.ai/mcp/servers/mcpindex-ai/mcp-server-mcpindex)
233
+
220
234
  Unofficial. Not affiliated with Anthropic.
package/manifest.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "manifest_version": "0.2",
3
+ "name": "mcp-server-mcpindex",
4
+ "display_name": "mcpindex",
5
+ "version": "0.3.9",
6
+ "description": "The MCP directory that vets servers, not just lists them: search by task, then get an advisory screen on a server before an agent calls its tools. Advisory, conformance monitored not enforced, not a safety verdict.",
7
+ "long_description": "mcpindex is the MCP directory that vets servers, not just lists them. Search by task to find the right server (ranked picks with install commands and quality scores), then get an advisory screen on a specific tool or a whole server before your agent calls it: whether each tool does what it claims. check_tool_trust and assess_server return an advisory verdict (REVIEW / UNVERIFIED at v1), backed by conformance monitoring and a live drift ledger, and fail closed to human review. Zero-config: queries the public mcpindex.ai API, no credentials. Monitored, not enforced; not a safety verdict and not an in-path gate.",
8
+ "author": {
9
+ "name": "Bhartis LLC",
10
+ "email": "hello@mcpindex.ai",
11
+ "url": "https://mcpindex.ai"
12
+ },
13
+ "homepage": "https://mcpindex.ai",
14
+ "documentation": "https://mcpindex.ai/methodology",
15
+ "support": "https://github.com/mcpindex-ai/mcpindex-web/issues",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/mcpindex-ai/mcpindex-web"
19
+ },
20
+ "license": "MIT",
21
+ "keywords": [
22
+ "mcp",
23
+ "model-context-protocol",
24
+ "discovery",
25
+ "trust",
26
+ "tool-safety",
27
+ "registry"
28
+ ],
29
+ "server": {
30
+ "type": "node",
31
+ "entry_point": "src/index.mjs",
32
+ "mcp_config": {
33
+ "command": "node",
34
+ "args": ["${__dirname}/src/index.mjs"],
35
+ "env": {
36
+ "MCPINDEX_API_BASE": "${user_config.api_base}"
37
+ }
38
+ }
39
+ },
40
+ "tools_generated": true,
41
+ "user_config": {
42
+ "api_base": {
43
+ "type": "string",
44
+ "title": "API base URL",
45
+ "description": "Override the mcpindex API base if you self-host. Leave as the default otherwise.",
46
+ "default": "https://mcpindex.ai",
47
+ "required": false
48
+ }
49
+ },
50
+ "compatibility": {
51
+ "runtimes": {
52
+ "node": ">=18.0.0"
53
+ }
54
+ }
55
+ }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "mcp-server-mcpindex",
3
- "version": "0.3.7",
3
+ "version": "0.3.9",
4
4
  "mcpName": "io.github.gautamgb/mcp-server-mcpindex",
5
- "description": "An MCP server for finding MCP servers, plus advisory screen verdicts (check_tool_trust, assess_server). Directory client - not the in-path gate (mcpindex-gate). Drop-in for Claude Desktop, Claude Code, Cursor, Gemini CLI, Cline, Zed.",
5
+ "description": "The MCP directory that vets servers, not just lists them. Search by task, then get an advisory screen on a server before your agent calls its tools: whether each tool does what it claims, backed by conformance monitoring and a public drift ledger. Advisory (REVIEW / UNVERIFIED), monitored not enforced, not a safety verdict. Drop-in for Claude Desktop, Claude Code, Cursor, Gemini CLI, Cline, Zed.",
6
6
  "keywords": [
7
7
  "mcp",
8
8
  "model-context-protocol",
@@ -38,12 +38,15 @@
38
38
  "src/",
39
39
  "README.md",
40
40
  "CHANGELOG.md",
41
- "LICENSE"
41
+ "LICENSE",
42
+ "manifest.json"
42
43
  ],
43
44
  "scripts": {
44
45
  "build": "node --check src/index.mjs && node --check src/trust.mjs && node --check src/update-check.mjs",
45
46
  "test": "node --test test/*.test.mjs",
46
47
  "check-published": "node scripts/check-published.mjs",
48
+ "sync-glama": "node scripts/sync-glama-repo.mjs",
49
+ "bundle": "node scripts/bundle-mcpb.mjs",
47
50
  "release": "node scripts/release.mjs"
48
51
  },
49
52
  "dependencies": {
package/src/index.mjs CHANGED
@@ -12,15 +12,22 @@ import { createRequire } from 'node:module';
12
12
  export { checkToolTrust, assessServer, VERDICT_CONTRACT_VERSION, V1_HONEST_LIMITS } from './trust.mjs';
13
13
  import { notifyUpdateIfAvailable } from './update-check.mjs';
14
14
 
15
- const API_BASE = process.env.MCPINDEX_API_BASE ?? 'https://mcpindex.ai';
16
- // Single source of truth for the running version read from package.json so the
15
+ // `||` (not `??`) so an empty MCPINDEX_API_BASE - which some MCPB hosts substitute
16
+ // for an unset optional user_config field - falls back to the default instead of
17
+ // becoming "" and breaking every fetch with a relative URL.
18
+ const API_BASE = process.env.MCPINDEX_API_BASE || 'https://mcpindex.ai';
19
+ // Single source of truth for the running version - read from package.json so the
17
20
  // User-Agent and the update-check can never drift from what npm actually shipped.
18
21
  const PKG_VERSION = createRequire(import.meta.url)('../package.json').version;
22
+ // Single source of truth for tool name/description, shared with the hosted
23
+ // remote endpoint (mcpindex-web/app/api/[transport]/route.ts) so copy can't drift.
24
+ const TOOL_META = createRequire(import.meta.url)('./tools-meta.json');
25
+ const TOOL_DESC = Object.fromEntries(TOOL_META.map((m) => [m.name, m.description]));
19
26
 
20
27
  const server = new Server(
21
28
  { name: 'mcp-server-mcpindex', version: PKG_VERSION },
22
29
  // Tools only. We do NOT advertise `logging`: the update notice goes to stderr (which
23
- // every host surfaces), not via `notifications/message` (rendered inconsistently Cursor
30
+ // every host surfaces), not via `notifications/message` (rendered inconsistently - Cursor
24
31
  // logs it as a bare ` undefined`). stderr is the universal, clean channel.
25
32
  { capabilities: { tools: {} } },
26
33
  );
@@ -29,7 +36,7 @@ const TOOLS = [
29
36
  {
30
37
  name: 'recommend_mcp_for_task',
31
38
  description:
32
- 'Recommend the best MCP servers for a natural-language task. Returns top 3 ranked picks with reasoning, install commands, and quality scores. Use this when the user asks for the right MCP server for a task they want to do.',
39
+ TOOL_DESC.recommend_mcp_for_task,
33
40
  inputSchema: {
34
41
  type: 'object',
35
42
  properties: {
@@ -45,7 +52,7 @@ const TOOLS = [
45
52
  {
46
53
  name: 'search_mcp_servers',
47
54
  description:
48
- 'Keyword + semantic search across the full MCP server registry. Use when the user knows what tool category they want but not which server.',
55
+ TOOL_DESC.search_mcp_servers,
49
56
  inputSchema: {
50
57
  type: 'object',
51
58
  properties: {
@@ -67,7 +74,7 @@ const TOOLS = [
67
74
  {
68
75
  name: 'get_install_command',
69
76
  description:
70
- 'Get the exact install command for a given MCP server and client. Returns a JSON block ready to paste into the client config.',
77
+ TOOL_DESC.get_install_command,
71
78
  inputSchema: {
72
79
  type: 'object',
73
80
  properties: {
@@ -88,7 +95,7 @@ const TOOLS = [
88
95
  {
89
96
  name: 'compare_servers',
90
97
  description:
91
- 'Side-by-side comparison of 2-5 MCP servers - quality scores, install paths, transport types, env vars.',
98
+ TOOL_DESC.compare_servers,
92
99
  inputSchema: {
93
100
  type: 'object',
94
101
  properties: {
@@ -106,7 +113,7 @@ const TOOLS = [
106
113
  {
107
114
  name: 'check_tool_trust',
108
115
  description:
109
- 'Pre-invocation advisory screen for a specific tool on an MCP server. Returns an advisory verdict object (directive ALLOW | DENY | REVIEW | UNVERIFIED, dimensions, freshness). At v1 the public screen produces REVIEW or UNVERIFIED only — ALLOW/DENY are reserved. Not the in-path gate (mcpindex-gate). Agents SHOULD treat UNVERIFIED as "human review required", never as ALLOW.',
116
+ TOOL_DESC.check_tool_trust,
110
117
  inputSchema: {
111
118
  type: 'object',
112
119
  properties: {
@@ -125,7 +132,7 @@ const TOOLS = [
125
132
  {
126
133
  name: 'assess_server',
127
134
  description:
128
- 'Aggregated pre-flight trust assessment across all tools on an MCP server. Same verdict shape as check_tool_trust. Use for "is THIS server worth integrating?" decisions. v1 advisory; conformance monitored not enforced; verdicts may be UNVERIFIED if not yet probed.',
135
+ TOOL_DESC.assess_server,
129
136
  inputSchema: {
130
137
  type: 'object',
131
138
  properties: {
@@ -227,7 +234,7 @@ function formatRecommend(data) {
227
234
  const lines = [`Top ${data.recommendations.length} for: "${data.task}"`, ''];
228
235
  for (const r of data.recommendations) {
229
236
  lines.push(`[${r.rank}] ${r.title} · QS ${r.qualityScore}/100 · ${r.category}`);
230
- lines.push(` ${r.name}@${r.qualityScore ? '' : ''}`);
237
+ lines.push(` ${r.name}`);
231
238
  lines.push(` ${r.reasoning}`);
232
239
  const install = r.installs.npm
233
240
  ? `npx -y ${r.installs.npm}`
@@ -292,7 +299,7 @@ const transport = new StdioServerTransport();
292
299
  await server.connect(transport);
293
300
  console.error('[mcp-server-mcpindex] connected via stdio');
294
301
 
295
- // Fire-and-forget: tell the user if a newer version exists (stderr only the channel
302
+ // Fire-and-forget: tell the user if a newer version exists (stderr only - the channel
296
303
  // every host renders cleanly). Dropped onto the event loop AFTER connect so it can never
297
304
  // delay or crash startup; all errors are swallowed inside.
298
305
  notifyUpdateIfAvailable({ currentVersion: PKG_VERSION }).catch(() => {});
@@ -0,0 +1,32 @@
1
+ [
2
+ {
3
+ "name": "recommend_mcp_for_task",
4
+ "title": "Recommend MCP servers for a task",
5
+ "description": "Recommend the best MCP servers for a natural-language task. Returns top 3 ranked picks with reasoning, install commands, and quality scores. Use this when the user asks for the right MCP server for a task they want to do."
6
+ },
7
+ {
8
+ "name": "search_mcp_servers",
9
+ "title": "Search MCP servers",
10
+ "description": "Keyword + semantic search across the full MCP server registry. Use when the user knows what tool category they want but not which server."
11
+ },
12
+ {
13
+ "name": "get_install_command",
14
+ "title": "Get install command",
15
+ "description": "Get the exact install command for a given MCP server and client. Returns a JSON block ready to paste into the client config."
16
+ },
17
+ {
18
+ "name": "compare_servers",
19
+ "title": "Compare MCP servers",
20
+ "description": "Side-by-side comparison of 2-5 MCP servers - quality scores, install paths, transport types, env vars."
21
+ },
22
+ {
23
+ "name": "check_tool_trust",
24
+ "title": "Check tool trust (advisory)",
25
+ "description": "Pre-invocation advisory screen for a specific tool on an MCP server. Returns an advisory verdict object (directive ALLOW | DENY | REVIEW | UNVERIFIED, dimensions, freshness). At v1 the public screen produces REVIEW or UNVERIFIED only - ALLOW/DENY are reserved. Not the in-path gate (mcpindex-gate). Agents SHOULD treat UNVERIFIED as \"human review required\", never as ALLOW."
26
+ },
27
+ {
28
+ "name": "assess_server",
29
+ "title": "Assess server trust (advisory)",
30
+ "description": "Aggregated pre-flight trust assessment across all tools on an MCP server. Same verdict shape as check_tool_trust. Use for \"is THIS server worth integrating?\" decisions. v1 advisory; conformance monitored not enforced; verdicts may be UNVERIFIED if not yet probed."
31
+ }
32
+ ]
@@ -1,12 +1,12 @@
1
- // update-check.mjs best-effort "a newer mcp-server-mcpindex exists" notice.
1
+ // update-check.mjs - best-effort "a newer mcp-server-mcpindex exists" notice.
2
2
  //
3
3
  // Why this is safe to ship in a server that already egresses:
4
4
  // - outbound to the PINNED npm registry host only, https, no redirect-following
5
5
  // (no SSRF pivot), time-boxed, and fail-silent on ANY error;
6
- // - fire-and-forget it never blocks or crashes startup (the caller drops it
6
+ // - fire-and-forget - it never blocks or crashes startup (the caller drops it
7
7
  // onto the event loop after connect and ignores rejections);
8
8
  // - no telemetry beyond the standard registry GET (no version of the user, no
9
- // machine id just "what's the latest published version of this package");
9
+ // machine id - just "what's the latest published version of this package");
10
10
  // - opt-out via MCPINDEX_NO_UPDATE_CHECK.
11
11
  //
12
12
  // Pure + injectable (fetchImpl) so it is unit-testable with no network.
@@ -88,11 +88,11 @@ export async function fetchLatestVersion({
88
88
  }
89
89
 
90
90
  /** Orchestration: check, and if a newer version exists, emit the notice to STDERR only.
91
- * stderr is the UNIVERSAL channel every MCP host (Cursor, Claude Desktop/Code, Gemini
91
+ * stderr is the UNIVERSAL channel - every MCP host (Cursor, Claude Desktop/Code, Gemini
92
92
  * CLI, …) surfaces a spawned server's stderr in its per-server log. We deliberately do NOT
93
93
  * emit an MCP `notifications/message`: hosts render it inconsistently (Cursor logs it as a
94
94
  * bare ` undefined`, swallowing the text), so it only adds noise where stderr already
95
- * carries the message cleanly. Returns the message it emitted (or null) handy for
95
+ * carries the message cleanly. Returns the message it emitted (or null) - handy for
96
96
  * tests/callers. Never throws; never blocks the caller (caller fire-and-forgets). */
97
97
  export async function notifyUpdateIfAvailable({
98
98
  currentVersion,
@@ -106,7 +106,7 @@ export async function notifyUpdateIfAvailable({
106
106
  const latest = await fetchLatestVersion({ pkg, fetchImpl });
107
107
  if (!latest || !isOlder(currentVersion, latest)) return null;
108
108
  const msg = formatUpdateMessage(currentVersion, latest);
109
- log(msg); // stderr the one channel every host renders cleanly
109
+ log(msg); // stderr - the one channel every host renders cleanly
110
110
  return msg;
111
111
  } catch {
112
112
  return null; // belt-and-suspenders: this path must never surface an error