@chargetrip/mcp
Version:
Chargetrip MCP server
240 lines (225 loc) • 7.53 kB
text/typescript
import { CallToolResult } from '@modelcontextprotocol/sdk/types';
import { GraphQLError } from 'graphql';
import { GraphQLClient } from './graphql-client';
export class FetchAndProcessUtil {
/**
* @description Unified method to fetch a list of items from the Chargetrip GraphQL API and process the results.
* Please make sure that the query return the elements of the list in a field named `list`.
*
* @param {string} query The GraphQL query string to execute.
* @param {Record<string, any>} variables The variables to be used in the GraphQL query.
* @param {Function} mapFunction A function that maps each item in the list to a string representation.
* @returns {Promise<CallToolResult>} A promise that resolves to a CallToolResult containing the processed list.
*/
static async getList<T>({
query,
variables,
mapFunction,
}: {
query: string;
variables: Record<string, any>;
mapFunction: (item: T) => string;
}): Promise<CallToolResult> {
try {
const { data, error } = await GraphQLClient.getInstance().query<{
list: T[];
}>(query, variables);
if (error) {
throw new GraphQLError(error.message);
}
if (!data?.list || data.list.length === 0) {
throw new Error('No data found or an error occurred while fetching the list.');
}
return {
content: [
{
type: 'text',
text: 'Here is the response of the API for the list:',
},
{
type: 'text',
text: data.list.map(mapFunction).join('\n'),
},
{
type: 'text',
text: 'Here is the query that was used to fetch the list:',
},
{
type: 'text',
text: `Query: "${query}"\nVariables: "${JSON.stringify(variables, null, 2)}"`,
},
],
};
} catch (error) {
if (error instanceof GraphQLError) {
return {
content: [
{
type: 'text',
text: `GraphQL error occurred while fetching the list: ${error.message}`,
},
],
};
}
return {
content: [
{
type: 'text',
text: `Unexpected error occurred while fetching the list: ${error instanceof Error ? error.message : String(error)}`,
},
],
};
}
}
/**
* @description Unified method to fetch a single item from the Chargetrip GraphQL API and process the result.
* Please make sure that the query return the item in a field named `item`.
*
* @param {string} itemName The name of the item being fetched, used for error messages.
* @param {string} query The GraphQL query string to execute.
* @param {Record<string, any>} variables The variables to be used in the GraphQL query.
* @param {Function} mapFunction A function that maps the item to a string representation.
* @param {string} operationType The type of operation to perform, either 'query' or 'mutation'.
* @returns {Promise<CallToolResult>} A promise that resolves to a CallToolResult containing the processed item.
*/
static async getItem<T>({
itemName,
query,
variables,
operationType = 'query',
mapFunction,
}: {
itemName: string;
query: string;
variables: Record<string, any>;
operationType?: 'query' | 'mutation';
mapFunction: (item: T) => string;
}): Promise<CallToolResult> {
try {
const { data, error } =
operationType === 'mutation'
? await GraphQLClient.getInstance().mutate<{ item: T }>(query, variables)
: await GraphQLClient.getInstance().query<{ item: T }>(query, variables);
if (error) {
throw new GraphQLError(error.message);
}
if (!data?.item) {
throw new Error('No data found or an error occurred while fetching the data.');
}
return {
content: [
{
type: 'text',
text: `Here is the response of the API for the ${itemName}:`,
},
{
type: 'text',
text: mapFunction(data.item),
},
{
type: 'text',
text: `Here is the query that was used to fetch the ${itemName}:`,
},
{
type: 'text',
text: `Query: "${query}"\nVariables: "${JSON.stringify(variables, null, 2)}"`,
},
],
};
} catch (error) {
if (error instanceof GraphQLError) {
return {
content: [
{
type: 'text',
text: `GraphQL error occurred while fetching the ${itemName}: ${error.message}`,
},
],
};
}
return {
content: [
{
type: 'text',
text: `Unexpected error occurred while fetching the ${itemName}: ${error instanceof Error ? error.message : String(error)}`,
},
],
};
}
}
/**
* @description Unified method to fetch a single item from the Chargetrip GraphQL API using a subscription and process the result.
*
* @param {string} itemName The name of the item being fetched, used for error messages.
* @param {string} query The GraphQL query string to execute.
* @param {Record<string, any>} variables The variables to be used in the GraphQL query.
* @param {Function} subscribeFunction A function that determines whether to continue subscribing based on the item received.
* @param {Function} mapFunction A function that maps the item to a string representation.
* @returns {Promise<CallToolResult>} A promise that resolves to a CallToolResult containing the processed item.
*/
static async getItemFromSubscription<T>({
itemName,
query,
variables,
subscribeFunction,
mapFunction,
}: {
itemName: string;
query: string;
variables: Record<string, any>;
subscribeFunction: (item: T) => boolean;
mapFunction: (item: T) => string;
}): Promise<CallToolResult> {
try {
const data: T = await new Promise(resolve => {
const { unsubscribe } = GraphQLClient.getInstance()
.subscription<T>(query, variables)
.subscribe(data => {
if (subscribeFunction(data.data as T)) {
unsubscribe();
return resolve(data.data as T);
}
});
});
return {
content: [
{
type: 'text',
text: `Here is the response of the API for the ${itemName}:`,
},
{
type: 'text',
text: mapFunction(data),
},
{
type: 'text',
text: `Here is the query that was used to fetch the ${itemName}:`,
},
{
type: 'text',
text: `Query: "${query}"\nVariables: "${JSON.stringify(variables, null, 2)}"`,
},
],
};
} catch (error) {
if (error instanceof GraphQLError) {
return {
content: [
{
type: 'text',
text: `GraphQL error occurred while waiting for the ${itemName}: ${error.message}`,
},
],
};
}
return {
content: [
{
type: 'text',
text: `Unexpected error occurred while waiting for the ${itemName}: ${error instanceof Error ? error.message : String(error)}`,
},
],
};
}
}
}