mcp-ts-template 1.4.1 → 1.4.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.
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![TypeScript](https://img.shields.io/badge/TypeScript-^5.8.3-blue.svg)](https://www.typescriptlang.org/)
4
4
  [![Model Context Protocol SDK](https://img.shields.io/badge/MCP%20SDK-1.12.1-green.svg)](https://github.com/modelcontextprotocol/typescript-sdk)
5
5
  [![MCP Spec Version](https://img.shields.io/badge/MCP%20Spec-2025--03--26-lightgrey.svg)](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-03-26/changelog.mdx)
6
- [![Version](https://img.shields.io/badge/Version-1.4.1-blue.svg)](./CHANGELOG.md)
6
+ [![Version](https://img.shields.io/badge/Version-1.4.2-blue.svg)](./CHANGELOG.md)
7
7
  [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
8
8
  [![Status](https://img.shields.io/badge/Status-Stable-green.svg)](https://github.com/cyanheads/mcp-ts-template/issues)
9
9
  [![GitHub](https://img.shields.io/github/stars/cyanheads/mcp-ts-template?style=social)](https://github.com/cyanheads/mcp-ts-template)
@@ -14,23 +14,37 @@ This template provides a solid, beginner-friendly foundation for building robust
14
14
 
15
15
  Whether you're creating a new MCP server to extend an AI's capabilities or integrating MCP client features into your application, this template is your starting point.
16
16
 
17
+ ## 📋 Table of Contents
18
+
19
+ - [✨ Key Features](#-key-features)
20
+ - [🌟 Projects Using This Template](#-projects-using-this-template)
21
+ - [🏁 Quick Start](#quick-start)
22
+ - [⚙️ Configuration](#️-configuration)
23
+ - [🔩 Server Configuration (Environment Variables)](#server-configuration-environment-variables)
24
+ - [🔌 Client Configuration (`src/mcp-client/client-config/mcp-config.json`)](#client-configuration-mcp-configjson)
25
+ - [🏗️ Project Structure](#️-project-structure)
26
+ - [🧩 Adding Tools/Resources](#-adding-your-own-tools--resources)
27
+ - [🌍 More MCP Resources](#-explore-more-mcp-resources)
28
+ - [📜 License](#-license)
29
+ - [📊 Detailed Features Table](#detailed-features-table)
30
+
17
31
  ## ✨ Key Features
18
32
 
19
- | Feature Area | Description | Key Components / Location |
20
- | :-------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------- |
33
+ | Feature Area | Description | Key Components / Location |
34
+ | :-------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------- |
21
35
  | **🔌 MCP Server** | Functional server with example tools (`EchoTool`, `CatFactFetcher` for async/Promise API example) and an `EchoResource`. Supports `stdio` and **Streamable HTTP** transports. | `src/mcp-server/` |
22
- | **💻 MCP Client** | Working client aligned with **MCP 2025-03-26 spec**. Connects via `mcp-config.json`. Includes detailed comments. | `src/mcp-client/` |
23
- | **🚀 Production Utilities** | Logging, Error Handling, ID Generation, Rate Limiting, Request Context tracking, Input Sanitization. | `src/utils/` |
24
- | **🔒 Type Safety/Security** | Strong type checking via TypeScript & Zod validation. Built-in security utilities (sanitization, auth middleware stub for HTTP). | Throughout, `src/utils/security/`, `src/mcp-server/transports/authentication/` |
25
- | **⚙️ Error Handling** | Consistent error categorization (`BaseErrorCode`), detailed logging, centralized handling (`ErrorHandler`). | `src/utils/internal/errorHandler.ts`, `src/types-global/` |
26
- | **📚 Documentation** | Comprehensive `README.md`, structured JSDoc comments, API references | `README.md`, Codebase, `tsdoc.json`, `docs/api-references/` |
27
- | **🤖 Agent Ready** | Includes a [.clinerules](.clinerules) developer cheatsheet tailored for LLM coding agents. | `.clinerules` |
28
- | **🛠️ Utility Scripts** | Scripts for cleaning builds, setting executable permissions, generating directory trees, and fetching OpenAPI specs. | `scripts/` |
29
- | **🧩 Services** | Reusable modules for LLM (OpenRouter) and data storage (DuckDB) integration, with examples. | `src/services/`, `src/storage/duckdbExample.ts`, ` |
36
+ | **💻 MCP Client** | Working client aligned with **MCP 2025-03-26 spec**. Connects via `mcp-config.json`. Includes detailed comments. | `src/mcp-client/` |
37
+ | **🚀 Production Utilities** | Logging, Error Handling, ID Generation, Rate Limiting, Request Context tracking, Input Sanitization. | `src/utils/` |
38
+ | **🔒 Type Safety/Security** | Strong type checking via TypeScript & Zod validation. Built-in security utilities (sanitization, auth middleware stub for HTTP). | Throughout, `src/utils/security/`, `src/mcp-server/transports/authentication/` |
39
+ | **⚙️ Error Handling** | Consistent error categorization (`BaseErrorCode`), detailed logging, centralized handling (`ErrorHandler`). | `src/utils/internal/errorHandler.ts`, `src/types-global/` |
40
+ | **📚 Documentation** | Comprehensive `README.md`, structured JSDoc comments, API references | `README.md`, Codebase, `tsdoc.json`, `docs/api-references/` |
41
+ | **🤖 Agent Ready** | Includes a [.clinerules](.clinerules) developer cheatsheet tailored for LLM coding agents. | `.clinerules` |
42
+ | **🛠️ Utility Scripts** | Scripts for cleaning builds, setting executable permissions, generating directory trees, and fetching OpenAPI specs. | `scripts/` |
43
+ | **🧩 Services** | Reusable modules for LLM (OpenRouter) and data storage (DuckDB) integration, with examples. | `src/services/`, `src/storage/duckdbExample.ts` |
30
44
 
31
45
  _For a more granular breakdown, see the [Detailed Features Table](#detailed-features-table) below._
32
46
 
33
- ## 🚀 Projects Using This Template
47
+ ## 🌟 Projects Using This Template
34
48
 
35
49
  This template is already powering several MCP servers, demonstrating its flexibility and robustness:
36
50
 
@@ -46,11 +60,7 @@ _Note: [**toolkit-mcp-server**](https://github.com/cyanheads/toolkit-mcp-server)
46
60
 
47
61
  You can also **see my [GitHub profile](https://github.com/cyanheads/)** for additional MCP servers I've created, many of which are planned to be migrated to or built upon this template in the future.
48
62
 
49
- ## 📋 Table of Contents
50
-
51
- [✨ Key Features](#-key-features) | [🚀 Projects Using This Template](#-projects-using-this-template) | [🚀 Quick Start](#quick-start) | [⚙️ Configuration](#️-configuration) | [Server Configuration](#server-configuration-environment-variables) | [Client Configuration](#client-configuration-mcp-configjson) | [🏗️ Project Structure](#️-project-structure) | [🧩 Adding Tools/Resources](#-adding-your-own-tools--resources) | [🌍 More MCP Resources](#-explore-more-mcp-resources) | [📜 License](#-license) | [Detailed Features](#detailed-features-table)
52
-
53
- ## Quick Start
63
+ ## 🏁 Quick Start
54
64
 
55
65
  Get the example server running in minutes:
56
66
 
@@ -95,7 +105,7 @@ Get the example server running in minutes:
95
105
 
96
106
  ## ⚙️ Configuration
97
107
 
98
- ### Server Configuration (Environment Variables)
108
+ ### 🔩 Server Configuration (Environment Variables)
99
109
 
100
110
  Configure the MCP server's behavior using these environment variables:
101
111
 
@@ -111,21 +121,15 @@ Configure the MCP server's behavior using these environment variables:
111
121
  | `LOGS_DIR` | Directory for log files. | `logs/` (in project root) |
112
122
  | `NODE_ENV` | Runtime environment (`development`, `production`). | `development` |
113
123
  | `MCP_AUTH_SECRET_KEY` | **Required for HTTP transport.** Secret key (min 32 chars) for signing/verifying auth tokens (JWT). | (none - **MUST be set in production**) |
114
- | `OPENROUTER_APP_URL` | URL of the application (used by OpenRouter service for HTTP Referer). | `http://localhost:3000` |
115
- | `OPENROUTER_APP_NAME` | Name of the application (used by OpenRouter service for X-Title header). | 'mcp-ts-template' |
116
124
  | `OPENROUTER_API_KEY` | API key for OpenRouter.ai service. Optional, but service will be unconfigured without it. | (none) |
117
125
  | `LLM_DEFAULT_MODEL` | Default model to use for LLM calls via OpenRouter. | `google/gemini-2.5-flash-preview-05-20` |
118
126
  | `LLM_DEFAULT_TEMPERATURE` | Default temperature for LLM calls (0-2). Optional. | (none) |
119
- | `LLM_DEFAULT_TOP_P` | Default top_p for LLM calls (0-1). Optional. | (none) |
120
- | `LLM_DEFAULT_MAX_TOKENS` | Default max_tokens for LLM calls. Optional. | (none) |
121
- | `LLM_DEFAULT_TOP_K` | Default top_k for LLM calls (non-negative integer). Optional. | (none) |
122
- | `LLM_DEFAULT_MIN_P` | Default min_p for LLM calls (0-1). Optional. | (none) |
123
127
 
124
128
  **Note on HTTP Port Retries:** If the `MCP_HTTP_PORT` is busy, the server automatically tries the next port (up to 15 times).
125
129
 
126
130
  **Security Note for HTTP Transport:** When using `MCP_TRANSPORT_TYPE=http`, authentication is **mandatory** as per the MCP specification. This template includes JWT-based authentication middleware (`src/mcp-server/transports/authentication/authMiddleware.ts`). You **MUST** set a strong, unique `MCP_AUTH_SECRET_KEY` in your production environment for this security mechanism to function correctly. Failure to do so will result in bypassed authentication checks in development and fatal errors in production.
127
131
 
128
- ### Client Configuration (`src/mcp-client/client-config/mcp-config.json`)
132
+ ### 🔌 Client Configuration (`src/mcp-client/client-config/mcp-config.json`)
129
133
 
130
134
  Configure the connections for the built-in **MCP client** using `src/mcp-client/client-config/mcp-config.json`. If this file is missing, it falls back to `src/mcp-client/client-config/mcp-config.json.example`.
131
135
 
@@ -148,7 +152,6 @@ This file defines external MCP servers the client can connect to. The client imp
148
152
  "env": {}, // Not used for HTTP
149
153
  "transportType": "http" // Explicitly http
150
154
  }
151
- // ... add other servers
152
155
  }
153
156
  }
154
157
  ```
@@ -162,43 +165,30 @@ See `src/mcp-client/client-config/configLoader.ts` for the Zod validation schema
162
165
 
163
166
  ## 🏗️ Project Structure
164
167
 
165
- The `src/` directory is organized for clarity:
166
-
167
- - `config/`: Loads environment variables and package info.
168
- - `mcp-client/`: Logic for the client connecting to _external_ MCP servers (updated to MCP 2025-03-26 spec).
169
- - `client-config/`: Handles loading and validation of `mcp-config.json`.
170
- - `configLoader.ts`: Loads and validates server configurations.
171
- - `mcp-config.json.example`: Example configuration file.
172
- - `core/`: Core client logic including connection management and caching.
173
- - `clientManager.ts`: Manages client instances and their lifecycle.
174
- - `clientConnectionLogic.ts`: Handles the details of connecting and initializing with servers.
175
- - `clientCache.ts`: Caches active client connections.
176
- - `transports/`: Manages different communication transports (Stdio, HTTP).
177
- - `transportFactory.ts`: Creates appropriate transport instances.
178
- - `stdioClientTransport.ts`: Implements Stdio transport.
179
- - `httpClientTransport.ts`: Implements HTTP transport.
180
- - `index.ts`: Barrel file exporting key client functionalities.
181
- - `mcp-server/`: Logic for the MCP server _provided by this template_.
182
- - `server.ts`: Initializes the server, registers tools/resources.
183
- - `resources/`: Example resource implementations (e.g., `EchoResource`).
184
- - `tools/`: Example tool implementations (e.g., `EchoTool`, and `CatFactFetcher` demonstrating async/Promise API calls).
185
- - `transports/`: Handles `stdio` and `http` communication for the server.
186
- - `services/`: Contains service integrations.
187
- - `duck-db/`: Service for interacting with DuckDB, an in-process analytical data management system.
188
- - `duckDBConnectionManager.ts`: Manages DuckDB instance and connection lifecycle.
189
- - `duckDBQueryExecutor.ts`: Executes SQL queries and manages transactions.
190
- - `duckDBService.ts`: Main service class for DuckDB interaction.
191
- - `types.ts`: TypeScript types and interfaces for the DuckDB service.
192
- - `llm-providers/`: API Providers for Large Language Models.
193
- - `openRouter/`: OpenRouter provider implementation.
194
- - `llmFactory.ts`: Factory for creating LLM provider clients.
195
- - `index.ts`: Barrel file for all LLM providers.
196
- - `index.ts`: Barrel file for services.
197
- - `storage/`: Example usage of services, e.g., `duckdbExample.ts`.
198
- - `types-global/`: Shared TypeScript definitions (Errors, MCP types).
199
- - `utils/`: Reusable utilities (logging, errors, security, parsing, etc.). Exported via `index.ts`.
200
-
201
- **Explore the structure yourself:**
168
+ This project follows a standard TypeScript project layout. Here's an overview of the key directories and files:
169
+
170
+ - **`.clinerules`**: Developer cheatsheet and guidelines for LLM coding agents working with this repository.
171
+ - **`docs/`**: Contains project documentation, including API references and the auto-generated `tree.md` file.
172
+ - **`scripts/`**: Utility scripts for development tasks like cleaning builds, generating directory trees, and fetching OpenAPI specs.
173
+ - **`src/`**: The heart of the application, containing all TypeScript source code.
174
+ - `src/config/`: Handles loading and validation of environment variables and application configuration.
175
+ - `src/mcp-client/`: Implements the MCP client logic for connecting to and interacting with external MCP servers. This includes client configuration, core connection management, and transport handlers.
176
+ - `src/mcp-server/`: Contains the MCP server implementation provided by this template, including example tools, resources, and transport handlers (Stdio, HTTP).
177
+ - `src/services/`: Provides reusable modules for integrating with external services, such as DuckDB for local data storage and OpenRouter for LLM access.
178
+ - `src/types-global/`: Defines shared TypeScript interfaces and type definitions used across the project, particularly for error handling and MCP-specific types.
179
+ - `src/utils/`: A collection of core utilities.
180
+ - `src/utils/internal/`: Core internal utilities like the logger, error handler, and request context management.
181
+ - `src/utils/metrics/`: Utilities related to metrics, such as token counting.
182
+ - `src/utils/network/`: Network-related utilities, like fetch with timeout.
183
+ - `src/utils/parsing/`: Utilities for parsing data, such as dates and JSON.
184
+ - `src/utils/security/`: Security-focused utilities including ID generation, rate limiting, and input sanitization.
185
+ - `src/index.ts`: The main entry point for the application, responsible for initializing and starting the MCP server. The MCP client is meant to be built upon, so it does not have a dedicated entry point in this template.
186
+ - **`package.json`**: Defines project metadata, dependencies, and npm scripts.
187
+ - **`README.md`**: This file, providing an overview of the project.
188
+ - **`tsconfig.json`**: TypeScript compiler options for the project.
189
+ - **`LICENSE`**: Apache 2.0 License file.
190
+
191
+ **Explore the full structure yourself:**
202
192
 
203
193
  See the current file tree in [docs/tree.md](docs/tree.md) or generate it dynamically:
204
194
 
@@ -206,7 +196,7 @@ See the current file tree in [docs/tree.md](docs/tree.md) or generate it dynamic
206
196
  npm run tree
207
197
  ```
208
198
 
209
- (This uses `scripts/tree.ts` to generate a current file tree.)
199
+ (This uses `scripts/tree.ts` to generate a current file tree, respecting `.gitignore`.)
210
200
 
211
201
  ## 🧩 Adding Your Own Tools & Resources
212
202
 
@@ -236,7 +226,7 @@ This collection includes servers for Filesystem, Obsidian, Git, GitHub, Perplexi
236
226
 
237
227
  This project is licensed under the Apache License 2.0. See the [LICENSE](LICENSE) file for details.
238
228
 
239
- ## Detailed Features Table
229
+ ## 📊 Detailed Features Table
240
230
 
241
231
  | Category | Feature | Description | Location(s) |
242
232
  | :----------------------- | :------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------- |
@@ -1,7 +1,15 @@
1
1
  import { ChatCompletion, ChatCompletionChunk, ChatCompletionCreateParamsNonStreaming, ChatCompletionCreateParamsStreaming } from "openai/resources/chat/completions";
2
2
  import { Stream } from "openai/streaming";
3
- import { OperationContext, RequestContext } from "../../../utils/internal/requestContext.js";
4
- import { OpenRouterClientOptions } from "../llmFactory.js";
3
+ import { OperationContext, RequestContext } from "../../utils/internal/requestContext.js";
4
+ /**
5
+ * Options for configuring the OpenRouter client.
6
+ */
7
+ export interface OpenRouterClientOptions {
8
+ apiKey?: string;
9
+ baseURL?: string;
10
+ siteUrl?: string;
11
+ siteName?: string;
12
+ }
5
13
  /**
6
14
  * Defines the parameters for an OpenRouter chat completion request.
7
15
  * This type extends standard OpenAI chat completion parameters and includes
@@ -53,7 +61,7 @@ declare class OpenRouterProvider {
53
61
  * Constructs an `OpenRouterProvider` instance.
54
62
  * Initializes the OpenAI client for OpenRouter if an API key is provided.
55
63
  * Sets default headers required by OpenRouter.
56
- * @param apiKey - The OpenRouter API key. If undefined, the service remains 'unconfigured'.
64
+ * @param options - Optional configuration for the OpenRouter client.
57
65
  * @param parentOpContext - Optional parent operation context for linked logging.
58
66
  */
59
67
  constructor(options?: OpenRouterClientOptions, parentOpContext?: OperationContext);
@@ -1,11 +1,18 @@
1
- import { config } from "../../../config/index.js";
2
- import { BaseErrorCode, McpError } from "../../../types-global/errors.js";
3
- import { ErrorHandler } from "../../../utils/internal/errorHandler.js";
4
- import { logger } from "../../../utils/internal/logger.js";
5
- import { requestContextService, } from "../../../utils/internal/requestContext.js";
6
- import { rateLimiter } from "../../../utils/security/rateLimiter.js";
7
- import { sanitization } from "../../../utils/security/sanitization.js";
8
- import { llmFactory } from "../llmFactory.js"; // Import factory
1
+ /**
2
+ * @fileoverview Provides a service class (`OpenRouterProvider`) for interacting with the
3
+ * OpenRouter API, using the OpenAI SDK for chat completions. It handles API key
4
+ * configuration, default parameters, rate limiting, model-specific parameter adjustments,
5
+ * and error handling.
6
+ * @module src/services/llm-providers/openRouterProvider
7
+ */
8
+ import OpenAI from "openai";
9
+ import { config } from "../../config/index.js";
10
+ import { BaseErrorCode, McpError } from "../../types-global/errors.js";
11
+ import { ErrorHandler } from "../../utils/internal/errorHandler.js";
12
+ import { logger } from "../../utils/internal/logger.js";
13
+ import { requestContextService, } from "../../utils/internal/requestContext.js";
14
+ import { rateLimiter } from "../../utils/security/rateLimiter.js";
15
+ import { sanitization } from "../../utils/security/sanitization.js";
9
16
  /**
10
17
  * Service class for interacting with the OpenRouter API.
11
18
  * Uses the OpenAI SDK for chat completions, configured for OpenRouter.
@@ -17,7 +24,7 @@ class OpenRouterProvider {
17
24
  * Constructs an `OpenRouterProvider` instance.
18
25
  * Initializes the OpenAI client for OpenRouter if an API key is provided.
19
26
  * Sets default headers required by OpenRouter.
20
- * @param apiKey - The OpenRouter API key. If undefined, the service remains 'unconfigured'.
27
+ * @param options - Optional configuration for the OpenRouter client.
21
28
  * @param parentOpContext - Optional parent operation context for linked logging.
22
29
  */
23
30
  constructor(options, parentOpContext) {
@@ -34,38 +41,43 @@ class OpenRouterProvider {
34
41
  parentRequestId: parentOpContext?.requestId,
35
42
  });
36
43
  this.status = "initializing";
37
- // The factory will use config.openrouterApiKey if options.apiKey is not provided.
38
- // If neither is available, the factory will throw a CONFIGURATION_ERROR.
39
- // The 'unconfigured' status here might become less relevant if factory handles all key checks.
40
- // However, we can keep it for cases where the service is instantiated without attempting client creation immediately.
41
- if (!options?.apiKey && !config.openrouterApiKey) {
44
+ const apiKey = options?.apiKey || config.openrouterApiKey;
45
+ const baseURL = options?.baseURL || "https://openrouter.ai/api/v1";
46
+ const siteUrl = options?.siteUrl || config.openrouterAppUrl;
47
+ const siteName = options?.siteName || config.openrouterAppName;
48
+ if (!apiKey) {
42
49
  this.status = "unconfigured";
43
- logger.warning("OpenRouter API key not provided in options or global config. Service is unconfigured.", { ...opContext, service: "OpenRouterProvider" });
44
- // Early return if no key is available at all, factory would fail anyway.
45
- // Or, let the factory attempt and catch the error. For now, let's try to initialize.
50
+ this.initializationError = new McpError(BaseErrorCode.CONFIGURATION_ERROR, "OpenRouter API key is not configured.", { operation: operationName });
51
+ logger.error(`[${operationName}] OpenRouter API key not provided in options or global config. Service is unconfigured.`, { ...opContext, service: "OpenRouterProvider" });
52
+ return;
46
53
  }
47
- llmFactory
48
- .getLlmClient("openrouter", opContext, options)
49
- .then((client) => {
50
- this.client = client; // Factory returns OpenAI for 'openrouter'
54
+ try {
55
+ this.client = new OpenAI({
56
+ baseURL,
57
+ apiKey,
58
+ defaultHeaders: {
59
+ "HTTP-Referer": siteUrl,
60
+ "X-Title": siteName,
61
+ },
62
+ });
51
63
  this.status = "ready";
52
- logger.info("OpenRouter Service Initialized and Ready via LlmFactory", {
64
+ logger.info("OpenRouter Service Initialized and Ready", {
53
65
  ...opContext,
54
66
  service: "OpenRouterProvider",
55
67
  });
56
- })
57
- .catch((error) => {
68
+ }
69
+ catch (error) {
58
70
  this.status = "error";
59
71
  this.initializationError =
60
72
  error instanceof Error
61
73
  ? error
62
74
  : new McpError(BaseErrorCode.INITIALIZATION_FAILED, String(error));
63
- logger.error("Failed to initialize OpenRouter client via LlmFactory", {
75
+ logger.error("Failed to initialize OpenRouter client", {
64
76
  ...opContext,
65
77
  service: "OpenRouterProvider",
66
78
  error: this.initializationError.message,
67
79
  });
68
- });
80
+ }
69
81
  }
70
82
  /**
71
83
  * Checks if the service is ready to make API calls.
@@ -165,11 +177,6 @@ class OpenRouterProvider {
165
177
  else if (extraBody.provider === undefined) {
166
178
  extraBody.provider = { sort: "throughput" };
167
179
  }
168
- // Conditional logic for max_tokens vs max_completion_tokens
169
- // Certain underlying models (e.g., newer OpenAI models like the o1 series)
170
- // may require `max_completion_tokens` instead of `max_tokens`.
171
- // This client sends `max_completion_tokens` in `extra_body` for these models if a limit is specified.
172
- // For other models, `max_tokens` is used as a standard parameter.
173
180
  const modelsRequiringMaxCompletionTokens = ["openai/o1", "openai/gpt-4.1"];
174
181
  const needsMaxCompletionTokens = modelsRequiringMaxCompletionTokens.some((modelPrefix) => effectiveModelId.startsWith(modelPrefix));
175
182
  const effectiveMaxTokensValue = params.max_tokens ?? config.llmDefaultMaxTokens;
@@ -179,8 +186,6 @@ class OpenRouterProvider {
179
186
  logger.info(`[${operation}] Using 'max_completion_tokens: ${effectiveMaxTokensValue}' for model ${effectiveModelId} (sent via extra_body).`, context);
180
187
  }
181
188
  else {
182
- // For models not in the list, or if OpenRouter handles the mapping transparently,
183
- // send max_tokens as a standard parameter.
184
189
  standardParams.max_tokens = effectiveMaxTokensValue;
185
190
  logger.info(`[${operation}] Using 'max_tokens: ${effectiveMaxTokensValue}' for model ${effectiveModelId}.`, context);
186
191
  }
@@ -280,8 +285,6 @@ class OpenRouterProvider {
280
285
  method: "GET",
281
286
  headers: {
282
287
  "Content-Type": "application/json",
283
- // Authorization header might be needed if OpenRouter changes their /models endpoint access
284
- // "Authorization": `Bearer ${this.client?.apiKey}`, // apiKey is private on OpenAI client
285
288
  },
286
289
  });
287
290
  if (!response.ok) {
@@ -321,9 +324,5 @@ class OpenRouterProvider {
321
324
  * Singleton instance of the `OpenRouterProvider`.
322
325
  * Initialized with the OpenRouter API key from application configuration.
323
326
  */
324
- // Update instantiation to pass options if needed, or rely on factory's use of global config.
325
- // For a singleton, it usually relies on global config.
326
- // If the constructor now takes OpenRouterClientOptions, and we want the singleton
327
- // to use global config, we'd pass undefined or an empty object for options.
328
327
  const openRouterProviderInstance = new OpenRouterProvider(undefined);
329
328
  export { openRouterProviderInstance as openRouterProvider };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-ts-template",
3
- "version": "1.4.1",
3
+ "version": "1.4.2",
4
4
  "description": "TypeScript template for building Model Context Protocol (MCP) Servers & Clients. Features extensive utilities (logger, requestContext, etc.), STDIO & Streamable HTTP (with authMiddleware), examples, and type safety. Ideal starting point for creating production-ready MCP Servers & Clients.",
5
5
  "main": "dist/index.js",
6
6
  "files": [
@@ -46,7 +46,7 @@
46
46
  "express": "^5.1.0",
47
47
  "ignore": "^7.0.5",
48
48
  "jsonwebtoken": "^9.0.2",
49
- "openai": "^5.0.1",
49
+ "openai": "^5.0.2",
50
50
  "partial-json": "^0.1.7",
51
51
  "sanitize-html": "^2.17.0",
52
52
  "tiktoken": "^1.0.21",
@@ -56,7 +56,7 @@
56
56
  "winston": "^3.17.0",
57
57
  "winston-daily-rotate-file": "^5.0.0",
58
58
  "yargs": "^18.0.0",
59
- "zod": "^3.25.42"
59
+ "zod": "^3.25.49"
60
60
  },
61
61
  "keywords": [
62
62
  "typescript",
@@ -1,7 +0,0 @@
1
- /**
2
- * @fileoverview Main barrel file for all services.
3
- * This file re-exports all service modules, providing a single entry point
4
- * for accessing various services within the application.
5
- * @module src/services/index
6
- */
7
- export * from "./llm-providers";
@@ -1,7 +0,0 @@
1
- /**
2
- * @fileoverview Main barrel file for all services.
3
- * This file re-exports all service modules, providing a single entry point
4
- * for accessing various services within the application.
5
- * @module src/services/index
6
- */
7
- export * from "./llm-providers";
@@ -1,7 +0,0 @@
1
- /**
2
- * @fileoverview Barrel file for LLM provider services.
3
- * This file re-exports all services related to different Large Language Model providers,
4
- * making them easily accessible from a single import path.
5
- * @module src/services/llm-providers/index
6
- */
7
- export * from "./openRouter";
@@ -1,7 +0,0 @@
1
- /**
2
- * @fileoverview Barrel file for LLM provider services.
3
- * This file re-exports all services related to different Large Language Model providers,
4
- * making them easily accessible from a single import path.
5
- * @module src/services/llm-providers/index
6
- */
7
- export * from "./openRouter"; // Changed to export from the new barrel file
@@ -1,50 +0,0 @@
1
- /**
2
- * @fileoverview Factory for creating LLM client instances.
3
- * Provides a centralized way to instantiate clients for LLM providers
4
- * like OpenRouter, handling API key configuration and basic client setup.
5
- * @module src/services/llm-providers/llmFactory
6
- */
7
- import OpenAI from "openai";
8
- import { RequestContext } from "../../utils/index.js";
9
- /**
10
- * Defines the supported LLM providers.
11
- */
12
- export type LlmProviderType = "openrouter";
13
- /**
14
- * Options for configuring the OpenRouter client.
15
- */
16
- export interface OpenRouterClientOptions {
17
- apiKey?: string;
18
- baseURL?: string;
19
- siteUrl?: string;
20
- siteName?: string;
21
- }
22
- /**
23
- * Union type for all LLM client options.
24
- */
25
- export type LlmClientOptions = OpenRouterClientOptions;
26
- /**
27
- * LLM Factory class to create and configure LLM clients.
28
- */
29
- declare class LlmFactory {
30
- /**
31
- * Creates and returns an LLM client instance for the specified provider.
32
- *
33
- * @param provider - The LLM provider to create a client for.
34
- * @param context - The request context for logging.
35
- * @param options - Optional provider-specific configuration options.
36
- * @returns A Promise resolving to an instance of OpenAI (for OpenRouter).
37
- * @throws {McpError} If the provider is unsupported or API key/config is missing.
38
- */
39
- getLlmClient(provider: LlmProviderType, context: RequestContext, options?: LlmClientOptions): Promise<OpenAI>;
40
- /**
41
- * Creates an OpenAI client configured for OpenRouter.
42
- * @private
43
- */
44
- private createOpenRouterClient;
45
- }
46
- /**
47
- * Singleton instance of the LlmFactory.
48
- */
49
- export declare const llmFactory: LlmFactory;
50
- export {};
@@ -1,81 +0,0 @@
1
- /**
2
- * @fileoverview Factory for creating LLM client instances.
3
- * Provides a centralized way to instantiate clients for LLM providers
4
- * like OpenRouter, handling API key configuration and basic client setup.
5
- * @module src/services/llm-providers/llmFactory
6
- */
7
- import OpenAI from "openai";
8
- import { config } from "../../config/index.js";
9
- import { BaseErrorCode, McpError } from "../../types-global/errors.js";
10
- import { logger } from "../../utils/index.js";
11
- /**
12
- * LLM Factory class to create and configure LLM clients.
13
- */
14
- class LlmFactory {
15
- /**
16
- * Creates and returns an LLM client instance for the specified provider.
17
- *
18
- * @param provider - The LLM provider to create a client for.
19
- * @param context - The request context for logging.
20
- * @param options - Optional provider-specific configuration options.
21
- * @returns A Promise resolving to an instance of OpenAI (for OpenRouter).
22
- * @throws {McpError} If the provider is unsupported or API key/config is missing.
23
- */
24
- async getLlmClient(provider, context, options) {
25
- const operation = `LlmFactory.getLlmClient.${provider}`;
26
- logger.info(`[${operation}] Requesting LLM client`, {
27
- ...context,
28
- provider,
29
- });
30
- switch (provider) {
31
- case "openrouter":
32
- return this.createOpenRouterClient(context, options);
33
- // No default case needed if LlmProviderType only allows 'openrouter'
34
- // However, to be safe and handle potential future extensions or direct calls with invalid provider:
35
- default:
36
- // This part of the code should ideally be unreachable if LlmProviderType is strictly 'openrouter'.
37
- // If it's reached, it implies an internal logic error or misuse.
38
- const exhaustiveCheck = provider; // Ensures all LlmProviderType cases are handled
39
- logger.error(`[${operation}] Unsupported LLM provider requested: ${exhaustiveCheck}`, context);
40
- throw new McpError(BaseErrorCode.CONFIGURATION_ERROR, `Unsupported LLM provider: ${provider}`, { operation, provider: exhaustiveCheck });
41
- }
42
- }
43
- /**
44
- * Creates an OpenAI client configured for OpenRouter.
45
- * @private
46
- */
47
- createOpenRouterClient(context, options) {
48
- const operation = "LlmFactory.createOpenRouterClient";
49
- const apiKey = options?.apiKey || config.openrouterApiKey;
50
- const baseURL = options?.baseURL || "https://openrouter.ai/api/v1";
51
- const siteUrl = options?.siteUrl || config.openrouterAppUrl;
52
- const siteName = options?.siteName || config.openrouterAppName;
53
- if (!apiKey) {
54
- logger.error(`[${operation}] OPENROUTER_API_KEY is not set.`, context);
55
- throw new McpError(BaseErrorCode.CONFIGURATION_ERROR, "OpenRouter API key is not configured.", { operation });
56
- }
57
- try {
58
- const client = new OpenAI({
59
- baseURL,
60
- apiKey,
61
- defaultHeaders: {
62
- "HTTP-Referer": siteUrl,
63
- "X-Title": siteName,
64
- },
65
- });
66
- logger.info(`[${operation}] OpenRouter client created successfully.`, context);
67
- return client;
68
- }
69
- catch (error) {
70
- logger.error(`[${operation}] Failed to create OpenRouter client`, {
71
- ...context,
72
- error: error.message,
73
- });
74
- throw new McpError(BaseErrorCode.INITIALIZATION_FAILED, `Failed to initialize OpenRouter client: ${error.message}`, { operation, cause: error });
75
- }
76
- }
77
- }
78
- /**
79
- * Singleton instance of the LlmFactory.
80
- */
81
- export const llmFactory = new LlmFactory();
@@ -1,6 +0,0 @@
1
- /**
2
- * @fileoverview Barrel file for the OpenRouter provider service.
3
- * Exports the OpenRouterProvider class and any related types.
4
- * @module services/llm-providers/openRouter/index
5
- */
6
- export * from "./openRouterProvider";
@@ -1,7 +0,0 @@
1
- /**
2
- * @fileoverview Barrel file for the OpenRouter provider service.
3
- * Exports the OpenRouterProvider class and any related types.
4
- * @module services/llm-providers/openRouter/index
5
- */
6
- export * from "./openRouterProvider";
7
- // Add other exports from this module if any in the future