@bdmarvin/mcp-server-gbp v0.3.9
Google Business Profile (GBP) MCP Server
This is a Model Context Protocol (MCP) server designed to interact with the Google Business Profile (GBP) APIs, including Account Management, Business Information, and Performance. It integrates with an MCP OAuth Controller (like @bdmarvin/typingmind-mcp) to securely access GBP data on behalf of an authenticated user.
Overview
This server acts as a specialized tool provider, enabling applications to query and retrieve data from Google Business Profile. It relies on an upstream MCP OAuth Controller to handle the Google OAuth 2.0 flow and to provide a valid Google Access Token for API calls.
The server listens for requests over STDIO (standard input/output) when launched by an MCP controller.
Prerequisites
- Node.js (Version 18.x or later recommended).
- MCP OAuth Controller: A running instance of an MCP OAuth Controller (e.g.,
@bdmarvin/typingmind-mcp) properly configured with Google Cloud Project credentials (OAuth Client ID & Secret) and the necessary GBP APIs enabled in the Google Cloud Console. - Enabled APIs in Google Cloud Project:
- My Business Account Management API
- My Business Business Information API
- Business Profile Performance API
- OAuth Scopes: The access token provided by the OAuth Controller must have been granted with sufficient scopes to access the GBP APIs. The
https://www.googleapis.com/auth/business.managescope is generally recommended for comprehensive access to these APIs. - User Permissions: The authenticated Google user must have appropriate permissions (Owner, Manager, etc.) for the GBP accounts and locations they intend to query.
How it Works with an MCP OAuth Controller
- The MCP OAuth Controller launches this
mcp-server-gbpprocess (typically vianpx @bdmarvin/mcp-server-gbp). - The controller establishes communication with this server over STDIO and handles the MCP initialization handshake.
- When a tool on this server is called (via the controller's API), the controller injects a fresh Google Access Token (as
__google_access_token__) and potentially user identifiers (__google_user_id__,__google_user_email__) into the tool arguments. - This server uses the provided access token to make authenticated calls to the relevant Google Business Profile APIs.
- Results are returned to the controller, which then relays them to the end-user or application.
Setup and Installation (for Development or Direct Use)
- Clone the repository:
git clone https://github.com/bdmarvin1/mcp-server-gbp.git cd mcp-server-gbp - Install dependencies:
npm install - Build the project (compiles TypeScript):
npm run build
Running Locally (for Development and STDIO Testing)
While primarily designed to be run by an MCP OAuth Controller, you can run the server directly for local development and testing using STDIO JSON-RPC messages:
- Build the project:
npm run build - Run the server:
node dist/index.js- The server will print:
Google Business Profile MCP Server (vX.Y.Z) running on stdio, expecting __google_access_token__
- The server will print:
- Paste properly formatted JSON-RPC 2.0 messages (as single lines) into the terminal and press Enter. See "Manual STDIO Testing" section below for examples.
Using with npx (Intended for MCP Controllers)
Once published to NPM (e.g., as @bdmarvin/mcp-server-gbp), MCP OAuth Controllers can launch it using npx:
npx @bdmarvin/mcp-server-gbpAvailable Tools
This server provides tools to navigate and retrieve Google Business Profile data. A typical workflow is:
1. list_managed_accounts: To find the accountId for the desired business entity.
2. list_businesses: To list locations under that accountId and get their locationName (e.g., locations/12345).
3. Use the locationName with get_business_information or performance tools.
1. Account Management Tools
list_managed_accounts
Lists all Google Business Profile accounts (Personal, Location Groups, Organizations) that the authenticated user has access to.
- Input Parameters (
arguments):pageSize(number, optional): Accounts per page (1-20, default usually 20 by API).pageToken(string, optional): Token for paginating results.filterAccountType(string, optional): Filter by account type. Valid values:"PERSONAL","LOCATION_GROUP","USER_GROUP","ORGANIZATION".
- Output: The
result.content[0].textwill be a JSON string.- Success Example (JSON string content):
{ "accounts": [ { "name": "accounts/113493492542427782722", "accountName": "Client Services", "type": "PERSONAL", "verificationState": "UNVERIFIED", "vettedState": "NOT_VETTED" }, { "name": "accounts/107454337197860553297", "accountName": "Absolute Storage", "type": "LOCATION_GROUP", "role": "MANAGER", "verificationState": "VERIFIED", "vettedState": "NOT_VETTED" } ], "nextPageToken": "ABHRLX..." } - The numerical part of the
namefield (e.g.,113493492542427782722) is theaccountIdneeded for thelist_businessestool.
- Success Example (JSON string content):
2. Business Information Tools
list_businesses
Lists businesses (locations) associated with a specific accountId (obtained from list_managed_accounts).
- Input Parameters (
arguments):accountId(string, required): The numerical ID of the Google Account.readMask(string, optional): Comma-separated list of fields to return for each location (e.g.,"name,title,storefrontAddress.postalCode"). See Google's documentation forLocationfields. Default returns:locations.name,locations.title,locations.storeCode,locations.storefrontAddress,locations.openInfo.status.pageSize(number, optional): Locations per page (1-100).pageToken(string, optional): Pagination token.filter(string, optional): Filter string (e.g.,"title = \"My Awesome Store\""). See Location Data Guide.orderBy(string, optional): Order results (e.g.,"title, store_code desc"). Valid fields:title,store_code.
- Output: JSON string containing a list of
Locationobjects.- Success Example (JSON string content, partial):
{ "locations": [ { "name": "locations/12345678901234567890", "title": "My Awesome Store", "storefrontAddress": { "postalCode": "94043" } } ], "nextPageToken": "CIV..." } - The
namefield (e.g.,locations/12345678901234567890) is thelocationNamefor other tools.
- Success Example (JSON string content, partial):
get_business_information
Fetches detailed information for a specific locationName (obtained from list_businesses).
- Input Parameters (
arguments):locationName(string, required): Formatlocations/{location_id}.readMask(string, optional): Comma-separated list of fields to return. Default returns a comprehensive set of fields (seeDEFAULT_GET_LOCATION_READ_MASKin the service class). Example:"name,title,phoneNumbers,regularHours.periods".
- Output: JSON string of the detailed
Locationobject.
get_multiple_business_information
Fetches detailed information for multiple locationNames.
- Input Parameters (
arguments):locationNames(array of strings, required): E.g.,["locations/123", "locations/456"].readMask(string, optional): Field mask applied to each location. Uses same default asget_business_informationif omitted.
- Output: JSON string. The structure will be:
{ "results": [ // Location object for first locationName, or an error object if that call failed { "name": "locations/123", "title": "Store 1", ... }, // Location object for second locationName, or an error object { "locationName": "locations/456", "error": { "message": "API error message...", "data": { ... } } } ] }
3. Performance Data Tools
get_daily_performance_metrics
Fetches daily performance metrics for a specific locationName.
- Input Parameters (
arguments):locationName(string, required): Formatlocations/{location_id}.dailyMetrics(array of strings, required): E.g.,["WEBSITE_CLICKS", "CALL_CLICKS"]. SeeDailyMetricEnuminsrc/schemas.tsfor all valid metric names.startDate(object, required):{ "year": number, "month": number, "day": number }.endDate(object, required):{ "year": number, "month": number, "day": number }.
- Output: JSON string containing time series data for the requested metrics.
get_monthly_search_keywords
Fetches monthly search keyword impressions for a specific locationName.
- Input Parameters (
arguments):parentLocationName(string, required): Formatlocations/{location_id}(this is thelocationName).startMonth(object, required):{ "year": number, "month": number, "day": number }(day is usually 0 or 1).endMonth(object, required):{ "year": number, "month": number, "day": number }(day is usually 0 or 1).pageSize(number, optional): Max 100.pageToken(string, optional): Pagination token.
- Output: JSON string listing search keywords and their impression counts.
Manual STDIO Testing (for Local Development)
When running node dist/index.js directly, you can send JSON-RPC 2.0 messages to test tools. Ensure the JSON is a single line.
- List Tools:
{"jsonrpc":"2.0","id":"local-list-tools","method":"tools/list","params":{}} - Call a Tool (Example:
list_managed_accounts):- Replace
YOUR_ACCESS_TOKENwith a valid token.
(Refer to the "Available Tools" section for argument structures for other tools.){"jsonrpc":"2.0","id":"local-call-list-accounts","method":"tools/call","params":{"name":"list_managed_accounts","arguments":{"__google_access_token__":"YOUR_ACCESS_TOKEN","pageSize":5}}} - Replace
Error Handling
The server will attempt to catch errors from Google APIs and Zod validation.
- Zod Validation Errors: Will indicate invalid arguments provided to a tool.
- Google API Errors: Will often include a message and details from Google (logged to
stderrand returned in the JSON-RPC error response). Common issues include expired access tokens, insufficient permissions for the authenticated user, incorrectaccountIdorlocationName, or invalidreadMaskvalues.
Development
- Watch Mode:
npm run watchfor continuous compilation. - API Documentation:
License
This project is licensed under the MIT License. See the LICENSE file for details.
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago