Skip to main content
Glama
client.ts6.11 kB
import { google } from 'googleapis'; import { getAuthClient } from '../auth/auth.js'; export class BusinessProfileClient { private accountManagement; private businessInformation; private authClient: any; constructor(authClient: any) { this.authClient = authClient; this.accountManagement = google.mybusinessaccountmanagement({ version: 'v1', auth: authClient }); this.businessInformation = google.mybusinessbusinessinformation({ version: 'v1', auth: authClient }); } static async create() { const authClient = await getAuthClient(); return new BusinessProfileClient(authClient); } async listAccounts() { const res = await this.accountManagement.accounts.list(); return res.data.accounts || []; } async listLocations(accountId: string) { // accountId should be in format "accounts/12345" // The API expects parent to be the account name const res = await this.businessInformation.accounts.locations.list({ parent: accountId, readMask: 'name,title,metadata', }); return res.data.locations || []; } async getLocation(name: string, readMask: string) { const res = await this.businessInformation.locations.get({ name, readMask, }); return res.data; } async getReviews(locationName: string) { // locationName format: "locations/12345" or "accounts/12345/locations/12345" // The v4 API expects "accounts/{accountId}/locations/{locationId}/reviews" // However, the new API returns locationName as "locations/{locationId}" usually? // Let's check what listLocations returns. It returns "locations/{locationId}". // But v4 API needs account ID. // We might need to extract account ID from the context or pass it in. // Actually, let's try to use the locationName as provided if it contains account info, // or construct it. // If locationName is just "locations/{id}", we need to find the account. // But for simplicity, let's assume the user passes the full resource name if possible, // OR we just try to hit the endpoint. // Wait, v4 API endpoint is: https://mybusiness.googleapis.com/v4/{parent}/reviews // where parent is "accounts/{accountId}/locations/{locationId}". // If we only have "locations/{locationId}", we can't easily construct the v4 name without looking up the location details // which might contain the parent, or listing locations for an account. // Let's assume the input `locationName` is the full resource name required by v4, // OR we require the user to pass accountId and locationId. // Let's make the tool take `accountId` and `locationId` to be safe, or `locationName` if it's full. // Actually, `listLocations` returns `name` as `locations/{locationId}`. // But `metadata` might contain `parent`. // Let's try to use the `authClient.request` to hit the v4 API. const url = `https://mybusiness.googleapis.com/v4/${locationName}/reviews`; const res = await this.authClient.request({ url }); return res.data.reviews || []; } async replyToReview(reviewName: string, comment: string) { // reviewName: accounts/{accountId}/locations/{locationId}/reviews/{reviewId} const url = `https://mybusiness.googleapis.com/v4/${reviewName}/reply`; const res = await this.authClient.request({ url, method: 'PUT', data: { comment } }); return res.data; } async updateLocation(locationName: string, locationData: any, updateMask: string) { // locationName: locations/{locationId} const res = await this.businessInformation.locations.patch({ name: locationName, updateMask, requestBody: locationData, }); return res.data; } async createPost(locationName: string, postData: any) { // locationName: locations/{locationId} // API expects: accounts/{accountId}/locations/{locationId}/localPosts // We need to fetch the account ID first if not provided in the name, but usually locationName from listLocations includes it? // Actually listLocations returns "locations/{locationId}". // We need the account ID. // Wait, the v4 API for reviews used `accounts/{accId}/locations/{locId}`. // Let's check how we handled reviews. // In `getReviews`, we passed `resourceName` which was constructed in the tool handler. // So we should expect `locationName` here to be the full resource name: `accounts/{accId}/locations/{locId}`. const url = `https://mybusiness.googleapis.com/v4/${locationName}/localPosts`; const res = await this.authClient.request({ url, method: 'POST', data: postData }); return res.data; } async listPosts(parent: string) { // parent: accounts/{accountId}/locations/{locationId} const url = `https://mybusiness.googleapis.com/v4/${parent}/localPosts`; const res = await this.authClient.request({ url }); return res.data.localPosts || []; } async deletePost(name: string) { // name: accounts/{accountId}/locations/{locationId}/localPosts/{postId} const url = `https://mybusiness.googleapis.com/v4/${name}`; const res = await this.authClient.request({ url, method: 'DELETE' }); return res.data; } async updatePost(name: string, postData: any, updateMask: string) { // name: accounts/{accountId}/locations/{locationId}/localPosts/{postId} const url = `https://mybusiness.googleapis.com/v4/${name}?updateMask=${updateMask}`; const res = await this.authClient.request({ url, method: 'PATCH', data: postData }); return res.data; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ehukaimedia/google-webmaster-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server