@index9/mcp 1.0.0-beta.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.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +155 -0
  3. package/dist/client.d.ts +8 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +53 -0
  6. package/dist/config.d.ts +4 -0
  7. package/dist/config.d.ts.map +1 -0
  8. package/dist/config.js +3 -0
  9. package/dist/index.d.ts +3 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +30 -0
  12. package/dist/logger.d.ts +4 -0
  13. package/dist/logger.d.ts.map +1 -0
  14. package/dist/logger.js +3 -0
  15. package/dist/mcp.d.ts +4 -0
  16. package/dist/mcp.d.ts.map +1 -0
  17. package/dist/mcp.js +159 -0
  18. package/dist/schemas.d.ts +58 -0
  19. package/dist/schemas.d.ts.map +1 -0
  20. package/dist/schemas.js +35 -0
  21. package/dist/tools/compare_models.d.ts +3 -0
  22. package/dist/tools/compare_models.d.ts.map +1 -0
  23. package/dist/tools/compare_models.js +4 -0
  24. package/dist/tools/get_model.d.ts +3 -0
  25. package/dist/tools/get_model.d.ts.map +1 -0
  26. package/dist/tools/get_model.js +4 -0
  27. package/dist/tools/list_models.d.ts +23 -0
  28. package/dist/tools/list_models.d.ts.map +1 -0
  29. package/dist/tools/list_models.js +25 -0
  30. package/dist/tools/recommend_model.d.ts +3 -0
  31. package/dist/tools/recommend_model.d.ts.map +1 -0
  32. package/dist/tools/recommend_model.js +4 -0
  33. package/dist/tools/search_models.d.ts +14 -0
  34. package/dist/tools/search_models.d.ts.map +1 -0
  35. package/dist/tools/search_models.js +9 -0
  36. package/dist/tools/test_model.d.ts +3 -0
  37. package/dist/tools/test_model.d.ts.map +1 -0
  38. package/dist/tools/test_model.js +5 -0
  39. package/dist/types/api.d.ts +156 -0
  40. package/dist/types/api.d.ts.map +1 -0
  41. package/dist/types/api.js +4 -0
  42. package/dist/types/index.d.ts +3 -0
  43. package/dist/types/index.d.ts.map +1 -0
  44. package/dist/types/index.js +2 -0
  45. package/dist/types/models.d.ts +68 -0
  46. package/dist/types/models.d.ts.map +1 -0
  47. package/dist/types/models.js +4 -0
  48. package/package.json +61 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Index9
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,155 @@
1
+ # @index9/mcp
2
+
3
+ [![npm version](https://badge.fury.io/js/%40index9%2Fmcp.svg)](https://badge.fury.io/js/%40index9%2Fmcp)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ Give your AI assistant up-to-date model knowledge. 1000+ models with real-time pricing, context windows, and capabilities. Latest data, instant responses, zero cost.
7
+
8
+ ## ❌ Without Index9 MCP
9
+
10
+ LLMs rely on outdated training data about AI models:
11
+
12
+ - ❌ "Use GPT-4 for complex reasoning" (missing GPT-5.1, Claude Opus 4.5, and latest models)
13
+ - ❌ "This fits in GPT-3.5's 4K context" (current models have 128K-2M+ context windows)
14
+ - ❌ Generic advice without real pricing or capability comparisons
15
+ - ❌ No awareness of cutting-edge models released this month
16
+
17
+ ## ✅ With Index9 MCP
18
+
19
+ Your AI assistant has real-time access to the latest models and provides specific, data-driven recommendations:
20
+
21
+ - ✅ "Use **GPT-5.1** - 400K context, $1.25/million input, latest frontier-grade reasoning with adaptive computation"
22
+ - ✅ "For massive documents, try **Grok 4.1 Fast** with 2M context at $0.2/million input tokens"
23
+ - ✅ "Vision + reasoning needed? Use **Claude Opus 4.5** at $5/million - multimodal with 200K context"
24
+ - ✅ "Budget option: **Arcee Trinity Mini** at $0.04/million for text-only tasks"
25
+ - ✅ Compare the latest models side-by-side with current pricing, test live performance, and get cutting-edge recommendations
26
+
27
+ > *🤖 This section was written using Index9 MCP data - the AI assistant knew about Arcee Trinity Mini before it was cool!*
28
+
29
+ ## Quick Start
30
+
31
+ ### Cursor
32
+
33
+ Open Cursor Settings → MCP → Add new global MCP server
34
+
35
+ ```json
36
+ {
37
+ "mcpServers": {
38
+ "index9": {
39
+ "command": "npx",
40
+ "args": ["-y", "@index9/mcp"]
41
+ }
42
+ }
43
+ }
44
+ ```
45
+
46
+ ### VS Code
47
+
48
+ Open VS Code Settings → MCP Servers → Add Server
49
+
50
+ ```json
51
+ "mcp": {
52
+ "servers": {
53
+ "index9": {
54
+ "type": "stdio",
55
+ "command": "npx",
56
+ "args": ["-y", "@index9/mcp"]
57
+ }
58
+ }
59
+ }
60
+ ```
61
+
62
+ ### Other MCP Clients
63
+
64
+ #### Claude Desktop
65
+
66
+ Edit `~/Library/Application Support/Claude/claude_desktop_config.json`
67
+
68
+ ```json
69
+ {
70
+ "mcpServers": {
71
+ "index9": {
72
+ "command": "npx",
73
+ "args": ["-y", "@index9/mcp"]
74
+ }
75
+ }
76
+ }
77
+ ```
78
+
79
+ #### Claude Code
80
+
81
+ Run in terminal:
82
+
83
+ ```bash
84
+ claude mcp add index9 -- npx -y @index9/mcp
85
+ ```
86
+
87
+ #### Windsurf
88
+
89
+ Add to Windsurf MCP config file
90
+
91
+ ```json
92
+ {
93
+ "mcpServers": {
94
+ "index9": {
95
+ "command": "npx",
96
+ "args": ["-y", "@index9/mcp"]
97
+ }
98
+ }
99
+ }
100
+ ```
101
+
102
+ #### Cline
103
+
104
+ Open Cline → MCP Servers → Edit Configuration
105
+
106
+ ```json
107
+ {
108
+ "mcpServers": {
109
+ "index9": {
110
+ "command": "npx",
111
+ "args": ["-y", "@index9/mcp"]
112
+ }
113
+ }
114
+ }
115
+ ```
116
+
117
+ ## Configuration
118
+
119
+ ### Testing Models (Optional)
120
+
121
+ To use the `test_model` tool, add your OpenRouter API key:
122
+
123
+ ```json
124
+ {
125
+ "mcpServers": {
126
+ "index9": {
127
+ "command": "npx",
128
+ "args": ["@index9/mcp"],
129
+ "env": {
130
+ "OPEN_ROUTER_API_KEY": "your-key-here"
131
+ }
132
+ }
133
+ }
134
+ }
135
+ ```
136
+
137
+ Get your API key from [openrouter.ai/keys](https://openrouter.ai/keys).
138
+
139
+ ## Available Tools
140
+
141
+ - **`list_models`** - List models with optional filters (provider, context, modality, pricing, capabilities)
142
+ - **`search_models`** - Semantic search across models using natural language
143
+ - **`get_model`** - Get complete model details and specifications
144
+ - **`compare_models`** - Compare 2-10 models side-by-side
145
+ - **`recommend_model`** - Get AI-powered model recommendations for use cases
146
+ - **`test_model`** - Run live tests against models via OpenRouter API (requires API key)
147
+
148
+ ## License
149
+
150
+ MIT © [Index9](https://index9.dev)
151
+
152
+ ## Related
153
+
154
+ - [Index9](https://index9.dev) - AI model registry and testing platform
155
+ - [Model Context Protocol](https://modelcontextprotocol.io/) - The protocol this server implements
@@ -0,0 +1,8 @@
1
+ import type { ListModelsResponse, GetModelResponse, SearchModelsResponse, CompareModelsResponse, RecommendModelResponse, TestModelResponse, ListModelsQueryParams } from "./types/index.js";
2
+ export declare function listModels(params: ListModelsQueryParams): Promise<ListModelsResponse>;
3
+ export declare function getModel(modelId: string): Promise<GetModelResponse>;
4
+ export declare function searchModels(query: string, limit?: number, threshold?: number): Promise<SearchModelsResponse>;
5
+ export declare function compareModels(modelIds: string[]): Promise<CompareModelsResponse>;
6
+ export declare function recommendModel(useCase: string, maxPrice?: number, minContext?: number, requiredCapabilities?: string[], limit?: number): Promise<RecommendModelResponse>;
7
+ export declare function testModel(modelIds: string[], testType?: "quick" | "code" | "reasoning" | "instruction" | "tool_calling", openRouterApiKey?: string | null): Promise<TestModelResponse>;
8
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,kBAAkB,CAAC;AAuB1B,wBAAsB,UAAU,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAG3F;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAGzE;AAED,wBAAsB,YAAY,CAChC,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,oBAAoB,CAAC,CAG/B;AAED,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAKtF;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,EACnB,oBAAoB,CAAC,EAAE,MAAM,EAAE,EAC/B,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,sBAAsB,CAAC,CASjC;AAED,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,MAAM,EAAE,EAClB,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,WAAW,GAAG,aAAa,GAAG,cAAc,EAC1E,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CAO5B"}
package/dist/client.js ADDED
@@ -0,0 +1,53 @@
1
+ import axios from "axios";
2
+ import { API_URL } from "./config.js";
3
+ const client = axios.create({
4
+ baseURL: API_URL,
5
+ timeout: 30000,
6
+ });
7
+ client.interceptors.response.use((res) => res, (error) => {
8
+ if (error.response?.status === 404) {
9
+ const message = error.response?.data?.message || "Resource not found";
10
+ throw new Error(message);
11
+ }
12
+ const message = error.response?.data?.message ||
13
+ (error.code === "ECONNABORTED" ? `Request timeout` : null) ||
14
+ (error.code === "ECONNREFUSED" ? `Unable to connect to API server` : null) ||
15
+ error.message;
16
+ throw new Error(message);
17
+ });
18
+ export async function listModels(params) {
19
+ const { data } = await client.get("/models", { params });
20
+ return data;
21
+ }
22
+ export async function getModel(modelId) {
23
+ const { data } = await client.get(`/models/${encodeURIComponent(modelId)}`);
24
+ return data;
25
+ }
26
+ export async function searchModels(query, limit, threshold) {
27
+ const { data } = await client.post("/search", { query, limit, threshold });
28
+ return data;
29
+ }
30
+ export async function compareModels(modelIds) {
31
+ const { data } = await client.post("/models/compare", {
32
+ model_ids: modelIds,
33
+ });
34
+ return data;
35
+ }
36
+ export async function recommendModel(useCase, maxPrice, minContext, requiredCapabilities, limit) {
37
+ const { data } = await client.post("/models/recommend", {
38
+ use_case: useCase,
39
+ max_price_per_m: maxPrice,
40
+ min_context: minContext,
41
+ required_capabilities: requiredCapabilities,
42
+ limit,
43
+ });
44
+ return data;
45
+ }
46
+ export async function testModel(modelIds, testType, openRouterApiKey) {
47
+ const { data } = await client.post("/test", {
48
+ model_ids: modelIds,
49
+ test_type: testType,
50
+ open_router_api_key: openRouterApiKey || undefined,
51
+ });
52
+ return data;
53
+ }
@@ -0,0 +1,4 @@
1
+ declare const API_URL: string;
2
+ declare const OPEN_ROUTER_API_KEY: string | null;
3
+ export { API_URL, OPEN_ROUTER_API_KEY };
4
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,OAAO,QAAyD,CAAC;AACvE,QAAA,MAAM,mBAAmB,eAA0C,CAAC;AAEpE,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,3 @@
1
+ const API_URL = process.env.INDEX9_API_URL || "https://index9.dev/api";
2
+ const OPEN_ROUTER_API_KEY = process.env.OPEN_ROUTER_API_KEY || null;
3
+ export { API_URL, OPEN_ROUTER_API_KEY };
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export * from "./types/index.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAMA,cAAc,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+ import { logger } from "./logger.js";
3
+ import { startMCPServer } from "./mcp.js";
4
+ // Export types for library usage
5
+ export * from "./types/index.js";
6
+ async function main() {
7
+ logger.info("Starting index9 MCP server");
8
+ await startMCPServer();
9
+ }
10
+ process.on("unhandledRejection", (error) => {
11
+ logger.error({
12
+ error: error instanceof Error ? error.message : String(error),
13
+ stack: error instanceof Error ? error.stack : undefined,
14
+ }, "Unhandled rejection");
15
+ process.exit(1);
16
+ });
17
+ process.on("uncaughtException", (error) => {
18
+ logger.error({
19
+ error: error instanceof Error ? error.message : String(error),
20
+ stack: error instanceof Error ? error.stack : undefined,
21
+ }, "Uncaught exception");
22
+ process.exit(1);
23
+ });
24
+ main().catch((error) => {
25
+ logger.error({
26
+ error: error instanceof Error ? error.message : String(error),
27
+ stack: error instanceof Error ? error.stack : undefined,
28
+ }, "Failed to start");
29
+ process.exit(1);
30
+ });
@@ -0,0 +1,4 @@
1
+ import pino from "pino";
2
+ declare const logger: pino.Logger<never, boolean>;
3
+ export { logger };
4
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,QAAA,MAAM,MAAM,6BAA0D,CAAC;AAEvE,OAAO,EAAE,MAAM,EAAE,CAAC"}
package/dist/logger.js ADDED
@@ -0,0 +1,3 @@
1
+ import pino from "pino";
2
+ const logger = pino({ name: "index9", level: "info" }, process.stderr);
3
+ export { logger };
package/dist/mcp.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function createMCPServer(): McpServer;
3
+ export declare function startMCPServer(): Promise<void>;
4
+ //# sourceMappingURL=mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA4BpE,wBAAgB,eAAe,cAgK9B;AAED,wBAAsB,cAAc,kBAenC"}
package/dist/mcp.js ADDED
@@ -0,0 +1,159 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { readFileSync } from "node:fs";
4
+ import { fileURLToPath } from "node:url";
5
+ import { dirname, join } from "node:path";
6
+ import { logger } from "./logger.js";
7
+ import { listModelsTool } from "./tools/list_models.js";
8
+ import { searchModelsTool } from "./tools/search_models.js";
9
+ import { getModelTool } from "./tools/get_model.js";
10
+ import { compareModelsTool } from "./tools/compare_models.js";
11
+ import { recommendModelTool } from "./tools/recommend_model.js";
12
+ import { testModelTool } from "./tools/test_model.js";
13
+ import { OPEN_ROUTER_API_KEY } from "./config.js";
14
+ import { listModelsSchema, searchModelsSchema, getModelSchema, compareModelsSchema, recommendModelSchema, testModelSchema, } from "./schemas.js";
15
+ const __filename = fileURLToPath(import.meta.url);
16
+ const __dirname = dirname(__filename);
17
+ const packageJson = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf-8"));
18
+ export function createMCPServer() {
19
+ const server = new McpServer({
20
+ name: "index9",
21
+ version: packageJson.version,
22
+ });
23
+ server.registerTool("list_models", {
24
+ title: "List Models",
25
+ description: "List AI models with optional filters. Filter by: provider or owner (openai, anthropic, google, etc.), min_context (e.g. 100000), modality (text, vision, audio, video, image), max_price_per_m (USD per million tokens), supports_tool_calling (boolean), supports_json_mode (boolean), tokenizer (model family: GPT, Claude, Llama3), output_modality (text, image, embeddings). Returns pricing, context window, max output tokens, input_modalities array, output_modalities array, capabilities (vision, audio, tool_calling, json_mode), and architecture (tokenizer family) for each model.",
26
+ inputSchema: listModelsSchema,
27
+ }, async (input) => {
28
+ try {
29
+ const result = await listModelsTool(input);
30
+ return {
31
+ content: [{ type: "text", text: JSON.stringify(result) }],
32
+ structuredContent: result,
33
+ };
34
+ }
35
+ catch (error) {
36
+ const errorMessage = error instanceof Error ? error.message : String(error);
37
+ logger.error({ tool: "list_models", error: errorMessage }, "Tool execution failed");
38
+ throw error;
39
+ }
40
+ });
41
+ server.registerTool("search_models", {
42
+ title: "Search Models",
43
+ description: 'Semantic search across 1000+ AI models using natural language queries. Uses vector embeddings (semantic search) combined with fuzzy text matching to find relevant models. Examples: "fast cheap model for code generation", "vision model under $1 per million tokens", "best reasoning model with large context". Returns models ranked by similarity score (0-1, default threshold 0.5) with descriptions, pricing, context window, and capabilities (vision, tool_calling).',
44
+ inputSchema: searchModelsSchema,
45
+ }, async (input) => {
46
+ try {
47
+ const result = await searchModelsTool(input);
48
+ return {
49
+ content: [{ type: "text", text: JSON.stringify(result) }],
50
+ structuredContent: result,
51
+ };
52
+ }
53
+ catch (error) {
54
+ const errorMessage = error instanceof Error ? error.message : String(error);
55
+ logger.error({ tool: "search_models", error: errorMessage }, "Tool execution failed");
56
+ throw error;
57
+ }
58
+ });
59
+ server.registerTool("get_model", {
60
+ title: "Get Model",
61
+ description: "Get complete details for a specific model by ID. Returns: description, context window, max output tokens, pricing (input/output per million tokens), extended pricing (image, audio, web_search, cache_read, cache_write), capabilities (vision, audio, function_calling, tool_calling, json_mode, custom), supported_parameters, input/output modalities, architecture (tokenizer, instruct_type), is_moderated, per_request_limits, and deployments. If exact match fails, semantic search may be used to find similar models.",
62
+ inputSchema: getModelSchema,
63
+ }, async (input) => {
64
+ try {
65
+ const result = await getModelTool(input);
66
+ return {
67
+ content: [{ type: "text", text: JSON.stringify(result) }],
68
+ structuredContent: result,
69
+ };
70
+ }
71
+ catch (error) {
72
+ const errorMessage = error instanceof Error ? error.message : String(error);
73
+ logger.error({ tool: "get_model", error: errorMessage }, "Tool execution failed");
74
+ throw error;
75
+ }
76
+ });
77
+ server.registerTool("compare_models", {
78
+ title: "Compare Models",
79
+ description: "Compare 2-10 models side-by-side. Returns unified view of: context windows, max output tokens, pricing (input/output), and capabilities (vision, tool_calling, custom). Includes not_found array for any model IDs that couldn't be located. Useful for making final selection between candidate models.",
80
+ inputSchema: compareModelsSchema,
81
+ }, async (input) => {
82
+ try {
83
+ const model_ids = Array.from(new Set(input.model_ids || []));
84
+ if (model_ids.length < 2) {
85
+ throw new Error("At least 2 unique model IDs are required");
86
+ }
87
+ const result = await compareModelsTool({ model_ids });
88
+ return {
89
+ content: [{ type: "text", text: JSON.stringify(result) }],
90
+ structuredContent: result,
91
+ };
92
+ }
93
+ catch (error) {
94
+ const errorMessage = error instanceof Error ? error.message : String(error);
95
+ logger.error({ tool: "compare_models", error: errorMessage }, "Tool execution failed");
96
+ throw error;
97
+ }
98
+ });
99
+ server.registerTool("recommend_model", {
100
+ title: "Recommend Model",
101
+ description: "Get ranked model recommendations for a use case. Describe what you're building (e.g. 'coding assistant', 'customer support chatbot', 'RAG pipeline'). Optionally set max_price_per_m, min_context, and required_capabilities (vision, tool_calling, audio, video). Returns scored recommendations (higher score = better match) optimized for your requirements with context window and pricing.",
102
+ inputSchema: recommendModelSchema,
103
+ }, async (input) => {
104
+ try {
105
+ const result = await recommendModelTool(input);
106
+ return {
107
+ content: [{ type: "text", text: JSON.stringify(result) }],
108
+ structuredContent: result,
109
+ };
110
+ }
111
+ catch (error) {
112
+ const errorMessage = error instanceof Error ? error.message : String(error);
113
+ logger.error({ tool: "recommend_model", error: errorMessage }, "Tool execution failed");
114
+ throw error;
115
+ }
116
+ });
117
+ server.registerTool("test_model", {
118
+ title: "Test Model",
119
+ description: "Run live tests against 1-5 models via OpenRouter API. **Requires OPEN_ROUTER_API_KEY environment variable** - set this in your MCP client configuration to enable. Test types: 'quick' (basic math), 'code' (Python function), 'reasoning' (logic puzzle), 'instruction' (follow formatting), 'tool_calling' (verify tool use works). Returns latency, output, token usage, cost estimates, and for tool_calling tests: tool_calls_detected boolean. Use to validate models before committing. Charges are billed directly to your OpenRouter account. Get your API key from: https://openrouter.ai/keys",
120
+ inputSchema: testModelSchema,
121
+ }, async (input) => {
122
+ try {
123
+ if (!OPEN_ROUTER_API_KEY) {
124
+ return {
125
+ content: [
126
+ {
127
+ type: "text",
128
+ text: "Error: OPEN_ROUTER_API_KEY is required to use test_model. This tool allows you to run live tests against AI models via OpenRouter API.\n\nTo use this tool:\n1. Get your API key from https://openrouter.ai/keys\n2. Add OPEN_ROUTER_API_KEY to your MCP client configuration (e.g., in Cursor settings or Claude Desktop config)\n3. Restart your MCP client\n\nCharges are billed directly to your OpenRouter account.",
129
+ },
130
+ ],
131
+ isError: true,
132
+ };
133
+ }
134
+ const result = await testModelTool(input);
135
+ return {
136
+ content: [{ type: "text", text: JSON.stringify(result) }],
137
+ structuredContent: result,
138
+ };
139
+ }
140
+ catch (error) {
141
+ const errorMessage = error instanceof Error ? error.message : String(error);
142
+ logger.error({ tool: "test_model", error: errorMessage }, "Tool execution failed");
143
+ throw error;
144
+ }
145
+ });
146
+ return server;
147
+ }
148
+ export async function startMCPServer() {
149
+ logger.info("Starting MCP server with stdio transport");
150
+ const server = createMCPServer();
151
+ const transport = new StdioServerTransport();
152
+ await server.connect(transport);
153
+ logger.info("MCP server ready - awaiting requests");
154
+ process.on("SIGINT", async () => {
155
+ logger.info("Shutting down MCP server");
156
+ await server.close();
157
+ process.exit(0);
158
+ });
159
+ }
@@ -0,0 +1,58 @@
1
+ import { z } from "zod";
2
+ export declare const listModelsSchema: z.ZodObject<{
3
+ provider: z.ZodOptional<z.ZodString>;
4
+ owner: z.ZodOptional<z.ZodString>;
5
+ min_context: z.ZodOptional<z.ZodNumber>;
6
+ modality: z.ZodOptional<z.ZodEnum<{
7
+ text: "text";
8
+ vision: "vision";
9
+ audio: "audio";
10
+ video: "video";
11
+ image: "image";
12
+ }>>;
13
+ supports_tool_calling: z.ZodOptional<z.ZodBoolean>;
14
+ supports_json_mode: z.ZodOptional<z.ZodBoolean>;
15
+ tokenizer: z.ZodOptional<z.ZodString>;
16
+ output_modality: z.ZodOptional<z.ZodEnum<{
17
+ text: "text";
18
+ image: "image";
19
+ embeddings: "embeddings";
20
+ }>>;
21
+ max_price_per_m: z.ZodOptional<z.ZodNumber>;
22
+ limit: z.ZodDefault<z.ZodNumber>;
23
+ }, z.core.$strip>;
24
+ export declare const searchModelsSchema: z.ZodObject<{
25
+ query: z.ZodString;
26
+ limit: z.ZodDefault<z.ZodNumber>;
27
+ threshold: z.ZodDefault<z.ZodNumber>;
28
+ }, z.core.$strip>;
29
+ export declare const getModelSchema: z.ZodObject<{
30
+ model_id: z.ZodString;
31
+ }, z.core.$strip>;
32
+ export declare const compareModelsSchema: z.ZodObject<{
33
+ model_ids: z.ZodArray<z.ZodString>;
34
+ }, z.core.$strip>;
35
+ export declare const recommendModelSchema: z.ZodObject<{
36
+ use_case: z.ZodString;
37
+ max_price_per_m: z.ZodOptional<z.ZodNumber>;
38
+ min_context: z.ZodOptional<z.ZodNumber>;
39
+ required_capabilities: z.ZodOptional<z.ZodArray<z.ZodString>>;
40
+ limit: z.ZodDefault<z.ZodNumber>;
41
+ }, z.core.$strip>;
42
+ export declare const testModelSchema: z.ZodObject<{
43
+ model_ids: z.ZodArray<z.ZodString>;
44
+ test_type: z.ZodDefault<z.ZodEnum<{
45
+ tool_calling: "tool_calling";
46
+ quick: "quick";
47
+ code: "code";
48
+ reasoning: "reasoning";
49
+ instruction: "instruction";
50
+ }>>;
51
+ }, z.core.$strip>;
52
+ export type ListModelsInput = z.infer<typeof listModelsSchema>;
53
+ export type SearchModelsInput = z.infer<typeof searchModelsSchema>;
54
+ export type GetModelInput = z.infer<typeof getModelSchema>;
55
+ export type CompareModelsInput = z.infer<typeof compareModelsSchema>;
56
+ export type RecommendModelInput = z.infer<typeof recommendModelSchema>;
57
+ export type TestModelInput = z.infer<typeof testModelSchema>;
58
+ //# sourceMappingURL=schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;iBAW3B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;iBAI7B,CAAC;AAEH,eAAO,MAAM,cAAc;;iBAEzB,CAAC;AAEH,eAAO,MAAM,mBAAmB;;iBAE9B,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;iBAM/B,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;iBAG1B,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC/D,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AACnE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAC3D,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AACrE,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACvE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { z } from "zod";
2
+ export const listModelsSchema = z.object({
3
+ provider: z.string().optional(),
4
+ owner: z.string().optional(),
5
+ min_context: z.number().min(0).optional(),
6
+ modality: z.enum(["text", "vision", "audio", "video", "image"]).optional(),
7
+ supports_tool_calling: z.boolean().optional(),
8
+ supports_json_mode: z.boolean().optional(),
9
+ tokenizer: z.string().optional(),
10
+ output_modality: z.enum(["text", "image", "embeddings"]).optional(),
11
+ max_price_per_m: z.number().min(0).optional(),
12
+ limit: z.number().min(1).max(100).default(10),
13
+ });
14
+ export const searchModelsSchema = z.object({
15
+ query: z.string().min(1),
16
+ limit: z.number().min(1).max(50).default(10),
17
+ threshold: z.number().min(0).max(1).default(0.5),
18
+ });
19
+ export const getModelSchema = z.object({
20
+ model_id: z.string().min(1),
21
+ });
22
+ export const compareModelsSchema = z.object({
23
+ model_ids: z.array(z.string()).min(2).max(10),
24
+ });
25
+ export const recommendModelSchema = z.object({
26
+ use_case: z.string().min(1),
27
+ max_price_per_m: z.number().min(0).optional(),
28
+ min_context: z.number().min(0).optional(),
29
+ required_capabilities: z.array(z.string()).optional(),
30
+ limit: z.number().min(1).max(20).default(5),
31
+ });
32
+ export const testModelSchema = z.object({
33
+ model_ids: z.array(z.string()).min(1).max(5),
34
+ test_type: z.enum(["quick", "code", "reasoning", "instruction", "tool_calling"]).default("quick"),
35
+ });
@@ -0,0 +1,3 @@
1
+ import type { CompareModelsInput } from "../schemas.js";
2
+ export declare function compareModelsTool(input: CompareModelsInput): Promise<import("../index.js").CompareModelsResponse>;
3
+ //# sourceMappingURL=compare_models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare_models.d.ts","sourceRoot":"","sources":["../../src/tools/compare_models.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExD,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,kBAAkB,wDAEhE"}
@@ -0,0 +1,4 @@
1
+ import { compareModels } from "../client.js";
2
+ export async function compareModelsTool(input) {
3
+ return compareModels(input.model_ids);
4
+ }
@@ -0,0 +1,3 @@
1
+ import type { GetModelInput } from "../schemas.js";
2
+ export declare function getModelTool(input: GetModelInput): Promise<import("../index.js").GetModelResponse>;
3
+ //# sourceMappingURL=get_model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get_model.d.ts","sourceRoot":"","sources":["../../src/tools/get_model.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,wBAAsB,YAAY,CAAC,KAAK,EAAE,aAAa,mDAEtD"}
@@ -0,0 +1,4 @@
1
+ import { getModel } from "../client.js";
2
+ export async function getModelTool(input) {
3
+ return getModel(input.model_id);
4
+ }
@@ -0,0 +1,23 @@
1
+ import type { ListModelsInput } from "../schemas.js";
2
+ export declare function listModelsTool(input: ListModelsInput): Promise<{
3
+ models: {
4
+ id: string;
5
+ name: string;
6
+ provider: string;
7
+ context_window: number | null;
8
+ max_output_tokens: number | null;
9
+ input_modalities: string[];
10
+ pricing: {
11
+ input: number | null;
12
+ output: number | null;
13
+ };
14
+ capabilities: {
15
+ vision: boolean;
16
+ audio: boolean;
17
+ tool_calling: boolean;
18
+ json_mode: boolean;
19
+ };
20
+ architecture: Pick<import("../index.js").ModelArchitecture, "tokenizer">;
21
+ }[];
22
+ }>;
23
+ //# sourceMappingURL=list_models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list_models.d.ts","sourceRoot":"","sources":["../../src/tools/list_models.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,wBAAsB,cAAc,CAAC,KAAK,EAAE,eAAe;;;;;;;;;;;;;;;;;;;;GAuB1D"}
@@ -0,0 +1,25 @@
1
+ import { listModels } from "../client.js";
2
+ export async function listModelsTool(input) {
3
+ const result = await listModels(input);
4
+ return {
5
+ models: result.models.map((m) => ({
6
+ id: m.id,
7
+ name: m.name,
8
+ provider: m.provider,
9
+ context_window: m.context_window,
10
+ max_output_tokens: m.max_output_tokens,
11
+ input_modalities: m.input_modalities,
12
+ pricing: {
13
+ input: m.pricing.input,
14
+ output: m.pricing.output,
15
+ },
16
+ capabilities: {
17
+ vision: m.capabilities.vision,
18
+ audio: m.capabilities.audio,
19
+ tool_calling: m.capabilities.tool_calling,
20
+ json_mode: m.capabilities.json_mode,
21
+ },
22
+ architecture: m.architecture,
23
+ })),
24
+ };
25
+ }
@@ -0,0 +1,3 @@
1
+ import type { RecommendModelInput } from "../schemas.js";
2
+ export declare function recommendModelTool(input: RecommendModelInput): Promise<import("../index.js").RecommendModelResponse>;
3
+ //# sourceMappingURL=recommend_model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recommend_model.d.ts","sourceRoot":"","sources":["../../src/tools/recommend_model.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEzD,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,mBAAmB,yDAQlE"}
@@ -0,0 +1,4 @@
1
+ import { recommendModel } from "../client.js";
2
+ export async function recommendModelTool(input) {
3
+ return recommendModel(input.use_case, input.max_price_per_m, input.min_context, input.required_capabilities, input.limit);
4
+ }
@@ -0,0 +1,14 @@
1
+ import type { SearchModelsInput } from "../schemas.js";
2
+ export declare function searchModelsTool(input: SearchModelsInput): Promise<{
3
+ results: {
4
+ id: string;
5
+ name: string;
6
+ description: string | null;
7
+ similarity: number;
8
+ provider: string;
9
+ context_window: number | null;
10
+ pricing: import("../index.js").ModelPricing;
11
+ capabilities: import("../index.js").SearchModelCapabilities;
12
+ }[];
13
+ }>;
14
+ //# sourceMappingURL=search_models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search_models.d.ts","sourceRoot":"","sources":["../../src/tools/search_models.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEvD,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB;;;;;;;;;;;GAO9D"}
@@ -0,0 +1,9 @@
1
+ import { searchModels } from "../client.js";
2
+ export async function searchModelsTool(input) {
3
+ const query = input.query.trim();
4
+ if (!query) {
5
+ throw new Error("Search query is required and must not be empty");
6
+ }
7
+ const result = await searchModels(query, input.limit, input.threshold);
8
+ return { results: result.results };
9
+ }
@@ -0,0 +1,3 @@
1
+ import type { TestModelInput } from "../schemas.js";
2
+ export declare function testModelTool(input: TestModelInput): Promise<import("../index.js").TestModelResponse>;
3
+ //# sourceMappingURL=test_model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test_model.d.ts","sourceRoot":"","sources":["../../src/tools/test_model.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,wBAAsB,aAAa,CAAC,KAAK,EAAE,cAAc,oDAExD"}
@@ -0,0 +1,5 @@
1
+ import { testModel } from "../client.js";
2
+ import { OPEN_ROUTER_API_KEY } from "../config.js";
3
+ export async function testModelTool(input) {
4
+ return testModel(input.model_ids, input.test_type, OPEN_ROUTER_API_KEY);
5
+ }
@@ -0,0 +1,156 @@
1
+ /**
2
+ * API Types - Request and response types for HTTP API endpoints
3
+ */
4
+ import type { ListModelsFilters, ModelPricing, ModelCapabilities, ModelArchitecture, ExtendedPricing, ModelLimits, PerRequestLimits } from "./models.js";
5
+ export interface ListModelsQueryParams extends ListModelsFilters {
6
+ owner?: string;
7
+ }
8
+ export interface ListModelsResponse {
9
+ models: Array<{
10
+ id: string;
11
+ name: string;
12
+ provider: string;
13
+ context_window: number | null;
14
+ max_output_tokens: number | null;
15
+ input_modalities: string[];
16
+ output_modalities: string[];
17
+ pricing: ModelPricing;
18
+ capabilities: ModelCapabilities;
19
+ architecture: Pick<ModelArchitecture, "tokenizer">;
20
+ }>;
21
+ }
22
+ export interface DeploymentPricing {
23
+ input: number | null;
24
+ output: number | null;
25
+ }
26
+ export interface Benchmark {
27
+ dataset: string;
28
+ score: number;
29
+ percentile: number | null;
30
+ }
31
+ export interface GetModelCapabilities extends Omit<ModelCapabilities, "audio"> {
32
+ function_calling: boolean;
33
+ custom: string[];
34
+ }
35
+ export interface GetModelResponse {
36
+ id: string;
37
+ name: string;
38
+ provider: string;
39
+ description: string | null;
40
+ family: string | null;
41
+ version: string | null;
42
+ release_date: string | null;
43
+ limits: {
44
+ context_window: number;
45
+ max_output_tokens: number | null;
46
+ };
47
+ pricing: ModelPricing;
48
+ extended_pricing: ExtendedPricing | null;
49
+ capabilities: GetModelCapabilities;
50
+ supported_parameters: string[];
51
+ is_moderated: boolean;
52
+ input_modalities: string[];
53
+ output_modalities: string[];
54
+ architecture: ModelArchitecture;
55
+ per_request_limits: PerRequestLimits | null;
56
+ deployments: Array<{
57
+ provider: string;
58
+ external_id: string | null;
59
+ is_available: boolean;
60
+ pricing: DeploymentPricing;
61
+ }>;
62
+ benchmarks: Benchmark[];
63
+ }
64
+ export interface SearchModelsRequest {
65
+ query: string;
66
+ limit?: number;
67
+ threshold?: number;
68
+ }
69
+ export interface SearchModelCapabilities {
70
+ vision: boolean | null;
71
+ tool_calling: boolean | null;
72
+ }
73
+ export interface SearchModelsResponse {
74
+ results: Array<{
75
+ id: string;
76
+ name: string;
77
+ description: string | null;
78
+ similarity: number;
79
+ provider: string;
80
+ context_window: number | null;
81
+ pricing: ModelPricing;
82
+ capabilities: SearchModelCapabilities;
83
+ }>;
84
+ }
85
+ export interface CompareModelsRequest {
86
+ model_ids: string[];
87
+ }
88
+ export interface CompareModelCapabilities {
89
+ vision: boolean | null;
90
+ tool_calling: boolean | null;
91
+ custom: string[];
92
+ }
93
+ export interface CompareModelsResponse {
94
+ models: Array<{
95
+ id: string;
96
+ name: string;
97
+ provider: string;
98
+ limits: ModelLimits;
99
+ pricing: ModelPricing;
100
+ capabilities: CompareModelCapabilities;
101
+ benchmarks: Benchmark[];
102
+ }>;
103
+ not_found?: string[];
104
+ suggestions?: Record<string, Array<{
105
+ id: string;
106
+ name: string;
107
+ similarity: number;
108
+ }>>;
109
+ }
110
+ export interface RecommendModelRequest {
111
+ use_case: string;
112
+ max_price_per_m?: number;
113
+ min_context?: number;
114
+ required_capabilities?: string[];
115
+ limit?: number;
116
+ }
117
+ export interface RecommendModelResponse {
118
+ use_case: string;
119
+ recommendations: Array<{
120
+ id: string;
121
+ name: string;
122
+ score: number;
123
+ context_window: number | null;
124
+ pricing: ModelPricing;
125
+ }>;
126
+ }
127
+ export interface TestModelRequest {
128
+ model_ids: string[];
129
+ test_type?: "quick" | "code" | "reasoning" | "instruction" | "tool_calling";
130
+ }
131
+ export interface TokensUsed {
132
+ prompt_tokens: number;
133
+ completion_tokens: number;
134
+ total_tokens: number;
135
+ }
136
+ export interface CostEstimate {
137
+ input_cost: number | null;
138
+ output_cost: number | null;
139
+ total_cost: number | null;
140
+ }
141
+ export interface TestModelResult {
142
+ model_id: string;
143
+ model_name: string;
144
+ latency_ms: number;
145
+ output: string | null;
146
+ tokens_used: TokensUsed | null;
147
+ cost_estimate: CostEstimate;
148
+ tool_calls_detected?: boolean;
149
+ error: string | null;
150
+ }
151
+ export interface TestModelResponse {
152
+ test_type: string;
153
+ prompt: string;
154
+ results: TestModelResult[];
155
+ }
156
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/types/api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAGrB,MAAM,WAAW,qBAAsB,SAAQ,iBAAiB;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,KAAK,CAAC;QACZ,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;QACjC,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAC3B,iBAAiB,EAAE,MAAM,EAAE,CAAC;QAC5B,OAAO,EAAE,YAAY,CAAC;QACtB,YAAY,EAAE,iBAAiB,CAAC;QAChC,YAAY,EAAE,IAAI,CAAC,iBAAiB,EAAE,WAAW,CAAC,CAAC;KACpD,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,OAAO,CAAC;IAC5E,gBAAgB,EAAE,OAAO,CAAC;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE;QACN,cAAc,EAAE,MAAM,CAAC;QACvB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;KAClC,CAAC;IACF,OAAO,EAAE,YAAY,CAAC;IACtB,gBAAgB,EAAE,eAAe,GAAG,IAAI,CAAC;IACzC,YAAY,EAAE,oBAAoB,CAAC;IACnC,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,YAAY,EAAE,OAAO,CAAC;IACtB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,YAAY,EAAE,iBAAiB,CAAC;IAChC,kBAAkB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC5C,WAAW,EAAE,KAAK,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,YAAY,EAAE,OAAO,CAAC;QACtB,OAAO,EAAE,iBAAiB,CAAC;KAC5B,CAAC,CAAC;IACH,UAAU,EAAE,SAAS,EAAE,CAAC;CACzB;AAGD,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,KAAK,CAAC;QACb,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,OAAO,EAAE,YAAY,CAAC;QACtB,YAAY,EAAE,uBAAuB,CAAC;KACvC,CAAC,CAAC;CACJ;AAGD,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,KAAK,CAAC;QACZ,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,WAAW,CAAC;QACpB,OAAO,EAAE,YAAY,CAAC;QACtB,YAAY,EAAE,wBAAwB,CAAC;QACvC,UAAU,EAAE,SAAS,EAAE,CAAC;KACzB,CAAC,CAAC;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;CACvF;AAGD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,KAAK,CAAC;QACrB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,OAAO,EAAE,YAAY,CAAC;KACvB,CAAC,CAAC;CACJ;AAGD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,WAAW,GAAG,aAAa,GAAG,cAAc,CAAC;CAC7E;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,WAAW,EAAE,UAAU,GAAG,IAAI,CAAC;IAC/B,aAAa,EAAE,YAAY,CAAC;IAC5B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * API Types - Request and response types for HTTP API endpoints
3
+ */
4
+ export {};
@@ -0,0 +1,3 @@
1
+ export * from "./models.js";
2
+ export * from "./api.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from "./models.js";
2
+ export * from "./api.js";
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Model Types - Normalized model interface for real-time provider federation
3
+ */
4
+ export interface ModelPricing {
5
+ input: number | null;
6
+ output: number | null;
7
+ }
8
+ export interface ModelCapabilities {
9
+ vision: boolean;
10
+ audio: boolean;
11
+ tool_calling: boolean;
12
+ json_mode: boolean;
13
+ }
14
+ export interface ModelArchitecture {
15
+ tokenizer: string | null;
16
+ instruct_type: string | null;
17
+ }
18
+ export interface ExtendedPricing {
19
+ image: number | null;
20
+ audio: number | null;
21
+ web_search: number | null;
22
+ cache_read: number | null;
23
+ cache_write: number | null;
24
+ discount: number | null;
25
+ }
26
+ export interface ModelLimits {
27
+ context_window: number | null;
28
+ max_output_tokens: number | null;
29
+ }
30
+ export interface PerRequestLimits {
31
+ prompt_tokens: number | null;
32
+ completion_tokens: number | null;
33
+ }
34
+ export interface NormalizedModel {
35
+ id: string;
36
+ name: string;
37
+ provider: string;
38
+ context_window: number | null;
39
+ max_output_tokens: number | null;
40
+ pricing: ModelPricing;
41
+ capabilities: ModelCapabilities;
42
+ description: string | null;
43
+ release_date: string | null;
44
+ input_modalities: string[];
45
+ output_modalities: string[];
46
+ supported_parameters: string[];
47
+ architecture: ModelArchitecture;
48
+ extended_pricing: ExtendedPricing | null;
49
+ is_moderated: boolean;
50
+ per_request_limits: PerRequestLimits | null;
51
+ }
52
+ export interface ProviderAdapter {
53
+ id: string;
54
+ name: string;
55
+ fetchModels(): Promise<NormalizedModel[]>;
56
+ }
57
+ export interface ListModelsFilters {
58
+ provider?: string;
59
+ min_context?: number;
60
+ modality?: "text" | "vision" | "audio" | "video" | "image";
61
+ max_price_per_m?: number;
62
+ supports_tool_calling?: boolean;
63
+ supports_json_mode?: boolean;
64
+ tokenizer?: string;
65
+ output_modality?: "text" | "image" | "embeddings";
66
+ limit?: number;
67
+ }
68
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/types/models.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,OAAO,EAAE,YAAY,CAAC;IACtB,YAAY,EAAE,iBAAiB,CAAC;IAChC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,YAAY,EAAE,iBAAiB,CAAC;IAChC,gBAAgB,EAAE,eAAe,GAAG,IAAI,CAAC;IACzC,YAAY,EAAE,OAAO,CAAC;IACtB,kBAAkB,EAAE,gBAAgB,GAAG,IAAI,CAAC;CAC7C;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,YAAY,CAAC;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Model Types - Normalized model interface for real-time provider federation
3
+ */
4
+ export {};
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@index9/mcp",
3
+ "version": "1.0.0-beta.0",
4
+ "description": "Give your AI assistant up-to-date model knowledge. 1000+ models with real-time pricing, context windows, and capabilities. Latest data, instant responses, zero cost.",
5
+ "keywords": [
6
+ "mcp",
7
+ "model-context-protocol",
8
+ "ai",
9
+ "llm",
10
+ "models",
11
+ "pricing",
12
+ "capabilities",
13
+ "context-window",
14
+ "real-time",
15
+ "api",
16
+ "sdk",
17
+ "openrouter"
18
+ ],
19
+ "homepage": "https://index9.dev",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/index9-org/mcp.git"
23
+ },
24
+ "bugs": {
25
+ "url": "https://github.com/index9-org/mcp/issues"
26
+ },
27
+ "license": "MIT",
28
+ "author": "Index9 <hello@index9.dev>",
29
+ "type": "module",
30
+ "main": "dist/index.js",
31
+ "types": "dist/index.d.ts",
32
+ "files": [
33
+ "dist"
34
+ ],
35
+ "bin": {
36
+ "index9": "./dist/index.js"
37
+ },
38
+ "dependencies": {
39
+ "@modelcontextprotocol/sdk": "^1.24.2",
40
+ "axios": "^1.13.2",
41
+ "pino": "^10.1.0",
42
+ "zod": "^4.1.13"
43
+ },
44
+ "devDependencies": {
45
+ "@types/node": "^24.10.1",
46
+ "pino-pretty": "^13.1.3",
47
+ "tsx": "^4.21.0",
48
+ "typescript": "^5.9.3"
49
+ },
50
+ "publishConfig": {
51
+ "access": "public"
52
+ },
53
+ "scripts": {
54
+ "build": "tsc",
55
+ "typecheck": "tsc --noEmit",
56
+ "start": "node dist/index.js",
57
+ "dev": "tsx watch --env-file=.env src/index.ts",
58
+ "publish:beta": "pnpm publish --tag beta",
59
+ "publish:prod": "pnpm publish --tag latest"
60
+ }
61
+ }