@bdmarvin/mcp-server-gbp
Version:
MCP server for Google Business Profile Performance API.
153 lines (152 loc) • 6.38 kB
JavaScript
import { google } from 'googleapis';
const DEFAULT_LIST_LOCATIONS_READ_MASK = 'name,title,storeCode,storefrontAddress,openInfo.status';
const DEFAULT_GET_LOCATION_READ_MASK = 'name,title,languageCode,storeCode,phoneNumbers,categories,storefrontAddress,websiteUri,regularHours,specialHours,serviceArea,labels,latlng,openInfo,profile,metadata.mapsUri,metadata.newReviewUri,metadata.placeId';
export class GbpBusinessInformationService {
constructor() { }
getOAuth2Client(accessToken) {
const oauth2Client = new google.auth.OAuth2();
oauth2Client.setCredentials({ access_token: accessToken });
return oauth2Client;
}
getMyBusinessInfoApi(accessToken) {
const authClient = this.getOAuth2Client(accessToken);
return google.mybusinessbusinessinformation({
version: 'v1',
auth: authClient,
});
}
getMyBusinessAccountManagementApi(accessToken) {
const authClient = this.getOAuth2Client(accessToken);
return google.mybusinessaccountmanagement({
version: 'v1',
auth: authClient,
});
}
getMyBusinessQandaApi(accessToken) {
const oauth2Client = this.getOAuth2Client(accessToken);
return google.mybusinessqanda({
version: 'v1',
auth: oauth2Client,
});
}
async listBusinesses(accessToken, params) {
const gbpInfoApi = this.getMyBusinessInfoApi(accessToken);
let { accountId, pageSize, pageToken, filter, orderBy } = params; // Use 'let' for accountId
const readMask = params.readMask || DEFAULT_LIST_LOCATIONS_READ_MASK;
// Remove 'accounts/' prefix if it exists in accountId
if (accountId.startsWith('accounts/')) {
accountId = accountId.replace('accounts/', '');
}
const requestParams = {
parent: `accounts/${accountId}`,
readMask: readMask,
pageSize: pageSize,
pageToken: pageToken,
filter: filter,
orderBy: orderBy,
};
try {
const response = await gbpInfoApi.accounts.locations.list(requestParams);
return response.data;
}
catch (error) {
console.log('Error listing businesses (message):', error.message);
if (error.response) {
console.log('Error listing businesses (status):', error.response.status);
console.log('Error listing businesses (data):', error.response.data);
}
throw new Error(`Failed to list businesses: ${error.response?.data?.error?.message || error.message}`);
}
}
async listQuestions(accessToken, params) {
console.log('listQuestions function called.');
const gbpQandaApi = this.getMyBusinessQandaApi(accessToken);
const { locationName, pageSize, pageToken } = params;
const requestParams = {
parent: locationName,
pageSize: pageSize,
pageToken: pageToken,
};
try {
console.log(`Attempting to list questions for: ${locationName}`);
const response = await gbpQandaApi.locations.questions.list(requestParams);
return response.data;
}
catch (error) {
console.log('Error listing questions (message):', error.message);
if (error.response) {
console.log('Error listing questions (status):', error.response.status);
console.log('Error listing questions (data):', error.response.data);
}
throw new Error(`Failed to list questions: ${error.response?.data?.error?.message || error.message}`);
}
}
async getBusinessInformation(accessToken, params) {
const gbpInfoApi = this.getMyBusinessInfoApi(accessToken);
const { locationName } = params;
const readMask = params.readMask || DEFAULT_GET_LOCATION_READ_MASK;
const requestParams = {
name: locationName,
readMask,
};
return gbpInfoApi.locations.get(requestParams);
}
async updateBusinessInformation(accessToken, params) {
const gbpInfoApi = this.getMyBusinessInfoApi(accessToken);
const { locationName, updateMask, data } = params;
const requestParams = {
name: locationName,
updateMask,
requestBody: data,
};
return gbpInfoApi.locations.patch(requestParams);
}
async getMultipleBusinessInformation(accessToken, params) {
const gbpInfoApi = this.getMyBusinessInfoApi(accessToken);
const { locationNames } = params;
const readMask = params.readMask || DEFAULT_GET_LOCATION_READ_MASK;
const results = await Promise.all(locationNames.map(locationName => gbpInfoApi.locations.get({
name: locationName,
readMask,
}).then(response => response.data)
.catch(error => ({
locationName,
error: {
message: error.message,
data: error.response?.data || null
}
}))));
return { results };
}
async listServices(accessToken, params) {
const gbpInfoApi = this.getMyBusinessInfoApi(accessToken);
const { locationName } = params;
const requestParams = {
name: locationName,
readMask: 'serviceItems',
};
return gbpInfoApi.locations.get(requestParams);
}
async updateServices(accessToken, params) {
const gbpInfoApi = this.getMyBusinessInfoApi(accessToken);
const { locationName, services } = params;
const requestParams = {
name: locationName,
updateMask: 'serviceItems',
requestBody: {
serviceItems: services,
},
};
return gbpInfoApi.locations.patch(requestParams);
}
async listManagedAccounts(accessToken, params) {
const gbpAccountApi = this.getMyBusinessAccountManagementApi(accessToken);
const { pageSize, pageToken, filterAccountType } = params;
const requestParams = {
pageSize,
pageToken,
filter: filterAccountType ? `type=${filterAccountType}` : undefined,
};
return gbpAccountApi.accounts.list(requestParams);
}
}