Skip to content

Commit f077710

Browse files
authored
Add title annotation to tools (#24)
1 parent 482ff83 commit f077710

25 files changed

+144
-51
lines changed

Dockerfile

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
FROM node:22.12-alpine AS builder
2+
3+
COPY ./ /app
4+
5+
WORKDIR /app
6+
7+
RUN --mount=type=cache,target=/root/.npm npm install
8+
RUN --mount=type=cache,target=/root/.npm npm run build
9+
10+
FROM node:22.12-alpine AS release
11+
12+
WORKDIR /app
13+
14+
COPY --from=builder /app/dist /app/dist
15+
COPY --from=builder /app/package.json /app/package.json
16+
COPY --from=builder /app/package-lock.json /app/package-lock.json
17+
18+
ENV NODE_ENV=production
19+
20+
RUN npm ci --ignore-scripts --omit-dev
21+
22+
ENTRYPOINT ["node", "dist/index.js"]

README.md

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@
55

66
A Model Context Protocol (MCP) server for Genesys Cloud's Platform API.
77

8-
## Tools Overview
9-
10-
An overview of the tools that this MCP server makes available. Read more about each specific tool
11-
in the [tools doc](/docs/tools.md).
8+
## Features
129

1310
| Tool | Description |
1411
| ----------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
@@ -21,6 +18,29 @@ in the [tools doc](/docs/tools.md).
2118
| [Search Voice Conversation](/docs/tools.md#search-voice-conversations) | Searches voice conversations by optional criteria |
2219
| [Conversation Transcript](/docs/tools.md#conversation-transcript) | Retrieves conversation transcript |
2320

21+
## Usage with Claude Desktop
22+
23+
Add this to your `claude_desktop_config.json`:
24+
25+
### NPX
26+
27+
```json
28+
{
29+
"mcpServers": {
30+
"genesys-cloud": {
31+
"type": "stdio",
32+
"command": "npx",
33+
"args": ["-y", "@makingchatbots/genesys-cloud-mcp-server"],
34+
"env": {
35+
"GENESYSCLOUD_REGION": "<PUT REGION HERE>",
36+
"GENESYSCLOUD_OAUTHCLIENT_ID": "<PUT OAUTHCLIENT ID HERE>",
37+
"GENESYSCLOUD_OAUTHCLIENT_SECRET": "<PUT OAUTHCLIENT SECRET HERE>"
38+
}
39+
}
40+
}
41+
}
42+
```
43+
2444
## Authentication
2545

2646
This currently only supports a stdio server. To configure authentication you'll need to:
@@ -32,7 +52,9 @@ This currently only supports a stdio server. To configure authentication you'll
3252
- `GENESYSCLOUD_OAUTHCLIENT_ID`
3353
- `GENESYSCLOUD_OAUTHCLIENT_SECRET`
3454

35-
## Getting Started
55+
## Development
56+
57+
### Getting Started
3658

3759
```bash
3860
nvm use

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@makingchatbots/genesys-cloud-mcp-server",
3-
"version": "0.0.12",
3+
"version": "0.0.13",
44
"description": "A Model Context Protocol (MCP) server exposing Genesys Cloud tools for LLMs, including sentiment analysis, conversation search, topic detection and more.",
55
"bin": "./dist/cli.js",
66
"type": "module",

src/auth/OAuthClientCredentialsWrapper.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
import { z } from "zod";
12
import { type ApiClientClass } from "purecloud-platform-client-v2";
23
import { type ToolCall } from "../tools/utils/createTool.js";
3-
import { ConfigRetriever } from "../createConfigRetriever.js";
4+
import { type ConfigRetriever } from "../createConfigRetriever.js";
45
import { errorResult } from "../tools/utils/errorResult.js";
5-
import { z } from "zod";
66

77
let isAuthenticated = false;
88

src/index.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,15 @@ import { conversationTopics } from "./tools/conversationTopics/conversationTopic
1111
import { searchVoiceConversations } from "./tools/searchVoiceConversations.js";
1212
import { conversationTranscription } from "./tools/conversationTranscription/conversationTranscription.js";
1313
import { OAuthClientCredentialsWrapper } from "./auth/OAuthClientCredentialsWrapper.js";
14-
import packageInfo from "../package.json" with { type: "json" };
1514

16-
const configRetriever = createConfigRetriever(process.env);
1715
const withAuth = OAuthClientCredentialsWrapper(
18-
configRetriever,
16+
createConfigRetriever(process.env),
1917
platformClient.ApiClient.instance,
2018
);
2119

2220
const server: McpServer = new McpServer({
2321
name: "Genesys Cloud",
24-
version: packageInfo.version,
22+
version: "0.0.13", // Same version as version in package.json
2523
});
2624

2725
const routingApi = new platformClient.RoutingApi();
@@ -34,9 +32,7 @@ server.tool(
3432
searchQueuesTool.schema.name,
3533
searchQueuesTool.schema.description,
3634
searchQueuesTool.schema.paramsSchema.shape,
37-
{
38-
title: "",
39-
},
35+
searchQueuesTool.schema.annotations,
4036
withAuth(searchQueuesTool.call),
4137
);
4238

@@ -47,6 +43,7 @@ server.tool(
4743
sampleConversationsByQueueTool.schema.name,
4844
sampleConversationsByQueueTool.schema.description,
4945
sampleConversationsByQueueTool.schema.paramsSchema.shape,
46+
sampleConversationsByQueueTool.schema.annotations,
5047
withAuth(sampleConversationsByQueueTool.call),
5148
);
5249

@@ -55,6 +52,7 @@ server.tool(
5552
queryQueueVolumesTool.schema.name,
5653
queryQueueVolumesTool.schema.description,
5754
queryQueueVolumesTool.schema.paramsSchema.shape,
55+
queryQueueVolumesTool.schema.annotations,
5856
withAuth(queryQueueVolumesTool.call),
5957
);
6058

@@ -63,6 +61,7 @@ server.tool(
6361
voiceCallQualityTool.schema.name,
6462
voiceCallQualityTool.schema.description,
6563
voiceCallQualityTool.schema.paramsSchema.shape,
64+
voiceCallQualityTool.schema.annotations,
6665
withAuth(voiceCallQualityTool.call),
6766
);
6867

@@ -73,6 +72,7 @@ server.tool(
7372
conversationSentimentTool.schema.name,
7473
conversationSentimentTool.schema.description,
7574
conversationSentimentTool.schema.paramsSchema.shape,
75+
conversationSentimentTool.schema.annotations,
7676
withAuth(conversationSentimentTool.call),
7777
);
7878

@@ -84,6 +84,7 @@ server.tool(
8484
conversationTopicsTool.schema.name,
8585
conversationTopicsTool.schema.description,
8686
conversationTopicsTool.schema.paramsSchema.shape,
87+
conversationTopicsTool.schema.annotations,
8788
withAuth(conversationTopicsTool.call),
8889
);
8990

@@ -94,6 +95,7 @@ server.tool(
9495
searchVoiceConversationsTool.schema.name,
9596
searchVoiceConversationsTool.schema.description,
9697
searchVoiceConversationsTool.schema.paramsSchema.shape,
98+
searchVoiceConversationsTool.schema.annotations,
9799
withAuth(searchVoiceConversationsTool.call),
98100
);
99101

@@ -106,6 +108,7 @@ server.tool(
106108
conversationTranscriptTool.schema.name,
107109
conversationTranscriptTool.schema.description,
108110
conversationTranscriptTool.schema.paramsSchema.shape,
111+
conversationTranscriptTool.schema.annotations,
109112
withAuth(conversationTranscriptTool.call),
110113
);
111114

src/tools/conversationSentiment/conversationSentiment.test.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { beforeEach, describe, expect, test, vi } from "vitest";
2-
import { MockedObjectDeep } from "@vitest/spy";
2+
import { type MockedObjectDeep } from "@vitest/spy";
33
import { randomUUID } from "node:crypto";
44
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
55
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
66
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
7-
import { McpError } from "@modelcontextprotocol/sdk/types.js";
7+
import { type McpError } from "@modelcontextprotocol/sdk/types.js";
88
import {
99
conversationSentiment,
10-
ToolDependencies,
10+
type ToolDependencies,
1111
} from "./conversationSentiment.js";
1212

1313
describe("Conversation Sentiment Tool", () => {
@@ -30,6 +30,7 @@ describe("Conversation Sentiment Tool", () => {
3030
toolDefinition.schema.name,
3131
toolDefinition.schema.description,
3232
toolDefinition.schema.paramsSchema.shape,
33+
toolDefinition.schema.annotations,
3334
toolDefinition.call,
3435
);
3536

@@ -47,6 +48,7 @@ describe("Conversation Sentiment Tool", () => {
4748
expect(tools.tools[0]).toStrictEqual({
4849
name: "conversation_sentiment",
4950
title: undefined,
51+
annotations: { title: "Conversation Sentiment" },
5052
description:
5153
"Retrieves sentiment analysis scores for one or more conversations. Sentiment is evaluated based on customer phrases, categorized as positive, neutral, or negative. The result includes both a numeric sentiment score (-100 to 100) and an interpreted sentiment label.",
5254
inputSchema: {
@@ -70,7 +72,6 @@ describe("Conversation Sentiment Tool", () => {
7072
additionalProperties: false,
7173
$schema: "http://json-schema.org/draft-07/schema#",
7274
},
73-
annotations: undefined,
7475
});
7576
});
7677

src/tools/conversationSentiment/conversationSentiment.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export const conversationSentiment: ToolFactory<
4040
name: "conversation_sentiment",
4141
description:
4242
"Retrieves sentiment analysis scores for one or more conversations. Sentiment is evaluated based on customer phrases, categorized as positive, neutral, or negative. The result includes both a numeric sentiment score (-100 to 100) and an interpreted sentiment label.",
43+
annotations: { title: "Conversation Sentiment" },
4344
paramsSchema,
4445
},
4546
call: async ({ conversationIds }) => {

src/tools/conversationTopics/conversationTopics.test.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import { beforeEach, describe, expect, test, vi } from "vitest";
2-
import { MockedObjectDeep } from "@vitest/spy";
2+
import { type MockedObjectDeep } from "@vitest/spy";
33
import { randomUUID } from "node:crypto";
44
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
55
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
66
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
7-
import { McpError } from "@modelcontextprotocol/sdk/types.js";
8-
import { conversationTopics, ToolDependencies } from "./conversationTopics.js";
7+
import { type McpError } from "@modelcontextprotocol/sdk/types.js";
8+
import {
9+
conversationTopics,
10+
type ToolDependencies,
11+
} from "./conversationTopics.js";
912

1013
describe("Conversation Topics Tool", () => {
1114
let toolDeps: MockedObjectDeep<ToolDependencies>;
@@ -31,6 +34,7 @@ describe("Conversation Topics Tool", () => {
3134
toolDefinition.schema.name,
3235
toolDefinition.schema.description,
3336
toolDefinition.schema.paramsSchema.shape,
37+
toolDefinition.schema.annotations,
3438
toolDefinition.call,
3539
);
3640

@@ -48,6 +52,7 @@ describe("Conversation Topics Tool", () => {
4852
expect(tools.tools[0]).toStrictEqual({
4953
name: "conversation_topics",
5054
title: undefined,
55+
annotations: { title: "Conversation Topics" },
5156
description:
5257
"Retrieves Speech and Text Analytics topics detected for a specific conversation. Topics represent business-level intents (e.g. cancellation, billing enquiry) inferred from recognised phrases in the customer-agent interaction.",
5358
inputSchema: {
@@ -64,7 +69,6 @@ describe("Conversation Topics Tool", () => {
6469
additionalProperties: false,
6570
$schema: "http://json-schema.org/draft-07/schema#",
6671
},
67-
annotations: undefined,
6872
});
6973
});
7074

src/tools/conversationTopics/conversationTopics.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export const conversationTopics: ToolFactory<
3939
createTool({
4040
schema: {
4141
name: "conversation_topics",
42+
annotations: { title: "Conversation Topics" },
4243
description:
4344
"Retrieves Speech and Text Analytics topics detected for a specific conversation. Topics represent business-level intents (e.g. cancellation, billing enquiry) inferred from recognised phrases in the customer-agent interaction.",
4445
paramsSchema,

src/tools/conversationTranscription/conversationTranscription.test.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { beforeEach, describe, expect, test, vi } from "vitest";
2-
import { MockedObjectDeep } from "@vitest/spy";
2+
import { type MockedObjectDeep } from "@vitest/spy";
33
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
44
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
55
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
66
import { randomUUID } from "node:crypto";
77
import {
88
conversationTranscription,
9-
ToolDependencies,
9+
type ToolDependencies,
1010
} from "./conversationTranscription.js";
11-
import { TranscriptResponseFormat } from "./TranscriptResponse.js";
11+
import { type TranscriptResponseFormat } from "./TranscriptResponse.js";
1212

1313
describe("Conversation Transcription Tool", () => {
1414
let toolDeps: MockedObjectDeep<ToolDependencies>;
@@ -35,6 +35,7 @@ describe("Conversation Transcription Tool", () => {
3535
toolDefinition.schema.name,
3636
toolDefinition.schema.description,
3737
toolDefinition.schema.paramsSchema.shape,
38+
toolDefinition.schema.annotations,
3839
toolDefinition.call,
3940
);
4041

@@ -52,6 +53,7 @@ describe("Conversation Transcription Tool", () => {
5253
expect(tools.tools[0]).toStrictEqual({
5354
name: "conversation_transcript",
5455
title: undefined,
56+
annotations: { title: "Conversation Transcript" },
5557
description:
5658
"Retrieves a structured transcript of the conversation, including speaker labels, utterance timestamps, and sentiment annotations where available. The transcript is formatted as a time-aligned list of utterances attributed to each participant (e.g., customer or agent)",
5759
inputSchema: {
@@ -69,7 +71,6 @@ describe("Conversation Transcription Tool", () => {
6971

7072
$schema: "http://json-schema.org/draft-07/schema#",
7173
},
72-
annotations: undefined,
7374
});
7475
});
7576

0 commit comments

Comments
 (0)