UNPKG

ultra-mcp

Version:

Ultra MCP, a MCP server for using OpenAI, Gemini, and Grok Models with a single MCP interface. Supports node.js and Vercel AI SDK

1,276 lines (1,262 loc) 400 kB
#!/usr/bin/env node "use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __esm = (fn, res) => function __init() { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc4) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc4 = __getOwnPropDesc(from, key)) || desc4.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // node_modules/tsup/assets/cjs_shims.js var init_cjs_shims = __esm({ "node_modules/tsup/assets/cjs_shims.js"() { "use strict"; } }); // src/config/schema.ts var import_zod, ApiKeySchema, VectorConfigSchema, ConfigSchema, defaultConfig; var init_schema = __esm({ "src/config/schema.ts"() { "use strict"; init_cjs_shims(); import_zod = require("zod"); ApiKeySchema = import_zod.z.string().min(1).optional(); VectorConfigSchema = import_zod.z.object({ defaultProvider: import_zod.z.enum(["openai", "azure", "gemini", "openai-compatible"]).default("openai"), chunkSize: import_zod.z.number().min(500).max(4e3).default(1500), chunkOverlap: import_zod.z.number().min(0).max(500).default(200), batchSize: import_zod.z.number().min(1).max(50).default(10), filePatterns: import_zod.z.array(import_zod.z.string()).default([ "**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "**/*.md", "**/*.mdx", "**/*.txt", "**/*.json", "**/*.yaml", "**/*.yml" ]), embeddingModel: import_zod.z.object({ openai: import_zod.z.string().default("text-embedding-3-small"), azure: import_zod.z.string().default("text-embedding-3-small"), gemini: import_zod.z.string().default("text-embedding-004"), "openai-compatible": import_zod.z.string().default("text-embedding-3-small") }).optional() }); ConfigSchema = import_zod.z.object({ openai: import_zod.z.object({ apiKey: ApiKeySchema, baseURL: import_zod.z.string().url().optional(), preferredModel: import_zod.z.string().optional() }).optional(), google: import_zod.z.object({ apiKey: ApiKeySchema, baseURL: import_zod.z.string().url().optional() }).optional(), // Room for future expansion azure: import_zod.z.object({ apiKey: ApiKeySchema, resourceName: import_zod.z.string().optional(), baseURL: import_zod.z.string().url().optional(), preferredModel: import_zod.z.string().optional() }).optional(), xai: import_zod.z.object({ apiKey: ApiKeySchema, baseURL: import_zod.z.string().url().optional() }).optional(), openaiCompatible: import_zod.z.object({ apiKey: ApiKeySchema, baseURL: import_zod.z.string().url(), providerName: import_zod.z.enum(["ollama", "openrouter"]).default("ollama"), models: import_zod.z.array(import_zod.z.string()).optional(), preferredModel: import_zod.z.string().optional() }).optional(), vectorConfig: VectorConfigSchema.optional() }); defaultConfig = { openai: { apiKey: void 0, baseURL: void 0, preferredModel: "gpt-5" }, google: { apiKey: void 0, baseURL: void 0 }, azure: { apiKey: void 0, resourceName: void 0, baseURL: void 0, preferredModel: "gpt-5" }, xai: { apiKey: void 0, baseURL: void 0 }, openaiCompatible: { apiKey: void 0, baseURL: "http://localhost:11434/v1", providerName: "ollama", models: void 0, preferredModel: void 0 }, vectorConfig: VectorConfigSchema.parse({}) }; } }); // src/utils/logger.ts var isMCPServer, logger; var init_logger = __esm({ "src/utils/logger.ts"() { "use strict"; init_cjs_shims(); isMCPServer = process.argv.length <= 2 || process.argv[2] === void 0; logger = { log: (message, ...args) => { if (!isMCPServer) { console.log(message, ...args); } }, error: (message, ...args) => { console.error(message, ...args); }, warn: (message, ...args) => { console.warn(message, ...args); }, debug: (message, ...args) => { if (!isMCPServer && process.env.DEBUG) { console.log("[DEBUG]", message, ...args); } } }; } }); // src/config/manager.ts var manager_exports = {}; __export(manager_exports, { ConfigManager: () => ConfigManager, getConfigManager: () => getConfigManager }); async function getConfigManager() { if (!configManagerInstance) { configManagerInstance = new ConfigManager(); } return configManagerInstance; } var import_path, import_os, import_fs, ConfigManager, configManagerInstance; var init_manager = __esm({ "src/config/manager.ts"() { "use strict"; init_cjs_shims(); init_schema(); import_path = require("path"); import_os = require("os"); import_fs = require("fs"); init_logger(); ConfigManager = class { store; initialized; constructor() { this.initialized = this.init(); } async init() { const Conf = (await import("conf")).default; this.store = new Conf({ projectName: "ultra-mcp", defaults: defaultConfig }); } async ensureInitialized() { await this.initialized; } // Get the entire configuration async getConfig() { await this.ensureInitialized(); if (!this.store) { throw new Error("Configuration store not initialized"); } await this.migrateLegacyAzureConfig(); const rawConfig = this.store.store; const result = ConfigSchema.safeParse(rawConfig); if (!result.success) { logger.error("Invalid configuration found, resetting to defaults"); await this.reset(); return defaultConfig; } return result.data; } // Migrate legacy Azure configuration async migrateLegacyAzureConfig() { if (!this.store) return; const rawConfig = this.store.store; if (rawConfig?.azure && !rawConfig?.azure?.resourceName) { const legacyUrl = rawConfig.azure.endpoint || rawConfig.azure.baseURL; if (legacyUrl) { const match = legacyUrl.match(/https:\/\/(.+?)\.openai\.azure\.com/); if (match && match[1]) { this.store.set("azure.resourceName", match[1]); this.store.delete("azure.baseURL"); logger.log(`Migrated legacy Azure ${rawConfig.azure.endpoint ? "endpoint" : "baseURL"} to resourceName: ${match[1]}`); } } } } // Set a specific API key async setApiKey(provider, apiKey) { await this.ensureInitialized(); if (!this.store) { throw new Error("Configuration store not initialized"); } if (!apiKey) { this.store.delete(`${provider}.apiKey`); } else { this.store.set(`${provider}.apiKey`, apiKey); } } // Get a specific API key async getApiKey(provider) { await this.ensureInitialized(); if (!this.store) { throw new Error("Configuration store not initialized"); } return this.store.get(`${provider}.apiKey`); } // Set a specific baseURL async setBaseURL(provider, baseURL) { await this.ensureInitialized(); if (!this.store) { throw new Error("Configuration store not initialized"); } if (!baseURL) { this.store.delete(`${provider}.baseURL`); } else { this.store.set(`${provider}.baseURL`, baseURL); } } // Get a specific baseURL async getBaseURL(provider) { await this.ensureInitialized(); if (!this.store) { throw new Error("Configuration store not initialized"); } return this.store.get(`${provider}.baseURL`); } // Set Azure baseURL (deprecated, use setBaseURL instead) async setAzureBaseURL(baseURL) { return this.setBaseURL("azure", baseURL); } // Set Azure resource name async setAzureResourceName(resourceName) { await this.ensureInitialized(); if (!this.store) { throw new Error("Configuration store not initialized"); } if (!resourceName) { this.store.delete("azure.resourceName"); } else { this.store.set("azure.resourceName", resourceName); } } // Get Azure resource name async getAzureResourceName() { await this.ensureInitialized(); if (!this.store) { throw new Error("Configuration store not initialized"); } return this.store.get("azure.resourceName"); } // Set vector configuration async setVectorConfig(vectorConfig) { await this.ensureInitialized(); if (!this.store) { throw new Error("Configuration store not initialized"); } this.store.set("vectorConfig", vectorConfig); } // Check if any API keys are configured async hasAnyApiKeys() { const config = await this.getConfig(); return !!(config.openai?.apiKey || config.google?.apiKey || config.azure?.apiKey || config.xai?.apiKey); } // Get the path to the config file async getConfigPath() { await this.ensureInitialized(); if (!this.store) { throw new Error("Configuration store not initialized"); } return this.store.path; } // Update configuration with partial data async updateConfig(updates) { await this.ensureInitialized(); if (!this.store) { throw new Error("Configuration store not initialized"); } const currentConfig = await this.getConfig(); const newConfig = { ...currentConfig, ...updates }; Object.keys(updates).forEach((key) => { if (updates[key] && typeof updates[key] === "object" && !Array.isArray(updates[key])) { newConfig[key] = { ...currentConfig[key], ...updates[key] }; } }); this.store.store = newConfig; } // Reset configuration to defaults async reset() { await this.ensureInitialized(); if (!this.store) { throw new Error("Configuration store not initialized"); } this.store.clear(); } // Validate the current configuration async validate() { await this.ensureInitialized(); if (!this.store) { throw new Error("Configuration store not initialized"); } const result = ConfigSchema.safeParse(this.store.store); if (result.success) { return { valid: true }; } const errors = result.error.errors.map( (err) => `${err.path.join(".")}: ${err.message}` ); return { valid: false, errors }; } // Get the database file path getDatabasePath() { const configDir = this.getConfigDir(); return (0, import_path.join)(configDir, "usage-v1.db"); } // Get the configuration directory path getConfigDir() { const os2 = (0, import_os.platform)(); let configDir; if (os2 === "win32") { const appData = process.env.APPDATA; if (!appData) { throw new Error("APPDATA environment variable not found"); } configDir = (0, import_path.join)(appData, "ultra-mcp-nodejs"); } else { configDir = (0, import_path.join)((0, import_os.homedir)(), ".config", "ultra-mcp"); } try { (0, import_fs.mkdirSync)(configDir, { recursive: true }); } catch { } return configDir; } }; configManagerInstance = null; } }); // src/db/schema.ts var schema_exports = {}; __export(schema_exports, { conversationBudgets: () => conversationBudgets, conversationFiles: () => conversationFiles, conversationMessages: () => conversationMessages, llmRequests: () => llmRequests, sessions: () => sessions }); var import_sqlite_core, llmRequests, sessions, conversationMessages, conversationFiles, conversationBudgets; var init_schema2 = __esm({ "src/db/schema.ts"() { "use strict"; init_cjs_shims(); import_sqlite_core = require("drizzle-orm/sqlite-core"); llmRequests = (0, import_sqlite_core.sqliteTable)("llm_requests", { id: (0, import_sqlite_core.text)("id").primaryKey().$defaultFn(() => crypto.randomUUID()), timestamp: (0, import_sqlite_core.integer)("timestamp", { mode: "timestamp_ms" }).$defaultFn(() => /* @__PURE__ */ new Date()), provider: (0, import_sqlite_core.text)("provider", { enum: ["openai", "gemini", "azure", "grok", "openai-compatible"] }).notNull(), model: (0, import_sqlite_core.text)("model").notNull(), toolName: (0, import_sqlite_core.text)("tool_name"), // MCP tool that triggered this request inputTokens: (0, import_sqlite_core.integer)("input_tokens"), outputTokens: (0, import_sqlite_core.integer)("output_tokens"), totalTokens: (0, import_sqlite_core.integer)("total_tokens"), estimatedCost: (0, import_sqlite_core.real)("estimated_cost"), // Cost in USD durationMs: (0, import_sqlite_core.integer)("duration_ms"), status: (0, import_sqlite_core.text)("status", { enum: ["success", "error"] }).notNull(), errorMessage: (0, import_sqlite_core.text)("error_message"), requestData: (0, import_sqlite_core.text)("request_data", { mode: "json" }), // Store prompt, params responseData: (0, import_sqlite_core.text)("response_data", { mode: "json" }), // Store response content finishReason: (0, import_sqlite_core.text)("finish_reason") // stop, length, content-filter, etc. }, (table) => ({ timestampIdx: (0, import_sqlite_core.index)("llm_requests_timestamp_idx").on(table.timestamp), providerIdx: (0, import_sqlite_core.index)("llm_requests_provider_idx").on(table.provider), statusIdx: (0, import_sqlite_core.index)("llm_requests_status_idx").on(table.status) })); sessions = (0, import_sqlite_core.sqliteTable)("sessions", { id: (0, import_sqlite_core.text)("id").primaryKey().$defaultFn(() => crypto.randomUUID()), name: (0, import_sqlite_core.text)("name"), // Optional human-readable name createdAt: (0, import_sqlite_core.integer)("created_at", { mode: "timestamp_ms" }).$defaultFn(() => /* @__PURE__ */ new Date()), updatedAt: (0, import_sqlite_core.integer)("updated_at", { mode: "timestamp_ms" }).$defaultFn(() => /* @__PURE__ */ new Date()), lastMessageAt: (0, import_sqlite_core.integer)("last_message_at", { mode: "timestamp_ms" }), status: (0, import_sqlite_core.text)("status", { enum: ["active", "archived", "deleted"] }).default("active").notNull(), metadata: (0, import_sqlite_core.text)("metadata", { mode: "json" }) // Store session-level context }, (table) => ({ createdAtIdx: (0, import_sqlite_core.index)("sessions_created_at_idx").on(table.createdAt), statusIdx: (0, import_sqlite_core.index)("sessions_status_idx").on(table.status), lastMessageAtIdx: (0, import_sqlite_core.index)("sessions_last_message_at_idx").on(table.lastMessageAt) })); conversationMessages = (0, import_sqlite_core.sqliteTable)("conversation_messages", { id: (0, import_sqlite_core.text)("id").primaryKey().$defaultFn(() => crypto.randomUUID()), sessionId: (0, import_sqlite_core.text)("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }), messageIndex: (0, import_sqlite_core.integer)("message_index").notNull(), // Order within conversation timestamp: (0, import_sqlite_core.integer)("timestamp", { mode: "timestamp_ms" }).$defaultFn(() => /* @__PURE__ */ new Date()), role: (0, import_sqlite_core.text)("role", { enum: ["user", "assistant", "system", "tool"] }).notNull(), content: (0, import_sqlite_core.text)("content").notNull(), toolName: (0, import_sqlite_core.text)("tool_name"), // If this message was from/to a tool parentMessageId: (0, import_sqlite_core.text)("parent_message_id"), // For threading/branching conversations metadata: (0, import_sqlite_core.text)("metadata", { mode: "json" }) // Store message-level context }, (table) => ({ sessionIdIdx: (0, import_sqlite_core.index)("conversation_messages_session_id_idx").on(table.sessionId), timestampIdx: (0, import_sqlite_core.index)("conversation_messages_timestamp_idx").on(table.timestamp), messageIndexIdx: (0, import_sqlite_core.index)("conversation_messages_message_index_idx").on(table.sessionId, table.messageIndex), // Unique constraint to prevent duplicate message indices within a session sessionMessageIdx: (0, import_sqlite_core.uniqueIndex)("conversation_messages_session_message_idx_unique").on(table.sessionId, table.messageIndex) })); conversationFiles = (0, import_sqlite_core.sqliteTable)("conversation_files", { id: (0, import_sqlite_core.text)("id").primaryKey().$defaultFn(() => crypto.randomUUID()), sessionId: (0, import_sqlite_core.text)("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }), filePath: (0, import_sqlite_core.text)("file_path").notNull(), fileContent: (0, import_sqlite_core.text)("file_content"), contentHash: (0, import_sqlite_core.text)("content_hash"), // For deduplication addedAt: (0, import_sqlite_core.integer)("added_at", { mode: "timestamp_ms" }).$defaultFn(() => /* @__PURE__ */ new Date()), lastAccessedAt: (0, import_sqlite_core.integer)("last_accessed_at", { mode: "timestamp_ms" }).$defaultFn(() => /* @__PURE__ */ new Date()), accessCount: (0, import_sqlite_core.integer)("access_count").default(0).notNull(), isRelevant: (0, import_sqlite_core.integer)("is_relevant", { mode: "boolean" }).default(true) // For context pruning }, (table) => ({ sessionIdIdx: (0, import_sqlite_core.index)("conversation_files_session_id_idx").on(table.sessionId), contentHashIdx: (0, import_sqlite_core.index)("conversation_files_content_hash_idx").on(table.contentHash), relevanceIdx: (0, import_sqlite_core.index)("conversation_files_relevance_idx").on(table.sessionId, table.isRelevant), // Unique constraint to prevent duplicate file hashes within a session sessionHashIdx: (0, import_sqlite_core.uniqueIndex)("conversation_files_session_hash_unique").on(table.sessionId, table.contentHash) })); conversationBudgets = (0, import_sqlite_core.sqliteTable)("conversation_budgets", { id: (0, import_sqlite_core.text)("id").primaryKey().$defaultFn(() => crypto.randomUUID()), sessionId: (0, import_sqlite_core.text)("session_id").notNull().references(() => sessions.id, { onDelete: "cascade" }), maxTokens: (0, import_sqlite_core.integer)("max_tokens"), maxCostUsd: (0, import_sqlite_core.real)("max_cost_usd"), maxDurationMs: (0, import_sqlite_core.integer)("max_duration_ms"), usedTokens: (0, import_sqlite_core.integer)("used_tokens").default(0).notNull(), usedCostUsd: (0, import_sqlite_core.real)("used_cost_usd").default(0).notNull(), usedDurationMs: (0, import_sqlite_core.integer)("used_duration_ms").default(0).notNull(), createdAt: (0, import_sqlite_core.integer)("created_at", { mode: "timestamp_ms" }).$defaultFn(() => /* @__PURE__ */ new Date()), updatedAt: (0, import_sqlite_core.integer)("updated_at", { mode: "timestamp_ms" }).$defaultFn(() => /* @__PURE__ */ new Date()) }, (table) => ({ sessionIdIdx: (0, import_sqlite_core.index)("conversation_budgets_session_id_idx").on(table.sessionId), // Unique constraint to ensure one budget per session sessionIdUnique: (0, import_sqlite_core.uniqueIndex)("conversation_budgets_session_id_unique").on(table.sessionId) })); } }); // src/db/connection.ts async function getDatabase() { if (db) { return db; } const configManager = new ConfigManager(); const dbPath = configManager.getDatabasePath(); try { const client = (0, import_client.createClient)({ url: `file:${dbPath}` }); db = (0, import_libsql.drizzle)(client, { schema: schema_exports }); try { await db.select().from(llmRequests).limit(1).execute(); } catch { logger.log("Database initialized, will create tables on first migration"); } logger.log("Database connected using @libsql/client"); return db; } catch (error) { throw new Error(`Failed to connect to database: ${error instanceof Error ? error.message : String(error)}`); } } var import_libsql, import_client, db; var init_connection = __esm({ "src/db/connection.ts"() { "use strict"; init_cjs_shims(); import_libsql = require("drizzle-orm/libsql"); import_client = require("@libsql/client"); init_manager(); init_schema2(); init_logger(); db = null; } }); // src/db/migrate.ts async function runMigrations() { try { const db2 = await getDatabase(); let migrationsFolder = (0, import_path2.join)(__dirname, "drizzle"); if (!(0, import_fs2.existsSync)(migrationsFolder)) { migrationsFolder = (0, import_path2.join)(__dirname, "..", "..", "drizzle"); } if (!(0, import_fs2.existsSync)(migrationsFolder)) { throw new Error(`Migrations folder not found. Searched: ${migrationsFolder}`); } await (0, import_migrator.migrate)(db2, { migrationsFolder }); logger.log("Database migrations completed successfully"); } catch (error) { logger.error("Database migration failed:", error); throw error; } } async function ensureDatabaseReady() { if (_migrationsDone) return; if (_migrationsPromise) { return _migrationsPromise; } _migrationsPromise = (async () => { try { await runMigrations(); _migrationsDone = true; } catch (error) { logger.warn("Failed to run migrations, database may not be initialized:", error instanceof Error ? error.message : String(error)); } finally { _migrationsPromise = null; } })(); return _migrationsPromise; } var import_migrator, import_path2, import_fs2, _migrationsDone, _migrationsPromise; var init_migrate = __esm({ "src/db/migrate.ts"() { "use strict"; init_cjs_shims(); import_migrator = require("drizzle-orm/libsql/migrator"); init_connection(); import_path2 = require("path"); import_fs2 = require("fs"); init_logger(); _migrationsDone = false; _migrationsPromise = null; } }); // src/pricing/types.ts var import_zod2, ModelPricingSchema, PricingDataSchema; var init_types = __esm({ "src/pricing/types.ts"() { "use strict"; init_cjs_shims(); import_zod2 = require("zod"); ModelPricingSchema = import_zod2.z.object({ // Token limits (can be string or number in the source data) max_tokens: import_zod2.z.union([import_zod2.z.number(), import_zod2.z.string()]).optional(), max_input_tokens: import_zod2.z.union([import_zod2.z.number(), import_zod2.z.string()]).optional(), max_output_tokens: import_zod2.z.union([import_zod2.z.number(), import_zod2.z.string()]).optional(), // Base pricing (optional for image models) input_cost_per_token: import_zod2.z.number().optional(), output_cost_per_token: import_zod2.z.number().optional(), // Tiered pricing (for models like Gemini) input_cost_per_token_above_200k_tokens: import_zod2.z.number().optional(), output_cost_per_token_above_200k_tokens: import_zod2.z.number().optional(), // Cache pricing cache_read_input_token_cost: import_zod2.z.number().optional(), // Provider info litellm_provider: import_zod2.z.string().optional(), mode: import_zod2.z.string().optional(), // Capabilities supports_vision: import_zod2.z.boolean().optional(), supports_function_calling: import_zod2.z.boolean().optional(), supports_parallel_function_calling: import_zod2.z.boolean().optional(), supports_response_schema: import_zod2.z.boolean().optional(), supports_prompt_caching: import_zod2.z.boolean().optional(), supports_system_messages: import_zod2.z.boolean().optional(), supports_tool_choice: import_zod2.z.boolean().optional(), supports_native_streaming: import_zod2.z.boolean().optional(), supports_reasoning: import_zod2.z.boolean().optional(), supports_web_search: import_zod2.z.boolean().optional(), supports_audio_input: import_zod2.z.boolean().optional(), supports_video_input: import_zod2.z.boolean().optional(), supports_pdf_input: import_zod2.z.boolean().optional(), // Media limits max_images_per_prompt: import_zod2.z.number().optional(), max_videos_per_prompt: import_zod2.z.number().optional(), max_video_length: import_zod2.z.number().optional(), max_audio_length_hours: import_zod2.z.number().optional(), max_audio_per_prompt: import_zod2.z.number().optional(), max_pdf_size_mb: import_zod2.z.number().optional(), // Endpoints and modalities supported_endpoints: import_zod2.z.array(import_zod2.z.string()).optional(), supported_modalities: import_zod2.z.array(import_zod2.z.string()).optional(), supported_output_modalities: import_zod2.z.array(import_zod2.z.string()).optional(), // Source source: import_zod2.z.string().optional(), // Image model pricing input_cost_per_image: import_zod2.z.number().optional(), output_cost_per_image: import_zod2.z.number().optional(), cost_per_image: import_zod2.z.number().optional() }).refine( (data) => { const hasTokenPricing = data.input_cost_per_token !== void 0 && data.output_cost_per_token !== void 0; const hasImagePricing = data.input_cost_per_image !== void 0 || data.output_cost_per_image !== void 0 || data.cost_per_image !== void 0; return hasTokenPricing || hasImagePricing; }, { message: "Model must have either token-based or image-based pricing" } ); PricingDataSchema = import_zod2.z.record(import_zod2.z.string(), ModelPricingSchema); } }); // src/pricing/fetcher.ts var import_promises, import_path3, import_os2, import_zod3, PricingFetcher; var init_fetcher = __esm({ "src/pricing/fetcher.ts"() { "use strict"; init_cjs_shims(); import_promises = __toESM(require("fs/promises")); import_path3 = __toESM(require("path")); import_os2 = __toESM(require("os")); import_zod3 = require("zod"); init_types(); PricingFetcher = class _PricingFetcher { static LITELLM_PRICING_URL = "https://raw.githubusercontent.com/BerriAI/litellm/refs/heads/main/model_prices_and_context_window.json"; static DEFAULT_TTL = 60 * 60 * 1e3; // 1 hour in milliseconds cacheFilePath; ttl; constructor(ttl = _PricingFetcher.DEFAULT_TTL) { this.ttl = ttl; this.cacheFilePath = this.getCacheFilePath(); } getCacheFilePath() { const platform3 = process.platform; let configDir; if (platform3 === "win32") { configDir = import_path3.default.join(process.env.APPDATA || import_path3.default.join(import_os2.default.homedir(), "AppData", "Roaming"), "ultra-mcp-nodejs"); } else { configDir = import_path3.default.join(import_os2.default.homedir(), ".config", "ultra-mcp"); } return import_path3.default.join(configDir, "litellm-pricing-cache.json"); } async ensureCacheDirectory() { const dir = import_path3.default.dirname(this.cacheFilePath); await import_promises.default.mkdir(dir, { recursive: true }); } async fetchFromRemote() { try { const response = await fetch(_PricingFetcher.LITELLM_PRICING_URL); if (!response.ok) { throw new Error(`Failed to fetch pricing data: ${response.statusText}`); } const rawData = await response.json(); if (typeof rawData !== "object" || rawData === null) { throw new Error("Invalid pricing data format received from API"); } const filteredData = {}; for (const [modelName, modelData] of Object.entries(rawData)) { if (modelName.includes("dall-e") || modelName.includes("whisper") || modelName.includes("tts") || modelName.includes("embedding") || modelName.includes("moderation") || modelName.includes("flux") || modelName.includes("stable-diffusion") || modelName.includes("sample_spec")) { continue; } if (typeof modelData !== "object" || modelData === null) { continue; } try { const processedData = { ...modelData, max_tokens: typeof modelData.max_tokens === "string" ? parseInt(modelData.max_tokens, 10) : modelData.max_tokens, max_input_tokens: typeof modelData.max_input_tokens === "string" ? parseInt(modelData.max_input_tokens, 10) : modelData.max_input_tokens, max_output_tokens: typeof modelData.max_output_tokens === "string" ? parseInt(modelData.max_output_tokens, 10) : modelData.max_output_tokens }; if (processedData.input_cost_per_token !== void 0 && processedData.output_cost_per_token !== void 0) { const validated = ModelPricingSchema.parse(processedData); filteredData[modelName] = validated; } } catch { continue; } } return filteredData; } catch (error) { if (error instanceof import_zod3.z.ZodError) { throw new Error(`Invalid pricing data format: ${error.message}`); } throw error; } } async saveToCache(data) { await this.ensureCacheDirectory(); const cacheFile = { metadata: { timestamp: Date.now(), source: _PricingFetcher.LITELLM_PRICING_URL, ttl: this.ttl }, data }; await import_promises.default.writeFile( this.cacheFilePath, JSON.stringify(cacheFile, null, 2), "utf-8" ); } async loadFromCache() { try { const content = await import_promises.default.readFile(this.cacheFilePath, "utf-8"); const cacheFile = JSON.parse(content); PricingDataSchema.parse(cacheFile.data); return cacheFile; } catch (error) { return null; } } isCacheExpired(metadata) { const age = Date.now() - metadata.timestamp; return age > this.ttl; } async getLatestPricing(forceRefresh = false) { if (!forceRefresh) { const cached = await this.loadFromCache(); if (cached && !this.isCacheExpired(cached.metadata)) { return cached.data; } } try { const freshData = await this.fetchFromRemote(); await this.saveToCache(freshData); return freshData; } catch (fetchError) { const cached = await this.loadFromCache(); if (cached) { console.warn("Using stale cache due to network error:", fetchError); return cached.data; } throw new Error(`Failed to fetch pricing data and no cache available: ${fetchError}`); } } async getCacheInfo() { const cached = await this.loadFromCache(); if (!cached) { return { exists: false }; } const age = Date.now() - cached.metadata.timestamp; return { exists: true, age: Math.floor(age / 1e3), // Age in seconds expired: this.isCacheExpired(cached.metadata) }; } async clearCache() { try { await import_promises.default.unlink(this.cacheFilePath); } catch (error) { } } }; } }); // src/pricing/calculator.ts var PricingCalculator; var init_calculator = __esm({ "src/pricing/calculator.ts"() { "use strict"; init_cjs_shims(); PricingCalculator = class _PricingCalculator { static TIERED_PRICING_THRESHOLD = 2e5; // 200k tokens /** * Normalize model names to match LiteLLM's naming convention */ normalizeModelName(model) { const normalizations = { // OpenAI models "gpt-5": "gpt-5", "o3": "o3", "gpt-4o": "gpt-4o", "gpt-4o-mini": "gpt-4o-mini", "gpt-4-turbo": "gpt-4-turbo", "gpt-4": "gpt-4", "gpt-3.5-turbo": "gpt-3.5-turbo", // Gemini models "gemini-2.5-pro": "gemini-2.5-pro", "gemini-2.0-flash": "gemini-2.0-flash", "gemini-2.0-flash-exp": "gemini-2.0-flash", "gemini-1.5-pro": "gemini-1.5-pro", "gemini-1.5-flash": "gemini-1.5-flash", "gemini-pro": "gemini-1.5-pro", // Map old name to new // Anthropic models "claude-3-5-sonnet": "claude-3.5-sonnet", "claude-3-5-sonnet-20241022": "claude-3.5-sonnet", "claude-3-opus": "claude-3-opus", "claude-3-sonnet": "claude-3-sonnet", "claude-3-haiku": "claude-3-haiku", // xAI Grok models "grok-4": "grok-4", "grok-3": "grok-3", "grok-2": "grok-2", "grok-1": "grok-1", // Add Azure-specific mappings if needed "gpt-5-azure": "gpt-5", "o3-azure": "o3" }; const normalized = normalizations[model.toLowerCase()]; if (normalized) { return normalized; } for (const [pattern, replacement] of Object.entries(normalizations)) { if (model.toLowerCase().includes(pattern.toLowerCase())) { return replacement; } } return model; } /** * Convert ModelPricing to SimplifiedPricing for easier calculation */ simplifyPricing(model, pricing) { return { model, inputCostPerToken: pricing.input_cost_per_token ?? 0, outputCostPerToken: pricing.output_cost_per_token ?? 0, inputCostPerTokenAbove200k: pricing.input_cost_per_token_above_200k_tokens, outputCostPerTokenAbove200k: pricing.output_cost_per_token_above_200k_tokens, maxInputTokens: typeof pricing.max_input_tokens === "number" ? pricing.max_input_tokens : typeof pricing.max_tokens === "number" ? pricing.max_tokens : void 0, maxOutputTokens: typeof pricing.max_output_tokens === "number" ? pricing.max_output_tokens : typeof pricing.max_tokens === "number" ? pricing.max_tokens : void 0 }; } /** * Calculate cost with support for tiered pricing */ calculateCost(pricing, inputTokens, outputTokens) { let inputCost = 0; let outputCost = 0; let tieredPricingApplied = false; if (pricing.inputCostPerTokenAbove200k && inputTokens > _PricingCalculator.TIERED_PRICING_THRESHOLD) { const baseTokens = _PricingCalculator.TIERED_PRICING_THRESHOLD; const excessTokens = inputTokens - baseTokens; inputCost = baseTokens * pricing.inputCostPerToken + excessTokens * pricing.inputCostPerTokenAbove200k; tieredPricingApplied = true; } else { inputCost = inputTokens * pricing.inputCostPerToken; } if (pricing.outputCostPerTokenAbove200k && outputTokens > _PricingCalculator.TIERED_PRICING_THRESHOLD) { const baseTokens = _PricingCalculator.TIERED_PRICING_THRESHOLD; const excessTokens = outputTokens - baseTokens; outputCost = baseTokens * pricing.outputCostPerToken + excessTokens * pricing.outputCostPerTokenAbove200k; tieredPricingApplied = true; } else { outputCost = outputTokens * pricing.outputCostPerToken; } return { inputCost, outputCost, totalCost: inputCost + outputCost, inputTokens, outputTokens, model: pricing.model, tieredPricingApplied }; } /** * Calculate cost directly from ModelPricing */ calculateCostFromPricing(model, pricing, inputTokens, outputTokens) { const simplified = this.simplifyPricing(model, pricing); return this.calculateCost(simplified, inputTokens, outputTokens); } /** * Format cost as a readable string */ formatCost(cost) { if (cost < 0.01) { return `$${cost.toFixed(6)}`; } else if (cost < 1) { return `$${cost.toFixed(4)}`; } else { return `$${cost.toFixed(2)}`; } } /** * Get a cost estimate message */ getCostEstimateMessage(calculation) { const parts = [ `Model: ${calculation.model}`, `Input: ${calculation.inputTokens.toLocaleString()} tokens (${this.formatCost(calculation.inputCost)})`, `Output: ${calculation.outputTokens.toLocaleString()} tokens (${this.formatCost(calculation.outputCost)})`, `Total: ${this.formatCost(calculation.totalCost)}` ]; if (calculation.tieredPricingApplied) { parts.push("(Tiered pricing applied for tokens above 200k)"); } return parts.join(" | "); } }; } }); // src/pricing/service.ts var PricingService; var init_service = __esm({ "src/pricing/service.ts"() { "use strict"; init_cjs_shims(); init_fetcher(); init_calculator(); PricingService = class _PricingService { static instance; fetcher; calculator; pricingDataCache = null; lastFetchTime = 0; MEMORY_CACHE_TTL = 5 * 60 * 1e3; // 5 minutes in-memory cache constructor() { this.fetcher = new PricingFetcher(); this.calculator = new PricingCalculator(); } static getInstance() { if (!_PricingService.instance) { _PricingService.instance = new _PricingService(); } return _PricingService.instance; } /** * Get pricing data with in-memory caching for performance */ async getPricingData(forceRefresh = false) { const now = Date.now(); if (!forceRefresh && this.pricingDataCache && now - this.lastFetchTime < this.MEMORY_CACHE_TTL) { return this.pricingDataCache; } this.pricingDataCache = await this.fetcher.getLatestPricing(forceRefresh); this.lastFetchTime = now; return this.pricingDataCache; } /** * Get pricing for a specific model */ async getModelPricing(model) { try { const pricingData = await this.getPricingData(); const normalizedModel = this.calculator.normalizeModelName(model); if (pricingData[normalizedModel]) { return pricingData[normalizedModel]; } for (const [key, value] of Object.entries(pricingData)) { if (key.toLowerCase() === normalizedModel.toLowerCase()) { return value; } } console.warn(`Pricing not found for model: ${model} (normalized: ${normalizedModel})`); return null; } catch (error) { console.error("Error getting model pricing:", error); return null; } } /** * Calculate cost for a model with given token usage */ async calculateCost(model, inputTokens, outputTokens) { const pricing = await this.getModelPricing(model); if (!pricing) { return { inputCost: 0, outputCost: 0, totalCost: 0, inputTokens, outputTokens, model, tieredPricingApplied: false }; } return this.calculator.calculateCostFromPricing( model, pricing, inputTokens, outputTokens ); } /** * Refresh the pricing cache */ async refreshCache() { this.pricingDataCache = null; this.lastFetchTime = 0; await this.getPricingData(true); } /** * Get cache information */ async getCacheInfo() { const cacheInfo = await this.fetcher.getCacheInfo(); return { exists: cacheInfo?.exists ?? false, age: cacheInfo?.age, expired: cacheInfo?.expired, lastInMemoryFetch: this.lastFetchTime ? Date.now() - this.lastFetchTime : void 0 }; } /** * Clear all caches */ async clearCache() { this.pricingDataCache = null; this.lastFetchTime = 0; await this.fetcher.clearCache(); } /** * Get all available models with pricing */ async getAllModels() { try { const pricingData = await this.getPricingData(); return Object.keys(pricingData).sort(); } catch (error) { console.error("Error getting all models:", error); return []; } } /** * Check if a model has pricing information */ async hasModelPricing(model) { const pricing = await this.getModelPricing(model); return pricing !== null; } /** * Get a formatted cost estimate */ async getFormattedCostEstimate(model, inputTokens, outputTokens) { const calculation = await this.calculateCost(model, inputTokens, outputTokens); if (!calculation) { return null; } return this.calculator.getCostEstimateMessage(calculation); } /** * Format a cost value */ formatCost(cost) { return this.calculator.formatCost(cost); } }; } }); // src/pricing/index.ts var pricingService; var init_pricing = __esm({ "src/pricing/index.ts"() { "use strict"; init_cjs_shims(); init_service(); init_fetcher(); init_calculator(); init_service(); pricingService = PricingService.getInstance(); } }); // src/db/tracking.ts async function estimateCost(model, inputTokens, outputTokens) { try { const calculation = await pricingService.calculateCost(model, inputTokens, outputTokens); if (calculation && calculation.totalCost > 0) { return calculation.totalCost; } } catch (error) { logger.warn(`Failed to get pricing from service for model ${model}:`, error); } const pricing = FALLBACK_PRICING[model]; if (!pricing) { return (inputTokens * 1e-3 + outputTokens * 2e-3) / 1e3; } return (inputTokens * pricing.input + outputTokens * pricing.output) / 1e3; } async function trackLLMRequest(data) { const requestId = crypto2.randomUUID(); try { await ensureDatabaseReady(); const db2 = await getDatabase(); await db2.insert(llmRequests).values({ id: requestId, timestamp: new Date(data.startTime), provider: data.provider, model: data.model, toolName: data.toolName, requestData: data.requestData, status: "success", // Will update when completed durationMs: 0 // Will update when completed }).execute(); } catch (error) { logger.warn("Failed to track LLM request:", error instanceof Error ? error.message : String(error)); } return requestId; } async function updateLLMCompletion(data) { try { await ensureDatabaseReady(); const db2 = await getDatabase(); const startTime = await getRequestStartTime(data.requestId); const updateData = { responseData: data.responseData, status: data.error ? "error" : "success", errorMessage: data.error, finishReason: data.finishReason, durationMs: data.endTime - startTime }; if (data.usage) { updateData.inputTokens = data.usage.promptTokens; updateData.outputTokens = data.usage.completionTokens; updateData.totalTokens = data.usage.totalTokens; const request = await db2.select({ model: llmRequests.model }).from(llmRequests).where((0, import_drizzle_orm.eq)(llmRequests.id, data.requestId)).limit(1).execute(); if (request.length > 0 && request[0].model) { updateData.estimatedCost = await estimateCost( request[0].model, data.usage.promptTokens, data.usage.completionTokens ); } } await db2.update(llmRequests).set(updateData).where((0, import_drizzle_orm.eq)(llmRequests.id, data.requestId)).execute(); } catch (error) { logger.warn("Failed to update LLM completion:", error instanceof Error ? error.message : String(error)); } } async function getRequestStartTime(requestId) { try { const db2 = await getDatabase(); const result = await db2.select({ timestamp: llmRequests.timestamp }).from(llmRequests).where((0, import_drizzle_orm.eq)(llmRequests.id, requestId)).limit(1).execute(); return result.length > 0 && result[0].timestamp ? result[0].timestamp.getTime() : Date.now(); } catch { return Date.now(); } } async function getUsageStats(_days = 30) { try { await ensureDatabaseReady(); const db2 = await getDatabase(); const stats = await db2.select().from(llmRequests).where((0, import_drizzle_orm.eq)(llmRequests.status, "success")).execute(); return { totalRequests: stats.length, totalTokens: stats.reduce((sum2, req) => sum2 + (req.totalTokens || 0), 0), totalCost: stats.reduce((sum2, req) => sum2 + (req.estimatedCost || 0), 0), byProvider: stats.reduce((acc, req) => { acc[req.provider] = (acc[req.provider] || 0) + 1; return acc; }, {}) }; } catch (error) { console.warn("Failed to get usage stats:", error instanceof Error ? error.message : String(error)); return null; } } var import_drizzle_orm, crypto2, FALLBACK_PRICING; var init_tracking = __esm({ "src/db/tracking.ts"() { "use strict"; init_cjs_shims(); init_connection(); init_schema2(); init_migrate(); import_drizzle_orm = require("drizzle-orm"); crypto2 = __toESM(require("crypto")); init_logger(); init_pricing(); FALLBACK_PRICING = { // OpenAI Models "gpt-5": { input: 125e-5, output: 0.01 }, "o3": { input: 0.015, output: 0.06 }, "o3-mini": { input: 15e-4, output: 2e-3 }, "gpt-4": { input: 0.03, output: 0.06 }, "gpt-4-turbo": { input: 0.01, output: 0.03 }, "gpt-3.5-turbo": { input: 15e-4, output: 2e-3 }, // Gemini Models "gemini-2.5-pro": { input: 125e-5, output: 0.01 }, "gemini-2.5-flash": { input: 75e-6, output: 3e-4 }, "gemini-2.0-flash": { input: 75e-6, output: 3e-4 }, "gemini-pro": { input: 25e-5, output: 5e-4 }, // Azure OpenAI (same as OpenAI but may have different pricing) "azure-gpt-4": { input: 0.03, output: 0.06 }, "azure-gpt-35-turbo": { input: 15e-4, output: 2e-3 }, // xAI Grok Models "grok-4": { input: 0.015, output: 0.015 }, "grok-3": { input: 0.01, output: 0.01 }, "grok-3-fast": { input: 5e-3, output: 5e-3 }, "grok-3-mini": { input: 2e-3, output: 2e-3 }, "grok-beta": { input: 5e-3, output: 5e-3 } }; } }); // src/providers/openai-compatible.ts var import_openai_compatible, import_ai, OpenAICompatibleProvider; var init_openai_compatible = __esm({ "src/providers/openai-compatible.ts"() { "use strict"; init_cjs_shims(); import_openai_compatible = require("@ai-sdk/openai-compatible"); import_ai = require("ai"); init_tracking(); OpenAICompatibleProvider = class { name = "openai-compatible"; configManager; constructor(configManager) { this.configManager = configManager; } // Helper function to get models filtered by provider type static getModelsByProvider(providerType) { const ollamaModels = [ // DeepSeek R1 series (latest reasoning models) "deepseek-r1:1.5b", "deepseek-r1:7b", "deepseek-r1:8b", "deepseek-r1:14b", "deepseek-r1:32b", // Latest Llama models "llama3.2:1b", "llama3.2:3b", "llama3.1:8b", "llama3.1:70b", // Qwen series (including QwQ reasoning model) "qwen