@makingchatbots/genesys-cloud-mcp-server
Version:
A Model Context Protocol (MCP) server exposing Genesys Cloud tools for LLMs, including sentiment analysis, conversation search, topic detection and more.
111 lines (110 loc) • 4.75 kB
JavaScript
import { z } from "zod";
import { createTool } from "../utils/createTool.js";
import { errorResult } from "../utils/errorResult.js";
import { isUnauthorisedError } from "../utils/genesys/isUnauthorisedError.js";
import { waitFor } from "../utils/waitFor.js";
const MAX_ATTEMPTS = 10;
const TOOL_CACHE_KEY = "oauth-client-usage";
const paramsSchema = z.object({
oauthClientId: z
.string()
.uuid()
.describe("The UUID of the OAuth Client to retrieve the usage for (e.g., 00000000-0000-0000-0000-000000000000)"),
startDate: z
.string()
.describe("The start date/time in ISO-8601 format (e.g., '2024-01-01T00:00:00Z')"),
endDate: z
.string()
.describe("The end date/time in ISO-8601 format (e.g., '2024-01-07T23:59:59Z')"),
});
export const oauthClientUsage = ({ oauthApi, cache }) => createTool({
schema: {
name: "oauth_client_usage",
annotations: { title: "OAuth Client Usage" },
description: "Retrieves the usage of an OAuth Client for a given period. It returns the total number of requests and a breakdown of Platform API endpoints used by the client.",
paramsSchema,
},
call: async ({ oauthClientId, startDate, endDate }) => {
const from = new Date(startDate);
const to = new Date(endDate);
if (Number.isNaN(from.getTime()))
return errorResult("startDate is not a valid ISO-8601 date");
if (Number.isNaN(to.getTime()))
return errorResult("endDate is not a valid ISO-8601 date");
if (from >= to)
return errorResult("Start date must be before end date");
const now = new Date();
if (to > now) {
to.setTime(now.getTime());
}
const cacheName = `${TOOL_CACHE_KEY}.${oauthClientId}-${from.getTime()}-${to.getTime()}`;
const cachedResult = cache?.get(cacheName);
if (cachedResult) {
return {
content: [
{
type: "text",
text: JSON.stringify(cachedResult),
},
],
};
}
let result;
try {
result = await oauthApi.postOauthClientUsageQuery(oauthClientId, {
interval: `${from.toISOString()}/${to.toISOString()}`,
metrics: ["Requests"],
groupBy: ["TemplateUri", "HttpMethod"],
});
}
catch (error) {
const errorMessage = isUnauthorisedError(error)
? "Failed to retrieve usage of OAuth client: Unauthorised access. Please check API credentials or permissions"
: `Failed to retrieve usage of OAuth client: ${error instanceof Error ? error.message : JSON.stringify(error)}`;
return errorResult(errorMessage);
}
if (!result.executionId) {
return errorResult("Failed to get an Execution ID from Genesys Cloud's Platform API");
}
let apiUsageQueryResult;
let state;
let attempts = 0;
while (attempts < MAX_ATTEMPTS) {
const executionResult = await oauthApi.getOauthClientUsageQueryResult(result.executionId, oauthClientId);
state = executionResult?.queryStatus?.toUpperCase() ?? "UNKNOWN";
if (state === "COMPLETE") {
apiUsageQueryResult = executionResult;
break;
}
switch (executionResult.queryStatus) {
case "FAILED":
return errorResult(`Failed to get usage data for OAuth Client ${oauthClientId}.`);
case "UNKNOWN":
return errorResult("Execution returned an unknown or undefined state.");
}
await waitFor(3000);
attempts++;
}
if (state !== "COMPLETE") {
return errorResult(`Timed out waiting for OAuth Client usage to complete for client ${oauthClientId}.`);
}
const toolResult = {
startDate,
endDate,
totalRequests: (apiUsageQueryResult?.results ?? []).reduce((acc, curr) => acc + (curr.requests ?? 0), 0),
requestsPerEndpoint: (apiUsageQueryResult?.results ?? []).map((result) => ({
endpoint: [result.httpMethod, result.templateUri].join(" ") || undefined,
requests: result.requests,
})),
};
cache?.set(`${TOOL_CACHE_KEY}.${oauthClientId}-${from.getTime()}-${to.getTime()}`, toolResult);
return {
content: [
{
type: "text",
text: JSON.stringify(toolResult),
},
],
};
},
});