Skip to content
This repository was archived by the owner on Nov 18, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 1 addition & 18 deletions modelcontextprotocol/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,23 +94,6 @@ Access the MCP settings by clicking "Edit MCP Settings" in Roo Code settings or

To contribute to this project, please see the [contribution guide](CONTRIBUTING.md).

## Telemetry

The Chargebee MCP server collects anonymous usage data to help improve the product. This data includes:

- Server startup and shutdown events
- Tool usage statistics
- Error information
- Session duration

### Disabling Telemetry

You can disable telemetry by setting the `CHARGEBEE_TELEMETRY_DISABLED` environment variable to `1`:

```bash
export CHARGEBEE_TELEMETRY_DISABLED=1
```

## License

[MIT](https://github.com/chargebee/agentkit/blob/develop/LICENSE)
[MIT](https://github.com/chargebee/agentkit/blob/main/LICENSE)
33 changes: 2 additions & 31 deletions modelcontextprotocol/src/chargebee-ai-client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@ import {
DocumentationSearchResponse,
Method,
RequestOptions,
TelemetryData,
} from './types.js';
import { logger } from '@/utils/log.js';

/**
* Client for interacting with the Chargebee AI API
* Provides methods for documentation search and telemetry reporting
*/
export class ChargebeeAIClient {
private readonly clientConfig: ClientConfig;
Expand Down Expand Up @@ -74,44 +71,18 @@ export class ChargebeeAIClient {
* @returns Promise resolving to an array of search results in markdown format
*/
public documentationSearch: Method<DocumentationSearchParams, string[]> =
async (params: DocumentationSearchParams, options = {}) => {
async (params: DocumentationSearchParams) => {
const response = await this.request<DocumentationSearchResponse>({
endpoint: '/v1/documentation/search',
method: 'POST',
body: JSON.stringify({
...params,
}),
...options,
});
return response.results;
};

/**
* Send telemetry data to the telemetry endpoint
* @param data - The telemetry data to send
* @param options - Optional request configuration
* @returns A promise that resolves when the telemetry is sent
*/
public sendTelemetry: Method<TelemetryData, void> = async (
data: TelemetryData,
options = {},
) => {
try {
await this.request<void>({
endpoint: '/v1/telemetry',
method: 'POST',
body: JSON.stringify(data),
...options,
});
} catch (error) {
// Silently fail telemetry errors to not disrupt the main application flow
logger.debug(
`Telemetry error: ${error instanceof Error ? error.message : String(error)}`,
);
}
};
}

export const chargebeeAIClient = new ChargebeeAIClient({
baseUrl: AGENTKIT_BASE_URL,
});
});
9 changes: 0 additions & 9 deletions modelcontextprotocol/src/chargebee-ai-client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,6 @@ export interface DocumentationSearchParams {
user_request?: string;
}

export interface TelemetryData {
event: string;
timestamp: string;
version: string;
platform: string;
sessionDuration: number;
[key: string]: any;
}

export interface RequestOptions extends RequestInit {
endpoint: string;
}
Expand Down
8 changes: 0 additions & 8 deletions modelcontextprotocol/src/config.ts

This file was deleted.

1 change: 0 additions & 1 deletion modelcontextprotocol/src/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ declare global {

namespace NodeJS {
interface ProcessEnv {
CHARGEBEE_TELEMETRY_DISABLED?: string;
AGENTKIT_BASE_URL?: string;
}
}
Expand Down
26 changes: 0 additions & 26 deletions modelcontextprotocol/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import { Command } from 'commander';
import { VERSION } from './constants.js';
import { ChargebeeMCPServer } from './mcp.js';
import { telemetryService } from './utils/telemetry.js';

/**
* Main entry point for the Chargebee MCP server
Expand All @@ -23,24 +22,13 @@ async function main() {
const mcpServer = new ChargebeeMCPServer();
const transport = new StdioServerTransport();

// Track server startup
await telemetryService.trackEvent('server_start', {
version: VERSION,
});

await mcpServer.connect(transport);

// Track server connected
await telemetryService.trackEvent('server_connected');

// Handle process signals
const cleanup = async () => {
if (mcpServer) {
logger.info('Shutting down Chargebee MCP server...');

// Track server shutdown
await telemetryService.trackEvent('server_shutdown');

await mcpServer.close();
process.exit(0);
}
Expand All @@ -52,11 +40,6 @@ async function main() {
// Keep the process running
await new Promise(() => {});
} catch (error) {
// Track server error
await telemetryService.trackEvent('server_error', {
error: error instanceof Error ? error.message : String(error),
});

logger.error('Error starting Chargebee MCP server:', error);
process.exit(1);
}
Expand All @@ -70,15 +53,6 @@ async function main() {
* @param error - The error that occurred during initialization
*/
function handleError(error: any) {
// Track initialization error
telemetryService
.trackEvent('initialization_error', {
error: error instanceof Error ? error.message : String(error),
})
.catch(() => {
// Ignore telemetry errors during shutdown
});

logger.error('\n🚨 Error initializing Aero AI MCP server:\n');
logger.warn(` ${error.message}\n`);
process.exit(1);
Expand Down
62 changes: 15 additions & 47 deletions modelcontextprotocol/src/mcp.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import crypto from 'node:crypto';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { MCP_SERVER_NAME, VERSION } from './constants.js';
import { tools } from './tools/index.js';
import { logger } from './utils/log.js';
import { telemetryService } from './utils/telemetry.js';
import { getUserAgent } from './utils/platform.js';
import { chargebeeAIClient } from './chargebee-ai-client/index.js';

/**
* A server implementation for the Model Context Protocol (MCP) specific to Chargebee.
Expand All @@ -16,15 +17,20 @@ export class ChargebeeMCPServer extends McpServer {
version: VERSION,
});

const mcpClientDetails = this.server.getClientVersion();

this.registerTools();

// Track server initialization
telemetryService.trackEvent('server_initialized', {
clientName: mcpClientDetails?.name,
clientVersion: mcpClientDetails?.version,
});
this.server.oninitialized = () => {
const mcpClient = this.server.getClientVersion();
const userAgent = getUserAgent({
mcpClientName: mcpClient?.name,
mcpClientVersion: mcpClient?.version,
});

chargebeeAIClient.attachHeaders({
'User-Agent': userAgent,
'x-mcp-session-id': crypto.randomUUID(),
});
};
}

/**
Expand All @@ -40,26 +46,8 @@ export class ChargebeeMCPServer extends McpServer {
tool.description,
tool.parameters.shape,
async (arg: any) => {
const startTime = Date.now();
let success = false;

try {
logger.info('Received tool call:', tool.name);

await this.trackEvent('tool_call_start', {
tool: tool.name,
method: tool.method,
});

const result = await tool.execute(arg, this);
success = true;

// Track tool call success
await this.trackEvent('tool_call_success', {
tool: tool.name,
method: tool.method,
duration: Date.now() - startTime,
});

return {
content: [
Expand All @@ -70,16 +58,6 @@ export class ChargebeeMCPServer extends McpServer {
],
};
} catch (error) {
logger.error(`Error executing tool: ${tool.name}`, error);

// Track tool call error
await this.trackEvent('tool_call_error', {
tool: tool.name,
method: tool.method,
error: error instanceof Error ? error.message : String(error),
duration: Date.now() - startTime,
});

return {
content: [
{
Expand All @@ -94,14 +72,4 @@ export class ChargebeeMCPServer extends McpServer {
);
});
}

private async trackEvent(eventName: string, data: any) {
const mcpClientDetails = this.server.getClientVersion();

await telemetryService.trackEvent(eventName, {
...data,
clientName: mcpClientDetails?.name,
clientVersion: mcpClientDetails?.version,
});
}
}
4 changes: 1 addition & 3 deletions modelcontextprotocol/src/tools/documentation-search.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { chargebeeAIClient } from '@/chargebee-ai-client/index.js';
import { ChargebeeMCPServer } from '@/mcp.js';
import { z } from 'zod';

/**
Expand All @@ -25,7 +24,7 @@ It takes the following arguments:

const documentationSearchParameters = z.object({
query: z.string().describe(queryParamDescription),
user_request: z.string().describe(userRequestParamDescription),
user_request: z.string().describe(userRequestParamDescription).optional(),
data_sources: z
.array(z.enum(['help_documentation', 'api_documentation', 'release_notes']))
.describe(dataSourceParamDescription)
Expand Down Expand Up @@ -121,7 +120,6 @@ const documentationSearchParameters = z.object({
*/
const documentationSearch = async (
parameters: z.infer<typeof documentationSearchParameters>,
mcpServer: ChargebeeMCPServer,
) => {
try {
const results = await chargebeeAIClient.documentationSearch({
Expand Down
1 change: 0 additions & 1 deletion modelcontextprotocol/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export * from './log.js';
export * from './platform.js';
export * from './telemetry.js';
24 changes: 20 additions & 4 deletions modelcontextprotocol/src/utils/platform.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
import os from 'os';
import { VERSION } from '@/constants.js';
import os from 'node:os';

export function getPlatformInfo() {
return `${os.platform()}`;
}
interface UserAgentParams {
mcpClientName?: string;
mcpClientVersion?: string;
}

/**
* Generates a User-Agent string
* @param {Object} params - Configuration parameters
* @param {string} params.mcpClientName - Name of the MCP client
* @param {string} params.mcpClientVersion - Version of the MCP client
* @returns {string} Formatted User-Agent string
*/
export function getUserAgent({
mcpClientName = 'unknown',
mcpClientVersion = 'unknown',
}: UserAgentParams) {
return `ChargebeeMCP/${VERSION} (${os.platform()}; Node/${process.version}; ${mcpClientName}/${mcpClientVersion})`;
}
Loading