pocketsmith-mcp
Version:
MCP server for managing budgets via PocketSmith API
79 lines (78 loc) • 3.13 kB
JavaScript
/**
* @fileoverview Defines the core logic, schemas, and types for the `get_random_cat_fact` tool.
* This tool fetches a random cat fact from the public Cat Fact Ninja API.
* @module src/mcp-server/tools/catFactFetcher/logic
*/
import { z } from "zod";
import { BaseErrorCode, McpError } from "../../../types-global/errors.js";
import { fetchWithTimeout, logger, } from "../../../utils/index.js";
/**
* Zod schema for validating input arguments for the `get_random_cat_fact` tool.
*/
export const CatFactFetcherInputSchema = z
.object({
maxLength: z
.number()
.int("Max length must be an integer.")
.min(1, "Max length must be at least 1.")
.optional()
.describe("Optional: The maximum character length of the cat fact to retrieve."),
})
.describe("Input schema for the get_random_cat_fact tool. Allows specifying a maximum length for the fact.");
/**
* Zod schema for the successful response of the `get_random_cat_fact` tool.
*/
export const CatFactFetcherResponseSchema = z.object({
fact: z.string().describe("The retrieved cat fact."),
length: z.number().int().describe("The character length of the cat fact."),
requestedMaxLength: z
.number()
.int()
.optional()
.describe("The maximum length that was requested for the fact."),
timestamp: z
.string()
.datetime()
.describe("ISO 8601 timestamp of when the response was generated."),
});
/**
* Processes the core logic for the `get_random_cat_fact` tool.
* It calls the Cat Fact Ninja API and returns the fetched fact.
* @param params - The validated input parameters for the tool.
* @param context - The request context for logging and tracing.
* @returns A promise that resolves to an object containing the cat fact data.
* @throws {McpError} If the API request fails or returns an error.
*/
export async function catFactFetcherLogic(params, context) {
logger.debug("Processing get_random_cat_fact logic.", {
...context,
toolInput: params,
});
let apiUrl = "https://catfact.ninja/fact";
if (params.maxLength !== undefined) {
apiUrl += `?max_length=${params.maxLength}`;
}
logger.info(`Fetching random cat fact from: ${apiUrl}`, context);
const CAT_FACT_API_TIMEOUT_MS = 5000;
const response = await fetchWithTimeout(apiUrl, CAT_FACT_API_TIMEOUT_MS, context);
if (!response.ok) {
const errorText = await response.text();
throw new McpError(BaseErrorCode.SERVICE_UNAVAILABLE, `Cat Fact API request failed: ${response.status} ${response.statusText}`, {
...context,
httpStatusCode: response.status,
responseBody: errorText,
});
}
const data = await response.json();
const toolResponse = {
fact: data.fact,
length: data.length,
requestedMaxLength: params.maxLength,
timestamp: new Date().toISOString(),
};
logger.notice("Random cat fact fetched and processed successfully.", {
...context,
factLength: toolResponse.length,
});
return toolResponse;
}