@index9/mcp 6.5.0 → 6.5.2

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 CHANGED
@@ -2,17 +2,15 @@
2
2
 
3
3
  Discover, shortlist, compare, cost-model, and live-test 300+ AI models from your editor
4
4
 
5
+ > Per-editor install configs (Cursor, VS Code, Claude Code, Codex): https://index9.dev/#install
6
+
5
7
  ## Install
6
8
 
7
9
  ```bash
8
10
  npx -y @index9/mcp@latest
9
11
  ```
10
12
 
11
- ## OpenRouter API key
12
-
13
- Optional: set OPENROUTER_API_KEY in your MCP client config for live test_model calls. dryRun=true works without a key.
14
-
15
- Add the key as `OPENROUTER_API_KEY` in the MCP server environment for your client. Example:
13
+ Generic MCP client config:
16
14
 
17
15
  ```json
18
16
  {
@@ -28,25 +26,28 @@ Add the key as `OPENROUTER_API_KEY` in the MCP server environment for your clien
28
26
  }
29
27
  ```
30
28
 
31
- **Claude Code:** Run `claude mcp add --transport stdio index9 -- npx -y @index9/mcp` or add the same config to .mcp.json / ~/.claude.json.
29
+ Claude Code one-liner: `claude mcp add --transport stdio index9 -- npx -y @index9/mcp`.
30
+
31
+ ## OpenRouter API key
32
+
33
+ Required for live test_model calls. Set OPENROUTER_API_KEY in your MCP client config. dryRun=true works without it.
32
34
 
33
35
  ## Tools
34
36
 
35
- - **find_models** Search and paginate AI models by semantic query or filters
36
- - **get_models** Get full model metadata by IDs or aliases (batch, up to 100)
37
- - **compare_models** Diff 2-10 models across pricing, context, capabilities, and tokenizer
38
- - **list_facets** Enumerate available providers, capabilities, modalities, and tokenizers
39
- - **test_model** Run live inference or dry-run cost estimation across up to 10 models (requires OpenRouter API key)
37
+ - **list_facets**: List available providers, capabilities, modalities, and tokenizers
38
+ - **find_models**: Search AI models by semantic query or filters
39
+ - **get_models**: Fetch full model metadata for up to 100 IDs or aliases
40
+ - **compare_models**: Diff 2-10 models across pricing, context, capabilities, and tokenizer
41
+ - **test_model**: Run live inference or dry-run cost estimates on 1-10 models (requires OpenRouter API key)
40
42
 
41
- ## Response Metadata
43
+ ## Response metadata
42
44
 
43
- All tool responses include an `_index9` object with at least:
45
+ All tool responses include an `_index9` object with:
44
46
 
45
- - `apiBaseUrl` — The API base URL used for the request
47
+ - `apiBaseUrl`: API base URL used for the request
46
48
 
47
49
  Error responses also include:
48
50
 
49
- - `status` Upstream HTTP status code
50
- - `_index9.retryAfterSeconds` Present when `Retry-After` is returned
51
- - `_index9.rateLimit` Present when rate-limit headers are returned (`x-ratelimit-limit`, `x-ratelimit-remaining`, `x-ratelimit-reset`)
52
-
51
+ - `status`: upstream HTTP status code
52
+ - `_index9.retryAfterSeconds`: present when `Retry-After` is returned
53
+ - `_index9.rateLimit`: present when rate-limit headers are returned (`x-ratelimit-limit`, `x-ratelimit-remaining`, `x-ratelimit-reset`)
package/dist/cli.js CHANGED
@@ -121,10 +121,21 @@ Key rules:
121
121
  - Reasoning-capable models (capabilities includes "reasoning") burn hidden reasoning tokens against \`maxTokens\` before emitting visible text. Leave \`maxTokens\` unset, or set it to at least 2000, when testing reasoning models \u2014 otherwise results may fail with finish_reason=length.
122
122
  - Cursors are opaque and tied to query/sort/filters. Reuse the same query/sort/filters when paginating. \`limit\` may change between pages.`;
123
123
  var TOOLS = {
124
+ list_facets: {
125
+ name: "list_facets",
126
+ title: "List filter vocabulary",
127
+ summary: "List available providers, capabilities, modalities, and tokenizers",
128
+ description: `Return the live vocabulary derived from the current model cache: providers (id-prefixes with model counts), capability flags (with counts), input/output modalities, and tokenizers.
129
+
130
+ Use this once at the start of a session to learn what filter values find_models will accept, instead of trial-and-error against find_models.
131
+
132
+ Response: { providers: { id, modelCount }[], capabilities: { id, modelCount }[], modalities: { input: string[], output: string[] }, tokenizers: string[], totalModels: number, updatedAt: string (ISO 8601) }. No inputs.`,
133
+ requiresKey: false
134
+ },
124
135
  find_models: {
125
136
  name: "find_models",
126
137
  title: "Search AI models",
127
- summary: "Search and paginate AI models by semantic query or filters",
138
+ summary: "Search AI models by semantic query or filters",
128
139
  description: `Filter ${MODEL_COUNT} AI models by structured constraints (capabilities, price, context, modality, provider). The semantic \`q\` is a soft tiebreaker on top of filters \u2014 trust filters first; weak \`q\`-only queries surface as \`meta.confidence: "low"\` with a hint to drop \`q\` and use \`sortBy=created\` or \`sortBy=price\` instead.
129
140
 
130
141
  Call this after list_facets (or directly when you already know the filters). Always include one call with sortBy=created (no q) when recommending models to the user \u2014 your training-data list of "good" models is likely stale, and sorting purely by price surfaces old tiny models and misses this month's cheap frontier.
@@ -153,7 +164,7 @@ Pass result.id to get_models for full specs or to test_model for live testing.`,
153
164
  get_models: {
154
165
  name: "get_models",
155
166
  title: "Inspect AI models",
156
- summary: "Get full model metadata by IDs or aliases (batch, up to 100)",
167
+ summary: "Fetch full model metadata for up to 100 IDs or aliases",
157
168
  description: `Get full specs for one or more models by id or alias. Accepts up to ${LIMITS.getModelsMax} ids per call \u2014 use this for batch comparison.
158
169
 
159
170
  Call after find_models to inspect candidates, or directly when the user names a model (format: 'provider/model-name').
@@ -189,21 +200,10 @@ Optional: pass \`expectedPromptTokens\` AND \`expectedCompletionTokens\` to also
189
200
  Accepts the same alias formats as get_models. Unknown ids are returned in missingIds (with \`suggestions[id]\` as newest-first \`{id, name, created}\` entries when partial matches exist, plus \`missingDiagnostics\` carrying a machine-readable reason per id). When fewer than 2 ids resolve, this returns 400 with the diagnostics so you can retry with \`suggestions[id][0].id\` for each missing id.`,
190
201
  requiresKey: false
191
202
  },
192
- list_facets: {
193
- name: "list_facets",
194
- title: "List filter vocabulary",
195
- summary: "Enumerate available providers, capabilities, modalities, and tokenizers",
196
- description: `Return the live vocabulary derived from the current model cache: providers (id-prefixes with model counts), capability flags (with counts), input/output modalities, and tokenizers.
197
-
198
- Use this once at the start of a session to learn what filter values find_models will accept, instead of trial-and-error against find_models.
199
-
200
- Response: { providers: { id, modelCount }[], capabilities: { id, modelCount }[], modalities: { input: string[], output: string[] }, tokenizers: string[], totalModels: number, updatedAt: string (ISO 8601) }. No inputs.`,
201
- requiresKey: false
202
- },
203
203
  test_model: {
204
204
  name: "test_model",
205
205
  title: "Test AI models live",
206
- summary: "Run live inference or dry-run cost estimation across up to 10 models",
206
+ summary: "Run live inference or dry-run cost estimates on 1-10 models",
207
207
  description: `Run model tests on 1-${LIMITS.testModelsMax} models. Use dryRun=true to estimate token usage/cost, or dryRun=false (default) to run live OpenRouter inference.
208
208
 
209
209
  When dryRun=true:
@@ -262,13 +262,13 @@ var SITE = {
262
262
  installCta: "Install"
263
263
  },
264
264
  hero: {
265
- title: "Pick AI models from live data, not your assistant's memory.",
266
- subtitle: "An MCP server with five tools for Claude Code, Cursor, VS Code, and Codex. Search, compare, cost-model, and live-test 300+ models.",
267
- pricingNote: "Free. You only pay OpenRouter for live model calls.",
265
+ title: "Index9 helps coding assistants pick models from live data.",
266
+ subtitle: "MCP tools for Claude Code, Cursor, VS Code, and Codex. Search, compare, cost-model, and live-test 300+ models.",
267
+ pricingNote: "Free to install. Live tests use your OpenRouter key.",
268
268
  seeHowItWorks: "See a real session",
269
269
  updatedBadge: "OpenRouter data \xB7 refreshed ",
270
270
  toolList: [
271
- { name: "list_facets", role: "vocabulary" },
271
+ { name: "list_facets", role: "filter vocabulary" },
272
272
  { name: "find_models", role: "search & filter" },
273
273
  { name: "get_models", role: "full specs" },
274
274
  { name: "compare_models", role: "side-by-side diff" },
@@ -285,6 +285,7 @@ var SITE = {
285
285
  ]
286
286
  },
287
287
  howItWorks: {
288
+ label: "Workflow",
288
289
  heading: "How it works",
289
290
  subtitle: "Index9 adds 5 tools to your editor. Your assistant calls them when you ask about models.",
290
291
  steps: [
@@ -308,7 +309,7 @@ var SITE = {
308
309
  caseStudy: {
309
310
  label: "Real session",
310
311
  heading: "A real session, not a mockup",
311
- subheading: "Claude Sonnet 4.6 driven through the index9 MCP server, picking a model for a TypeScript code-review bot. Real prompt, real tool calls, real verdict.",
312
+ subheading: "Claude Sonnet 4.6 using Index9 to pick a model for a TypeScript code-review bot. Real prompt, tool calls, and verdict.",
312
313
  prompt: {
313
314
  title: "The prompt",
314
315
  body: "Pick a model for a TypeScript code-review bot that runs on every PR. I want real quality without paying frontier rates. Quote model ids verbatim from the tool responses."
@@ -339,44 +340,44 @@ var SITE = {
339
340
  }
340
341
  ]
341
342
  },
342
- consideredTitle: "Candidates the session evaluated",
343
- consideredSubtitle: "Lifted from the tool responses. Per-PR cost is the dry-run test_model output for a 3,000 token diff and an 800 token review.",
343
+ consideredTitle: "Candidates evaluated",
344
+ consideredSubtitle: "5 evaluated, 1 pick",
344
345
  consideredRows: [
345
346
  {
346
347
  id: "anthropic/claude-opus-4.7-fast",
347
348
  age: "5d ago",
348
349
  decision: "skip",
349
- reason: "$30/M input, filtered out by the maxPrice constraint on the second find_models call"
350
+ reason: "$30/M input, above the maxPrice filter"
350
351
  },
351
352
  {
352
353
  id: "mistralai/devstral-medium",
353
354
  age: "10mo ago",
354
355
  decision: "tested",
355
- reason: "$0.40/M input, completion-heavy at $2/M, $0.0028 per PR"
356
+ reason: "$0.40/M input, $2/M output, $0.0028 per PR"
356
357
  },
357
358
  {
358
359
  id: "qwen/qwen3-coder",
359
360
  age: "10mo ago",
360
361
  decision: "tested",
361
- reason: "$0.22/M input, 1M context but no file_input, $0.0021 per PR"
362
+ reason: "$0.22/M input, 1M context, no file_input, $0.0021 per PR"
362
363
  },
363
364
  {
364
365
  id: "google/gemini-3.1-flash-lite",
365
366
  age: "1w ago",
366
367
  decision: "tested",
367
- reason: "$0.25/M input, newest of the shortlist, adds reasoning and vision, $0.00195 per PR"
368
+ reason: "$0.25/M input, newest finalist, reasoning + vision, $0.00195 per PR"
368
369
  },
369
370
  {
370
371
  id: "mistralai/codestral-2508",
371
372
  age: "9mo ago",
372
373
  decision: "shortlisted",
373
- reason: "$0.30/M input, Mistral's coding-specific model, $0.00162 per PR"
374
+ reason: "$0.30/M input, coding-specific, $0.00162 per PR"
374
375
  }
375
376
  ],
376
377
  verdict: {
377
378
  title: "The pick",
378
379
  model: "mistralai/codestral-2508",
379
- body: "Lowest realistic per-PR cost at $0.00162 on a 3,000 token diff and an 800 token review. Mistral's coding-specific model, structured output, file input for diffs, 256K context. About 100\xD7 cheaper on input than running claude-opus-4.7-fast on every commit."
380
+ body: "$0.00162 per PR (3K diff + 800 review, dry-run). Coding-specific, structured output, file input, 256K context. About 100\xD7 cheaper on input than claude-opus-4.7-fast."
380
381
  }
381
382
  },
382
383
  toolsSection: {
@@ -442,7 +443,7 @@ var SITE = {
442
443
  items: [
443
444
  {
444
445
  question: "What is MCP?",
445
- answer: "A protocol that lets AI assistants call external tools. Index9 is one of those tools.",
446
+ answer: "A protocol that lets AI assistants call external tools. Index9 is one.",
446
447
  link: {
447
448
  label: "Learn more about MCP",
448
449
  url: "https://modelcontextprotocol.io"
@@ -450,45 +451,45 @@ var SITE = {
450
451
  },
451
452
  {
452
453
  question: "Who is index9 for?",
453
- answer: "Developers using Claude Code, Cursor, VS Code, or Codex who want their assistant to pick models from current data instead of training-data memory.",
454
+ answer: "Developers in Claude Code, Cursor, VS Code, or Codex who want model picks from live data, not training memory.",
454
455
  link: null
455
456
  },
456
457
  {
457
458
  question: "Does it pick the model for me?",
458
- answer: "No. It gives your assistant the data: search results, specs, cost diffs, live test outputs. Your assistant makes the call.",
459
+ answer: "No. It hands your assistant the data: search, specs, cost diffs, test outputs. The assistant makes the call.",
459
460
  link: null
460
461
  },
461
462
  {
462
463
  question: "How does live testing work?",
463
- answer: `test_model sends your prompt to up to ${LIMITS.testModelsMax} models via OpenRouter and returns output, latency, tokens, and cost. Dry-run mode estimates cost without running inference.`,
464
+ answer: `test_model runs your prompt against up to ${LIMITS.testModelsMax} models via OpenRouter and returns output, latency, tokens, and cost. Set dryRun=true to estimate cost without inference.`,
464
465
  link: null
465
466
  },
466
467
  {
467
468
  question: "Which models?",
468
- answer: `${MODEL_COUNT} from OpenRouter: OpenAI, Anthropic, Google, Meta, Mistral, DeepSeek, and more. Metadata refreshes every 30 minutes.`,
469
+ answer: `${MODEL_COUNT} from OpenRouter: OpenAI, Anthropic, Google, Meta, Mistral, DeepSeek. Metadata refreshes every 30 minutes.`,
469
470
  link: null
470
471
  },
471
472
  {
472
473
  question: "Do you store my prompts or keys?",
473
- answer: "No. Index9 doesn't store prompts, outputs, or API keys. Live tests are proxied straight to OpenRouter.",
474
+ answer: "No. Index9 stores no prompts, outputs, or API keys. Live tests proxy directly to OpenRouter.",
474
475
  link: null
475
476
  },
476
477
  {
477
478
  question: "What's the project status?",
478
- answer: "Stable. Issues and feature requests on GitHub.",
479
+ answer: "Stable. File issues and feature requests on GitHub.",
479
480
  link: null
480
481
  }
481
482
  ]
482
483
  },
483
484
  install: {
484
485
  label: "Setup",
485
- heading: "Install",
486
- subheading: "Pick your editor and paste the config.",
486
+ heading: "Install Index9",
487
+ subheading: "Choose a client, copy the config, restart your assistant.",
487
488
  configs: [
488
489
  {
489
490
  id: "cursor",
490
491
  label: "Cursor",
491
- paths: [".cursor/mcp.json"],
492
+ paths: [".cursor/mcp.json", "~/.cursor/mcp.json"],
492
493
  config: `{
493
494
  "mcpServers": {
494
495
  "index9": {
@@ -501,7 +502,7 @@ var SITE = {
501
502
  {
502
503
  id: "vscode",
503
504
  label: "VS Code",
504
- paths: [".vscode/mcp.json"],
505
+ paths: [".vscode/mcp.json", "user profile mcp.json"],
505
506
  config: `{
506
507
  "servers": {
507
508
  "index9": {
@@ -516,7 +517,7 @@ var SITE = {
516
517
  id: "claude-code",
517
518
  label: "Claude Code",
518
519
  paths: [],
519
- config: `claude mcp add --transport stdio index9 -- npx -y @index9/mcp@latest`,
520
+ config: `claude mcp add --transport stdio --scope user index9 -- npx -y @index9/mcp@latest`,
520
521
  copyHint: "# Run in terminal (adds to ~/.claude.json)"
521
522
  },
522
523
  {
@@ -525,19 +526,33 @@ var SITE = {
525
526
  paths: [],
526
527
  config: `codex mcp add index9 -- npx -y @index9/mcp@latest`,
527
528
  copyHint: "# Run in terminal (adds to ~/.codex/config.toml)"
529
+ },
530
+ {
531
+ id: "generic",
532
+ label: "Any MCP client",
533
+ paths: ["mcp.json"],
534
+ config: `{
535
+ "mcpServers": {
536
+ "index9": {
537
+ "command": "npx",
538
+ "args": ["-y", "@index9/mcp@latest"]
539
+ }
540
+ }
541
+ }`
528
542
  }
529
543
  ],
530
544
  copyButton: "Copy",
531
545
  copiedButton: "Copied",
532
546
  copyAriaLabel: "Copy configuration",
533
547
  copiedAnnouncement: "Configuration copied to clipboard",
534
- setupNote: "Want live tests?",
535
- setupLink: "Add an OpenRouter key",
548
+ nextStep: "Search, compare, and dry-run cost estimates work without a key.",
549
+ setupNote: "Live tests need",
550
+ setupLink: "an OpenRouter key",
536
551
  setupUrl: "https://github.com/index9-org/mcp#openrouter-api-key"
537
552
  },
538
553
  footer: {
539
554
  brand: "index9",
540
- tagline: "MCP-native model picker. Live data from OpenRouter.",
555
+ tagline: "Live model data, via MCP.",
541
556
  copyrightSuffix: "index9",
542
557
  github: "GitHub",
543
558
  privacy: "Privacy",
@@ -547,7 +562,8 @@ var SITE = {
547
562
  var README = {
548
563
  mcpDescription: `Discover, shortlist, compare, cost-model, and live-test ${MODEL_COUNT} AI models from your editor`,
549
564
  mcpInstall: {
550
- envNote: "Optional: set OPENROUTER_API_KEY in your MCP client config for live test_model calls. dryRun=true works without a key."
565
+ envNote: "Required for live test_model calls. Set OPENROUTER_API_KEY in your MCP client config. dryRun=true works without it.",
566
+ envVarDescription: "Required for live test_model calls. dryRun=true works without it."
551
567
  }
552
568
  };
553
569
 
package/manifest.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": "0.3",
3
3
  "name": "index9",
4
- "version": "6.4.0",
4
+ "version": "6.5.1",
5
5
  "description": "Discover, shortlist, compare, cost-model, and live-test 300+ AI models from your editor",
6
6
  "author": {
7
7
  "name": "Index9"
@@ -11,42 +11,36 @@
11
11
  "entry_point": "dist/cli.js",
12
12
  "mcp_config": {
13
13
  "command": "node",
14
- "args": [
15
- "${__dirname}/dist/cli.js"
16
- ],
14
+ "args": ["${__dirname}/dist/cli.js"],
17
15
  "env": {
18
16
  "OPENROUTER_API_KEY": "${user_config.openrouter_api_key}"
19
17
  }
20
18
  }
21
19
  },
22
20
  "tools": [
21
+ {
22
+ "name": "list_facets",
23
+ "description": "List available providers, capabilities, modalities, and tokenizers"
24
+ },
23
25
  {
24
26
  "name": "find_models",
25
- "description": "Search and paginate AI models by semantic query or filters"
27
+ "description": "Search AI models by semantic query or filters"
26
28
  },
27
29
  {
28
30
  "name": "get_models",
29
- "description": "Get full model metadata by IDs or aliases (batch, up to 100)"
31
+ "description": "Fetch full model metadata for up to 100 IDs or aliases"
30
32
  },
31
33
  {
32
34
  "name": "compare_models",
33
35
  "description": "Diff 2-10 models across pricing, context, capabilities, and tokenizer"
34
36
  },
35
- {
36
- "name": "list_facets",
37
- "description": "Enumerate available providers, capabilities, modalities, and tokenizers"
38
- },
39
37
  {
40
38
  "name": "test_model",
41
- "description": "Run live inference or dry-run cost estimation across up to 10 models"
39
+ "description": "Run live inference or dry-run cost estimates on 1-10 models"
42
40
  }
43
41
  ],
44
42
  "compatibility": {
45
- "platforms": [
46
- "darwin",
47
- "linux",
48
- "win32"
49
- ],
43
+ "platforms": ["darwin", "linux", "win32"],
50
44
  "runtimes": {
51
45
  "node": ">=20.0.0"
52
46
  }
@@ -55,7 +49,7 @@
55
49
  "openrouter_api_key": {
56
50
  "type": "string",
57
51
  "title": "OpenRouter API Key",
58
- "description": "Required for live test_model calls. dryRun=true does not require it.",
52
+ "description": "Required for live test_model calls. dryRun=true works without it.",
59
53
  "sensitive": true,
60
54
  "required": false
61
55
  }
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@index9/mcp",
3
- "version": "6.5.0",
3
+ "version": "6.5.2",
4
+ "description": "Discover, shortlist, compare, cost-model, and live-test 300+ AI models from your editor",
4
5
  "license": "MIT",
5
6
  "repository": {
6
7
  "type": "git",
@@ -11,7 +12,8 @@
11
12
  },
12
13
  "files": [
13
14
  "dist",
14
- "manifest.json"
15
+ "manifest.json",
16
+ "server.json"
15
17
  ],
16
18
  "type": "module",
17
19
  "main": "./dist/cli.js",
@@ -33,6 +35,7 @@
33
35
  "engines": {
34
36
  "node": ">=20"
35
37
  },
38
+ "mcpName": "io.github.index9-org/mcp",
36
39
  "scripts": {
37
40
  "build": "node ../../scripts/generate-docs.mjs && tsup",
38
41
  "clean": "rm -rf dist",
package/server.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.index9-org/mcp",
4
+ "title": "Index9",
5
+ "description": "Discover, shortlist, compare, cost-model, and live-test 300+ AI models from your editor",
6
+ "repository": {
7
+ "url": "https://github.com/index9-org/mcp",
8
+ "source": "github"
9
+ },
10
+ "version": "6.5.1",
11
+ "packages": [
12
+ {
13
+ "registryType": "npm",
14
+ "registryBaseUrl": "https://registry.npmjs.org",
15
+ "identifier": "@index9/mcp",
16
+ "version": "6.5.1",
17
+ "transport": {
18
+ "type": "stdio"
19
+ },
20
+ "environmentVariables": [
21
+ {
22
+ "name": "OPENROUTER_API_KEY",
23
+ "description": "Required for live test_model calls. dryRun=true works without it.",
24
+ "format": "string",
25
+ "isRequired": false,
26
+ "isSecret": true
27
+ }
28
+ ]
29
+ }
30
+ ]
31
+ }