@orcarouter/mcp 1.1.2

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/server.ts","../src/errors.ts","../src/version.ts","../src/api_client.ts","../src/tools/types.ts","../src/tools/chat.ts","../src/tools/model_card.ts","../src/tools/models_list.ts","../src/tools/providers_list.ts"],"sourcesContent":["import { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { createOrcaRouterMcpServer } from \"./server.js\";\n\nasync function main(): Promise<void> {\n const apiKey = process.env.ORCAROUTER_API_KEY?.trim() || undefined;\n const baseUrl = process.env.ORCAROUTER_BASE_URL?.trim() || undefined;\n const timeoutRaw = process.env.ORCAROUTER_REQUEST_TIMEOUT?.trim();\n let timeoutMs: number | undefined;\n if (timeoutRaw) {\n const parsedSeconds = Number(timeoutRaw);\n if (Number.isFinite(parsedSeconds) && parsedSeconds > 0) {\n timeoutMs = parsedSeconds * 1000;\n }\n }\n\n const { server } = createOrcaRouterMcpServer({\n apiKey,\n baseUrl,\n timeoutMs,\n });\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nmain().catch((err) => {\n process.stderr.write(\n `[orcarouter-mcp] fatal: ${err instanceof Error ? err.message : String(err)}\\n`,\n );\n process.exit(1);\n});\n","import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport Ajv, { type ValidateFunction } from \"ajv\";\nimport addFormats from \"ajv-formats\";\nimport { ApiClient } from \"./api_client.js\";\nimport {\n ApiError,\n InsufficientQuotaError,\n MissingApiKeyError,\n PermissionDeniedError,\n RateLimitError,\n} from \"./errors.js\";\nimport type { ToolDefinition, ToolContext } from \"./tools/types.js\";\nimport { ValidationError } from \"./tools/types.js\";\nimport { chatTool } from \"./tools/chat.js\";\nimport { modelCardTool } from \"./tools/model_card.js\";\nimport { modelsListTool } from \"./tools/models_list.js\";\nimport { providersListTool } from \"./tools/providers_list.js\";\n\nconst TOOLS: ToolDefinition<any>[] = [\n chatTool,\n modelsListTool,\n modelCardTool,\n providersListTool,\n];\n\nexport function listToolNames(): string[] {\n return TOOLS.map((t) => t.name);\n}\n\nexport interface CreateServerOptions {\n apiKey?: string;\n baseUrl?: string;\n serverName?: string;\n serverVersion?: string;\n timeoutMs?: number;\n}\n\nexport interface BuiltServer {\n server: Server;\n client: ApiClient;\n}\n\nfunction buildValidators(): Map<string, ValidateFunction> {\n // Ajv's CommonJS default export interop differs across bundlers; tolerate both.\n const AjvCtor: typeof Ajv = ((Ajv as unknown as { default?: typeof Ajv }).default ??\n Ajv) as typeof Ajv;\n const addFmt = (addFormats as unknown as { default?: typeof addFormats }).default ??\n addFormats;\n const ajv = new AjvCtor({ allErrors: true, strict: false });\n addFmt(ajv);\n const map = new Map<string, ValidateFunction>();\n for (const t of TOOLS) {\n map.set(t.name, ajv.compile(t.inputSchema));\n }\n return map;\n}\n\nexport function createOrcaRouterMcpServer(opts: CreateServerOptions = {}): BuiltServer {\n const client = new ApiClient({\n apiKey: opts.apiKey,\n baseUrl: opts.baseUrl,\n timeoutMs: opts.timeoutMs,\n });\n\n const ctx: ToolContext = {\n client,\n };\n\n const validators = buildValidators();\n\n const server = new Server(\n {\n name: opts.serverName ?? \"@orcarouter/mcp\",\n version: opts.serverVersion ?? \"1.1.2\",\n },\n {\n capabilities: {\n tools: {},\n },\n },\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: TOOLS.map((t) => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n })),\n };\n });\n\n server.setRequestHandler(CallToolRequestSchema, async (req): Promise<any> => {\n const name = req.params.name;\n const args = req.params.arguments ?? {};\n const tool = TOOLS.find((t) => t.name === name);\n if (!tool) {\n return {\n isError: true,\n content: [\n { type: \"text\", text: `Unknown tool: ${name}` },\n ],\n };\n }\n const validate = validators.get(name);\n if (validate && !validate(args)) {\n return {\n isError: true,\n content: [\n { type: \"text\", text: `Invalid input: ${formatAjvErrors(validate)}` },\n ],\n };\n }\n try {\n const result = await tool.handler(args, ctx);\n return result;\n } catch (e) {\n const msg = formatToolError(e);\n return {\n isError: true,\n content: [{ type: \"text\", text: msg }],\n };\n }\n });\n\n return { server, client };\n}\n\nfunction formatAjvErrors(validate: ValidateFunction): string {\n const errs = validate.errors ?? [];\n if (errs.length === 0) return \"schema validation failed\";\n return errs\n .map((e) => {\n const path = e.instancePath || \"(root)\";\n const detail =\n e.keyword === \"additionalProperties\" && e.params && \"additionalProperty\" in e.params\n ? `unexpected property '${(e.params as { additionalProperty: string }).additionalProperty}'`\n : e.message ?? \"invalid\";\n return `${path} ${detail}`;\n })\n .join(\"; \");\n}\n\nfunction formatToolError(err: unknown): string {\n if (err instanceof MissingApiKeyError) return err.message;\n if (err instanceof ValidationError) return `Invalid input: ${err.message}`;\n if (err instanceof RateLimitError) {\n const seconds = err.retryAfter;\n if (typeof seconds === \"number\" && Number.isFinite(seconds)) {\n return `OrcaRouter rate limited (429). Retry after ${seconds} seconds.`;\n }\n return `OrcaRouter rate limited (429). Retry shortly.`;\n }\n if (err instanceof InsufficientQuotaError) {\n return \"OrcaRouter quota exhausted. Top up at https://orcarouter.ai/console/billing.\";\n }\n if (err instanceof PermissionDeniedError) {\n return `OrcaRouter permission denied (403): ${err.message}`;\n }\n if (err instanceof ApiError) {\n return `OrcaRouter API error (${err.status}): ${err.message}`;\n }\n if (err instanceof Error) return err.message;\n return String(err);\n}\n","export class ApiError extends Error {\n status: number;\n body: unknown;\n\n constructor(\n message: string,\n status: number,\n body?: unknown,\n options?: ErrorOptions,\n ) {\n super(message, options);\n this.name = \"ApiError\";\n this.status = status;\n this.body = body;\n }\n}\n\nexport class AuthenticationError extends ApiError {\n constructor(message: string, body?: unknown) {\n super(message, 401, body);\n this.name = \"AuthenticationError\";\n }\n}\n\n/**\n * HTTP 403. Distinct from {@link AuthenticationError} (401): the credentials\n * are valid but the operation is not permitted. Preserves status 403 instead\n * of collapsing into a 401.\n */\nexport class PermissionDeniedError extends ApiError {\n constructor(message: string, body?: unknown) {\n super(message, 403, body);\n this.name = \"PermissionDeniedError\";\n }\n}\n\n/**\n * The account/key is out of quota (HTTP 402 or 403 carrying an\n * `insufficient_quota` / `insufficient_user_quota` error code). Mapped\n * separately so callers can surface a top-up prompt rather than a generic\n * auth/permission failure. Status mirrors the upstream response.\n */\nexport class InsufficientQuotaError extends ApiError {\n constructor(message: string, status: number, body?: unknown) {\n super(message, status, body);\n this.name = \"InsufficientQuotaError\";\n }\n}\n\n/**\n * The request was aborted via a caller-supplied `AbortSignal`. Distinct from\n * a timeout (the SDK's internal deadline) — name is `AbortError` so existing\n * abort-aware callers keep working.\n */\nexport class RequestCancelledError extends Error {\n constructor(\n message = \"OrcaRouter request cancelled by caller.\",\n options?: { cause?: unknown },\n ) {\n super(message, options);\n this.name = \"AbortError\";\n }\n}\n\nexport class RateLimitError extends ApiError {\n retryAfter?: number;\n constructor(message: string, retryAfter?: number, body?: unknown) {\n super(message, 429, body);\n this.name = \"RateLimitError\";\n this.retryAfter = retryAfter;\n }\n}\n\nexport class InternalServerError extends ApiError {\n constructor(message: string, status: number, body?: unknown) {\n super(message, status, body);\n this.name = \"InternalServerError\";\n }\n}\n\nexport class MissingApiKeyError extends Error {\n constructor(toolName: string) {\n super(\n `ORCAROUTER_API_KEY is required for tool \"${toolName}\". ` +\n `Set the ORCAROUTER_API_KEY environment variable when launching the MCP server.`,\n );\n this.name = \"MissingApiKeyError\";\n }\n}\n","/**\n * Package version, kept in sync manually with package.json.\n * We avoid a runtime read of package.json so the bundled binary stays self-contained.\n */\nexport const PACKAGE_VERSION = \"1.1.2\";\n","import {\n ApiError,\n AuthenticationError,\n InsufficientQuotaError,\n InternalServerError,\n PermissionDeniedError,\n RateLimitError,\n RequestCancelledError,\n} from \"./errors.js\";\nimport { PACKAGE_VERSION } from \"./version.js\";\n\nexport {\n ApiError,\n AuthenticationError,\n InsufficientQuotaError,\n InternalServerError,\n PermissionDeniedError,\n RateLimitError,\n RequestCancelledError,\n} from \"./errors.js\";\n\nexport interface ApiClientOptions {\n apiKey?: string;\n baseUrl?: string;\n fetchImpl?: typeof fetch;\n /** Per-request timeout in milliseconds. Defaults to 300000 (5 minutes). */\n timeoutMs?: number;\n}\n\nexport interface RequestOptions {\n query?: Record<string, string | number | boolean | undefined | null>;\n headers?: Record<string, string>;\n signal?: AbortSignal;\n}\n\nconst DEFAULT_BASE_URL = \"https://api.orcarouter.ai\";\nconst DEFAULT_TIMEOUT_MS = 300_000;\nconst USER_AGENT = `@orcarouter/mcp/${PACKAGE_VERSION} (Node.js)`;\n\nexport class ApiClient {\n readonly apiKey?: string;\n readonly baseUrl: string;\n readonly timeoutMs: number;\n private readonly fetchImpl: typeof fetch;\n\n constructor(opts: ApiClientOptions = {}) {\n this.apiKey = opts.apiKey;\n this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.fetchImpl = opts.fetchImpl ?? globalThis.fetch.bind(globalThis);\n this.timeoutMs =\n typeof opts.timeoutMs === \"number\" && opts.timeoutMs > 0\n ? opts.timeoutMs\n : DEFAULT_TIMEOUT_MS;\n }\n\n get<T = unknown>(path: string, opts: RequestOptions = {}): Promise<T> {\n return this.request<T>(\"GET\", path, undefined, opts);\n }\n\n post<T = unknown>(\n path: string,\n body: unknown,\n opts: RequestOptions = {},\n ): Promise<T> {\n return this.request<T>(\"POST\", path, body, opts);\n }\n\n async raw(\n method: \"GET\" | \"POST\",\n path: string,\n body: unknown,\n opts: RequestOptions = {},\n ): Promise<Response> {\n const url = this.buildUrl(path, opts.query);\n const headers = this.buildHeaders(body !== undefined, opts.headers);\n const externalSignal = opts.signal;\n const { signal, cancel, didTimeout } =\n this.makeTimeoutSignal(externalSignal);\n const init: RequestInit = {\n method,\n headers,\n signal,\n };\n if (body !== undefined) {\n init.body = typeof body === \"string\" ? body : JSON.stringify(body);\n }\n try {\n return await this.fetchImpl(url, init);\n } catch (e) {\n // The composed signal aborts for one of two reasons: the SDK's own\n // deadline elapsed, or the caller aborted their supplied signal.\n // Detection must rely on the *signal state*, not the thrown error's\n // `name`: fetch can reject with the exact AbortSignal.reason (e.g.\n // `controller.abort(new Error(\"cancelled\"))`) whose name is just\n // \"Error\", which would otherwise bypass the cancellation path.\n\n // 1. Internal deadline fired -> timeout (independent of error name).\n if (didTimeout()) {\n throw new Error(\n `OrcaRouter request timed out after ${this.timeoutMs}ms (${method} ${path}).`,\n );\n }\n // 2. Caller's signal (or the composed controller) aborted without the\n // internal timeout firing -> explicit caller cancellation. Preserve\n // the original error/reason as `cause` for debuggability.\n if (externalSignal?.aborted || signal.aborted) {\n throw new RequestCancelledError(\n `OrcaRouter request cancelled by caller (${method} ${path}).`,\n { cause: e },\n );\n }\n // 3. Fallback for environments that throw a plain DOMException without\n // an observable signal state. A timeout would have set the flag in\n // (1), so a name-based abort here is a caller cancellation.\n if (this.isAbortError(e)) {\n throw new RequestCancelledError(\n `OrcaRouter request cancelled by caller (${method} ${path}).`,\n { cause: e },\n );\n }\n throw e;\n } finally {\n cancel();\n }\n }\n\n private isAbortError(e: unknown): boolean {\n if (!e || typeof e !== \"object\") return false;\n const name = (e as { name?: string }).name;\n return name === \"AbortError\" || name === \"TimeoutError\";\n }\n\n private makeTimeoutSignal(external?: AbortSignal): {\n signal: AbortSignal;\n cancel: () => void;\n didTimeout: () => boolean;\n } {\n const controller = new AbortController();\n // Set strictly inside the timeout handler so the caller can later tell\n // an SDK-deadline abort apart from a caller-initiated cancellation.\n let didTimeoutFlag = false;\n const timer = setTimeout(() => {\n didTimeoutFlag = true;\n controller.abort(new Error(\"OrcaRouter request timeout\"));\n }, this.timeoutMs);\n const onExternalAbort = () => controller.abort(external?.reason);\n if (external) {\n if (external.aborted) {\n controller.abort(external.reason);\n } else {\n external.addEventListener(\"abort\", onExternalAbort, { once: true });\n }\n }\n const cancel = () => {\n clearTimeout(timer);\n if (external) external.removeEventListener(\"abort\", onExternalAbort);\n };\n // Strictly the internal-deadline flag. Caller-abort detection is done\n // separately via signal state in raw(), so this no longer conflates a\n // missing external signal with a timeout.\n const didTimeout = () => didTimeoutFlag;\n return { signal: controller.signal, cancel, didTimeout };\n }\n\n private async request<T>(\n method: \"GET\" | \"POST\",\n path: string,\n body: unknown,\n opts: RequestOptions,\n ): Promise<T> {\n const response = await this.raw(method, path, body, opts);\n if (!response.ok) {\n await this.throwForStatus(response);\n }\n if (response.status === 204) {\n return undefined as T;\n }\n return (await response.json()) as T;\n }\n\n private buildUrl(\n path: string,\n query?: Record<string, string | number | boolean | undefined | null>,\n ): string {\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n const url = new URL(this.baseUrl + normalizedPath);\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined || value === null) continue;\n url.searchParams.append(key, String(value));\n }\n }\n return url.toString();\n }\n\n private buildHeaders(\n hasBody: boolean,\n extra?: Record<string, string>,\n ): Headers {\n const headers = new Headers();\n if (this.apiKey) {\n headers.set(\"Authorization\", `Bearer ${this.apiKey}`);\n }\n headers.set(\"Accept\", \"application/json\");\n headers.set(\"User-Agent\", USER_AGENT);\n if (hasBody) {\n headers.set(\"Content-Type\", \"application/json\");\n }\n if (extra) {\n for (const [k, v] of Object.entries(extra)) {\n headers.set(k, v);\n }\n }\n return headers;\n }\n\n private async throwForStatus(response: Response): Promise<never> {\n const status = response.status;\n let bodyText = \"\";\n let parsed: unknown = undefined;\n try {\n bodyText = await response.text();\n if (bodyText) {\n try {\n parsed = JSON.parse(bodyText);\n } catch {\n parsed = undefined;\n }\n }\n } catch {\n // ignore body read failures\n }\n\n const message =\n extractErrorMessage(parsed) ?? (bodyText || response.statusText);\n\n // Quota exhaustion is reported as 402 or 403 with an\n // insufficient_quota / insufficient_user_quota error code. Map it\n // before the generic auth/permission handling so callers can prompt\n // a top-up instead of treating it as a credential problem.\n if (\n (status === 402 || status === 403) &&\n hasInsufficientQuotaCode(parsed)\n ) {\n throw new InsufficientQuotaError(message, status, parsed);\n }\n if (status === 401) {\n throw new AuthenticationError(message, parsed);\n }\n if (status === 403) {\n // Valid credentials, operation not permitted — preserve status 403\n // instead of collapsing into AuthenticationError (hardcoded 401).\n throw new PermissionDeniedError(message, parsed);\n }\n if (status === 429) {\n throw new RateLimitError(\n message,\n parseRetryAfter(response.headers.get(\"retry-after\")),\n parsed,\n );\n }\n if (status >= 500) {\n throw new InternalServerError(message, status, parsed);\n }\n throw new ApiError(message, status, parsed);\n }\n}\n\n/**\n * Parse a `Retry-After` header. Supports both the delta-seconds form\n * (`\"120\"`) and the HTTP-date form (`\"Wed, 21 Oct 2015 07:28:00 GMT\"`).\n * For an HTTP-date the delay is `max(0, round((parsed - now) / 1000))`.\n * Returns `undefined` when absent or unparseable.\n */\nfunction parseRetryAfter(raw: string | null): number | undefined {\n if (!raw) return undefined;\n const trimmed = raw.trim();\n if (trimmed.length === 0) return undefined;\n const asNumber = Number(trimmed);\n if (Number.isFinite(asNumber)) {\n return asNumber;\n }\n const asDate = Date.parse(trimmed);\n if (Number.isFinite(asDate)) {\n return Math.max(0, Math.round((asDate - Date.now()) / 1000));\n }\n return undefined;\n}\n\nfunction hasInsufficientQuotaCode(body: unknown): boolean {\n if (!body || typeof body !== \"object\") return false;\n const codes = new Set([\"insufficient_quota\", \"insufficient_user_quota\"]);\n const b = body as Record<string, unknown>;\n if (typeof b.code === \"string\" && codes.has(b.code)) return true;\n if (b.error && typeof b.error === \"object\") {\n const inner = b.error as Record<string, unknown>;\n if (typeof inner.code === \"string\" && codes.has(inner.code)) return true;\n }\n return false;\n}\n\nfunction extractErrorMessage(body: unknown): string | undefined {\n if (!body || typeof body !== \"object\") return undefined;\n const b = body as Record<string, unknown>;\n if (typeof b.message === \"string\") return b.message;\n if (b.error && typeof b.error === \"object\") {\n const inner = b.error as Record<string, unknown>;\n if (typeof inner.message === \"string\") return inner.message;\n }\n if (typeof b.error === \"string\") return b.error;\n return undefined;\n}\n","import type { ApiClient } from \"../api_client.js\";\n\nexport interface McpTextContent {\n type: \"text\";\n text: string;\n}\n\nexport interface McpToolResult {\n content: McpTextContent[];\n isError?: boolean;\n}\n\nexport interface JsonSchemaObject {\n type: \"object\";\n properties: Record<string, unknown>;\n required?: string[];\n additionalProperties?: boolean;\n [k: string]: unknown;\n}\n\nexport interface ToolDefinition<I = unknown> {\n name: string;\n description: string;\n inputSchema: JsonSchemaObject;\n handler: (input: I, ctx: ToolContext) => Promise<McpToolResult>;\n}\n\nexport interface ToolContext {\n client: ApiClient;\n}\n\nexport class ValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ValidationError\";\n }\n}\n\nexport function textResult(text: string): McpToolResult {\n return { content: [{ type: \"text\", text }] };\n}\n","import { MissingApiKeyError } from \"../errors.js\";\nimport { textResult, ValidationError, type ToolDefinition } from \"./types.js\";\n\ninterface ChatMessage {\n role: \"system\" | \"user\";\n content: string;\n}\n\ninterface ChatInput {\n // Optional — defaults to \"orcarouter/auto\" when absent or empty.\n model?: string;\n // Required, single-turn user message.\n prompt: string;\n // Optional system prompt prepended to the conversation.\n system_prompt?: string;\n // Optional fallback chain (primary auto-prepended, max 5 entries).\n models?: string[];\n temperature?: number;\n max_tokens?: number;\n // `stream` is intentionally not part of the schema; included here only as\n // defense-in-depth against clients that ignore the schema.\n stream?: boolean;\n}\n\ninterface ChatCompletionChoice {\n message?: { role?: string; content?: unknown };\n}\n\ninterface ChatCompletionResponse {\n id?: string;\n choices?: ChatCompletionChoice[];\n [k: string]: unknown;\n}\n\nconst DEFAULT_MODEL = \"orcarouter/auto\";\nconst DEFAULT_TEMPERATURE = 0.7;\nconst DEFAULT_MAX_TOKENS = 2000;\n\n// OpenAI's reasoning-model line (gpt-5 / o-series) rejects `max_tokens` and\n// instead requires `max_completion_tokens` on the wire. This SDK-side helper\n// translates a single `max_tokens` input field to the correct wire field so\n// callers never have to think about it.\n//\n// Matches (case-insensitive) provider/<bare> or just <bare>:\n// gpt-5, gpt-5-mini, gpt-5-pro, gpt-5.1, gpt-5.5, gpt-5.2-thinking,\n// o1, o1-mini, o1-preview, o3, o3-mini, o3-pro, o4, o4-mini, ...\n//\n// The next char after `gpt-5` / `o[1-9]` must be `-` (suffix), `.` (dotted\n// version like gpt-5.1), or end-of-string (bare).\nexport function isReasoningModel(modelId: string): boolean {\n const bare = modelId.split(\"/\").pop() ?? modelId;\n return /^(gpt-5|o[1-9])([-.]|$)/i.test(bare);\n}\n\nfunction stringifyContent(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n const parts = content\n .map((p) => {\n if (typeof p === \"string\") return p;\n if (p && typeof p === \"object\") {\n const pp = p as { type?: string; text?: string };\n if (pp.type === \"text\" && typeof pp.text === \"string\") return pp.text;\n }\n return \"\";\n })\n .filter(Boolean);\n if (parts.length > 0) return parts.join(\"\\n\");\n }\n try {\n return JSON.stringify(content);\n } catch {\n return String(content);\n }\n}\n\nexport const chatTool: ToolDefinition<ChatInput> = {\n name: \"orcarouter_chat\",\n description:\n \"Send a single-turn chat request to OrcaRouter. Default model is the \" +\n \"workspace's auto-router. Use `orcarouter/<name>` for other routers or \" +\n \"`<provider>/<model>` for direct calls. For OpenAI reasoning models \" +\n \"(gpt-5/o1/o3/...), max_tokens is automatically routed to \" +\n \"max_completion_tokens at the wire level.\",\n inputSchema: {\n type: \"object\",\n properties: {\n model: {\n type: \"string\",\n default: DEFAULT_MODEL,\n description:\n \"Model to call. Defaults to `orcarouter/auto` — your workspace's \" +\n \"seeded auto-router. Use `orcarouter/<name>` for other workspace \" +\n \"routers, or `<provider>/<model>` for direct upstream selection \" +\n \"(e.g. `openai/gpt-4o-mini`, `anthropic/claude-haiku-4.5`).\",\n },\n prompt: {\n type: \"string\",\n description: \"User message to send (single-turn).\",\n },\n system_prompt: {\n type: \"string\",\n description: \"Optional system prompt prepended to the conversation.\",\n },\n max_tokens: {\n type: \"integer\",\n default: DEFAULT_MAX_TOKENS,\n description:\n \"Maximum tokens to generate (default 2000). Automatically \" +\n \"translated to max_completion_tokens for OpenAI reasoning models.\",\n },\n temperature: {\n type: \"number\",\n default: DEFAULT_TEMPERATURE,\n description: \"Sampling temperature (default 0.7).\",\n },\n models: {\n type: \"array\",\n items: { type: \"string\" },\n minItems: 1,\n maxItems: 5,\n description:\n \"Optional fallback chain. Models are tried in order if the \" +\n \"primary fails. Max 5 entries including the primary.\",\n },\n },\n required: [\"prompt\"],\n additionalProperties: false,\n },\n async handler(input, { client }) {\n if (!client.apiKey) {\n throw new MissingApiKeyError(\"orcarouter_chat\");\n }\n\n // ------------------------------------------------------------------\n // model — optional, defaults to orcarouter/auto. Empty / whitespace-\n // only strings are treated as \"absent\" (Cursor and some clients send\n // an empty string rather than omitting the field).\n // ------------------------------------------------------------------\n const rawModel = typeof input.model === \"string\" ? input.model.trim() : \"\";\n const effectiveModel = rawModel.length > 0 ? rawModel : DEFAULT_MODEL;\n\n // ------------------------------------------------------------------\n // prompt — required, non-empty\n // ------------------------------------------------------------------\n if (typeof input.prompt !== \"string\" || input.prompt.length === 0) {\n throw new ValidationError(\"prompt must be a non-empty string\");\n }\n if (\n input.system_prompt !== undefined &&\n (typeof input.system_prompt !== \"string\" ||\n input.system_prompt.length === 0)\n ) {\n throw new ValidationError(\n \"system_prompt must be a non-empty string when provided\",\n );\n }\n\n const effectiveMessages: ChatMessage[] =\n typeof input.system_prompt === \"string\"\n ? [\n { role: \"system\", content: input.system_prompt },\n { role: \"user\", content: input.prompt },\n ]\n : [{ role: \"user\", content: input.prompt }];\n\n // ------------------------------------------------------------------\n // models — optional fallback chain. Primary auto-prepended, deduped,\n // capped at 5 entries on the resulting effective chain.\n // ------------------------------------------------------------------\n let effectiveModels: string[] | undefined;\n if (input.models !== undefined) {\n if (!Array.isArray(input.models) || input.models.length === 0) {\n throw new ValidationError(\n \"models must be a non-empty array of model slug strings\",\n );\n }\n if (input.models.some((m) => typeof m !== \"string\" || m.length === 0)) {\n throw new ValidationError(\"each entry in models must be a non-empty string\");\n }\n const chain = [\n effectiveModel,\n ...input.models.filter((m) => m !== effectiveModel),\n ];\n if (chain.length > 5) {\n throw new ValidationError(\n \"the effective fallback chain (primary model + models) must not \" +\n \"exceed 5 entries; reduce the models array or omit the primary \" +\n \"from it\",\n );\n }\n // Single fallback equal to primary collapses to a plain single-model\n // request — intentional, not an error.\n if (chain.length >= 2) {\n effectiveModels = chain;\n }\n }\n\n if (input.stream === true) {\n throw new ValidationError(\n \"stream:true is not supported via MCP tools — MCP returns a single result. Set stream:false or omit.\",\n );\n }\n\n // ------------------------------------------------------------------\n // Apply defaults: temperature=0.7, max_tokens=2000. max_tokens is\n // routed to max_completion_tokens at the wire for reasoning models.\n // ------------------------------------------------------------------\n const effectiveTemperature =\n typeof input.temperature === \"number\"\n ? input.temperature\n : DEFAULT_TEMPERATURE;\n\n const effectiveMaxTokens =\n typeof input.max_tokens === \"number\"\n ? input.max_tokens\n : DEFAULT_MAX_TOKENS;\n\n const body: Record<string, unknown> = {\n model: effectiveModel,\n messages: effectiveMessages,\n stream: false,\n temperature: effectiveTemperature,\n };\n\n if (isReasoningModel(effectiveModel)) {\n body.max_completion_tokens = effectiveMaxTokens;\n } else {\n body.max_tokens = effectiveMaxTokens;\n }\n\n if (effectiveModels && effectiveModels.length > 0) {\n body.extra_body = { models: effectiveModels, route: \"fallback\" };\n }\n\n const data = await client.post<ChatCompletionResponse>(\"/v1/chat/completions\", body);\n const choice = data.choices?.[0];\n const content = choice?.message?.content;\n const text = stringifyContent(content ?? \"\");\n return textResult(text);\n },\n};\n","import { ApiError } from \"../errors.js\";\nimport { textResult, ValidationError, type ToolDefinition, type McpToolResult } from \"./types.js\";\n\ninterface ModelCardInput {\n model: string;\n}\n\ninterface PublicEndpointDTO {\n type?: string;\n method?: string;\n path?: string;\n}\n\ninterface PublicPricingDTO {\n quota_type?: number;\n currency?: string;\n per_call_usd?: number;\n input_per_million_usd?: number;\n output_per_million_usd?: number;\n cache_read_per_million_usd?: number | null;\n cache_write_per_million_usd?: number | null;\n}\n\ninterface PublicLatencyDTO {\n p50_ms?: number;\n p95_ms?: number;\n output_tok_per_sec?: number;\n error_rate_percent?: number;\n window_days?: number;\n}\n\n// Response data shape from GET /api/public/models/{provider}/{slug}\n// (mirrors the OrcaRouter backend's PublicModelDTO).\ninterface PublicModelDTO {\n model_name?: string;\n slug?: string;\n provider_slug?: string;\n display_name?: string;\n long_description?: string;\n context_window?: number;\n max_output?: number;\n modalities_in?: string[];\n modalities_out?: string[];\n release_date?: string;\n supported_endpoints?: PublicEndpointDTO[];\n pricing?: PublicPricingDTO;\n latency?: PublicLatencyDTO;\n [k: string]: unknown;\n}\n\n// The endpoint always wraps the payload: success -> { success, data },\n// failure -> { success: false, message } (HTTP 200 or 404).\ninterface ModelCardEnvelope {\n success?: boolean;\n message?: string;\n data?: PublicModelDTO;\n}\n\nfunction errorResult(text: string): McpToolResult {\n return { isError: true, content: [{ type: \"text\", text }] };\n}\n\nexport const modelCardTool: ToolDefinition<ModelCardInput> = {\n name: \"orcarouter_model_card\",\n description:\n \"Get detailed information about a single model: pricing, context window, supported endpoints, latency.\",\n inputSchema: {\n type: \"object\",\n properties: {\n model: {\n type: \"string\",\n description:\n \"Model ref in `provider/slug` form (e.g. `openai/gpt-4o-mini`, \" +\n \"`anthropic/claude-haiku-4.5`). Use the exact `id` value \" +\n \"returned by orcarouter_models_list.\",\n },\n },\n required: [\"model\"],\n additionalProperties: false,\n },\n async handler(input, { client }): Promise<McpToolResult> {\n if (typeof input.model !== \"string\" || input.model.trim().length === 0) {\n throw new ValidationError(\"model must be a non-empty string\");\n }\n const ref = input.model.trim();\n const slashIdx = ref.indexOf(\"/\");\n\n // The public detail route has two shapes:\n // /api/public/models/:provider/:slug — for provider-prefixed ids\n // (most upstream catalog entries, e.g. openai/gpt-4o-mini)\n // /api/public/models/:provider — single-segment fallback for\n // bare model names the backend still emits (moonshot's kimi-k2.5,\n // ai360's 360gpt-pro, admin-configured bare ratios). Without this\n // branch the documented list → card workflow breaks on those ids.\n // Leading or trailing slashes never resolve and are rejected up front.\n let urlPath: string;\n if (slashIdx === -1) {\n urlPath = `/api/public/models/${encodeURIComponent(ref)}`;\n } else if (slashIdx === 0 || slashIdx === ref.length - 1) {\n throw new ValidationError(\n `model must not start or end with '/'; got: ${input.model}`,\n );\n } else {\n const provider = encodeURIComponent(ref.slice(0, slashIdx));\n const slug = encodeURIComponent(ref.slice(slashIdx + 1));\n urlPath = `/api/public/models/${provider}/${slug}`;\n }\n\n let body: ModelCardEnvelope;\n try {\n body = await client.get<ModelCardEnvelope>(urlPath);\n } catch (e) {\n // Failure responses are returned as { success:false, message } with\n // HTTP 404 (model not found) or 500. ApiError.message is already\n // extracted from the envelope's `message` field by the client.\n if (e instanceof ApiError) {\n const msg = e.message || \"\";\n if (e.status === 404 || /not found/i.test(msg)) {\n return errorResult(\n `Model not found: ${ref}. ` +\n `Check the model id, or use orcarouter_models_list to discover available models.`,\n );\n }\n return errorResult(\n `Failed to fetch model card for ${ref}: ${msg || `HTTP ${e.status}`}`,\n );\n }\n throw e instanceof Error\n ? new Error(`Failed to fetch model card for ${ref}: ${e.message}`, {\n cause: e,\n })\n : e;\n }\n\n // Unwrap the { success, data } envelope. A success:false body can also\n // arrive with HTTP 200 (e.g. \"missing slug\").\n if (body == null || body.success === false || body.data == null) {\n const msg = (body && body.message) || \"\";\n if (/not found/i.test(msg) || msg === \"\") {\n return errorResult(\n `Model not found: ${ref}. ` +\n `Check the model id, or use orcarouter_models_list to discover available models.`,\n );\n }\n return errorResult(`Failed to fetch model card for ${ref}: ${msg}`);\n }\n\n // Emit the full PublicModelDTO as JSON inside the text payload,\n // preceded by a one-line `Model card for X:` summary. Same JSON-in-\n // text convention used by orcarouter_models_list so callers can pluck\n // precise fields (pricing.input_per_million_usd, latency.p50_ms, ...)\n // without parsing prose.\n const summary = `Model card for ${ref}:`;\n const json = JSON.stringify(body.data, null, 2);\n return textResult(`${summary}\\n\\n${json}`);\n },\n};\n","import { textResult, type ToolDefinition } from \"./types.js\";\n\ntype Capability = \"chat\" | \"embedding\" | \"image\" | \"audio\";\n\ninterface ModelsListInput {\n provider?: string;\n capability?: Capability;\n min_context?: number;\n}\n\n// Real /v1/models item shape. The list is anonymous (no API key\n// required) and surfaces pricing, name, description, and other\n// enriched metadata when the admin has curated it. orcarouter/*\n// router aliases also appear alongside concrete models, declaring\n// the legacy wire values for supported_endpoint_types.\ninterface ModelPricing {\n prompt?: string;\n completion?: string;\n prompt_per_million?: string;\n completion_per_million?: string;\n request?: string;\n image?: string;\n}\n\ninterface ModelEntry {\n id?: string;\n object?: string;\n created?: number;\n owned_by?: string;\n supported_endpoint_types?: string[];\n context_length?: number;\n name?: string;\n description?: string;\n pricing?: ModelPricing;\n [k: string]: unknown;\n}\n\ninterface ModelsListResponse {\n data: ModelEntry[];\n}\n\nexport const modelsListTool: ToolDefinition<ModelsListInput> = {\n name: \"orcarouter_models_list\",\n description:\n \"List available LLM models. Filter by provider, capability, or minimum \" +\n \"context length — filters are applied server-side by the OrcaRouter backend.\",\n inputSchema: {\n type: \"object\",\n properties: {\n provider: {\n type: \"string\",\n description:\n \"Provider id (lowercase, e.g. 'openai', 'anthropic'). Get the full list via orcarouter_providers_list.\",\n },\n capability: {\n type: \"string\",\n enum: [\"chat\", \"embedding\", \"image\", \"audio\"],\n description: \"Filter to models supporting this capability.\",\n },\n min_context: {\n type: \"integer\",\n minimum: 1,\n description:\n \"Filter to models with context window at least this large (tokens).\",\n },\n },\n additionalProperties: false,\n },\n async handler(input, { client }) {\n // Filters are forwarded to the backend's /v1/models query string;\n // the SDK no longer applies a client-side predicate. Older backends\n // that ignore unknown query params will just return the unfiltered\n // list — callers should rely on a v0.2.0-compatible OrcaRouter\n // deployment for accurate filtering.\n const query: Record<string, string> = {};\n if (typeof input.provider === \"string\" && input.provider.trim()) {\n query.provider = input.provider.trim().toLowerCase();\n }\n if (typeof input.capability === \"string\" && input.capability.trim()) {\n query.capability = input.capability.trim().toLowerCase();\n }\n if (typeof input.min_context === \"number\" && input.min_context > 0) {\n query.min_context = String(input.min_context);\n }\n\n const data = await client.get<ModelsListResponse>(\"/v1/models\", { query });\n const all = Array.isArray(data.data) ? data.data : [];\n\n if (all.length === 0) {\n const activeFilters: string[] = [];\n if (query.provider) activeFilters.push(`provider=${query.provider}`);\n if (query.capability) activeFilters.push(`capability=${query.capability}`);\n if (query.min_context) activeFilters.push(`min_context=${query.min_context}`);\n const hint =\n activeFilters.length > 0\n ? `No models match: ${activeFilters.join(\", \")}`\n : `No models currently available.`;\n return textResult(hint);\n }\n\n // Emit the entries as a JSON array inside the text payload, preceded\n // by a one-line `Found N models:` summary. Shape mirrors the upstream\n // /v1/models response (id, name, description, context_length,\n // pricing, supported_endpoint_types, owned_by, ...) so LLM callers\n // can pluck precise fields (e.g. pricing.prompt_per_million for sort\n // / compare operations) instead of regex-ing values out of prose.\n // Pretty-printed (indent 2) for readability when surfaced to a\n // human-in-the-loop chat client.\n const summary = `Found ${all.length} model${all.length === 1 ? \"\" : \"s\"}:`;\n const json = JSON.stringify(all, null, 2);\n return textResult(`${summary}\\n\\n${json}`);\n },\n};\n","import { ApiError } from \"../errors.js\";\nimport { textResult, type ToolDefinition, type McpToolResult } from \"./types.js\";\n\ninterface ProvidersListInput {}\n\ninterface PublicProviderEntry {\n provider_id: string;\n model_count: number;\n display_name?: string;\n icon_url?: string;\n}\n\ninterface ProvidersListEnvelope {\n success?: boolean;\n message?: string;\n data?: {\n providers?: PublicProviderEntry[];\n unprefixed_model_count?: number;\n };\n}\n\nfunction errorResult(text: string): McpToolResult {\n return { isError: true, content: [{ type: \"text\", text }] };\n}\n\nexport const providersListTool: ToolDefinition<ProvidersListInput> = {\n name: \"orcarouter_providers_list\",\n description:\n \"List all model providers on OrcaRouter with their model counts and \" +\n \"display metadata. Works without an API key. Useful for discovering \" +\n \"provider ids (e.g. 'openai', 'anthropic') to pass to \" +\n \"orcarouter_models_list as the `provider` filter.\",\n inputSchema: {\n type: \"object\",\n properties: {},\n additionalProperties: false,\n },\n async handler(_input, { client }): Promise<McpToolResult> {\n let body: ProvidersListEnvelope;\n try {\n body = await client.get<ProvidersListEnvelope>(\"/api/public/providers\");\n } catch (e) {\n if (e instanceof ApiError) {\n if (e.status === 404) {\n return errorResult(\n \"This OrcaRouter deployment does not expose provider discovery. \" +\n \"Use orcarouter_models_list to discover available models.\",\n );\n }\n return errorResult(\n `Failed to fetch providers: ${e.message || `HTTP ${e.status}`}`,\n );\n }\n throw e instanceof Error\n ? new Error(`Failed to fetch providers: ${e.message}`, { cause: e })\n : e;\n }\n\n if (body == null || body.success === false || body.data == null) {\n const msg = (body && body.message) || \"unknown\";\n return errorResult(`Failed to fetch providers: ${msg}`);\n }\n\n if (!Array.isArray(body.data.providers)) {\n return errorResult(\n `Invalid response from OrcaRouter: 'providers' field is not an array.`,\n );\n }\n const providers = body.data.providers;\n const summary = `Found ${providers.length} providers:`;\n const json = JSON.stringify(body.data, null, 2);\n return textResult(`${summary}\\n\\n${json}`);\n },\n};\n"],"mappings":"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","names":["errorResult"]}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@orcarouter/mcp",
3
+ "version": "1.1.2",
4
+ "description": "Official Model Context Protocol server for OrcaRouter — an OpenAI-compatible LLM API gateway.",
5
+ "license": "MIT",
6
+ "author": "OrcaRouter",
7
+ "homepage": "https://github.com/Continuum-AI-Corp/orcarouter-mcp-server#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/Continuum-AI-Corp/orcarouter-mcp-server.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/Continuum-AI-Corp/orcarouter-mcp-server/issues"
14
+ },
15
+ "type": "module",
16
+ "bin": {
17
+ "orcarouter-mcp": "./dist/index.js"
18
+ },
19
+ "main": "./dist/index.js",
20
+ "files": [
21
+ "dist",
22
+ "README.md",
23
+ "LICENSE",
24
+ "assets"
25
+ ],
26
+ "engines": {
27
+ "node": ">=18"
28
+ },
29
+ "scripts": {
30
+ "build": "tsup",
31
+ "test": "vitest run",
32
+ "test:watch": "vitest",
33
+ "typecheck": "tsc --noEmit",
34
+ "start": "node dist/index.js"
35
+ },
36
+ "dependencies": {
37
+ "@modelcontextprotocol/sdk": "^1.29.0",
38
+ "ajv": "^8.20.0",
39
+ "ajv-formats": "^3.0.1"
40
+ },
41
+ "devDependencies": {
42
+ "@types/node": "^20.0.0",
43
+ "msw": "^2.4.0",
44
+ "tsup": "^8.0.0",
45
+ "typescript": "^5.4.0",
46
+ "vitest": "^1.6.0"
47
+ },
48
+ "keywords": [
49
+ "mcp",
50
+ "model-context-protocol",
51
+ "orcarouter",
52
+ "llm",
53
+ "ai-gateway"
54
+ ]
55
+ }