@index9/mcp 6.5.3 → 6.5.4

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,8 @@ 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: "Index9 helps coding assistants pick from live model data.",
266
+ subtitle: "MCP tools for Claude Code, Cursor, VS Code, and Codex to search, compare, cost-model, and live-test 300+ models.",
267
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 ",
@@ -279,9 +279,9 @@ var SITE = {
279
279
  label: "Why this exists",
280
280
  heading: "Your assistant's model knowledge is stale",
281
281
  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."
282
+ "New models ship every week. Prices, aliases, and capabilities change with them.",
283
+ "Without live data, your assistant falls back to training-time memory \u2014 usually a model that's been superseded by something cheaper or better-suited.",
284
+ "Index9 lets it check the live catalog before recommending."
285
285
  ]
286
286
  },
287
287
  howItWorks: {
@@ -309,76 +309,13 @@ var SITE = {
309
309
  caseStudy: {
310
310
  label: "Real session",
311
311
  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
- },
312
+ subheading: "A real eval run picking a model for a TypeScript code-review bot. Real prompt, real tool calls, real verdict.",
313
+ promptTitle: "The prompt",
314
+ toolCallsTitle: "What the assistant did",
343
315
  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
- }
316
+ verdictTitle: "The pick",
317
+ capturedPrefix: "Captured ",
318
+ sourcePrefix: " \xB7 source "
382
319
  },
383
320
  toolsSection: {
384
321
  label: "Tools",
@@ -767,56 +704,92 @@ var ListFacetsToolResultSchema = FacetsResponseSchema.extend({
767
704
  _index9: Index9MetaSchema
768
705
  });
769
706
 
770
- // ../core/dist/schemas/test.js
707
+ // ../core/dist/schemas/case-study.js
771
708
  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(),
709
+ var CaseStudyDecisionSchema = z6.enum(["shortlisted", "tested"]);
710
+ var CaseStudyToolCallSchema = z6.object({
711
+ tool: z6.string(),
712
+ params: z6.string()
713
+ }).strict();
714
+ var CaseStudyCandidateSchema = z6.object({
715
+ id: z6.string(),
716
+ createdAt: z6.string().nullable(),
717
+ decision: CaseStudyDecisionSchema,
718
+ promptPerMillion: z6.number().nullable(),
719
+ completionPerMillion: z6.number().nullable(),
720
+ perPromptCostUsd: z6.number().nullable()
721
+ }).strict();
722
+ var CaseStudyVerdictSchema = z6.object({
723
+ model: z6.string().nullable(),
724
+ body: z6.string()
725
+ }).strict();
726
+ var CaseStudySchema = z6.object({
727
+ capturedAt: z6.string(),
728
+ generatedAt: z6.string(),
729
+ sourceRun: z6.string(),
730
+ evaluatorModelId: z6.string(),
731
+ promptId: z6.string(),
732
+ promptBody: z6.string(),
733
+ totalLatencyMs: z6.number().int(),
734
+ totalCostUsd: z6.number().nullable(),
735
+ toolCallCount: z6.number().int(),
736
+ candidateCount: z6.number().int(),
737
+ selectedModelId: z6.string().nullable(),
738
+ toolCalls: z6.array(CaseStudyToolCallSchema),
739
+ candidates: z6.array(CaseStudyCandidateSchema),
740
+ verdict: CaseStudyVerdictSchema
741
+ }).strict();
742
+
743
+ // ../core/dist/schemas/test.js
744
+ import { z as z7 } from "zod";
745
+ var ResponseFormatSchema = z7.object({
746
+ type: z7.string().min(1)
747
+ }).catchall(z7.unknown()).optional();
748
+ var ProviderSortSchema = z7.enum(["throughput", "price", "latency"]);
749
+ var TestRequestSchema = z7.object({
750
+ prompt: z7.string().min(1).optional(),
751
+ userContent: z7.array(UserContentPartSchema).min(1).optional(),
752
+ dryRun: z7.boolean().optional(),
753
+ expectedPromptTokens: z7.number().int().positive().optional(),
754
+ expectedCompletionTokens: z7.number().int().positive().optional(),
755
+ 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`),
756
+ timeoutMs: z7.number().int().positive().optional(),
757
+ maxTokens: z7.number().int().positive().optional(),
758
+ systemPrompt: z7.string().min(1).optional(),
759
+ temperature: z7.number().min(0).max(2).optional(),
760
+ topP: z7.number().gt(0).lte(1).optional(),
761
+ seed: z7.number().int().optional(),
789
762
  responseFormat: ResponseFormatSchema,
790
- enforceJson: z6.boolean().optional(),
791
- retries: z6.number().int().min(0).max(3).optional(),
763
+ enforceJson: z7.boolean().optional(),
764
+ retries: z7.number().int().min(0).max(3).optional(),
792
765
  // Use OpenRouter's SSE streaming endpoint so capacity/refusal errors
793
766
  // surface in ~1s instead of waiting the full per-model timeout for an
794
767
  // empty 200 OK. Cost/tokens are still returned via stream_options.
795
- stream: z6.boolean().optional(),
768
+ stream: z7.boolean().optional(),
796
769
  // First-token deadline (streaming only). If the upstream sends no
797
770
  // delta within this window, abort the request. Defaults to 10s when
798
771
  // streaming. Ignored when stream=false.
799
- firstTokenTimeoutMs: z6.number().int().positive().optional(),
772
+ firstTokenTimeoutMs: z7.number().int().positive().optional(),
800
773
  // Forwards as `provider.sort` to OpenRouter — opt into routing toward
801
774
  // higher-throughput providers when running benchmarks.
802
775
  providerSort: ProviderSortSchema.optional(),
803
776
  // Forwards as `provider.order` — try these provider slugs first in the
804
777
  // given order before falling back. Capped to stay within reasonable
805
778
  // limits and prevent abuse.
806
- providerOrder: z6.array(z6.string().min(1)).min(1).max(8).optional(),
779
+ providerOrder: z7.array(z7.string().min(1)).min(1).max(8).optional(),
807
780
  // Forwards as the top-level `models` array (NOT `model`). OpenRouter
808
781
  // tries each in order if the primary is unavailable. Different intent
809
782
  // from providerOrder, which routes within a single model.
810
- fallbackModels: z6.array(z6.string().min(1)).min(1).max(5).optional(),
783
+ fallbackModels: z7.array(z7.string().min(1)).min(1).max(5).optional(),
811
784
  // When true, attach a `debug` field on each result with the raw
812
785
  // upstream finish_reason, error message, provider name, refusal, and
813
786
  // usage. Used to diagnose "missing assistant text" without re-running.
814
- debug: z6.boolean().optional()
787
+ debug: z7.boolean().optional()
815
788
  }).strict().superRefine((data, ctx) => {
816
789
  if (data.dryRun === true) {
817
790
  if (!data.prompt && data.expectedPromptTokens === void 0) {
818
791
  ctx.addIssue({
819
- code: z6.ZodIssueCode.custom,
792
+ code: z7.ZodIssueCode.custom,
820
793
  message: "dryRun requires either prompt or expectedPromptTokens",
821
794
  path: ["prompt"]
822
795
  });
@@ -825,24 +798,24 @@ var TestRequestSchema = z6.object({
825
798
  }
826
799
  if (!data.prompt && !data.userContent?.length) {
827
800
  ctx.addIssue({
828
- code: z6.ZodIssueCode.custom,
801
+ code: z7.ZodIssueCode.custom,
829
802
  message: "Prompt or userContent is required",
830
803
  path: ["prompt"]
831
804
  });
832
805
  }
833
806
  });
834
- var UsageTokensSchema = z6.object({
835
- prompt: z6.number().min(0),
836
- completion: z6.number().min(0)
807
+ var UsageTokensSchema = z7.object({
808
+ prompt: z7.number().min(0),
809
+ completion: z7.number().min(0)
837
810
  });
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()
811
+ var TestPricingUsedSchema = z7.object({
812
+ promptPerToken: z7.number().nullable().optional(),
813
+ completionPerToken: z7.number().nullable().optional(),
814
+ promptPerMillion: z7.number().nullable().optional(),
815
+ completionPerMillion: z7.number().nullable().optional(),
816
+ requestUsd: z7.number().nullable().optional()
844
817
  });
845
- var TestFailureReasonSchema = z6.enum([
818
+ var TestFailureReasonSchema = z7.enum([
846
819
  "insufficient_credits",
847
820
  "model_unavailable",
848
821
  "rate_limited",
@@ -854,86 +827,86 @@ var TestFailureReasonSchema = z6.enum([
854
827
  "invalid_request",
855
828
  "unknown"
856
829
  ]);
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()
830
+ var TestDebugInfoSchema = z7.object({
831
+ upstreamId: z7.string().optional(),
832
+ providerName: z7.string().optional(),
833
+ modelPublisher: z7.string().optional(),
834
+ finishReason: z7.string().optional(),
835
+ upstreamError: z7.string().optional(),
836
+ refusal: z7.string().optional(),
837
+ hasToolCalls: z7.boolean().optional(),
838
+ usage: z7.object({
839
+ promptTokens: z7.number().optional(),
840
+ completionTokens: z7.number().optional(),
841
+ totalTokens: z7.number().optional()
869
842
  }).optional()
870
843
  });
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(),
844
+ var TestModelMetadataSchema = z7.object({
845
+ id: z7.string(),
846
+ name: z7.string(),
847
+ created: z7.number().nullable().optional(),
848
+ createdAt: z7.string().nullable().optional(),
876
849
  pricingUsed: TestPricingUsedSchema.optional()
877
850
  });
878
- var TestResultSuccessSchema = z6.object({
879
- modelId: z6.string(),
880
- resolvedModelId: z6.string().optional(),
881
- ok: z6.literal(true),
851
+ var TestResultSuccessSchema = z7.object({
852
+ modelId: z7.string(),
853
+ resolvedModelId: z7.string().optional(),
854
+ ok: z7.literal(true),
882
855
  model: TestModelMetadataSchema,
883
- response: z6.string(),
884
- latencyMs: z6.number().min(0),
856
+ response: z7.string(),
857
+ latencyMs: z7.number().min(0),
885
858
  tokens: UsageTokensSchema,
886
- cost: z6.number().nullable().optional(),
887
- truncated: z6.boolean().optional(),
859
+ cost: z7.number().nullable().optional(),
860
+ truncated: z7.boolean().optional(),
888
861
  debug: TestDebugInfoSchema.optional()
889
862
  });
890
- var TestResultFailureSchema = z6.object({
891
- modelId: z6.string(),
892
- resolvedModelId: z6.string().optional(),
893
- ok: z6.literal(false),
863
+ var TestResultFailureSchema = z7.object({
864
+ modelId: z7.string(),
865
+ resolvedModelId: z7.string().optional(),
866
+ ok: z7.literal(false),
894
867
  model: TestModelMetadataSchema,
895
- error: z6.string(),
868
+ error: z7.string(),
896
869
  failureReason: TestFailureReasonSchema.optional(),
897
- latencyMs: z6.number().min(0),
870
+ latencyMs: z7.number().min(0),
898
871
  debug: TestDebugInfoSchema.optional()
899
872
  });
900
- var TestResultSchema = z6.discriminatedUnion("ok", [
873
+ var TestResultSchema = z7.discriminatedUnion("ok", [
901
874
  TestResultSuccessSchema,
902
875
  TestResultFailureSchema
903
876
  ]);
904
- var TestEstimateResultSchema = z6.object({
905
- modelId: z6.string(),
906
- resolvedModelId: z6.string().optional(),
877
+ var TestEstimateResultSchema = z7.object({
878
+ modelId: z7.string(),
879
+ resolvedModelId: z7.string().optional(),
907
880
  model: TestModelMetadataSchema,
908
881
  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(),
882
+ estimatedCost: z7.number().nullable().optional(),
883
+ tokenCostUsd: z7.number().nullable().optional(),
884
+ requestCostUsd: z7.number().nullable().optional(),
885
+ totalCostUsd: z7.number().nullable().optional(),
913
886
  estimatedCostBasis: PricingBasisSchema.optional()
914
887
  });
915
888
  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()
889
+ missingIds: z7.array(z7.string()).optional(),
890
+ resolvedAliases: z7.record(z7.string(), z7.string()).optional(),
891
+ ambiguousAliases: z7.record(z7.string(), z7.array(z7.string())).optional(),
892
+ suggestions: z7.record(z7.string(), z7.array(SuggestionEntrySchema)).optional(),
893
+ missingDiagnostics: z7.record(z7.string(), MissingModelDiagnosticSchema).optional()
921
894
  };
922
- var TestDryRunResponseSchema = z6.object({
923
- dryRun: z6.literal(true),
924
- results: z6.array(TestEstimateResultSchema),
925
- disclaimer: z6.string(),
895
+ var TestDryRunResponseSchema = z7.object({
896
+ dryRun: z7.literal(true),
897
+ results: z7.array(TestEstimateResultSchema),
898
+ disclaimer: z7.string(),
926
899
  ...TestResolutionFieldsSchema
927
900
  });
928
- var TestLiveResponseSchema = z6.object({
929
- results: z6.array(TestResultSchema),
901
+ var TestLiveResponseSchema = z7.object({
902
+ results: z7.array(TestResultSchema),
930
903
  ...TestResolutionFieldsSchema
931
904
  });
932
- var TestResponseSchema = z6.union([TestDryRunResponseSchema, TestLiveResponseSchema]);
905
+ var TestResponseSchema = z7.union([TestDryRunResponseSchema, TestLiveResponseSchema]);
933
906
 
934
907
  // src/server.ts
935
908
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
936
- import { z as z7 } from "zod";
909
+ import { z as z8 } from "zod";
937
910
 
938
911
  // src/config.ts
939
912
  var DEFAULT_BASE_URL = "https://index9.dev";
@@ -1230,22 +1203,22 @@ async function createServer() {
1230
1203
  title: TOOLS.find_models.title,
1231
1204
  description: TOOLS.find_models.description,
1232
1205
  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)
1206
+ q: z8.string().min(1).optional().describe(PARAM_DESCRIPTIONS.q),
1207
+ limit: z8.number().int().min(1).max(100).default(20).describe("Page size (1-100, default 20)."),
1208
+ cursor: z8.string().min(1).optional().describe(PARAM_DESCRIPTIONS.cursor),
1209
+ sortBy: z8.enum(["relevance", "created", "price"]).default("relevance").describe(PARAM_DESCRIPTIONS.sortBy),
1210
+ sortOrder: z8.enum(["asc", "desc"]).optional().describe("Sort order. Defaults by sortBy."),
1211
+ createdAfter: z8.string().optional().describe("Lower bound for model created timestamp."),
1212
+ createdBefore: z8.string().optional().describe("Upper bound for model created timestamp."),
1213
+ minPrice: z8.number().min(0).optional().describe(PARAM_DESCRIPTIONS.minPrice),
1214
+ maxPrice: z8.number().min(0).optional().describe(PARAM_DESCRIPTIONS.maxPrice),
1215
+ minContext: z8.number().int().min(1).optional().describe("Minimum context window in tokens."),
1216
+ capabilitiesAll: z8.array(z8.enum(CAPABILITIES)).optional().describe(PARAM_DESCRIPTIONS.capabilitiesAll),
1217
+ capabilitiesAny: z8.array(z8.enum(CAPABILITIES)).optional().describe(PARAM_DESCRIPTIONS.capabilitiesAny),
1218
+ modality: z8.enum(OUTPUT_MODALITIES).optional().describe(PARAM_DESCRIPTIONS.modality),
1219
+ provider: z8.array(z8.string().min(1)).optional().describe(PARAM_DESCRIPTIONS.provider),
1220
+ excludeFree: z8.boolean().optional().describe(PARAM_DESCRIPTIONS.excludeFree),
1221
+ requireKeywordMatch: z8.boolean().optional().describe(PARAM_DESCRIPTIONS.requireKeywordMatch)
1249
1222
  },
1250
1223
  outputSchema: FindModelsToolResultSchema.shape,
1251
1224
  annotations: { readOnlyHint: true }
@@ -1258,8 +1231,8 @@ async function createServer() {
1258
1231
  title: TOOLS.get_models.title,
1259
1232
  description: TOOLS.get_models.description,
1260
1233
  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.")
1234
+ ids: z8.array(z8.string().min(1)).min(1).max(100).describe("Model identifiers or aliases. Up to 100."),
1235
+ maxDescriptionChars: z8.number().int().min(0).max(2e3).optional().describe("Truncate descriptions to this many characters.")
1263
1236
  },
1264
1237
  outputSchema: GetModelsToolResultSchema.shape,
1265
1238
  annotations: { readOnlyHint: true }
@@ -1272,13 +1245,13 @@ async function createServer() {
1272
1245
  title: TOOLS.compare_models.title,
1273
1246
  description: TOOLS.compare_models.description,
1274
1247
  inputSchema: {
1275
- ids: z7.array(z7.string().min(1)).min(2).max(LIMITS.compareModelsMax).describe(
1248
+ ids: z8.array(z8.string().min(1)).min(2).max(LIMITS.compareModelsMax).describe(
1276
1249
  `Model identifiers or aliases to compare (2-${LIMITS.compareModelsMax}). Same alias formats as get_models.`
1277
1250
  ),
1278
- expectedPromptTokens: z7.number().int().min(1).optional().describe(
1251
+ expectedPromptTokens: z8.number().int().min(1).optional().describe(
1279
1252
  "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
1253
  ),
1281
- expectedCompletionTokens: z7.number().int().min(1).optional().describe(
1254
+ expectedCompletionTokens: z8.number().int().min(1).optional().describe(
1282
1255
  "Optional. Pair with expectedPromptTokens to surface workloadCosts and cheapestForRealisticWorkload. Both must be set to enable workload costing."
1283
1256
  )
1284
1257
  },
@@ -1304,39 +1277,39 @@ async function createServer() {
1304
1277
  title: TOOLS.test_model.title,
1305
1278
  description: TOOLS.test_model.description,
1306
1279
  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(
1280
+ prompt: z8.string().min(1).optional().describe("Prompt sent to each model."),
1281
+ userContent: z8.array(UserContentPartSchema).min(1).optional().describe("Multimodal user content. At least one of prompt or userContent required."),
1282
+ dryRun: z8.boolean().optional().describe(
1310
1283
  "When true, returns estimated token usage and cost without calling OpenRouter (no API key required)."
1311
1284
  ),
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(
1285
+ expectedPromptTokens: z8.number().int().min(1).optional().describe(PARAM_DESCRIPTIONS.expectedPromptTokens),
1286
+ expectedCompletionTokens: z8.number().int().min(1).optional().describe(PARAM_DESCRIPTIONS.expectedCompletionTokens),
1287
+ models: z8.array(z8.string().min(1)).min(1).max(LIMITS.testModelsMax).describe(`Model IDs to evaluate (1-${LIMITS.testModelsMax}).`),
1288
+ timeoutMs: z8.number().int().min(1).optional().describe("Per-model timeout in ms (default 15000, max 60000)."),
1289
+ maxTokens: z8.number().int().min(1).optional().describe(
1317
1290
  "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
1291
  ),
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."),
1292
+ systemPrompt: z8.string().min(1).optional().describe("System instruction prepended to prompt."),
1293
+ temperature: z8.number().min(0).max(2).optional().describe("Sampling temperature (0-2)."),
1294
+ topP: z8.number().gt(0).max(1).optional().describe("Nucleus sampling (0-1]."),
1295
+ seed: z8.number().int().optional().describe("Seed for repeatable outputs."),
1323
1296
  responseFormat: ResponseFormatSchema.describe(
1324
1297
  "Structured output shape request forwarded to OpenRouter (e.g., { type: 'json_object' })."
1325
1298
  ),
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(
1299
+ enforceJson: z8.boolean().optional().describe("When true, output must parse as JSON."),
1300
+ retries: z8.number().int().min(0).max(3).optional().describe("Retries for transient failures."),
1301
+ stream: z8.boolean().optional().describe(
1329
1302
  "Use OpenRouter SSE streaming so capacity/refusal errors surface quickly. Defaults to false."
1330
1303
  ),
1331
- firstTokenTimeoutMs: z7.number().int().min(1).optional().describe("Streaming-only first-token deadline in ms. Defaults to 10000."),
1304
+ firstTokenTimeoutMs: z8.number().int().min(1).optional().describe("Streaming-only first-token deadline in ms. Defaults to 10000."),
1332
1305
  providerSort: ProviderSortSchema.optional().describe(
1333
1306
  'OpenRouter provider routing sort: "throughput", "price", or "latency".'
1334
1307
  ),
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(
1308
+ providerOrder: z8.array(z8.string().min(1)).min(1).max(8).optional().describe("Provider slugs to try first, in order. Up to 8."),
1309
+ fallbackModels: z8.array(z8.string().min(1)).min(1).max(5).optional().describe(
1337
1310
  "Fallback model IDs OpenRouter may try if the primary is unavailable. Up to 5."
1338
1311
  ),
1339
- debug: z7.boolean().optional().describe(
1312
+ debug: z8.boolean().optional().describe(
1340
1313
  "When true, include upstream finish_reason, provider, error, refusal, and usage."
1341
1314
  )
1342
1315
  },
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.4",
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.4",
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.4",
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.4",
17
17
  "transport": {
18
18
  "type": "stdio"
19
19
  },