mcp-ts-template 1.3.4 → 1.4.1
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 +46 -37
- package/dist/mcp-server/server.js +2 -0
- package/dist/mcp-server/tools/catFactFetcher/catFactFetcherLogic.d.ts +39 -0
- package/dist/mcp-server/tools/catFactFetcher/catFactFetcherLogic.js +103 -0
- package/dist/mcp-server/tools/catFactFetcher/catFactFetcherRegistration.d.ts +15 -0
- package/dist/mcp-server/tools/catFactFetcher/catFactFetcherRegistration.js +80 -0
- package/dist/mcp-server/tools/catFactFetcher/index.d.ts +7 -0
- package/dist/mcp-server/tools/catFactFetcher/index.js +7 -0
- package/dist/services/duck-db/duckDBConnectionManager.d.ts +54 -0
- package/dist/services/duck-db/duckDBConnectionManager.js +185 -0
- package/dist/services/duck-db/duckDBQueryExecutor.d.ts +17 -0
- package/dist/services/duck-db/duckDBQueryExecutor.js +140 -0
- package/dist/services/duck-db/duckDBService.d.ts +25 -0
- package/dist/services/duck-db/duckDBService.js +138 -0
- package/dist/services/duck-db/types.d.ts +134 -0
- package/dist/services/duck-db/types.js +5 -0
- package/dist/storage/duckdbExample.d.ts +7 -0
- package/dist/storage/duckdbExample.js +188 -0
- package/dist/types-global/errors.d.ts +9 -1
- package/dist/types-global/errors.js +8 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/internal/logger.js +9 -1
- package/dist/utils/network/fetchWithTimeout.d.ts +21 -0
- package/dist/utils/network/fetchWithTimeout.js +59 -0
- package/dist/utils/network/index.d.ts +6 -0
- package/dist/utils/network/index.js +5 -0
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://www.typescriptlang.org/)
|
|
4
4
|
[](https://github.com/modelcontextprotocol/typescript-sdk)
|
|
5
5
|
[](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-03-26/changelog.mdx)
|
|
6
|
-
[](./CHANGELOG.md)
|
|
7
7
|
[](https://opensource.org/licenses/Apache-2.0)
|
|
8
8
|
[](https://github.com/cyanheads/mcp-ts-template/issues)
|
|
9
9
|
[](https://github.com/cyanheads/mcp-ts-template)
|
|
@@ -18,14 +18,15 @@ Whether you're creating a new MCP server to extend an AI's capabilities or integ
|
|
|
18
18
|
|
|
19
19
|
| Feature Area | Description | Key Components / Location |
|
|
20
20
|
| :-------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------- |
|
|
21
|
-
| **🔌 MCP Server** | Functional server example
|
|
21
|
+
| **🔌 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
22
|
| **💻 MCP Client** | Working client aligned with **MCP 2025-03-26 spec**. Connects via `mcp-config.json`. Includes detailed comments. | `src/mcp-client/` |
|
|
23
23
|
| **🚀 Production Utilities** | Logging, Error Handling, ID Generation, Rate Limiting, Request Context tracking, Input Sanitization. | `src/utils/` |
|
|
24
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
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
|
|
26
|
+
| **📚 Documentation** | Comprehensive `README.md`, structured JSDoc comments, API references | `README.md`, Codebase, `tsdoc.json`, `docs/api-references/` |
|
|
27
27
|
| **🤖 Agent Ready** | Includes a [.clinerules](.clinerules) developer cheatsheet tailored for LLM coding agents. | `.clinerules` |
|
|
28
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`, ` |
|
|
29
30
|
|
|
30
31
|
_For a more granular breakdown, see the [Detailed Features Table](#detailed-features-table) below._
|
|
31
32
|
|
|
@@ -179,15 +180,21 @@ The `src/` directory is organized for clarity:
|
|
|
179
180
|
- `index.ts`: Barrel file exporting key client functionalities.
|
|
180
181
|
- `mcp-server/`: Logic for the MCP server _provided by this template_.
|
|
181
182
|
- `server.ts`: Initializes the server, registers tools/resources.
|
|
182
|
-
- `resources/`: Example resource implementations (e.g., EchoResource).
|
|
183
|
-
- `tools/`: Example tool implementations (e.g., EchoTool).
|
|
183
|
+
- `resources/`: Example resource implementations (e.g., `EchoResource`).
|
|
184
|
+
- `tools/`: Example tool implementations (e.g., `EchoTool`, and `CatFactFetcher` demonstrating async/Promise API calls).
|
|
184
185
|
- `transports/`: Handles `stdio` and `http` communication for the server.
|
|
185
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.
|
|
186
192
|
- `llm-providers/`: API Providers for Large Language Models.
|
|
187
193
|
- `openRouter/`: OpenRouter provider implementation.
|
|
188
194
|
- `llmFactory.ts`: Factory for creating LLM provider clients.
|
|
189
195
|
- `index.ts`: Barrel file for all LLM providers.
|
|
190
196
|
- `index.ts`: Barrel file for services.
|
|
197
|
+
- `storage/`: Example usage of services, e.g., `duckdbExample.ts`.
|
|
191
198
|
- `types-global/`: Shared TypeScript definitions (Errors, MCP types).
|
|
192
199
|
- `utils/`: Reusable utilities (logging, errors, security, parsing, etc.). Exported via `index.ts`.
|
|
193
200
|
|
|
@@ -215,6 +222,8 @@ This template is designed for extension! Follow the high-level SDK patterns:
|
|
|
215
222
|
|
|
216
223
|
Refer to the included `EchoTool` and `EchoResource` examples and the [.clinerules](.clinerules) cheatsheet for detailed patterns.
|
|
217
224
|
|
|
225
|
+
For an example of a tool that performs asynchronous operations, such as making an external API call, see the `get_random_cat_fact` tool located in `src/mcp-server/tools/catFactFetcher/`. This tool demonstrates how to use `async/await` within your tool's logic and handler, manage Promises, and integrate external data sources.
|
|
226
|
+
|
|
218
227
|
## 🌍 Explore More MCP Resources
|
|
219
228
|
|
|
220
229
|
Looking for more examples, guides, and pre-built MCP servers? Check out the companion repository:
|
|
@@ -229,38 +238,38 @@ This project is licensed under the Apache License 2.0. See the [LICENSE](LICENSE
|
|
|
229
238
|
|
|
230
239
|
## Detailed Features Table
|
|
231
240
|
|
|
232
|
-
| Category | Feature | Description
|
|
233
|
-
| :----------------------- | :------------------------------ |
|
|
234
|
-
| **Core Components** | MCP Server | Core server logic, tool/resource registration, transport handling. Includes Echo Tool & Resource examples.
|
|
235
|
-
| | MCP Client | Logic for connecting to external MCP servers (updated to **MCP 2025-03-26 spec**). Refactored for modularity.
|
|
236
|
-
| | Configuration | Environment-aware settings with Zod validation.
|
|
237
|
-
| | Streamable HTTP Transport | Express-based server implementing the MCP **Streamable HTTP** transport (utilizing Server-Sent Events for server-to-client streaming), with session management, CORS, and port retries.
|
|
238
|
-
| | Stdio Transport | Handles MCP communication over standard input/output.
|
|
239
|
-
| **Utilities (Core)** | Logger | Structured, context-aware logging (files with rotation & MCP notifications).
|
|
240
|
-
| | ErrorHandler | Centralized error processing, classification, and logging.
|
|
241
|
-
| | RequestContext | Request/operation tracking and correlation.
|
|
242
|
-
| **Utilities (Metrics)** | TokenCounter | Estimates token counts using `tiktoken`.
|
|
243
|
-
| **Utilities (Parsing)** | DateParser | Parses natural language date strings using `chrono-node`.
|
|
244
|
-
| | JsonParser | Parses potentially partial JSON, handles `<think>` blocks.
|
|
245
|
-
| **Utilities (Security)** | IdGenerator | Generates unique IDs (prefixed or UUIDs).
|
|
246
|
-
| | RateLimiter | Request throttling based on keys.
|
|
247
|
-
| | Sanitization | Input validation/cleaning (HTML, paths, URLs, numbers, JSON) & log redaction (`validator`, `sanitize-html`).
|
|
248
|
-
| **Services** |
|
|
249
|
-
| | LLM
|
|
250
|
-
| **Type Safety** | Global Types | Shared TypeScript definitions for consistent interfaces (Errors, MCP types).
|
|
251
|
-
| | Zod Schemas | Used for robust validation of configuration files and tool/resource inputs.
|
|
252
|
-
| **Error Handling** | Pattern-Based Classification | Automatically categorize errors based on message patterns.
|
|
253
|
-
| | Consistent Formatting | Standardized error responses with additional context.
|
|
254
|
-
| | Safe Try/Catch Patterns | Centralized error processing helpers (`ErrorHandler.tryCatch`).
|
|
255
|
-
| | Client/Transport Error Handling | Specific handlers for MCP client and transport error handling.
|
|
256
|
-
| **Security** | Input Validation | Using `validator` and `zod` for various data type checks.
|
|
257
|
-
| | Input Sanitization | Using `sanitize-html` to prevent injection attacks.
|
|
258
|
-
| | Sensitive Data Redaction | Automatic redaction in logs.
|
|
259
|
-
| | Configuration Fallback | Safely falls back to `mcp-config.json.example` if primary client config is missing.
|
|
260
|
-
| **Scripts** | Clean Script | Removes `dist` and `logs` directories (or custom targets).
|
|
261
|
-
| | Make Executable Script | Sets executable permissions (`chmod +x`) on specified files (Unix-like only).
|
|
262
|
-
| | Tree Script | Generates a directory structure tree, respecting `.gitignore`.
|
|
263
|
-
| | Fetch OpenAPI Spec Script | Fetches an OpenAPI spec (YAML/JSON) from a URL with fallbacks, saves locally.
|
|
241
|
+
| Category | Feature | Description | Location(s) |
|
|
242
|
+
| :----------------------- | :------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------- |
|
|
243
|
+
| **Core Components** | MCP Server | Core server logic, tool/resource registration, transport handling. Includes Echo Tool & Resource examples. | `src/mcp-server/` |
|
|
244
|
+
| | MCP Client | Logic for connecting to external MCP servers (updated to **MCP 2025-03-26 spec**). Refactored for modularity. | `src/mcp-client/` (see subdirs: `core/`, `client-config/`, `transports/`) |
|
|
245
|
+
| | Configuration | Environment-aware settings with Zod validation. | `src/config/`, `src/mcp-client/client-config/configLoader.ts` |
|
|
246
|
+
| | Streamable HTTP Transport | Express-based server implementing the MCP **Streamable HTTP** transport (utilizing Server-Sent Events for server-to-client streaming), with session management, CORS, and port retries. | `src/mcp-server/transports/httpTransport.ts` |
|
|
247
|
+
| | Stdio Transport | Handles MCP communication over standard input/output. | `src/mcp-server/transports/stdioTransport.ts` |
|
|
248
|
+
| **Utilities (Core)** | Logger | Structured, context-aware logging (files with rotation & MCP notifications). | `src/utils/internal/logger.ts` |
|
|
249
|
+
| | ErrorHandler | Centralized error processing, classification, and logging. | `src/utils/internal/errorHandler.ts` |
|
|
250
|
+
| | RequestContext | Request/operation tracking and correlation. | `src/utils/internal/requestContext.ts` |
|
|
251
|
+
| **Utilities (Metrics)** | TokenCounter | Estimates token counts using `tiktoken`. | `src/utils/metrics/tokenCounter.ts` |
|
|
252
|
+
| **Utilities (Parsing)** | DateParser | Parses natural language date strings using `chrono-node`. | `src/utils/parsing/dateParser.ts` |
|
|
253
|
+
| | JsonParser | Parses potentially partial JSON, handles `<think>` blocks. | `src/utils/parsing/jsonParser.ts` |
|
|
254
|
+
| **Utilities (Security)** | IdGenerator | Generates unique IDs (prefixed or UUIDs). | `src/utils/security/idGenerator.ts` |
|
|
255
|
+
| | RateLimiter | Request throttling based on keys. | `src/utils/security/rateLimiter.ts` |
|
|
256
|
+
| | Sanitization | Input validation/cleaning (HTML, paths, URLs, numbers, JSON) & log redaction (`validator`, `sanitize-html`). | `src/utils/security/sanitization.ts` |
|
|
257
|
+
| **Services** | DuckDB Integration | Reusable module for in-process analytical data management using DuckDB. A storage layer that runs on the same level as the application. Includes connection management, query execution, and example usage. Integrated with our utils (logger, etc.) | `src/services/duck-db/`, `src/storage/duckdbExample.ts` |
|
|
258
|
+
| | OpenRouter LLM Integration | Reusable module for interacting with various LLMs via the OpenRouter API (OpenAI SDK compatible). Includes a factory for client instantiation. Integrated with our utils (logger, etc.) | `src/services/llm-providers/openRouter/`, `src/services/llm-providers/llmFactory.ts` |
|
|
259
|
+
| **Type Safety** | Global Types | Shared TypeScript definitions for consistent interfaces (Errors, MCP types). | `src/types-global/` |
|
|
260
|
+
| | Zod Schemas | Used for robust validation of configuration files and tool/resource inputs. | Throughout (`config`, `mcp-client`, tools, etc.) |
|
|
261
|
+
| **Error Handling** | Pattern-Based Classification | Automatically categorize errors based on message patterns. | `src/utils/internal/errorHandler.ts` |
|
|
262
|
+
| | Consistent Formatting | Standardized error responses with additional context. | `src/utils/internal/errorHandler.ts` |
|
|
263
|
+
| | Safe Try/Catch Patterns | Centralized error processing helpers (`ErrorHandler.tryCatch`). | `src/utils/internal/errorHandler.ts` |
|
|
264
|
+
| | Client/Transport Error Handling | Specific handlers for MCP client and transport error handling. | `src/mcp-client/core/`, `src/mcp-client/transports/` |
|
|
265
|
+
| **Security** | Input Validation | Using `validator` and `zod` for various data type checks. | `src/utils/security/sanitization.ts`, etc. |
|
|
266
|
+
| | Input Sanitization | Using `sanitize-html` to prevent injection attacks. | `src/utils/security/sanitization.ts` |
|
|
267
|
+
| | Sensitive Data Redaction | Automatic redaction in logs. | `src/utils/security/sanitization.ts` |
|
|
268
|
+
| | Configuration Fallback | Safely falls back to `mcp-config.json.example` if primary client config is missing. | `src/mcp-client/client-config/configLoader.ts` |
|
|
269
|
+
| **Scripts** | Clean Script | Removes `dist` and `logs` directories (or custom targets). | `scripts/clean.ts` |
|
|
270
|
+
| | Make Executable Script | Sets executable permissions (`chmod +x`) on specified files (Unix-like only). | `scripts/make-executable.ts` |
|
|
271
|
+
| | Tree Script | Generates a directory structure tree, respecting `.gitignore`. | `scripts/tree.ts` |
|
|
272
|
+
| | Fetch OpenAPI Spec Script | Fetches an OpenAPI spec (YAML/JSON) from a URL with fallbacks, saves locally. | `scripts/fetch-openapi-spec.ts` |
|
|
264
273
|
|
|
265
274
|
---
|
|
266
275
|
|
|
@@ -18,6 +18,7 @@ import { config, environment } from "../config/index.js";
|
|
|
18
18
|
import { ErrorHandler, logger, requestContextService } from "../utils/index.js";
|
|
19
19
|
import { registerEchoResource } from "./resources/echoResource/index.js";
|
|
20
20
|
import { registerEchoTool } from "./tools/echoTool/index.js";
|
|
21
|
+
import { registerCatFactFetcherTool } from "./tools/catFactFetcher/index.js";
|
|
21
22
|
import { startHttpTransport } from "./transports/httpTransport.js";
|
|
22
23
|
import { connectStdioTransport } from "./transports/stdioTransport.js";
|
|
23
24
|
/**
|
|
@@ -70,6 +71,7 @@ async function createMcpServerInstance() {
|
|
|
70
71
|
logger.debug("Registering resources and tools...", context);
|
|
71
72
|
await registerEchoResource(server);
|
|
72
73
|
await registerEchoTool(server);
|
|
74
|
+
await registerCatFactFetcherTool(server);
|
|
73
75
|
logger.info("Resources and tools registered successfully", context);
|
|
74
76
|
}
|
|
75
77
|
catch (err) {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Defines the core logic, schemas, and types for the `get_random_cat_fact` tool.
|
|
3
|
+
* This tool fetches a random cat fact from the public Cat Fact Ninja API.
|
|
4
|
+
* It demonstrates an asynchronous API call within an MCP tool.
|
|
5
|
+
* @module src/mcp-server/tools/catFactFetcher/catFactFetcherLogic
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { type RequestContext } from "../../../utils/index.js";
|
|
9
|
+
/**
|
|
10
|
+
* Zod schema for validating input arguments for the `get_random_cat_fact` tool.
|
|
11
|
+
*/
|
|
12
|
+
export declare const CatFactFetcherInputSchema: z.ZodObject<{
|
|
13
|
+
maxLength: z.ZodOptional<z.ZodNumber>;
|
|
14
|
+
}, "strip", z.ZodTypeAny, {
|
|
15
|
+
maxLength?: number | undefined;
|
|
16
|
+
}, {
|
|
17
|
+
maxLength?: number | undefined;
|
|
18
|
+
}>;
|
|
19
|
+
/**
|
|
20
|
+
* TypeScript type inferred from `CatFactFetcherInputSchema`.
|
|
21
|
+
*/
|
|
22
|
+
export type CatFactFetcherInput = z.infer<typeof CatFactFetcherInputSchema>;
|
|
23
|
+
/**
|
|
24
|
+
* Defines the structure of the JSON payload returned by the `get_random_cat_fact` tool handler.
|
|
25
|
+
*/
|
|
26
|
+
export interface CatFactFetcherResponse {
|
|
27
|
+
fact: string;
|
|
28
|
+
length: number;
|
|
29
|
+
requestedMaxLength?: number;
|
|
30
|
+
timestamp: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Processes the core logic for the `get_random_cat_fact` tool.
|
|
34
|
+
* It calls the Cat Fact Ninja API and returns the fetched fact.
|
|
35
|
+
* @param params - The validated input parameters for the tool.
|
|
36
|
+
* @param context - The request context for logging and tracing.
|
|
37
|
+
* @returns A promise that resolves to an object containing the cat fact data.
|
|
38
|
+
*/
|
|
39
|
+
export declare const processCatFactFetcher: (params: CatFactFetcherInput, context: RequestContext) => Promise<CatFactFetcherResponse>;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Defines the core logic, schemas, and types for the `get_random_cat_fact` tool.
|
|
3
|
+
* This tool fetches a random cat fact from the public Cat Fact Ninja API.
|
|
4
|
+
* It demonstrates an asynchronous API call within an MCP tool.
|
|
5
|
+
* @module src/mcp-server/tools/catFactFetcher/catFactFetcherLogic
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { logger, fetchWithTimeout, // Added import
|
|
9
|
+
} from "../../../utils/index.js";
|
|
10
|
+
import { McpError, BaseErrorCode } from "../../../types-global/errors.js";
|
|
11
|
+
/**
|
|
12
|
+
* Asynchronously fetches a random cat fact from the Cat Fact Ninja API.
|
|
13
|
+
* @param maxLength - Optional maximum length for the cat fact.
|
|
14
|
+
* @param context - The request context for logging.
|
|
15
|
+
* @returns A promise that resolves to the CatFactApiResponse.
|
|
16
|
+
* @throws {McpError} If the API request fails or returns an error.
|
|
17
|
+
*/
|
|
18
|
+
async function fetchRandomCatFactFromApi(maxLength, context) {
|
|
19
|
+
let apiUrl = "https://catfact.ninja/fact";
|
|
20
|
+
if (maxLength !== undefined) {
|
|
21
|
+
apiUrl += `?max_length=${maxLength}`;
|
|
22
|
+
}
|
|
23
|
+
logger.info(`Fetching random cat fact from: ${apiUrl}`, context);
|
|
24
|
+
const CAT_FACT_API_TIMEOUT_MS = 5000;
|
|
25
|
+
try {
|
|
26
|
+
// Use the fetchWithTimeout utility
|
|
27
|
+
const response = await fetchWithTimeout(apiUrl, CAT_FACT_API_TIMEOUT_MS, context);
|
|
28
|
+
if (!response.ok) {
|
|
29
|
+
const errorText = await response.text();
|
|
30
|
+
logger.error(`Cat Fact API request to ${apiUrl} failed with status ${response.status}: ${errorText}`, context);
|
|
31
|
+
throw new McpError(BaseErrorCode.SERVICE_UNAVAILABLE, `Cat Fact API request to ${apiUrl} failed: ${response.status} ${response.statusText}`, {
|
|
32
|
+
...context,
|
|
33
|
+
httpStatusCode: response.status,
|
|
34
|
+
responseBodyBrief: errorText.substring(0, 200), // Log a snippet of the response
|
|
35
|
+
errorSource: "CatFactApiNonOkResponse",
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
const data = await response.json();
|
|
39
|
+
logger.info(`Successfully fetched cat fact (length: ${data.length}): "${data.fact.substring(0, 50)}..."`, context);
|
|
40
|
+
return data;
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
// The fetchWithTimeout utility handles AbortError and throws McpError with BaseErrorCode.TIMEOUT.
|
|
44
|
+
// It also wraps other fetch-related network errors in McpError.
|
|
45
|
+
// So, we primarily need to catch McpErrors here or wrap any truly unexpected errors.
|
|
46
|
+
if (error instanceof McpError) {
|
|
47
|
+
// Log McpErrors specifically if needed, or just re-throw
|
|
48
|
+
// If it's a TIMEOUT error from fetchWithTimeout, it's already logged by the utility.
|
|
49
|
+
// If it's a SERVICE_UNAVAILABLE from fetchWithTimeout (generic network error), also logged.
|
|
50
|
+
// If it's from response.ok check above, it's also an McpError.
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
// Fallback for any other unexpected errors not already wrapped by McpError
|
|
54
|
+
logger.error(`Unexpected error during Cat Fact API processing for ${apiUrl}: ${error instanceof Error ? error.message : String(error)}`, context);
|
|
55
|
+
throw new McpError(BaseErrorCode.INTERNAL_ERROR, // Or UNKNOWN_ERROR if more appropriate
|
|
56
|
+
`Unexpected error processing response from Cat Fact API (${apiUrl}): ${error instanceof Error ? error.message : String(error)}`, {
|
|
57
|
+
...context,
|
|
58
|
+
originalErrorName: error instanceof Error ? error.name : "UnknownError",
|
|
59
|
+
errorSource: "CatFactApiUnexpectedCatch",
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Zod schema for validating input arguments for the `get_random_cat_fact` tool.
|
|
65
|
+
*/
|
|
66
|
+
export const CatFactFetcherInputSchema = z
|
|
67
|
+
.object({
|
|
68
|
+
maxLength: z
|
|
69
|
+
.number()
|
|
70
|
+
.int("Max length must be an integer.")
|
|
71
|
+
.min(1, "Max length must be at least 1.")
|
|
72
|
+
.optional()
|
|
73
|
+
.describe("Optional: The maximum character length of the cat fact to retrieve."),
|
|
74
|
+
})
|
|
75
|
+
.describe("Input schema for the get_random_cat_fact tool. Allows specifying a maximum length for the fact.");
|
|
76
|
+
/**
|
|
77
|
+
* Processes the core logic for the `get_random_cat_fact` tool.
|
|
78
|
+
* It calls the Cat Fact Ninja API and returns the fetched fact.
|
|
79
|
+
* @param params - The validated input parameters for the tool.
|
|
80
|
+
* @param context - The request context for logging and tracing.
|
|
81
|
+
* @returns A promise that resolves to an object containing the cat fact data.
|
|
82
|
+
*/
|
|
83
|
+
export const processCatFactFetcher = async (params, context) => {
|
|
84
|
+
logger.debug("Processing get_random_cat_fact logic with input parameters.", {
|
|
85
|
+
...context,
|
|
86
|
+
toolInput: { maxLength: params.maxLength },
|
|
87
|
+
});
|
|
88
|
+
const apiResponse = await fetchRandomCatFactFromApi(params.maxLength, context);
|
|
89
|
+
const toolResponse = {
|
|
90
|
+
fact: apiResponse.fact,
|
|
91
|
+
length: apiResponse.length,
|
|
92
|
+
requestedMaxLength: params.maxLength,
|
|
93
|
+
timestamp: new Date().toISOString(),
|
|
94
|
+
};
|
|
95
|
+
logger.debug("Random cat fact fetched and processed successfully.", {
|
|
96
|
+
...context,
|
|
97
|
+
toolResponseSummary: {
|
|
98
|
+
factLength: toolResponse.length,
|
|
99
|
+
requestedMaxLength: toolResponse.requestedMaxLength,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
return toolResponse;
|
|
103
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Handles the registration of the `get_random_cat_fact` tool
|
|
3
|
+
* with an MCP server instance. This tool fetches a random cat fact from the
|
|
4
|
+
* Cat Fact Ninja API.
|
|
5
|
+
* @module src/mcp-server/tools/catFactFetcher/catFactFetcherRegistration
|
|
6
|
+
*/
|
|
7
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8
|
+
/**
|
|
9
|
+
* Registers the 'get_random_cat_fact' tool and its handler with the MCP server.
|
|
10
|
+
*
|
|
11
|
+
* @param server - The MCP server instance to register the tool with.
|
|
12
|
+
* @returns A promise that resolves when tool registration is complete.
|
|
13
|
+
* @throws {McpError} If registration fails critically.
|
|
14
|
+
*/
|
|
15
|
+
export declare const registerCatFactFetcherTool: (server: McpServer) => Promise<void>;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Handles the registration of the `get_random_cat_fact` tool
|
|
3
|
+
* with an MCP server instance. This tool fetches a random cat fact from the
|
|
4
|
+
* Cat Fact Ninja API.
|
|
5
|
+
* @module src/mcp-server/tools/catFactFetcher/catFactFetcherRegistration
|
|
6
|
+
*/
|
|
7
|
+
import { BaseErrorCode, McpError } from "../../../types-global/errors.js";
|
|
8
|
+
import { ErrorHandler, logger, requestContextService, } from "../../../utils/index.js";
|
|
9
|
+
import { CatFactFetcherInputSchema, processCatFactFetcher, } from "./catFactFetcherLogic.js";
|
|
10
|
+
/**
|
|
11
|
+
* Registers the 'get_random_cat_fact' tool and its handler with the MCP server.
|
|
12
|
+
*
|
|
13
|
+
* @param server - The MCP server instance to register the tool with.
|
|
14
|
+
* @returns A promise that resolves when tool registration is complete.
|
|
15
|
+
* @throws {McpError} If registration fails critically.
|
|
16
|
+
*/
|
|
17
|
+
export const registerCatFactFetcherTool = async (server) => {
|
|
18
|
+
const toolName = "get_random_cat_fact";
|
|
19
|
+
const toolDescription = "Fetches a random cat fact from the Cat Fact Ninja API. Optionally, a maximum length for the fact can be specified.";
|
|
20
|
+
const registrationContext = requestContextService.createRequestContext({
|
|
21
|
+
operation: "RegisterTool",
|
|
22
|
+
toolName: toolName,
|
|
23
|
+
moduleName: "CatFactFetcherRegistration",
|
|
24
|
+
});
|
|
25
|
+
logger.info(`Attempting to register tool: '${toolName}'`, registrationContext);
|
|
26
|
+
await ErrorHandler.tryCatch(async () => {
|
|
27
|
+
server.tool(toolName, toolDescription, CatFactFetcherInputSchema.shape, // SDK uses this for schema generation & validation
|
|
28
|
+
async (params) => {
|
|
29
|
+
const handlerContext = requestContextService.createRequestContext({
|
|
30
|
+
parentContext: registrationContext,
|
|
31
|
+
operation: "HandleToolRequest",
|
|
32
|
+
toolName: toolName,
|
|
33
|
+
inputSummary: { maxLength: params.maxLength },
|
|
34
|
+
});
|
|
35
|
+
logger.debug(`Handling '${toolName}' tool request.`, handlerContext);
|
|
36
|
+
return await ErrorHandler.tryCatch(async () => {
|
|
37
|
+
const responsePayload = await processCatFactFetcher(params, handlerContext);
|
|
38
|
+
logger.debug(`'${toolName}' tool processed successfully. Preparing result.`, handlerContext);
|
|
39
|
+
return {
|
|
40
|
+
content: [
|
|
41
|
+
{
|
|
42
|
+
type: "text",
|
|
43
|
+
text: JSON.stringify(responsePayload, null, 2),
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
isError: false,
|
|
47
|
+
};
|
|
48
|
+
}, {
|
|
49
|
+
operation: `ExecutingCoreLogicFor_${toolName}`,
|
|
50
|
+
context: handlerContext,
|
|
51
|
+
input: params, // Input is sanitized by ErrorHandler for logging
|
|
52
|
+
errorMapper: (error) => {
|
|
53
|
+
// Ensure a specific McpError is created if not already one
|
|
54
|
+
if (error instanceof McpError)
|
|
55
|
+
return error;
|
|
56
|
+
const errorMessage = `Error processing '${toolName}' tool: ${error instanceof Error ? error.message : "An unknown error occurred"}`;
|
|
57
|
+
return new McpError(BaseErrorCode.INTERNAL_ERROR, errorMessage, {
|
|
58
|
+
...handlerContext,
|
|
59
|
+
originalErrorName: error instanceof Error ? error.name : typeof error,
|
|
60
|
+
});
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
logger.info(`Tool '${toolName}' registered successfully with the MCP server.`, registrationContext);
|
|
65
|
+
}, {
|
|
66
|
+
operation: `RegisteringTool_${toolName}`,
|
|
67
|
+
context: registrationContext,
|
|
68
|
+
errorCode: BaseErrorCode.INITIALIZATION_FAILED,
|
|
69
|
+
errorMapper: (error) => {
|
|
70
|
+
if (error instanceof McpError)
|
|
71
|
+
return error;
|
|
72
|
+
const errorMessage = `Failed to register tool '${toolName}': ${error instanceof Error ? error.message : "An unknown error occurred during registration."}`;
|
|
73
|
+
return new McpError(BaseErrorCode.INITIALIZATION_FAILED, errorMessage, {
|
|
74
|
+
...registrationContext,
|
|
75
|
+
originalErrorName: error instanceof Error ? error.name : typeof error,
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
critical: true, // Registration failure is critical
|
|
79
|
+
});
|
|
80
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Barrel file for the `catFactFetcher` tool.
|
|
3
|
+
* This file serves as the public interface for the cat fact fetcher tool module,
|
|
4
|
+
* primarily exporting the `registerCatFactFetcherTool` function.
|
|
5
|
+
* @module src/mcp-server/tools/catFactFetcher/index
|
|
6
|
+
*/
|
|
7
|
+
export { registerCatFactFetcherTool } from "./catFactFetcherRegistration.js";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Barrel file for the `catFactFetcher` tool.
|
|
3
|
+
* This file serves as the public interface for the cat fact fetcher tool module,
|
|
4
|
+
* primarily exporting the `registerCatFactFetcherTool` function.
|
|
5
|
+
* @module src/mcp-server/tools/catFactFetcher/index
|
|
6
|
+
*/
|
|
7
|
+
export { registerCatFactFetcherTool } from "./catFactFetcherRegistration.js";
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Manages DuckDB instance and connection lifecycle.
|
|
3
|
+
* @module services/duck-db/duckDBConnectionManager
|
|
4
|
+
*/
|
|
5
|
+
import * as duckdb from "@duckdb/node-api";
|
|
6
|
+
import { RequestContext } from "../../utils/index.js";
|
|
7
|
+
import { DuckDBServiceConfig } from "./types.js";
|
|
8
|
+
export declare class DuckDBConnectionManager {
|
|
9
|
+
private dbInstance;
|
|
10
|
+
private dbConnection;
|
|
11
|
+
private isInitialized;
|
|
12
|
+
private currentConfig;
|
|
13
|
+
/**
|
|
14
|
+
* Initializes the DuckDB instance and connection.
|
|
15
|
+
* @param {DuckDBServiceConfig} [config] - Configuration for the service.
|
|
16
|
+
* @returns {Promise<void>}
|
|
17
|
+
*/
|
|
18
|
+
initialize(config?: DuckDBServiceConfig): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Installs and loads a DuckDB extension.
|
|
21
|
+
* @param {string} extensionName - The name of the extension.
|
|
22
|
+
* @param {RequestContext} parentContext - The parent request context.
|
|
23
|
+
* @returns {Promise<void>}
|
|
24
|
+
*/
|
|
25
|
+
loadExtension(extensionName: string, parentContext: RequestContext): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Closes the DuckDB connection and instance.
|
|
28
|
+
* @returns {Promise<void>}
|
|
29
|
+
*/
|
|
30
|
+
close(): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Ensures that the service is initialized.
|
|
33
|
+
* @param {RequestContext} context - The request context for error reporting.
|
|
34
|
+
* @throws {McpError} If the service is not initialized.
|
|
35
|
+
*/
|
|
36
|
+
ensureInitialized(context: RequestContext): void;
|
|
37
|
+
/**
|
|
38
|
+
* Gets the underlying DuckDB connection object.
|
|
39
|
+
* @returns {duckdb.DuckDBConnection}
|
|
40
|
+
* @throws {McpError} If the service is not initialized.
|
|
41
|
+
*/
|
|
42
|
+
getConnection(): duckdb.DuckDBConnection;
|
|
43
|
+
/**
|
|
44
|
+
* Gets the underlying DuckDB instance object.
|
|
45
|
+
* @returns {duckdb.DuckDBInstance}
|
|
46
|
+
* @throws {McpError} If the service is not initialized.
|
|
47
|
+
*/
|
|
48
|
+
getInstance(): duckdb.DuckDBInstance;
|
|
49
|
+
/**
|
|
50
|
+
* Checks if the service is currently initialized.
|
|
51
|
+
* @returns {boolean} True if initialized, false otherwise.
|
|
52
|
+
*/
|
|
53
|
+
get isServiceInitialized(): boolean;
|
|
54
|
+
}
|