UNPKG

@bdmarvin/mcp-server-gbp

Version:

MCP server for Google Business Profile Performance API.

153 lines (152 loc) 6.38 kB
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); } }