@index9/mcp 6.5.3 → 6.5.5

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
@@ -262,8 +262,9 @@ var SITE = {
262
262
  installCta: "Install"
263
263
  },
264
264
  hero: {
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.",
265
+ title: "Live model catalog for coding assistants",
266
+ titleLines: ["Live model catalog", "for coding assistants"],
267
+ subtitle: "MCP tools for Claude Code, Cursor, VS Code, and Codex to search, compare, cost-model, and live-test 300+ models.",
267
268
  pricingNote: "Free to install. Live tests use your OpenRouter key.",
268
269
  seeHowItWorks: "See a real session",
269
270
  updatedBadge: "OpenRouter data \xB7 refreshed ",
@@ -277,11 +278,11 @@ var SITE = {
277
278
  },
278
279
  problem: {
279
280
  label: "Why this exists",
280
- heading: "Your assistant's model knowledge is stale",
281
+ heading: "Your assistant has no live model catalog",
281
282
  body: [
282
- 'New models ship every week. Pricing changes. "Use GPT-4" or "use Claude 3.5" is usually months behind reality.',
283
- "Without live data, your assistant defaults to whatever it learned in training. Usually a model superseded by something cheaper or better-suited to your task.",
284
- "Index9 gives it the data, and the tools to compare."
283
+ "New models ship weekly. Pricing, aliases, and capabilities change with them.",
284
+ "With no catalog to query, it uses training-time memory or web snippets. Pricing, context limits, and model ids in the answer may be wrong.",
285
+ `Index9 caches ${MODEL_COUNT} models, refreshes every 30 minutes, and exposes the catalog as five MCP tools in your editor.`
285
286
  ]
286
287
  },
287
288
  howItWorks: {
@@ -292,7 +293,7 @@ var SITE = {
292
293
  {
293
294
  number: "1",
294
295
  title: "You ask in chat",
295
- body: '"Pick the cheapest model that can review TypeScript PRs well."'
296
+ body: '"Pick a model for the support agent in our backend: real quality on 4k-token threads at ~30k calls a day, without frontier per-token rates."'
296
297
  },
297
298
  {
298
299
  number: "2",
@@ -309,76 +310,13 @@ var SITE = {
309
310
  caseStudy: {
310
311
  label: "Real session",
311
312
  heading: "A real session, not a mockup",
312
- subheading: "Claude Sonnet 4.6 using Index9 to pick a model for a TypeScript code-review bot. Real prompt, tool calls, and verdict.",
313
- prompt: {
314
- title: "The prompt",
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."
316
- },
317
- toolCalls: {
318
- title: "What the assistant did",
319
- subtitle: "4 calls, 42s",
320
- calls: [
321
- {
322
- tool: "find_models",
323
- params: "sortBy=created, function_calling + structured_output",
324
- note: "skip stale training picks"
325
- },
326
- {
327
- tool: "find_models",
328
- params: "code review, maxPrice=$5/M, minContext=64K",
329
- note: "task fit"
330
- },
331
- {
332
- tool: "compare_models",
333
- params: "4 finalists, 3,000 prompt + 800 completion",
334
- note: "per-PR cost diff"
335
- },
336
- {
337
- tool: "test_model",
338
- params: "dry-run \xD7 4, same token budget",
339
- note: "cost confirmation"
340
- }
341
- ]
342
- },
313
+ subheading: "Picking a model for a customer-support agent: live tool trace and measured verdict.",
314
+ promptTitle: "The ask",
315
+ toolCallsTitle: "What the assistant did",
343
316
  consideredTitle: "Candidates evaluated",
344
- consideredSubtitle: "5 evaluated, 1 pick",
345
- consideredRows: [
346
- {
347
- id: "anthropic/claude-opus-4.7-fast",
348
- age: "5d ago",
349
- decision: "skip",
350
- reason: "$30/M input, above the maxPrice filter"
351
- },
352
- {
353
- id: "mistralai/devstral-medium",
354
- age: "10mo ago",
355
- decision: "tested",
356
- reason: "$0.40/M input, $2/M output, $0.0028 per PR"
357
- },
358
- {
359
- id: "qwen/qwen3-coder",
360
- age: "10mo ago",
361
- decision: "tested",
362
- reason: "$0.22/M input, 1M context, no file_input, $0.0021 per PR"
363
- },
364
- {
365
- id: "google/gemini-3.1-flash-lite",
366
- age: "1w ago",
367
- decision: "tested",
368
- reason: "$0.25/M input, newest finalist, reasoning + vision, $0.00195 per PR"
369
- },
370
- {
371
- id: "mistralai/codestral-2508",
372
- age: "9mo ago",
373
- decision: "shortlisted",
374
- reason: "$0.30/M input, coding-specific, $0.00162 per PR"
375
- }
376
- ],
377
- verdict: {
378
- title: "The pick",
379
- model: "mistralai/codestral-2508",
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."
381
- }
317
+ verdictTitle: "The pick",
318
+ capturedPrefix: "Captured ",
319
+ sourcePrefix: " \xB7 source "
382
320
  },
383
321
  toolsSection: {
384
322
  label: "Tools",
@@ -451,7 +389,7 @@ var SITE = {
451
389
  },
452
390
  {
453
391
  question: "Who is index9 for?",
454
- answer: "Developers in Claude Code, Cursor, VS Code, or Codex who want model picks from live data, not training memory.",
392
+ answer: "Developers in Claude Code, Cursor, VS Code, or Codex who want model picks from live data, not training-time memory.",
455
393
  link: null
456
394
  },
457
395
  {
@@ -552,7 +490,7 @@ var SITE = {
552
490
  },
553
491
  footer: {
554
492
  brand: "index9",
555
- tagline: "Live model data, via MCP.",
493
+ tagline: "Live model catalog, via MCP.",
556
494
  copyrightSuffix: "index9",
557
495
  github: "GitHub",
558
496
  privacy: "Privacy",
@@ -767,56 +705,94 @@ var ListFacetsToolResultSchema = FacetsResponseSchema.extend({
767
705
  _index9: Index9MetaSchema
768
706
  });
769
707
 
770
- // ../core/dist/schemas/test.js
708
+ // ../core/dist/schemas/case-study.js
771
709
  import { z as z6 } from "zod";
772
- var ResponseFormatSchema = z6.object({
773
- type: z6.string().min(1)
774
- }).catchall(z6.unknown()).optional();
775
- var ProviderSortSchema = z6.enum(["throughput", "price", "latency"]);
776
- var TestRequestSchema = z6.object({
777
- prompt: z6.string().min(1).optional(),
778
- userContent: z6.array(UserContentPartSchema).min(1).optional(),
779
- dryRun: z6.boolean().optional(),
780
- expectedPromptTokens: z6.number().int().positive().optional(),
781
- expectedCompletionTokens: z6.number().int().positive().optional(),
782
- models: z6.array(z6.string().min(1)).min(1, "Models are required").max(LIMITS.testModelsMax, `Models must contain between 1 and ${LIMITS.testModelsMax} model IDs`),
783
- timeoutMs: z6.number().int().positive().optional(),
784
- maxTokens: z6.number().int().positive().optional(),
785
- systemPrompt: z6.string().min(1).optional(),
786
- temperature: z6.number().min(0).max(2).optional(),
787
- topP: z6.number().gt(0).lte(1).optional(),
788
- seed: z6.number().int().optional(),
710
+ var CaseStudyDecisionSchema = z6.enum(["shortlisted", "tested", "selected"]);
711
+ var CaseStudyToolCallSchema = z6.object({
712
+ tool: z6.string(),
713
+ params: z6.string()
714
+ }).strict();
715
+ var CaseStudyCandidateSchema = z6.object({
716
+ id: z6.string(),
717
+ createdAt: z6.string().nullable(),
718
+ decision: CaseStudyDecisionSchema,
719
+ promptPerMillion: z6.number().nullable(),
720
+ completionPerMillion: z6.number().nullable(),
721
+ perPromptCostUsd: z6.number().nullable()
722
+ }).strict();
723
+ var CaseStudyVerdictSchema = z6.object({
724
+ model: z6.string().nullable(),
725
+ body: z6.string()
726
+ }).strict();
727
+ var displayPromptBody = z6.string().max(220).refine((s) => !s.includes("\n"), "promptBody must be a single line").refine((s) => !/walk me through/i.test(s), "promptBody must not include eval harness steps").refine((s) => !/##\s*recommendation/i.test(s), "promptBody must not include extraction template");
728
+ var CaseStudySchema = z6.object({
729
+ capturedAt: z6.string(),
730
+ generatedAt: z6.string(),
731
+ sourceRun: z6.string(),
732
+ evaluatorModelId: z6.string(),
733
+ promptId: z6.string(),
734
+ promptBody: displayPromptBody,
735
+ promptContext: z6.string().max(80).optional(),
736
+ totalLatencyMs: z6.number().int(),
737
+ totalCostUsd: z6.number().nullable(),
738
+ toolCallCount: z6.number().int(),
739
+ candidateCount: z6.number().int(),
740
+ selectedModelId: z6.string().nullable(),
741
+ toolCalls: z6.array(CaseStudyToolCallSchema),
742
+ candidates: z6.array(CaseStudyCandidateSchema),
743
+ verdict: CaseStudyVerdictSchema
744
+ }).strict();
745
+
746
+ // ../core/dist/schemas/test.js
747
+ import { z as z7 } from "zod";
748
+ var ResponseFormatSchema = z7.object({
749
+ type: z7.string().min(1)
750
+ }).catchall(z7.unknown()).optional();
751
+ var ProviderSortSchema = z7.enum(["throughput", "price", "latency"]);
752
+ var TestRequestSchema = z7.object({
753
+ prompt: z7.string().min(1).optional(),
754
+ userContent: z7.array(UserContentPartSchema).min(1).optional(),
755
+ dryRun: z7.boolean().optional(),
756
+ expectedPromptTokens: z7.number().int().positive().optional(),
757
+ expectedCompletionTokens: z7.number().int().positive().optional(),
758
+ models: z7.array(z7.string().min(1)).min(1, "Models are required").max(LIMITS.testModelsMax, `Models must contain between 1 and ${LIMITS.testModelsMax} model IDs`),
759
+ timeoutMs: z7.number().int().positive().optional(),
760
+ maxTokens: z7.number().int().positive().optional(),
761
+ systemPrompt: z7.string().min(1).optional(),
762
+ temperature: z7.number().min(0).max(2).optional(),
763
+ topP: z7.number().gt(0).lte(1).optional(),
764
+ seed: z7.number().int().optional(),
789
765
  responseFormat: ResponseFormatSchema,
790
- enforceJson: z6.boolean().optional(),
791
- retries: z6.number().int().min(0).max(3).optional(),
766
+ enforceJson: z7.boolean().optional(),
767
+ retries: z7.number().int().min(0).max(3).optional(),
792
768
  // Use OpenRouter's SSE streaming endpoint so capacity/refusal errors
793
769
  // surface in ~1s instead of waiting the full per-model timeout for an
794
770
  // empty 200 OK. Cost/tokens are still returned via stream_options.
795
- stream: z6.boolean().optional(),
771
+ stream: z7.boolean().optional(),
796
772
  // First-token deadline (streaming only). If the upstream sends no
797
773
  // delta within this window, abort the request. Defaults to 10s when
798
774
  // streaming. Ignored when stream=false.
799
- firstTokenTimeoutMs: z6.number().int().positive().optional(),
775
+ firstTokenTimeoutMs: z7.number().int().positive().optional(),
800
776
  // Forwards as `provider.sort` to OpenRouter — opt into routing toward
801
777
  // higher-throughput providers when running benchmarks.
802
778
  providerSort: ProviderSortSchema.optional(),
803
779
  // Forwards as `provider.order` — try these provider slugs first in the
804
780
  // given order before falling back. Capped to stay within reasonable
805
781
  // limits and prevent abuse.
806
- providerOrder: z6.array(z6.string().min(1)).min(1).max(8).optional(),
782
+ providerOrder: z7.array(z7.string().min(1)).min(1).max(8).optional(),
807
783
  // Forwards as the top-level `models` array (NOT `model`). OpenRouter
808
784
  // tries each in order if the primary is unavailable. Different intent
809
785
  // from providerOrder, which routes within a single model.
810
- fallbackModels: z6.array(z6.string().min(1)).min(1).max(5).optional(),
786
+ fallbackModels: z7.array(z7.string().min(1)).min(1).max(5).optional(),
811
787
  // When true, attach a `debug` field on each result with the raw
812
788
  // upstream finish_reason, error message, provider name, refusal, and
813
789
  // usage. Used to diagnose "missing assistant text" without re-running.
814
- debug: z6.boolean().optional()
790
+ debug: z7.boolean().optional()
815
791
  }).strict().superRefine((data, ctx) => {
816
792
  if (data.dryRun === true) {
817
793
  if (!data.prompt && data.expectedPromptTokens === void 0) {
818
794
  ctx.addIssue({
819
- code: z6.ZodIssueCode.custom,
795
+ code: z7.ZodIssueCode.custom,
820
796
  message: "dryRun requires either prompt or expectedPromptTokens",
821
797
  path: ["prompt"]
822
798
  });
@@ -825,24 +801,24 @@ var TestRequestSchema = z6.object({
825
801
  }
826
802
  if (!data.prompt && !data.userContent?.length) {
827
803
  ctx.addIssue({
828
- code: z6.ZodIssueCode.custom,
804
+ code: z7.ZodIssueCode.custom,
829
805
  message: "Prompt or userContent is required",
830
806
  path: ["prompt"]
831
807
  });
832
808
  }
833
809
  });
834
- var UsageTokensSchema = z6.object({
835
- prompt: z6.number().min(0),
836
- completion: z6.number().min(0)
810
+ var UsageTokensSchema = z7.object({
811
+ prompt: z7.number().min(0),
812
+ completion: z7.number().min(0)
837
813
  });
838
- var TestPricingUsedSchema = z6.object({
839
- promptPerToken: z6.number().nullable().optional(),
840
- completionPerToken: z6.number().nullable().optional(),
841
- promptPerMillion: z6.number().nullable().optional(),
842
- completionPerMillion: z6.number().nullable().optional(),
843
- requestUsd: z6.number().nullable().optional()
814
+ var TestPricingUsedSchema = z7.object({
815
+ promptPerToken: z7.number().nullable().optional(),
816
+ completionPerToken: z7.number().nullable().optional(),
817
+ promptPerMillion: z7.number().nullable().optional(),
818
+ completionPerMillion: z7.number().nullable().optional(),
819
+ requestUsd: z7.number().nullable().optional()
844
820
  });
845
- var TestFailureReasonSchema = z6.enum([
821
+ var TestFailureReasonSchema = z7.enum([
846
822
  "insufficient_credits",
847
823
  "model_unavailable",
848
824
  "rate_limited",
@@ -854,86 +830,86 @@ var TestFailureReasonSchema = z6.enum([
854
830
  "invalid_request",
855
831
  "unknown"
856
832
  ]);
857
- var TestDebugInfoSchema = z6.object({
858
- upstreamId: z6.string().optional(),
859
- providerName: z6.string().optional(),
860
- modelPublisher: z6.string().optional(),
861
- finishReason: z6.string().optional(),
862
- upstreamError: z6.string().optional(),
863
- refusal: z6.string().optional(),
864
- hasToolCalls: z6.boolean().optional(),
865
- usage: z6.object({
866
- promptTokens: z6.number().optional(),
867
- completionTokens: z6.number().optional(),
868
- totalTokens: z6.number().optional()
833
+ var TestDebugInfoSchema = z7.object({
834
+ upstreamId: z7.string().optional(),
835
+ providerName: z7.string().optional(),
836
+ modelPublisher: z7.string().optional(),
837
+ finishReason: z7.string().optional(),
838
+ upstreamError: z7.string().optional(),
839
+ refusal: z7.string().optional(),
840
+ hasToolCalls: z7.boolean().optional(),
841
+ usage: z7.object({
842
+ promptTokens: z7.number().optional(),
843
+ completionTokens: z7.number().optional(),
844
+ totalTokens: z7.number().optional()
869
845
  }).optional()
870
846
  });
871
- var TestModelMetadataSchema = z6.object({
872
- id: z6.string(),
873
- name: z6.string(),
874
- created: z6.number().nullable().optional(),
875
- createdAt: z6.string().nullable().optional(),
847
+ var TestModelMetadataSchema = z7.object({
848
+ id: z7.string(),
849
+ name: z7.string(),
850
+ created: z7.number().nullable().optional(),
851
+ createdAt: z7.string().nullable().optional(),
876
852
  pricingUsed: TestPricingUsedSchema.optional()
877
853
  });
878
- var TestResultSuccessSchema = z6.object({
879
- modelId: z6.string(),
880
- resolvedModelId: z6.string().optional(),
881
- ok: z6.literal(true),
854
+ var TestResultSuccessSchema = z7.object({
855
+ modelId: z7.string(),
856
+ resolvedModelId: z7.string().optional(),
857
+ ok: z7.literal(true),
882
858
  model: TestModelMetadataSchema,
883
- response: z6.string(),
884
- latencyMs: z6.number().min(0),
859
+ response: z7.string(),
860
+ latencyMs: z7.number().min(0),
885
861
  tokens: UsageTokensSchema,
886
- cost: z6.number().nullable().optional(),
887
- truncated: z6.boolean().optional(),
862
+ cost: z7.number().nullable().optional(),
863
+ truncated: z7.boolean().optional(),
888
864
  debug: TestDebugInfoSchema.optional()
889
865
  });
890
- var TestResultFailureSchema = z6.object({
891
- modelId: z6.string(),
892
- resolvedModelId: z6.string().optional(),
893
- ok: z6.literal(false),
866
+ var TestResultFailureSchema = z7.object({
867
+ modelId: z7.string(),
868
+ resolvedModelId: z7.string().optional(),
869
+ ok: z7.literal(false),
894
870
  model: TestModelMetadataSchema,
895
- error: z6.string(),
871
+ error: z7.string(),
896
872
  failureReason: TestFailureReasonSchema.optional(),
897
- latencyMs: z6.number().min(0),
873
+ latencyMs: z7.number().min(0),
898
874
  debug: TestDebugInfoSchema.optional()
899
875
  });
900
- var TestResultSchema = z6.discriminatedUnion("ok", [
876
+ var TestResultSchema = z7.discriminatedUnion("ok", [
901
877
  TestResultSuccessSchema,
902
878
  TestResultFailureSchema
903
879
  ]);
904
- var TestEstimateResultSchema = z6.object({
905
- modelId: z6.string(),
906
- resolvedModelId: z6.string().optional(),
880
+ var TestEstimateResultSchema = z7.object({
881
+ modelId: z7.string(),
882
+ resolvedModelId: z7.string().optional(),
907
883
  model: TestModelMetadataSchema,
908
884
  tokens: UsageTokensSchema,
909
- estimatedCost: z6.number().nullable().optional(),
910
- tokenCostUsd: z6.number().nullable().optional(),
911
- requestCostUsd: z6.number().nullable().optional(),
912
- totalCostUsd: z6.number().nullable().optional(),
885
+ estimatedCost: z7.number().nullable().optional(),
886
+ tokenCostUsd: z7.number().nullable().optional(),
887
+ requestCostUsd: z7.number().nullable().optional(),
888
+ totalCostUsd: z7.number().nullable().optional(),
913
889
  estimatedCostBasis: PricingBasisSchema.optional()
914
890
  });
915
891
  var TestResolutionFieldsSchema = {
916
- missingIds: z6.array(z6.string()).optional(),
917
- resolvedAliases: z6.record(z6.string(), z6.string()).optional(),
918
- ambiguousAliases: z6.record(z6.string(), z6.array(z6.string())).optional(),
919
- suggestions: z6.record(z6.string(), z6.array(SuggestionEntrySchema)).optional(),
920
- missingDiagnostics: z6.record(z6.string(), MissingModelDiagnosticSchema).optional()
892
+ missingIds: z7.array(z7.string()).optional(),
893
+ resolvedAliases: z7.record(z7.string(), z7.string()).optional(),
894
+ ambiguousAliases: z7.record(z7.string(), z7.array(z7.string())).optional(),
895
+ suggestions: z7.record(z7.string(), z7.array(SuggestionEntrySchema)).optional(),
896
+ missingDiagnostics: z7.record(z7.string(), MissingModelDiagnosticSchema).optional()
921
897
  };
922
- var TestDryRunResponseSchema = z6.object({
923
- dryRun: z6.literal(true),
924
- results: z6.array(TestEstimateResultSchema),
925
- disclaimer: z6.string(),
898
+ var TestDryRunResponseSchema = z7.object({
899
+ dryRun: z7.literal(true),
900
+ results: z7.array(TestEstimateResultSchema),
901
+ disclaimer: z7.string(),
926
902
  ...TestResolutionFieldsSchema
927
903
  });
928
- var TestLiveResponseSchema = z6.object({
929
- results: z6.array(TestResultSchema),
904
+ var TestLiveResponseSchema = z7.object({
905
+ results: z7.array(TestResultSchema),
930
906
  ...TestResolutionFieldsSchema
931
907
  });
932
- var TestResponseSchema = z6.union([TestDryRunResponseSchema, TestLiveResponseSchema]);
908
+ var TestResponseSchema = z7.union([TestDryRunResponseSchema, TestLiveResponseSchema]);
933
909
 
934
910
  // src/server.ts
935
911
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
936
- import { z as z7 } from "zod";
912
+ import { z as z8 } from "zod";
937
913
 
938
914
  // src/config.ts
939
915
  var DEFAULT_BASE_URL = "https://index9.dev";
@@ -1230,22 +1206,22 @@ async function createServer() {
1230
1206
  title: TOOLS.find_models.title,
1231
1207
  description: TOOLS.find_models.description,
1232
1208
  inputSchema: {
1233
- q: z7.string().min(1).optional().describe(PARAM_DESCRIPTIONS.q),
1234
- limit: z7.number().int().min(1).max(100).default(20).describe("Page size (1-100, default 20)."),
1235
- cursor: z7.string().min(1).optional().describe(PARAM_DESCRIPTIONS.cursor),
1236
- sortBy: z7.enum(["relevance", "created", "price"]).default("relevance").describe(PARAM_DESCRIPTIONS.sortBy),
1237
- sortOrder: z7.enum(["asc", "desc"]).optional().describe("Sort order. Defaults by sortBy."),
1238
- createdAfter: z7.string().optional().describe("Lower bound for model created timestamp."),
1239
- createdBefore: z7.string().optional().describe("Upper bound for model created timestamp."),
1240
- minPrice: z7.number().min(0).optional().describe(PARAM_DESCRIPTIONS.minPrice),
1241
- maxPrice: z7.number().min(0).optional().describe(PARAM_DESCRIPTIONS.maxPrice),
1242
- minContext: z7.number().int().min(1).optional().describe("Minimum context window in tokens."),
1243
- capabilitiesAll: z7.array(z7.enum(CAPABILITIES)).optional().describe(PARAM_DESCRIPTIONS.capabilitiesAll),
1244
- capabilitiesAny: z7.array(z7.enum(CAPABILITIES)).optional().describe(PARAM_DESCRIPTIONS.capabilitiesAny),
1245
- modality: z7.enum(OUTPUT_MODALITIES).optional().describe(PARAM_DESCRIPTIONS.modality),
1246
- provider: z7.array(z7.string().min(1)).optional().describe(PARAM_DESCRIPTIONS.provider),
1247
- excludeFree: z7.boolean().optional().describe(PARAM_DESCRIPTIONS.excludeFree),
1248
- requireKeywordMatch: z7.boolean().optional().describe(PARAM_DESCRIPTIONS.requireKeywordMatch)
1209
+ q: z8.string().min(1).optional().describe(PARAM_DESCRIPTIONS.q),
1210
+ limit: z8.number().int().min(1).max(100).default(20).describe("Page size (1-100, default 20)."),
1211
+ cursor: z8.string().min(1).optional().describe(PARAM_DESCRIPTIONS.cursor),
1212
+ sortBy: z8.enum(["relevance", "created", "price"]).default("relevance").describe(PARAM_DESCRIPTIONS.sortBy),
1213
+ sortOrder: z8.enum(["asc", "desc"]).optional().describe("Sort order. Defaults by sortBy."),
1214
+ createdAfter: z8.string().optional().describe("Lower bound for model created timestamp."),
1215
+ createdBefore: z8.string().optional().describe("Upper bound for model created timestamp."),
1216
+ minPrice: z8.number().min(0).optional().describe(PARAM_DESCRIPTIONS.minPrice),
1217
+ maxPrice: z8.number().min(0).optional().describe(PARAM_DESCRIPTIONS.maxPrice),
1218
+ minContext: z8.number().int().min(1).optional().describe("Minimum context window in tokens."),
1219
+ capabilitiesAll: z8.array(z8.enum(CAPABILITIES)).optional().describe(PARAM_DESCRIPTIONS.capabilitiesAll),
1220
+ capabilitiesAny: z8.array(z8.enum(CAPABILITIES)).optional().describe(PARAM_DESCRIPTIONS.capabilitiesAny),
1221
+ modality: z8.enum(OUTPUT_MODALITIES).optional().describe(PARAM_DESCRIPTIONS.modality),
1222
+ provider: z8.array(z8.string().min(1)).optional().describe(PARAM_DESCRIPTIONS.provider),
1223
+ excludeFree: z8.boolean().optional().describe(PARAM_DESCRIPTIONS.excludeFree),
1224
+ requireKeywordMatch: z8.boolean().optional().describe(PARAM_DESCRIPTIONS.requireKeywordMatch)
1249
1225
  },
1250
1226
  outputSchema: FindModelsToolResultSchema.shape,
1251
1227
  annotations: { readOnlyHint: true }
@@ -1258,8 +1234,8 @@ async function createServer() {
1258
1234
  title: TOOLS.get_models.title,
1259
1235
  description: TOOLS.get_models.description,
1260
1236
  inputSchema: {
1261
- ids: z7.array(z7.string().min(1)).min(1).max(100).describe("Model identifiers or aliases. Up to 100."),
1262
- maxDescriptionChars: z7.number().int().min(0).max(2e3).optional().describe("Truncate descriptions to this many characters.")
1237
+ ids: z8.array(z8.string().min(1)).min(1).max(100).describe("Model identifiers or aliases. Up to 100."),
1238
+ maxDescriptionChars: z8.number().int().min(0).max(2e3).optional().describe("Truncate descriptions to this many characters.")
1263
1239
  },
1264
1240
  outputSchema: GetModelsToolResultSchema.shape,
1265
1241
  annotations: { readOnlyHint: true }
@@ -1272,13 +1248,13 @@ async function createServer() {
1272
1248
  title: TOOLS.compare_models.title,
1273
1249
  description: TOOLS.compare_models.description,
1274
1250
  inputSchema: {
1275
- ids: z7.array(z7.string().min(1)).min(2).max(LIMITS.compareModelsMax).describe(
1251
+ ids: z8.array(z8.string().min(1)).min(2).max(LIMITS.compareModelsMax).describe(
1276
1252
  `Model identifiers or aliases to compare (2-${LIMITS.compareModelsMax}). Same alias formats as get_models.`
1277
1253
  ),
1278
- expectedPromptTokens: z7.number().int().min(1).optional().describe(
1254
+ expectedPromptTokens: z8.number().int().min(1).optional().describe(
1279
1255
  "Optional. When set with expectedCompletionTokens, computes total per-call cost for each model and picks cheapestForRealisticWorkload \u2014 closes the gap where promptPerMillion alone misleads when prompt:completion price ratios diverge."
1280
1256
  ),
1281
- expectedCompletionTokens: z7.number().int().min(1).optional().describe(
1257
+ expectedCompletionTokens: z8.number().int().min(1).optional().describe(
1282
1258
  "Optional. Pair with expectedPromptTokens to surface workloadCosts and cheapestForRealisticWorkload. Both must be set to enable workload costing."
1283
1259
  )
1284
1260
  },
@@ -1304,39 +1280,39 @@ async function createServer() {
1304
1280
  title: TOOLS.test_model.title,
1305
1281
  description: TOOLS.test_model.description,
1306
1282
  inputSchema: {
1307
- prompt: z7.string().min(1).optional().describe("Prompt sent to each model."),
1308
- userContent: z7.array(UserContentPartSchema).min(1).optional().describe("Multimodal user content. At least one of prompt or userContent required."),
1309
- dryRun: z7.boolean().optional().describe(
1283
+ prompt: z8.string().min(1).optional().describe("Prompt sent to each model."),
1284
+ userContent: z8.array(UserContentPartSchema).min(1).optional().describe("Multimodal user content. At least one of prompt or userContent required."),
1285
+ dryRun: z8.boolean().optional().describe(
1310
1286
  "When true, returns estimated token usage and cost without calling OpenRouter (no API key required)."
1311
1287
  ),
1312
- expectedPromptTokens: z7.number().int().min(1).optional().describe(PARAM_DESCRIPTIONS.expectedPromptTokens),
1313
- expectedCompletionTokens: z7.number().int().min(1).optional().describe(PARAM_DESCRIPTIONS.expectedCompletionTokens),
1314
- models: z7.array(z7.string().min(1)).min(1).max(LIMITS.testModelsMax).describe(`Model IDs to evaluate (1-${LIMITS.testModelsMax}).`),
1315
- timeoutMs: z7.number().int().min(1).optional().describe("Per-model timeout in ms (default 15000, max 60000)."),
1316
- maxTokens: z7.number().int().min(1).optional().describe(
1288
+ expectedPromptTokens: z8.number().int().min(1).optional().describe(PARAM_DESCRIPTIONS.expectedPromptTokens),
1289
+ expectedCompletionTokens: z8.number().int().min(1).optional().describe(PARAM_DESCRIPTIONS.expectedCompletionTokens),
1290
+ models: z8.array(z8.string().min(1)).min(1).max(LIMITS.testModelsMax).describe(`Model IDs to evaluate (1-${LIMITS.testModelsMax}).`),
1291
+ timeoutMs: z8.number().int().min(1).optional().describe("Per-model timeout in ms (default 15000, max 60000)."),
1292
+ maxTokens: z8.number().int().min(1).optional().describe(
1317
1293
  "Completion token cap. For reasoning-capable models, set \u2265 2000 (or omit) \u2014 reasoning tokens count against this before visible output, and too-low caps cause finish_reason=length."
1318
1294
  ),
1319
- systemPrompt: z7.string().min(1).optional().describe("System instruction prepended to prompt."),
1320
- temperature: z7.number().min(0).max(2).optional().describe("Sampling temperature (0-2)."),
1321
- topP: z7.number().gt(0).max(1).optional().describe("Nucleus sampling (0-1]."),
1322
- seed: z7.number().int().optional().describe("Seed for repeatable outputs."),
1295
+ systemPrompt: z8.string().min(1).optional().describe("System instruction prepended to prompt."),
1296
+ temperature: z8.number().min(0).max(2).optional().describe("Sampling temperature (0-2)."),
1297
+ topP: z8.number().gt(0).max(1).optional().describe("Nucleus sampling (0-1]."),
1298
+ seed: z8.number().int().optional().describe("Seed for repeatable outputs."),
1323
1299
  responseFormat: ResponseFormatSchema.describe(
1324
1300
  "Structured output shape request forwarded to OpenRouter (e.g., { type: 'json_object' })."
1325
1301
  ),
1326
- enforceJson: z7.boolean().optional().describe("When true, output must parse as JSON."),
1327
- retries: z7.number().int().min(0).max(3).optional().describe("Retries for transient failures."),
1328
- stream: z7.boolean().optional().describe(
1302
+ enforceJson: z8.boolean().optional().describe("When true, output must parse as JSON."),
1303
+ retries: z8.number().int().min(0).max(3).optional().describe("Retries for transient failures."),
1304
+ stream: z8.boolean().optional().describe(
1329
1305
  "Use OpenRouter SSE streaming so capacity/refusal errors surface quickly. Defaults to false."
1330
1306
  ),
1331
- firstTokenTimeoutMs: z7.number().int().min(1).optional().describe("Streaming-only first-token deadline in ms. Defaults to 10000."),
1307
+ firstTokenTimeoutMs: z8.number().int().min(1).optional().describe("Streaming-only first-token deadline in ms. Defaults to 10000."),
1332
1308
  providerSort: ProviderSortSchema.optional().describe(
1333
1309
  'OpenRouter provider routing sort: "throughput", "price", or "latency".'
1334
1310
  ),
1335
- providerOrder: z7.array(z7.string().min(1)).min(1).max(8).optional().describe("Provider slugs to try first, in order. Up to 8."),
1336
- fallbackModels: z7.array(z7.string().min(1)).min(1).max(5).optional().describe(
1311
+ providerOrder: z8.array(z8.string().min(1)).min(1).max(8).optional().describe("Provider slugs to try first, in order. Up to 8."),
1312
+ fallbackModels: z8.array(z8.string().min(1)).min(1).max(5).optional().describe(
1337
1313
  "Fallback model IDs OpenRouter may try if the primary is unavailable. Up to 5."
1338
1314
  ),
1339
- debug: z7.boolean().optional().describe(
1315
+ debug: z8.boolean().optional().describe(
1340
1316
  "When true, include upstream finish_reason, provider, error, refusal, and usage."
1341
1317
  )
1342
1318
  },
package/manifest.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": "0.3",
3
3
  "name": "index9",
4
- "version": "6.5.3",
4
+ "version": "6.5.5",
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.5.3",
3
+ "version": "6.5.5",
4
4
  "description": "Discover, shortlist, compare, cost-model, and live-test 300+ AI models from your editor",
5
5
  "license": "MIT",
6
6
  "repository": {
package/server.json CHANGED
@@ -7,13 +7,13 @@
7
7
  "url": "https://github.com/index9-org/mcp",
8
8
  "source": "github"
9
9
  },
10
- "version": "6.5.3",
10
+ "version": "6.5.5",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "registryBaseUrl": "https://registry.npmjs.org",
15
15
  "identifier": "@index9/mcp",
16
- "version": "6.5.3",
16
+ "version": "6.5.5",
17
17
  "transport": {
18
18
  "type": "stdio"
19
19
  },