@index9/mcp 6.3.0 → 6.5.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/dist/cli.js CHANGED
@@ -224,7 +224,7 @@ Parameters:
224
224
  - providerSort: "throughput" | "price" | "latency" \u2014 opt-in OpenRouter provider routing. Defaults to OpenRouter's load-balanced choice.
225
225
  - providerOrder: ordered list of provider slugs (up to 8). Try these providers first before falling back. Useful for steering around an overloaded provider for a single model.
226
226
  - fallbackModels: ordered list of model ids (up to 5). OpenRouter automatically retries the request against the next id when the primary is unavailable. Use sparingly \u2014 a benchmark should usually test the model you asked for, not a substitute.
227
- - debug: When true, each result includes a \`debug\` field with the raw upstream finish_reason, error message, provider name, refusal, and usage. Use to diagnose "missing assistant text" without re-running.
227
+ - debug: When true, each result includes a \`debug\` field with the raw upstream finish_reason, error message, \`providerName\` (OpenRouter routing/fulfillment provider \u2014 can differ from the publisher, e.g. an anthropic/* model served via Google Vertex), \`modelPublisher\` (derived from the canonical id prefix \u2014 e.g. "anthropic", "x-ai"), refusal, and usage. Use to diagnose "missing assistant text" without re-running.
228
228
 
229
229
  Results (live): each result carries modelId (the id you passed), resolvedModelId (canonical id, present when the input was an alias), ok, response, latencyMs, tokens { prompt, completion }, cost (USD; live from OpenRouter when available, else estimated from cached pricing), and truncated=true when finish_reason is "length". On failure, results include \`error\` (free-form) plus \`failureReason\` ("insufficient_credits" | "model_unavailable" | "rate_limited" | "capacity" | "timeout" | "invalid_request" | "unknown") so callers can pick a retry strategy without parsing the error string. \`capacity\` indicates the provider is overloaded \u2014 apply a longer backoff or set \`fallbackModels\` and retry. When \`debug: true\` is set, each result also carries a \`debug\` block with the upstream provider's diagnostic fields.
230
230
 
@@ -245,13 +245,16 @@ var PARAM_DESCRIPTIONS = {
245
245
  excludeFree: `When true, exclude models with id ending in ':free'. Useful for sortBy=price (which would otherwise be dominated by free-tier preview models) and when you want a paid SLA. Default false.`,
246
246
  requireKeywordMatch: `When true, suppress weak vector-only results from semantic queries. If no candidate has a BM25 keyword hit, returns an empty page with meta.confidence='low' and meta.lowConfidenceReason \u2014 instead of returning misleading nearest-neighbor matches. Filter-only queries (sortBy=created or sortBy=price without q) ignore this flag. Default false.`,
247
247
  expectedPromptTokens: `Expected number of prompt tokens for dryRun cost estimation. When set, overrides the heuristic that counts characters from the literal \`prompt\` string \u2014 use this for capacity planning ("what would 6000-token reviews cost?") without pasting filler. If both are omitted, the prompt string is tokenized at ~4 chars/token.`,
248
- expectedCompletionTokens: `Expected number of completion tokens for cost estimation (default: 256). Typical ranges: 100-500 for quick tests, 1000-2000 for code generation, 4000+ for long-form content. This is a heuristic \u2014 actual billed tokens may differ.`
248
+ expectedCompletionTokens: `Expected number of completion tokens for cost estimation (default: 256). Typical ranges: 100-500 for quick tests, 1000-2000 for code generation, 4000+ for long-form content. This is a heuristic \u2014 actual billed tokens may differ.`,
249
+ minPrice: `Minimum effective prompt price in USD per million tokens. Matches the basis exposed in \`pricing.effectivePromptPerMillion\` and \`pageInfo.priceSortBasis\` \u2014 token price plus per-request fees scaled to per-million, so a model with $0.30/M tokens and a $0.30 per-request fee evaluates as $0.60/M effective. Models with no resolvable price (zero-token, no per-request fee, non-\`:free\` id) are excluded when this bound is set.`,
250
+ maxPrice: `Maximum effective prompt price in USD per million tokens. Matches the basis exposed in \`pricing.effectivePromptPerMillion\` and \`pageInfo.priceSortBasis\` \u2014 token price plus per-request fees scaled to per-million, so a model with $0.30/M tokens and a $0.30 per-request fee evaluates as $0.60/M effective and is excluded by \`maxPrice: 0.55\`. Models with no resolvable price (zero-token, no per-request fee, non-\`:free\` id) are excluded when this bound is set.`
249
251
  };
250
252
  var SITE = {
251
253
  nav: {
252
254
  brand: "index9",
253
255
  tools: "Tools",
254
256
  howItWorks: "How it works",
257
+ caseStudy: "Case study",
255
258
  install: "Install",
256
259
  faq: "FAQ",
257
260
  github: "GitHub",
@@ -259,19 +262,18 @@ var SITE = {
259
262
  installCta: "Install"
260
263
  },
261
264
  hero: {
262
- titleLine1: "Pick the right AI model",
263
- titleLine2: "from chat",
264
- subtitle: "An MCP server your coding assistant uses to search, compare, and live-test 300+ models for the task you're on.",
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.",
265
267
  pricingNote: "Free. You only pay OpenRouter for live model calls.",
266
268
  seeHowItWorks: "See a real session",
267
269
  updatedBadge: "OpenRouter data \xB7 refreshed ",
268
- panel: {
269
- signalEyebrow: "Just landed",
270
- signalTitle: "Newest on OpenRouter",
271
- liveLabel: "live",
272
- ctaEyebrow: "How your assistant picks",
273
- body: "Your assistant compares these against your task and live-tests the finalists."
274
- }
270
+ toolList: [
271
+ { name: "list_facets", role: "vocabulary" },
272
+ { name: "find_models", role: "search & filter" },
273
+ { name: "get_models", role: "full specs" },
274
+ { name: "compare_models", role: "side-by-side diff" },
275
+ { name: "test_model", role: "live inference" }
276
+ ]
275
277
  },
276
278
  problem: {
277
279
  label: "Why this exists",
@@ -304,70 +306,77 @@ var SITE = {
304
306
  ]
305
307
  },
306
308
  caseStudy: {
307
- label: "Case study",
309
+ label: "Real session",
308
310
  heading: "A real session, not a mockup",
309
- subheading: "A Claude Code session picking a TypeScript code-review model. Real tool calls, real verdict.",
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.",
310
312
  prompt: {
311
313
  title: "The prompt",
312
- body: "Pick a model for a TypeScript code-review bot that runs on every PR. I want quality without paying frontier rates on routine reviews. Test against this diff."
314
+ 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."
313
315
  },
314
316
  toolCalls: {
315
317
  title: "What the assistant did",
316
- subtitle: "in order",
318
+ subtitle: "4 calls, 42s",
317
319
  calls: [
318
- { tool: "find_models", params: "newest first", note: "skip stale training picks" },
319
320
  {
320
321
  tool: "find_models",
321
- params: "code review + structured output",
322
+ params: "sortBy=created, function_calling + structured_output",
323
+ note: "skip stale training picks"
324
+ },
325
+ {
326
+ tool: "find_models",
327
+ params: "code review, maxPrice=$5/M, minContext=64K",
322
328
  note: "task fit"
323
329
  },
324
- { tool: "find_models", params: "max $2/M, every-PR budget", note: "rule out frontier" },
325
- { tool: "get_models", params: "8 candidates", note: "metadata lookup" },
326
330
  {
327
331
  tool: "compare_models",
328
- params: "4 finalists, ~3000 token PR diff",
329
- note: "per-PR cost projection"
332
+ params: "4 finalists, 3,000 prompt + 800 completion",
333
+ note: "per-PR cost diff"
330
334
  },
331
- { tool: "test_model", params: "dry-run \xD7 4", note: "cost estimate" },
332
335
  {
333
336
  tool: "test_model",
334
- params: "live \xD7 4, JSON output",
335
- note: "real bug-catch test"
337
+ params: "dry-run \xD7 4, same token budget",
338
+ note: "cost confirmation"
336
339
  }
337
340
  ]
338
341
  },
339
- consideredTitle: "Recent models, evaluated",
340
- consideredSubtitle: "Candidates the assistant ruled in and out, with the reason.",
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.",
341
344
  consideredRows: [
342
345
  {
343
- id: "openai/gpt-5.5",
344
- age: "1d ago",
346
+ id: "anthropic/claude-opus-4.7-fast",
347
+ age: "5d ago",
345
348
  decision: "skip",
346
- reason: "~$0.027 per PR, 5\xD7 the pick for the same outcome"
349
+ reason: "$30/M input, filtered out by the maxPrice constraint on the second find_models call"
350
+ },
351
+ {
352
+ id: "mistralai/devstral-medium",
353
+ age: "10mo ago",
354
+ decision: "tested",
355
+ reason: "$0.40/M input, completion-heavy at $2/M, $0.0028 per PR"
347
356
  },
348
357
  {
349
- id: "xiaomi/mimo-v2.5-pro",
350
- age: "3d ago",
358
+ id: "qwen/qwen3-coder",
359
+ age: "10mo ago",
351
360
  decision: "tested",
352
- reason: "good structure, missed the precision edge case"
361
+ reason: "$0.22/M input, 1M context but no file_input, $0.0021 per PR"
353
362
  },
354
363
  {
355
- id: "deepseek/deepseek-v4-flash",
356
- age: "1d ago",
364
+ id: "google/gemini-3.1-flash-lite",
365
+ age: "1w ago",
357
366
  decision: "tested",
358
- reason: "7\xD7 cheaper than the pick, but missed both bugs"
367
+ reason: "$0.25/M input, newest of the shortlist, adds reasoning and vision, $0.00195 per PR"
359
368
  },
360
369
  {
361
- id: "z-ai/glm-5.1",
362
- age: "2w ago",
370
+ id: "mistralai/codestral-2508",
371
+ age: "9mo ago",
363
372
  decision: "shortlisted",
364
- reason: "caught both bugs at ~$0.005 per PR"
373
+ reason: "$0.30/M input, Mistral's coding-specific model, $0.00162 per PR"
365
374
  }
366
375
  ],
367
376
  verdict: {
368
377
  title: "The pick",
369
- model: "z-ai/glm-5.1",
370
- body: "Open-weight, $1.05 per million input tokens. Caught both bugs in the sample diff at roughly $0.005 per PR, about 5\xD7 cheaper than running gpt-5.5 on every commit."
378
+ 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."
371
380
  }
372
381
  },
373
382
  toolsSection: {
@@ -832,6 +841,7 @@ var TestFailureReasonSchema = z6.enum([
832
841
  var TestDebugInfoSchema = z6.object({
833
842
  upstreamId: z6.string().optional(),
834
843
  providerName: z6.string().optional(),
844
+ modelPublisher: z6.string().optional(),
835
845
  finishReason: z6.string().optional(),
836
846
  upstreamError: z6.string().optional(),
837
847
  refusal: z6.string().optional(),
@@ -1211,8 +1221,8 @@ async function createServer() {
1211
1221
  sortOrder: z7.enum(["asc", "desc"]).optional().describe("Sort order. Defaults by sortBy."),
1212
1222
  createdAfter: z7.string().optional().describe("Lower bound for model created timestamp."),
1213
1223
  createdBefore: z7.string().optional().describe("Upper bound for model created timestamp."),
1214
- minPrice: z7.number().min(0).optional().describe("Minimum prompt price in USD per million tokens."),
1215
- maxPrice: z7.number().min(0).optional().describe("Maximum prompt price in USD per million tokens."),
1224
+ minPrice: z7.number().min(0).optional().describe(PARAM_DESCRIPTIONS.minPrice),
1225
+ maxPrice: z7.number().min(0).optional().describe(PARAM_DESCRIPTIONS.maxPrice),
1216
1226
  minContext: z7.number().int().min(1).optional().describe("Minimum context window in tokens."),
1217
1227
  capabilitiesAll: z7.array(z7.enum(CAPABILITIES)).optional().describe(PARAM_DESCRIPTIONS.capabilitiesAll),
1218
1228
  capabilitiesAny: z7.array(z7.enum(CAPABILITIES)).optional().describe(PARAM_DESCRIPTIONS.capabilitiesAny),
package/manifest.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": "0.3",
3
3
  "name": "index9",
4
- "version": "6.2.0",
4
+ "version": "6.4.0",
5
5
  "description": "Discover, shortlist, compare, cost-model, and live-test 300+ AI models from your editor",
6
6
  "author": {
7
7
  "name": "Index9"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@index9/mcp",
3
- "version": "6.3.0",
3
+ "version": "6.5.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -28,7 +28,7 @@
28
28
  "tsup": "^8.5.1",
29
29
  "typescript": "6.0.3",
30
30
  "vitest": "^4.1.6",
31
- "@index9/core": "2.6.0"
31
+ "@index9/core": "2.8.0"
32
32
  },
33
33
  "engines": {
34
34
  "node": ">=20"