PinMeTo Location MCP
OfficialThis server connects AI assistants to PinMeTo location data, letting you ask natural-language questions about your locations and their Google, Facebook, and Apple performance.
Locations: Get details for a single location, list all locations with pagination/filtering (city, country, type, closed status), and search by name, address, or store ID.
Google insights: Views, searches, direction requests, calls, and clicks with daily/weekly/monthly/quarterly/yearly aggregation and period comparisons (MoM/QoQ/YoY).
Google reviews: Fetch and filter individual reviews by rating or response status; get summarized sentiment, rating distributions, and per-location comparisons.
Google ratings: Average rating, review count, and star distribution across locations.
Google keywords: See how customers search for your business via keyword impression counts.
Facebook insights: Page engagement and reach metrics for locations and brand pages, with aggregation and period comparisons.
Facebook ratings: Ratings and recommendation summaries per location.
Apple Maps insights: Apple Maps performance metrics with aggregation and period comparisons.
All tools are read-only, support JSON or markdown responses, and include caching and structured error handling.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@PinMeTo Location MCPWhat's my average Google rating?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
PinMeTo Location MCP
An MCP server that connects your PinMeTo locations to AI assistants. Ask questions about your business in natural language and get instant insights from Google, Facebook, and Apple.
Works with MCP-compatible clients that can run local STDIO servers, including Claude Desktop, the ChatGPT desktop app, VS Code, Cursor, and more.
What Can You Do With It?
Ask your AI assistant questions like:
"What's my average Google rating across all locations?"
"Show me negative reviews that need responses"
"Compare this quarter's performance to last year"
"Which locations are performing best?"
See Example Prompts for more ideas.
π Turn your data into reports. On top of the
.mcpbdata connection, install the PinMeTo Locations plugin to add formatted PDF and PowerPoint reports across all your locations. See Creating Reports below.
Related MCP server: mcp-ohmy-sql
Installation
Claude Desktop
Download the installer: click the
.mcpbbadge above, or grab pinmeto-location-mcp.mcpb from the latest releaseDouble-click the downloaded file (with Claude Desktop open), or drag it into Claude Desktop β Settings β Extensions
Enter your PinMeTo API credentials (Account ID, App ID, App Secret) in the install dialog
Done! This installs the data connection β the MCP server and its twelve tools. Start asking questions about your locations.
Get your credentials from PinMeTo Account Settings.
Reports (optional). To also generate PDF and PowerPoint reports:
Open Customize in the sidebar, go to Plugins
Click + in Personal plugins, choose Add marketplace
Enter
PinMeTo/claude-pluginsInstall PinMeTo Locations β this adds the report skill
Note: While the plugin repository is private, installing requires the Claude GitHub App to have access to it.
ChatGPT Desktop App
The ChatGPT desktop app can run PinMeTo locally as a STDIO MCP server. You need Node.js v22 or later, Git, and PinMeTo API credentials before you start.
Get your Account ID, App ID, and App Secret from PinMeTo Account Settings.
In the ChatGPT desktop app, open Settings β Plugins, then select the MCPs tab.
Select Add β Add MCP server.
Enter the following values:
Field
Value
Name
PinMeToType
STDIO
Command to launch
npxArgument 1
-yArgument 2
github:PinMeTo/pinmeto-location-mcpEnvironment variable
PINMETO_ACCOUNT_ID= your Account IDEnvironment variable
PINMETO_APP_ID= your App IDEnvironment variable
PINMETO_APP_SECRET= your App SecretAdd each argument and environment variable in its own row. Leave Environment variable passthrough and Working directory empty.
Select Save, then restart when prompted.
Start a new Codex task in the desktop app. Enter
/mcpto confirm thatPinMeTois connected, then try: βList my PinMeTo locations.β
If the server cannot find npx, locate it with command -v npx on macOS/Linux,
(Get-Command npx).Source in Windows PowerShell, or where npx in Windows
Command Prompt. Use the returned absolute path as Command to launch.
ChatGPT web: This local STDIO setup is available to Codex in the ChatGPT desktop app. ChatGPT on the web does not read local MCP configuration; web Chat and Work use remote MCP tools supplied by plugins instead. See OpenAI's MCP documentation.
Other Installation Options
Platform | Method |
VS Code | Click the VS Code badge above |
Cursor | Click the Cursor badge above |
Claude Code (CLI) | The plugin doesn't bundle a server. Run the server directly from GitHub: |
Manual |
Available Features
Feature | What You Can Do |
Locations | View all your locations, search by name or city |
Google Insights | Views, searches, direction requests, calls, clicks |
Google Reviews | Read reviews, filter by rating, find unresponded reviews |
Google Ratings | Average rating, review count, star distribution |
Google Keywords | See how customers search for your business |
Facebook Insights | Page engagement and reach metrics |
Facebook Ratings | Ratings and recommendations |
Apple Insights | Apple Maps performance metrics |
All insights support time aggregation (daily, monthly, quarterly) and period comparison (month-over-month, year-over-year).
Creating Reports
Generate professional reports from your location data using the PinMeTo Location Reports Skill.
What It Does
Transforms your multi-location analytics into formatted PDF and PowerPoint reports:
Monthly, Quarterly, Half-Yearly, and Yearly reports
Includes Google, Facebook, and Apple metrics
Review ratings and sentiment analysis
Search keyword performance
Data-driven strategic recommendations
The report skill comes from the PinMeTo Locations plugin;
the location data and tools come from the .mcpb. With both installed, ask for "a
quarterly report" or "a Q4 board presentation" and the skill activates automatically.
Prefer not to install the plugin? The skill is also available standalone from the skill repository.
Documentation
Guide | Description |
First steps, FAQ, and troubleshooting | |
Prompts organized by business need | |
Complete tool documentation | |
Time aggregation and comparisons | |
Developer setup instructions |
Requirements
An MCP-compatible client (Claude Desktop, VS Code, Cursor, or others)
For local installation in the ChatGPT desktop app: Node.js v22 or later
PinMeTo account with API access
Support
Setup issues: See Troubleshooting
Feature questions: See FAQ
Bug reports: GitHub Issues
PinMeTo account: PinMeTo Support
Privacy Policy
This server sends your PinMeTo API credentials to PinMeTo's API to fetch your own location data, and returns that data to your MCP client. It stores nothing remotely and transmits nothing to any third party.
Collected: your PinMeTo Account ID, App ID, and App Secret, supplied by you at install time.
Used for: authenticating requests to the PinMeTo API on your behalf.
Stored: credentials remain under your MCP client's control (for example, the macOS Keychain under Claude Desktop); this server never writes them to disk. Location and insights data is cached in memory for the duration of a session and never written to disk.
Shared: nothing is shared with third parties.
Retained: the server itself retains nothing after the process exits, and its in-memory location and insights cache is discarded then. Credential persistence is managed by your MCP client, not by this server.
Contact: PinMeTo Support
Full policy: https://places.pinmeto.com/listings/public/legal/privacypolicy
License
MIT
Available Tools
12 toolspinmeto_get_apple_insightsApple Maps insightsARead-only
Fetch Apple metrics for all locations, or a single location if storeId provided. Supports time aggregation (default: total) and period comparisons.
Comparison Options:
compare_with="prior_period": Compare with same-duration period before (MoM, QoQ)
compare_with="prior_year": Compare with same dates last year (YoY)
When comparison is active, each metric includes a comparison field with prior, delta, deltaPercent
Error Handling:
Rate limit (429): errorCode="RATE_LIMITED", message includes retry timing
Not found (404): errorCode="NOT_FOUND" if storeId doesn't exist
All errors: check structuredContent.errorCode and .retryable for programmatic handling
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | End date (YYYY-MM-DD) | |
| from | Yes | Start date (YYYY-MM-DD) | |
| storeId | No | Optional store ID to fetch a single location | |
| aggregation | No | Time aggregation: total (default, maximum token reduction), daily, weekly, monthly, quarterly, half-yearly, yearly | total |
| compare_with | No | Compare with: prior_period (MoM/QoQ for same-duration period before), prior_year (YoY for same dates last year), or none (default) | none |
| response_format | No | Response format: "json" (default, token-efficient) or "markdown" (human-readable with tables) | json |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Error message if the request failed |
| warning | No | Warning message (e.g., incomplete data due to lag) |
| insights | No | Array of insights by metric. Flattened (no values array) when aggregation=total, multi-period otherwise (absent on error) |
| errorCode | No | Error code for programmatic handling |
| retryable | No | Whether the operation can be retried |
| compareWith | No | Comparison period type used: "none", "prior_period", or "prior_year" |
| periodRange | No | Date range for the current period data |
| warningCode | No | Warning code for programmatic handling |
| comparisonError | No | Error message if comparison data could not be fetched (current period data still returned) |
| timeAggregation | No | Time aggregation level applied to the data (e.g., "total", "monthly", "daily") |
| priorPeriodRange | No | Date range for the prior period (present when compare_with is specified) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description discloses meaningful behavioral details: comparison response fields (prior, delta, deltaPercent), rate-limit error structure, 404 handling, and retryable/errorCode fields for programmatic handling. This significantly exceeds what annotations alone provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections for comparison options and error handling. Every sentence adds useful information. The main purpose is front-loaded, and formatting makes it easy for an agent to extract key behavior quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists and the input schema fully documents parameters, the description covers the remaining critical operational context: comparison behavior, error handling, and response format options. Nothing essential is missing for an agent to select and invoke this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents every parameter. The description adds value by explaining comparison semantics (MoM/QoQ, YoY), the resulting comparison fields, and the token-reduction intent behind 'total' aggregation, which is not evident from the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Fetch Apple metrics for all locations, or a single location if storeId provided.' This clearly differentiates it from sibling tools like Google or Facebook insights, and the storeId option clarifies scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context by identifying the tool as Apple Maps insights and explaining the all-locations vs. single-location behavior. It does not explicitly name sibling alternatives or state when not to use it, but the platform is unambiguous from purpose, title, and sibling names.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pinmeto_get_facebook_brandpage_insightsFacebook brand page insightsARead-only
Fetch Facebook metrics for all brand pages. Supports time aggregation (default: total) and period comparisons.
Comparison Options:
compare_with="prior_period": Compare with same-duration period before (MoM, QoQ)
compare_with="prior_year": Compare with same dates last year (YoY)
When comparison is active, each metric includes flat comparison fields (priorValue, delta, deltaPercent)
Error Handling:
Rate limit (429): errorCode="RATE_LIMITED", message includes retry timing
Auth failure (401): errorCode="AUTH_INVALID_CREDENTIALS"
All errors: check structuredContent.errorCode and .retryable for programmatic handling
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | End date (YYYY-MM-DD) | |
| from | Yes | Start date (YYYY-MM-DD) | |
| aggregation | No | Time aggregation: total (default, maximum token reduction), daily, weekly, monthly, quarterly, half-yearly, yearly | total |
| compare_with | No | Compare with: prior_period (MoM/QoQ for same-duration period before), prior_year (YoY for same dates last year), or none (default) | none |
| response_format | No | Response format: "json" (default, token-efficient) or "markdown" (human-readable with tables) | json |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Error message if the request failed |
| warning | No | Warning message (e.g., incomplete data due to lag) |
| insights | No | Array of insights by metric. Flattened (no values array) when aggregation=total, multi-period otherwise (absent on error) |
| errorCode | No | Error code for programmatic handling |
| retryable | No | Whether the operation can be retried |
| compareWith | No | Comparison period type used: "none", "prior_period", or "prior_year" |
| periodRange | No | Date range for the current period data |
| warningCode | No | Warning code for programmatic handling |
| comparisonError | No | Error message if comparison data could not be fetched (current period data still returned) |
| timeAggregation | No | Time aggregation level applied to the data (e.g., "total", "monthly", "daily") |
| priorPeriodRange | No | Date range for the prior period (present when compare_with is specified) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as read-only, and the description reinforces this while adding meaningful behavioral detail: comparison modes produce flat priorValue, delta, and deltaPercent fields, and errors expose structuredContent.errorCode and retryable with specific codes for rate limits and auth failures. This goes well beyond the annotation and helps an agent handle failures programmatically.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and default behavior. The comparison and error sections use tight bullet-style formatting with no filler. Every sentence contributes operational information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Combined with the rich input schema, output schema, and readOnlyHint annotation, the description covers the full call contract: required dates, aggregation choices, comparison behavior, response format, and error semantics. For a read-only metrics tool, nothing essential for invoking it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents all parameters. The description adds value by explaining what compare_with modes mean (MoM/QoQ vs YoY), what comparison-active responses include, and that response_format=json is more token-efficient. It does not add date syntax, but the schema already provides patterns.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description begins with a specific verb and resource: 'Fetch Facebook metrics for all brand pages.' It clearly identifies what the tool does and its scope. However, it does not explicitly distinguish itself from the sibling tool get_facebook_insights beyond the phrase 'brand page,' so it stops short of full sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no direct guidance on when to use this tool versus alternatives. It does not mention sibling tools, exclusions, or conditions such as 'for location-level Facebook data use get_facebook_insights.' The scope is implied by 'all brand pages,' but an agent is not explicitly routed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pinmeto_get_facebook_insightsFacebook insightsARead-only
Fetch Facebook metrics for all locations, or a single location if storeId provided. Supports time aggregation (default: total) and period comparisons.
Comparison Options:
compare_with="prior_period": Compare with same-duration period before (MoM, QoQ)
compare_with="prior_year": Compare with same dates last year (YoY)
When comparison is active, each metric includes a comparison field with prior, delta, deltaPercent
Error Handling:
Rate limit (429): errorCode="RATE_LIMITED", message includes retry timing
Not found (404): errorCode="NOT_FOUND" if storeId doesn't exist
All errors: check structuredContent.errorCode and .retryable for programmatic handling
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | End date (YYYY-MM-DD) | |
| from | Yes | Start date (YYYY-MM-DD) | |
| storeId | No | Optional store ID to fetch a single location | |
| aggregation | No | Time aggregation: total (default, maximum token reduction), daily, weekly, monthly, quarterly, half-yearly, yearly | total |
| compare_with | No | Compare with: prior_period (MoM/QoQ for same-duration period before), prior_year (YoY for same dates last year), or none (default) | none |
| response_format | No | Response format: "json" (default, token-efficient) or "markdown" (human-readable with tables) | json |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Error message if the request failed |
| warning | No | Warning message (e.g., incomplete data due to lag) |
| insights | No | Array of insights by metric. Flattened (no values array) when aggregation=total, multi-period otherwise (absent on error) |
| errorCode | No | Error code for programmatic handling |
| retryable | No | Whether the operation can be retried |
| compareWith | No | Comparison period type used: "none", "prior_period", or "prior_year" |
| periodRange | No | Date range for the current period data |
| warningCode | No | Warning code for programmatic handling |
| comparisonError | No | Error message if comparison data could not be fetched (current period data still returned) |
| timeAggregation | No | Time aggregation level applied to the data (e.g., "total", "monthly", "daily") |
| priorPeriodRange | No | Date range for the prior period (present when compare_with is specified) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint annotation already signals safety, and the description adds meaningful behavioral details beyond that: comparison fields (prior, delta, deltaPercent), rate-limit error codes and retry timing, not-found handling, and instructions to inspect structuredContent.errorCode and .retryable. These enrich the agent's understanding of expected runtime behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections for comparison options and error handling. It front-loads the main purpose and uses bullets effectively. A small amount of redundancy with the schema exists, but the overall structure earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema, readOnly annotation, and high parameter coverage, the description is largely complete: it covers scope, aggregation, comparisons, and error handling. The main missing piece is explicit guidance on how this tool relates to sibling insights tools such as facebook_brandpage_insights.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds some semantic value by noting that omitting storeId returns all locations and by expanding on comparison behavior, but it largely restates what the schema already documents for aggregation and response_format.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific action and resource: 'Fetch Facebook metrics for all locations, or a single location if storeId provided.' This clearly defines the tool's scope. However, it doesn't explicitly differentiate this from the sibling get_facebook_brandpage_insights, so it falls short of full sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives context by explaining that all locations are fetched unless storeId is provided, which implies the primary use case. But it does not explicitly state when to choose this tool versus siblings like facebook_brandpage_insights, google_insights, or apple_insights, nor does it mention any exclusions or alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pinmeto_get_facebook_ratingsFacebook ratingsARead-only
Fetch Facebook ratings for all locations, or a single location if storeId provided.
Error Handling:
Rate limit (429): errorCode="RATE_LIMITED", message includes retry timing
Not found (404): errorCode="NOT_FOUND" if storeId doesn't exist
All errors: check structuredContent.errorCode and .retryable for programmatic handling
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | End date (YYYY-MM-DD) | |
| from | Yes | Start date (YYYY-MM-DD) | |
| storeId | No | Optional store ID to fetch a single location | |
| response_format | No | Response format: "json" (default, token-efficient) or "markdown" (human-readable with tables) | json |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | Ratings data: single location summary or array of location summaries (absent on error) |
| error | No | Error message if the request failed |
| warning | No | Warning message (e.g., incomplete data due to lag) |
| cacheInfo | No | Cache status information |
| errorCode | No | Error code for programmatic handling |
| retryable | No | Whether the operation can be retried |
| warningCode | No | Warning code for programmatic handling |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the readOnlyHint annotation by detailing specific error behavior: rate limit (429), not found (404), and programmatic handling via structuredContent.errorCode and .retryable. This gives an agent actionable expectations for unexpected responses.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The main behavior is stated in one frontloaded sentence, with error handling kept in tight bullet points. No redundant text or repetition of schema definitions.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the core call semantics, optional filtering, and error handling. The output_schema covers return values, and the schema covers parameters, so nothing critical is missing. Minor gap: no mention of pagination or date-range constraints, but these are not essential for a correct call.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds meaningful clarification for storeId ('all locations, or a single location if storeId provided'), which is not fully expressed in the schema alone. It does not need to repeat date/format details already in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Uses a specific verb ('Fetch') plus a clear resource ('Facebook ratings') and explicitly describes the two scopes: all locations or a single location when storeId is provided. This clearly distinguishes it from sibling tools like facebook_insights and google_ratings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a clear usage context: use it for Facebook ratings, with an optional storeId filter. However, it does not explicitly state when to prefer this tool over alternatives (e.g., insights or review tools) or when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pinmeto_get_google_insightsGoogle insightsARead-only
Fetch Google metrics for all locations, or a single location if storeId provided. Supports time aggregation (default: total) and period comparisons.
Comparison Options:
compare_with="prior_period": Compare with same-duration period before (MoM, QoQ)
compare_with="prior_year": Compare with same dates last year (YoY)
When comparison is active, each metric includes a comparison field with prior, delta, deltaPercent
Data Lag Warning:
Google data has ~10 day lag. Requests with recent end dates may return incomplete data.
Check structuredContent.warning and warningCode for data completeness.
Error Handling:
Rate limit (429): errorCode="RATE_LIMITED", message includes retry timing
Not found (404): errorCode="NOT_FOUND" if storeId doesn't exist
All errors: check structuredContent.errorCode and .retryable for programmatic handling
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | End date (YYYY-MM-DD) | |
| from | Yes | Start date (YYYY-MM-DD) | |
| storeId | No | Optional store ID to fetch a single location | |
| aggregation | No | Time aggregation: total (default, maximum token reduction), daily, weekly, monthly, quarterly, half-yearly, yearly | total |
| compare_with | No | Compare with: prior_period (MoM/QoQ for same-duration period before), prior_year (YoY for same dates last year), or none (default) | none |
| response_format | No | Response format: "json" (default, token-efficient) or "markdown" (human-readable with tables) | json |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Error message if the request failed |
| warning | No | Warning message (e.g., incomplete data due to lag) |
| insights | No | Array of insights by metric. Flattened (no values array) when aggregation=total, multi-period otherwise (absent on error) |
| errorCode | No | Error code for programmatic handling |
| retryable | No | Whether the operation can be retried |
| compareWith | No | Comparison period type used: "none", "prior_period", or "prior_year" |
| periodRange | No | Date range for the current period data |
| warningCode | No | Warning code for programmatic handling |
| comparisonError | No | Error message if comparison data could not be fetched (current period data still returned) |
| timeAggregation | No | Time aggregation level applied to the data (e.g., "total", "monthly", "daily") |
| priorPeriodRange | No | Date range for the prior period (present when compare_with is specified) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the readOnlyHint annotation by disclosing the ~10 day Google data lag, incomplete-data warnings, rate-limit error codes, not-found behavior, and retryable flags. This gives the agent actionable expectations about latency and error handling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The one-line purpose is followed by well-labeled sections for comparison options, data lag, and error handling. Every block serves a distinct operational need, and the structure makes the information easy to consume.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists and the description covers core behavior, data-lag caveats, and error handling, an agent has what it needs to invoke this tool correctly. The description is complete for a read-only metrics tool with six well-documented parameters.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema covers 100% of parameters, so the baseline is already strong. The description adds extra meaning beyond the schema by explaining what the comparison output looks like (prior, delta, deltaPercent) and by detailing storeId's single-location behavior. This is helpful but mostly reinforces and slightly extends schema content.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Fetch Google metrics for all locations, or a single location if storeId provided.' This clearly distinguishes the tool from siblings focused on ratings, reviews, keywords, or Facebook/Apple data. It also states the key scope and filtering behavior.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly explains when to use it: for Google metrics, with optional single-location filtering via storeId, and with optional comparison/aggregation settings. It does not explicitly name alternatives or tell the agent when not to use this tool, but the context is clear enough for selection among siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pinmeto_get_google_keywordsGoogle search keywordsARead-only
Fetch Google keywords for all locations, or a single location if storeId provided.
Data Lag Warning:
Google data has ~10 day lag. Current month data may be incomplete.
Check structuredContent.warning and warningCode for data completeness.
Error Handling:
Rate limit (429): errorCode="RATE_LIMITED", message includes retry timing
Not found (404): errorCode="NOT_FOUND" if storeId doesn't exist
All errors: check structuredContent.errorCode and .retryable for programmatic handling
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | End month (YYYY-MM) | |
| from | Yes | Start month (YYYY-MM) | |
| storeId | No | Optional store ID to fetch a single location | |
| response_format | No | Response format: "json" (default, token-efficient) or "markdown" (human-readable with tables) | json |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | Array of keywords with impression data (absent on error) |
| error | No | Error message if the request failed |
| errorCode | No | Error code for programmatic handling |
| retryable | No | Whether the operation can be retried |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description discloses important behavioral details: the ~10 day data lag, possible incomplete current-month data, structuredContent.warning/warningCode fields, rate-limit behavior with errorCode RATE_LIMITED, not-found behavior with NOT_FOUND, and the retryable flag. This gives an agent a strong understanding of edge cases and response characteristics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core operation, then uses compact bulleted sections for data lag and error handling. Every sentence adds useful information, and the structure makes the warnings and error details easy to scan. There is no filler or repetition of schema content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for a tool with an output schema and readOnly annotation. It covers data freshness, programmatic error handling, and the storeId filtering behavior. The output schema already handles return-value details, so the description does not need to repeat them. An agent has enough context to invoke the tool correctly and interpret failure/warning conditions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% description coverage, so the baseline is 3. The description does not add substantial parameter-level detail beyond the schema: it restates the storeId single-location behavior, which the schema already documents. There is no extra meaning about from/to or response_format, so no score above baseline is warranted.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Fetch Google keywords for all locations, or a single location if storeId provided.' This clearly distinguishes the tool from siblings like google_insights, google_ratings, and google_reviews, and also clarifies the scope difference between all locations and a single filtered location.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use the tool: it fetches keywords for all locations or a single location when storeId is supplied. It also includes a data lag warning that implies the tool is best for historical/complete data. It does not explicitly name sibling alternatives or state when not to use this tool, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pinmeto_get_google_ratingsGoogle ratingsARead-only
Fetch Google rating statistics (averageRating, totalReviews, distribution) for all locations, or a single location.
Returns aggregate statistics only. For individual review text and sentiment analysis, use pinmeto_get_google_reviews.
Caching:
Results cached for 5 minutes (shared with reviews tool)
Use forceRefresh=true to bypass cache
Check structuredContent.cacheInfo for cache status
Data Lag Warning:
Google data has ~10 day lag. Requests with recent end dates may return incomplete data.
Check structuredContent.warning and warningCode for data completeness.
Error Handling:
Rate limit (429): errorCode="RATE_LIMITED", message includes retry timing
Not found (404): errorCode="NOT_FOUND" if storeId doesn't exist
All errors: check structuredContent.errorCode and .retryable for programmatic handling
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | End date (YYYY-MM-DD) | |
| from | Yes | Start date (YYYY-MM-DD) | |
| storeId | No | Optional store ID to fetch a single location | |
| forceRefresh | No | Bypass cache and fetch fresh data | |
| response_format | No | Response format: "json" (default, token-efficient) or "markdown" (human-readable with tables) | json |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | Ratings data: single location summary or array of location summaries (absent on error) |
| error | No | Error message if the request failed |
| warning | No | Warning message (e.g., incomplete data due to lag) |
| cacheInfo | No | Cache status information |
| errorCode | No | Error code for programmatic handling |
| retryable | No | Whether the operation can be retried |
| warningCode | No | Warning code for programmatic handling |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint=true, so the description carries the burden of behavioral disclosure. It adds caching semantics (5-minute TTL, forceRefresh, cacheInfo), Google's ~10 day data lag with warning codes, and structured error handling (429, 404) with retryable flags. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is organized into clear labeled sections: primary purpose, alternative tool, caching, data lag, and error handling. Every section serves a distinct purpose for invocation, and the most important info (what it returns and its scope) is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists and annotations cover read-only safety, the description covers all essential operational context: what it returns, how to get fresh data, how to check cache status, known data lag caveats, and how to handle errors programmatically. The agent has everything needed to invoke and interpret results correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds meaning beyond the schema by linking storeId to 'single location', explaining forceRefresh's purpose, and referencing structuredContent fields like cacheInfo and warningCode that clarify parameter-related behavior. This elevates it above baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Fetch Google rating statistics' naming a specific verb, resource, and the key data fields (averageRating, totalReviews, distribution). It also explicitly scopes to all locations or a single location, distinguishing it from sibling tools like pinmeto_get_google_reviews.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit routing guidance: 'For individual review text and sentiment analysis, use pinmeto_get_google_reviews.' Caching and data lag warnings further clarify when this tool is appropriate and when results may be incomplete, giving the agent actionable context for selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pinmeto_get_google_review_insightsGoogle review analysisARead-only
Summarize Google reviews into rating and sentiment statistics.
Computes aggregates over the matched reviews server-side and returns the summary instead of the raw reviews, which is far more token-efficient than fetching them. The returned data is descriptive statistics, not LLM-written prose: read it and draw your own conclusions for the user.
Analysis Types:
summary: Average rating, sentiment breakdown, rating distribution
comparison: The above, plus per-location metrics ranked by rating
issues, trends, themes: Accepted, but currently return the same payload as summary. No theme extraction, issue clustering, or period comparison is performed, and the response is flagged with warningCode UNDIFFERENTIATED_ANALYSIS_TYPE. To analyze review text, fetch pinmeto_get_google_reviews and read it yourself.
Large Dataset Handling:
<200 reviews: Processed immediately
200-1000: Processed with token estimate in metadata
1000-10000: Returns warning with options (set skipConfirmation=true to proceed)
10000: Requires sampling strategy (representative or recent_weighted)
Sampling Strategies (which reviews get analyzed):
full: Analyze all reviews (default for <10000 reviews)
representative: Stratified sample by rating and location
recent_weighted: Prioritize recent reviews
Caching:
Results cached for 1 hour
Use forceRefresh=true to bypass cache
When NOT to use this tool:
Need raw review text: Use pinmeto_get_google_reviews
Need only aggregate stats: Use pinmeto_get_google_ratings
Need specific review lookup: Use pinmeto_get_google_reviews with filters
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | End date (YYYY-MM-DD) | |
| from | Yes | Start date (YYYY-MM-DD) | |
| themes | No | Currently ignored - no theme extraction is performed | |
| storeIds | No | Optional store IDs to analyze (omit for all locations) | |
| maxRating | No | Maximum rating filter (1-5) | |
| minRating | No | Minimum rating filter (1-5) | |
| analysisType | Yes | Type of analysis: summary, issues, comparison, trends, or themes | |
| forceRefresh | No | Bypass cache and regenerate analysis | |
| response_format | No | Response format: "json" (default, token-efficient) or "markdown" (human-readable with tables) | json |
| samplingStrategy | No | Sampling strategy: full (default), representative, or recent_weighted | full |
| skipConfirmation | No | Skip large dataset confirmation (set true after receiving warning) |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | Analysis results (null or absent on error, warning, or no matching reviews) |
| error | No | Error message if the request failed |
| warning | No | Warning message |
| metadata | No | Analysis metadata |
| errorCode | No | Error code for programmatic handling |
| retryable | No | Whether the operation can be retried |
| warningCode | No | Warning code for programmatic handling |
| analysisNote | No | Note about the analysis itself, present when there is no metadata to carry it |
| largeDatasetWarning | No | Large dataset details and options (when requiresConfirmation is true) |
| requiresConfirmation | No | True if user must confirm before proceeding with large dataset |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even though readOnlyHint=true already signals a safe read, the description adds substantial behavioral context: analysis types 'issues', 'trends', and 'themes' currently return the same payload as 'summary' with a warningCode, results are cached for 1 hour, forceRefresh bypasses the cache, and large datasets trigger warnings or require sampling. It also clarifies that output is descriptive statistics, not LLM-generated prose.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear sections: summary, analysis types, large dataset handling, sampling strategies, caching, and exclusions. Each section earns its place by conveying decision-relevant behavior, and the main purpose is front-loaded in the first sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 11 parameters, 3 enums, and no nested objects, the description covers all decision-critical context: return behavior, analysis limitations, caching, dataset thresholds, sampling strategies, and alternatives. With the output schema also present, nothing an agent needs to call this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already describes all 11 parameters fully, so the baseline is solid. The description goes further by explaining what each analysisType actually returns, including the undifferentiated fallback behavior, what each sampling strategy does, and when skipConfirmation is meaningful. This adds real value beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence clearly states the verb, resource, and output: 'Summarize Google reviews into rating and sentiment statistics.' It explicitly contrasts itself with raw review retrieval and aggregate ratings, and later names the sibling tools it is not, making purpose and differentiation unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description includes an explicit 'When NOT to use this tool' section listing the exact sibling tools for raw text, aggregate stats, and specific review lookup. It also provides decision guidance for large datasets and sampling strategies, so an agent knows precisely when and how to invoke this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pinmeto_get_google_reviewsGoogle reviewsARead-only
Fetch individual Google reviews with pagination and filtering for sentiment analysis.
For aggregate statistics (averageRating, totalReviews), use pinmeto_get_google_ratings instead.
Pagination:
limit: Max reviews to return (default: 50, max: 500)
offset: Skip first N reviews (for pagination)
Check hasMore in response to know if more pages exist
Filtering:
minRating/maxRating: Filter by rating range (1-5)
hasResponse: true for responded reviews, false for unresponded
Caching:
Results cached for 5 minutes (shared with ratings tool)
Use forceRefresh=true to bypass cache
Filters are applied client-side on cached data
Data Lag Warning:
Google data has ~10 day lag. Requests with recent end dates may return incomplete data.
Error Handling:
Rate limit (429): errorCode="RATE_LIMITED", message includes retry timing
Not found (404): errorCode="NOT_FOUND" if storeId doesn't exist
All errors: check structuredContent.errorCode and .retryable for programmatic handling
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | End date (YYYY-MM-DD) | |
| from | Yes | Start date (YYYY-MM-DD) | |
| limit | No | Max reviews to return (default: 50, max: 500) | |
| offset | No | Skip first N reviews for pagination | |
| storeId | No | Optional store ID to fetch a single location | |
| maxRating | No | Maximum rating filter (1-5) | |
| minRating | No | Minimum rating filter (1-5) | |
| hasResponse | No | Filter: true for responded reviews, false for unresponded | |
| forceRefresh | No | Bypass cache and fetch fresh data | |
| response_format | No | Response format: "json" (default, token-efficient) or "markdown" (human-readable with tables) | json |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | Array of reviews (absent on error) |
| error | No | Error message if the request failed |
| limit | No | Requested limit |
| offset | No | Current offset position |
| hasMore | No | Whether more results exist beyond offset+limit |
| warning | No | Warning message (e.g., incomplete data due to lag) |
| cacheInfo | No | Cache status information |
| errorCode | No | Error code for programmatic handling |
| retryable | No | Whether the operation can be retried |
| totalCount | No | Total reviews matching filters |
| warningCode | No | Warning code for programmatic handling |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description discloses important behavioral traits: 5-minute caching, client-side filter application, forceRefresh bypass, a ~10 day Google data lag, and structured error codes (RATE_LIMITED, NOT_FOUND) with retryability. This is substantial value beyond the annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear section headings. Each section serves a purpose: purpose distinction, pagination, filtering, caching, data lag, and error handling. Some redundancy exists with schema parameter descriptions, but the organization makes it easy for an agent to scan and extract key semantics.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers all operational aspects an agent needs: pagination with hasMore, filtering, caching with refresh, data lag caveats, error handling format, and a clear sibling alternative. With an output schema present, no explanation of return fields is needed. The description is complete for correct invocation and result interpretation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema descriptions already cover all 10 parameters (100% coverage). The description enhances this by explaining pagination semantics (hasMore), the client-side filtering behavior on cached data, and forceRefresh's effect, which goes beyond the schema. Not a 5 because much of the parameter info is redundant with the schema, but it does add meaningful usage context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Fetch individual Google reviews') with a clear resource and purpose ('for sentiment analysis'). It explicitly differentiates from the sibling pinmeto_get_google_ratings by contrasting individual reviews with aggregate statistics.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells the agent when to use this tool vs. an alternative: 'For aggregate statistics (averageRating, totalReviews), use pinmeto_get_google_ratings instead.' It also provides concrete pagination/filtering usage in separate sections, leaving little to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pinmeto_get_locationGet locationARead-only
Get details for a SINGLE location by store ID. Returns structured location data including address, contact info, and network connections.
Error Handling:
Not found (404): errorCode="NOT_FOUND" if store ID doesn't exist
Auth failure (401): errorCode="AUTH_INVALID_CREDENTIALS"
All errors: check structuredContent.errorCode and .retryable for programmatic handling
| Name | Required | Description | Default |
|---|---|---|---|
| storeId | Yes | The store ID to look up | |
| response_format | No | Response format: "json" (default, token-efficient) or "markdown" (human-readable with tables) | json |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | Location data from the PinMeTo API (absent on error) |
| error | No | Error message if the request failed |
| errorCode | No | Error code for programmatic handling |
| retryable | No | Whether the operation can be retried |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint=true. The description adds a concrete error contract: 404 NOT_FOUND for unknown store ID, 401 AUTH_INVALID_CREDENTIALS for auth failures, and structuredContent.errorCode/.retryable for all errors. It also states the kind of returned data, adding behavioral context beyond structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Opening sentence states purpose with the key constraint; the error-handling section is compact, scannable, and adds real value. There is no filler or redundant restating of schema content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter read-only lookup with an output schema and annotations, the description covers purpose, uniqueness, return content, and error behavior. Nothing necessary for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema covers 100% of parameters, documenting storeId and response_format with enums and defaults. The description adds no syntax or format detail beyond that, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description opens with 'Get details for a SINGLE location by store ID', naming the verb, resource, and uniqueness constraint. This clearly distinguishes it from siblings like pinmeto_get_locations and pinmeto_search_locations without requiring schema inspection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'SINGLE location by store ID' conveys when to use this tool: when a single known store identifier is available. It does not explicitly name sibling alternatives or exclusion conditions, so it falls just short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pinmeto_get_locationsGet all locationsARead-only
Get ALL locations with pagination and filtering. Uses in-memory cache (5-min TTL) for fast queries on large datasets.
Examples:
Get first 50 locations: {}
Get next page: { offset: 50 }
Filter by city: { city: "Stockholm", limit: 20 }
Only open locations: { permanentlyClosed: false }
Force cache refresh: { forceRefresh: true }
Error Handling:
Partial results may be returned on API errors (check incomplete field)
Stale cache data returned with warning if fresh fetch fails
Check errorCode (string) and retryable (boolean) in structuredContent
| Name | Required | Description | Default |
|---|---|---|---|
| city | No | Filter by city name (case-insensitive) | |
| type | No | Filter by location type | |
| limit | No | Maximum results to return (default: 50, max: 1000) | |
| fields | No | Fields to include in the response (optional, defaults to all) | |
| offset | No | Number of results to skip (default: 0) | |
| country | No | Filter by country name (case-insensitive) | |
| forceRefresh | No | Force cache refresh (bypasses 5-minute TTL) | |
| response_format | No | Response format: "json" (default, token-efficient) or "markdown" (human-readable with tables) | json |
| permanentlyClosed | No | Filter by permanently closed status |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | Array of location objects (absent on error) |
| error | No | Error message if the request failed |
| limit | No | Requested limit |
| offset | No | Current offset position |
| hasMore | No | Whether more results exist beyond offset+limit |
| warning | No | Warning message if data may be incomplete |
| cacheInfo | No | Cache status information |
| errorCode | No | Error code for programmatic handling |
| retryable | No | Whether the operation can be retried |
| incomplete | No | Whether data may be incomplete due to pagination errors |
| totalCount | No | Total locations matching filters |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description discloses cache behavior (5-min TTL, forceRefresh), degraded response modes (partial results, stale cache with warning), and error-reporting fields (errorCode, retryable, incomplete). This gives an agent a clear picture of side effects and failure behavior for a read-only tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose, then organized into compact example bullets and a separate error-handling block. Every section contributes useful information without redundant prose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a low-risk read-only tool with no required parameters and an output schema, the description covers pagination, filtering, cache semantics, partial failures, and error fields. An agent has enough to invoke it correctly and interpret abnormal responses.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds concrete example arguments for offset, limit, city, permanentlyClosed, and forceRefresh, which helps an agent understand common calling patterns beyond the schema's individual field descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb and resource: get ALL locations, with pagination and filtering. This makes the tool's purpose obvious, but it does not explicitly distinguish itself from the sibling pinmeto_search_locations tool, so it stops short of full sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The first sentence implies when to use it: for fetching ALL locations with pagination/filtering, and the examples reinforce pagination and filter patterns. However, it never mentions alternatives such as pinmeto_get_location for a single location or pinmeto_search_locations for search, so when-not-to-use guidance is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pinmeto_search_locationsSearch locationsARead-only
Search ALL locations by name, address, store ID, or location descriptor. Returns lightweight results for quick discovery. Use pinmeto_get_location with storeId for full details.
Error Handling:
Network issues: errorCode="NETWORK_ERROR", retryable=true
Auth failure (401): errorCode="AUTH_INVALID_CREDENTIALS"
All errors: check structuredContent.errorCode and .retryable for programmatic handling
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum results to return (default: 20, max: 100) | |
| query | Yes | Search query - matches against name, storeId, locationDescriptor, street, city, or country | |
| response_format | No | Response format: "json" (default, token-efficient) or "markdown" (human-readable with tables) | json |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | Matching locations with minimal data for discovery (absent on error) |
| error | No | Error message if the request failed |
| hasMore | No | Whether more results exist beyond the limit |
| errorCode | No | Error code for programmatic handling |
| retryable | No | Whether the operation can be retried |
| totalMatches | No | Total number of locations matching the query |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint=true. The description adds meaningful behavior: results are lightweight, errors use structuredContent.errorCode and .retryable, and specific error codes for network and auth failures are provided. This goes beyond what the annotations convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the core purpose, then quickly gives the alternative for full details and structured error handling. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a search tool with readOnlyHint, full schema coverage, and an output schema, the description covers purpose, result nature, alternative use, and error handling. Nothing essential is missing for correct invocation and response interpretation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents query, limit, and response_format in detail. The description restates the search fields but does not add new parameter semantics beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Search') and resource ('ALL locations'), with clear searchable fields: name, address, store ID, and location descriptor. It further distinguishes itself by noting lightweight results and directing to pinmeto_get_location for full details.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells the agent to use pinmeto_get_location with storeId when full details are needed, providing a clear alternative. It does not explicitly discuss when to use pinmeto_get_locations, but the search-versus-retrieve distinction is reasonably clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
12 tool updates
v4.3.0- Changed
pinmeto_get_apple_insights11 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - removed
Input schema / properties / to / $refRemoved value: -"#/properties/from" - added
Input schema / properties / to / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - added
Input schema / properties / to / typeAdded value: +"string" - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Output schema / properties / priorPeriodRange / $refRemoved value: -"#/properties/periodRange" - added
Output schema / properties / priorPeriodRange / additionalPropertiesAdded value: +false - added
Output schema / properties / priorPeriodRange / propertiesAdded value: +{ + "from": { + "description": "Start date (YYYY-MM-DD)", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + }, + "to": { + "description": "End date (YYYY-MM-DD)", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + } +} - added
Output schema / properties / priorPeriodRange / requiredAdded value: +[ + "from", + "to" +] - added
Output schema / properties / priorPeriodRange / typeAdded value: +"object"
- Changed
pinmeto_get_facebook_brandpage_insights11 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - removed
Input schema / properties / to / $refRemoved value: -"#/properties/from" - added
Input schema / properties / to / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - added
Input schema / properties / to / typeAdded value: +"string" - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Output schema / properties / priorPeriodRange / $refRemoved value: -"#/properties/periodRange" - added
Output schema / properties / priorPeriodRange / additionalPropertiesAdded value: +false - added
Output schema / properties / priorPeriodRange / propertiesAdded value: +{ + "from": { + "description": "Start date (YYYY-MM-DD)", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + }, + "to": { + "description": "End date (YYYY-MM-DD)", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + } +} - added
Output schema / properties / priorPeriodRange / requiredAdded value: +[ + "from", + "to" +] - added
Output schema / properties / priorPeriodRange / typeAdded value: +"object"
- Changed
pinmeto_get_facebook_insights11 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - removed
Input schema / properties / to / $refRemoved value: -"#/properties/from" - added
Input schema / properties / to / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - added
Input schema / properties / to / typeAdded value: +"string" - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Output schema / properties / priorPeriodRange / $refRemoved value: -"#/properties/periodRange" - added
Output schema / properties / priorPeriodRange / additionalPropertiesAdded value: +false - added
Output schema / properties / priorPeriodRange / propertiesAdded value: +{ + "from": { + "description": "Start date (YYYY-MM-DD)", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + }, + "to": { + "description": "End date (YYYY-MM-DD)", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + } +} - added
Output schema / properties / priorPeriodRange / requiredAdded value: +[ + "from", + "to" +] - added
Output schema / properties / priorPeriodRange / typeAdded value: +"object"
- Changed
pinmeto_get_facebook_ratings7 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - removed
Input schema / properties / to / $refRemoved value: -"#/properties/from" - added
Input schema / properties / to / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - added
Input schema / properties / to / typeAdded value: +"string" - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / properties / data / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": { - "averageRating": { - "description": "Average rating (1-5); 0 when the location has no reviews in range", - "maximum": 5, - "minimum": 0, - "type": "number" - }, - "distribution": { - "additionalProperties": { - "minimum": 0, - "type": "number" - }, - "description": "Rating distribution (e.g., {\"5\": 100, \"4\": 50})", - "type": "object" - }, - "totalReviews": { - "description": "Total number of reviews", - "minimum": 0, - "type": "number" - } - }, - "type": "object" - }, - { - "items": { - "additionalProperties": true, - "properties": { - "averageRating": { - "$ref": "#/properties/data/anyOf/0/properties/averageRating" - }, - "distribution": { - "$ref": "#/properties/data/anyOf/0/properties/distribution" - }, - "storeId": { - "description": "Store identifier", - "type": "string" - }, - "totalReviews": { - "$ref": "#/properties/data/anyOf/0/properties/totalReviews" - } - }, - "required": [ - "storeId" - ], - "type": "object" - }, - "type": "array" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "averageRating": { + "description": "Average rating (1-5); 0 when the location has no reviews in range", + "maximum": 5, + "minimum": 0, + "type": "number" + }, + "distribution": { + "additionalProperties": { + "minimum": 0, + "type": "number" + }, + "description": "Rating distribution (e.g., {\"5\": 100, \"4\": 50})", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "totalReviews": { + "description": "Total number of reviews", + "minimum": 0, + "type": "number" + } + }, + "type": "object" + }, + { + "items": { + "additionalProperties": {}, + "properties": { + "averageRating": { + "description": "Average rating (1-5); 0 when the location has no reviews in range", + "maximum": 5, + "minimum": 0, + "type": "number" + }, + "distribution": { + "additionalProperties": { + "minimum": 0, + "type": "number" + }, + "description": "Rating distribution (e.g., {\"5\": 100, \"4\": 50})", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "storeId": { + "description": "Store identifier", + "type": "string" + }, + "totalReviews": { + "description": "Total number of reviews", + "minimum": 0, + "type": "number" + } + }, + "required": [ + "storeId" + ], + "type": "object" + }, + "type": "array" + } +]
- Changed
pinmeto_get_google_insights11 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - removed
Input schema / properties / to / $refRemoved value: -"#/properties/from" - added
Input schema / properties / to / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - added
Input schema / properties / to / typeAdded value: +"string" - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Output schema / properties / priorPeriodRange / $refRemoved value: -"#/properties/periodRange" - added
Output schema / properties / priorPeriodRange / additionalPropertiesAdded value: +false - added
Output schema / properties / priorPeriodRange / propertiesAdded value: +{ + "from": { + "description": "Start date (YYYY-MM-DD)", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + }, + "to": { + "description": "End date (YYYY-MM-DD)", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + } +} - added
Output schema / properties / priorPeriodRange / requiredAdded value: +[ + "from", + "to" +] - added
Output schema / properties / priorPeriodRange / typeAdded value: +"object"
- Changed
pinmeto_get_google_keywords4 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / properties / data / items / additionalPropertiesPrevious value: -trueNew value: +{}
- Changed
pinmeto_get_google_ratings7 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - removed
Input schema / properties / to / $refRemoved value: -"#/properties/from" - added
Input schema / properties / to / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - added
Input schema / properties / to / typeAdded value: +"string" - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / properties / data / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": { - "averageRating": { - "description": "Average rating (1-5); 0 when the location has no reviews in range", - "maximum": 5, - "minimum": 0, - "type": "number" - }, - "distribution": { - "additionalProperties": { - "minimum": 0, - "type": "number" - }, - "description": "Rating distribution (e.g., {\"5\": 100, \"4\": 50})", - "type": "object" - }, - "totalReviews": { - "description": "Total number of reviews", - "minimum": 0, - "type": "number" - } - }, - "type": "object" - }, - { - "items": { - "additionalProperties": true, - "properties": { - "averageRating": { - "$ref": "#/properties/data/anyOf/0/properties/averageRating" - }, - "distribution": { - "$ref": "#/properties/data/anyOf/0/properties/distribution" - }, - "storeId": { - "description": "Store identifier", - "type": "string" - }, - "totalReviews": { - "$ref": "#/properties/data/anyOf/0/properties/totalReviews" - } - }, - "required": [ - "storeId" - ], - "type": "object" - }, - "type": "array" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "averageRating": { + "description": "Average rating (1-5); 0 when the location has no reviews in range", + "maximum": 5, + "minimum": 0, + "type": "number" + }, + "distribution": { + "additionalProperties": { + "minimum": 0, + "type": "number" + }, + "description": "Rating distribution (e.g., {\"5\": 100, \"4\": 50})", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "totalReviews": { + "description": "Total number of reviews", + "minimum": 0, + "type": "number" + } + }, + "type": "object" + }, + { + "items": { + "additionalProperties": {}, + "properties": { + "averageRating": { + "description": "Average rating (1-5); 0 when the location has no reviews in range", + "maximum": 5, + "minimum": 0, + "type": "number" + }, + "distribution": { + "additionalProperties": { + "minimum": 0, + "type": "number" + }, + "description": "Rating distribution (e.g., {\"5\": 100, \"4\": 50})", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "storeId": { + "description": "Store identifier", + "type": "string" + }, + "totalReviews": { + "description": "Total number of reviews", + "minimum": 0, + "type": "number" + } + }, + "required": [ + "storeId" + ], + "type": "object" + }, + "type": "array" + } +]
- Changed
pinmeto_get_google_review_insights21 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - removed
Input schema / properties / to / $refRemoved value: -"#/properties/from" - added
Input schema / properties / to / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - added
Input schema / properties / to / typeAdded value: +"string" - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / properties / data / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "bestPerformer": { - "additionalProperties": false, - "description": "Best performing location (for comparison analysis)", - "properties": { - "bestPractices": { - "description": "Practices other locations should adopt", - "items": { - "type": "string" - }, - "type": "array" - }, - "reason": { - "description": "Why this location performs best", - "type": "string" - }, - "storeId": { - "description": "Store identifier of the best performing location", - "minLength": 1, - "type": "string" - } - }, - "required": [ - "storeId", - "reason", - "bestPractices" - ], - "type": "object" - }, - "commonStrengths": { - "description": "Strengths shared across locations (for comparison analysis)", - "items": { - "type": "string" - }, - "type": "array" - }, - "commonWeaknesses": { - "description": "Weaknesses shared across locations (for comparison analysis)", - "items": { - "type": "string" - }, - "type": "array" - }, - "issues": { - "description": "Issues identified (for issues analysis)", - "items": { - "additionalProperties": false, - "properties": { - "affectedLocations": { - "description": "Store IDs of affected locations", - "items": { - "type": "string" - }, - "type": "array" - }, - "category": { - "description": "Issue category (e.g., \"Wait Times\", \"Cleanliness\", \"Staff\")", - "minLength": 1, - "type": "string" - }, - "description": { - "description": "Description of the issue", - "minLength": 1, - "type": "string" - }, - "exampleQuotes": { - "description": "Representative quotes illustrating this issue", - "items": { - "type": "string" - }, - "type": "array" - }, - "frequency": { - "description": "How often this issue appears", - "minimum": 0, - "type": "integer" - }, - "severity": { - "description": "Severity level of the issue", - "enum": [ - "low", - "medium", - "high", - "critical" - ], - "type": "string" - }, - "suggestedAction": { - "description": "Recommended action to address the issue", - "type": "string" - } - }, - "required": [ - "category", - "description", - "severity", - "frequency" - ], - "type": "object" - }, - "type": "array" - }, - "locationComparison": { - "description": "Location comparison (for comparison analysis)", - "items": { - "additionalProperties": false, - "properties": { - "averageRating": { - "description": "Average rating for this location (1-5)", - "maximum": 5, - "minimum": 1, - "type": "number" - }, - "locationName": { - "description": "Location name", - "type": "string" - }, - "lowConfidence": { - "description": "True when location has few reviews (<10)", - "type": "boolean" - }, - "recommendations": { - "description": "Specific actions to improve this location", - "items": { - "type": "string" - }, - "type": "array" - }, - "reviewCount": { - "description": "Number of reviews analyzed", - "minimum": 0, - "type": "integer" - }, - "sentiment": { - "description": "Overall sentiment for this location", - "enum": [ - "positive", - "neutral", - "negative", - "mixed" - ], - "type": "string" - }, - "storeId": { - "description": "Store identifier", - "minLength": 1, - "type": "string" - }, - "strengths": { - "description": "Key strengths identified", - "items": { - "type": "string" - }, - "type": "array" - }, - "weaknesses": { - "description": "Key weaknesses identified", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "storeId", - "averageRating", - "reviewCount", - "sentiment", - "strengths", - "weaknesses" - ], - "type": "object" - }, - "type": "array" - }, - "summary": { - "additionalProperties": false, - "description": "Executive summary (for summary analysis)", - "properties": { - "averageRating": { - "description": "Average rating across analyzed reviews (1-5)", - "maximum": 5, - "minimum": 1, - "type": "number" - }, - "executiveSummary": { - "description": "2-3 sentence summary of findings", - "minLength": 1, - "type": "string" - }, - "lowConfidence": { - "description": "True when sample size is small (<20 reviews)", - "type": "boolean" - }, - "overallSentiment": { - "description": "Overall sentiment classification", - "enum": [ - "positive", - "neutral", - "negative", - "mixed" - ], - "type": "string" - }, - "ratingDistribution": { - "additionalProperties": { - "minimum": 0, - "type": "integer" - }, - "description": "Rating distribution (e.g., {\"5\": 100, \"4\": 50})", - "type": "object" - }, - "sentimentDistribution": { - "additionalProperties": false, - "description": "Sentiment breakdown by percentage", - "properties": { - "negative": { - "description": "Percentage of negative reviews (0-100)", - "maximum": 100, - "minimum": 0, - "type": "number" - }, - "neutral": { - "description": "Percentage of neutral reviews (0-100)", - "maximum": 100, - "minimum": 0, - "type": "number" - }, - "positive": { - "description": "Percentage of positive reviews (0-100)", - "maximum": 100, - "minimum": 0, - "type": "number" - } - }, - "required": [ - "positive", - "neutral", - "negative" - ], - "type": "object" - } - }, - "required": [ - "executiveSummary", - "overallSentiment", - "averageRating", - "sentimentDistribution", - "ratingDistribution" - ], - "type": "object" - }, - "themes": { - "additionalProperties": false, - "description": "Theme analysis (for summary/themes analysis)", - "properties": { - "negative": { - "description": "Negative themes/areas for improvement", - "items": { - "$ref": "#/properties/data/anyOf/0/properties/themes/properties/positive/items" - }, - "type": "array" - }, - "positive": { - "description": "Positive themes identified", - "items": { - "additionalProperties": false, - "properties": { - "exampleQuote": { - "description": "Representative quote illustrating this theme", - "type": "string" - }, - "frequency": { - "description": "How often this theme appears in reviews", - "minimum": 0, - "type": "integer" - }, - "severity": { - "description": "Severity level (for negative themes only)", - "enum": [ - "low", - "medium", - "high", - "critical" - ], - "type": "string" - }, - "theme": { - "description": "Theme or topic identified (e.g., \"Service Speed\", \"Staff Friendliness\")", - "minLength": 1, - "type": "string" - } - }, - "required": [ - "theme", - "frequency" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "positive", - "negative" - ], - "type": "object" - }, - "trends": { - "additionalProperties": false, - "description": "Trends analysis (for trends analysis)", - "properties": { - "currentPeriod": { - "additionalProperties": false, - "description": "Current period summary", - "properties": { - "averageRating": { - "description": "Average rating in current period (1-5)", - "maximum": 5, - "minimum": 1, - "type": "number" - }, - "reviewCount": { - "description": "Number of reviews in current period", - "minimum": 0, - "type": "integer" - }, - "sentiment": { - "description": "Overall sentiment in current period", - "enum": [ - "positive", - "neutral", - "negative", - "mixed" - ], - "type": "string" - } - }, - "required": [ - "averageRating", - "sentiment", - "reviewCount" - ], - "type": "object" - }, - "direction": { - "description": "Overall trend direction (based on Β±0.2 rating threshold)", - "enum": [ - "improving", - "stable", - "declining" - ], - "type": "string" - }, - "emergingIssues": { - "description": "New issues that emerged", - "items": { - "type": "string" - }, - "type": "array" - }, - "previousPeriod": { - "additionalProperties": false, - "description": "Prior period summary", - "properties": { - "averageRating": { - "description": "Average rating in prior period (1-5)", - "maximum": 5, - "minimum": 1, - "type": "number" - }, - "reviewCount": { - "description": "Number of reviews in prior period", - "minimum": 0, - "type": "integer" - }, - "sentiment": { - "description": "Overall sentiment in prior period", - "enum": [ - "positive", - "neutral", - "negative", - "mixed" - ], - "type": "string" - } - }, - "required": [ - "averageRating", - "sentiment", - "reviewCount" - ], - "type": "object" - }, - "prominenceChanges": { - "description": "Themes gaining or losing prominence", - "items": { - "additionalProperties": false, - "properties": { - "note": { - "description": "Brief explanation of the change", - "type": "string" - }, - "theme": { - "description": "Theme name", - "minLength": 1, - "type": "string" - }, - "trend": { - "description": "Direction of change", - "enum": [ - "increasing", - "stable", - "decreasing" - ], - "type": "string" - } - }, - "required": [ - "theme", - "trend" - ], - "type": "object" - }, - "type": "array" - }, - "ratingChange": { - "description": "Rating change between periods (current - previous)", - "type": "number" - }, - "resolvedIssues": { - "description": "Issues that were resolved", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "direction", - "previousPeriod", - "currentPeriod", - "emergingIssues", - "resolvedIssues" - ], - "type": "object" - } - }, - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "bestPerformer": { + "additionalProperties": false, + "description": "Best performing location (for comparison analysis)", + "properties": { + "bestPractices": { + "description": "Practices other locations should adopt", + "items": { + "type": "string" + }, + "type": "array" + }, + "reason": { + "description": "Why this location performs best", + "type": "string" + }, + "storeId": { + "description": "Store identifier of the best performing location", + "minLength": 1, + "type": "string" + } + }, + "required": [ + "storeId", + "reason", + "bestPractices" + ], + "type": "object" + }, + "commonStrengths": { + "description": "Strengths shared across locations (for comparison analysis)", + "items": { + "type": "string" + }, + "type": "array" + }, + "commonWeaknesses": { + "description": "Weaknesses shared across locations (for comparison analysis)", + "items": { + "type": "string" + }, + "type": "array" + }, + "issues": { + "description": "Issues identified (for issues analysis)", + "items": { + "additionalProperties": false, + "properties": { + "affectedLocations": { + "description": "Store IDs of affected locations", + "items": { + "type": "string" + }, + "type": "array" + }, + "category": { + "description": "Issue category (e.g., \"Wait Times\", \"Cleanliness\", \"Staff\")", + "minLength": 1, + "type": "string" + }, + "description": { + "description": "Description of the issue", + "minLength": 1, + "type": "string" + }, + "exampleQuotes": { + "description": "Representative quotes illustrating this issue", + "items": { + "type": "string" + }, + "type": "array" + }, + "frequency": { + "description": "How often this issue appears", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "severity": { + "description": "Severity level of the issue", + "enum": [ + "low", + "medium", + "high", + "critical" + ], + "type": "string" + }, + "suggestedAction": { + "description": "Recommended action to address the issue", + "type": "string" + } + }, + "required": [ + "category", + "description", + "severity", + "frequency" + ], + "type": "object" + }, + "type": "array" + }, + "locationComparison": { + "description": "Location comparison (for comparison analysis)", + "items": { + "additionalProperties": false, + "properties": { + "averageRating": { + "description": "Average rating for this location (1-5)", + "maximum": 5, + "minimum": 1, + "type": "number" + }, + "locationName": { + "description": "Location name", + "type": "string" + }, + "lowConfidence": { + "description": "True when location has few reviews (<10)", + "type": "boolean" + }, + "recommendations": { + "description": "Specific actions to improve this location", + "items": { + "type": "string" + }, + "type": "array" + }, + "reviewCount": { + "description": "Number of reviews analyzed", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "sentiment": { + "description": "Overall sentiment for this location", + "enum": [ + "positive", + "neutral", + "negative", + "mixed" + ], + "type": "string" + }, + "storeId": { + "description": "Store identifier", + "minLength": 1, + "type": "string" + }, + "strengths": { + "description": "Key strengths identified", + "items": { + "type": "string" + }, + "type": "array" + }, + "weaknesses": { + "description": "Key weaknesses identified", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "storeId", + "averageRating", + "reviewCount", + "sentiment", + "strengths", + "weaknesses" + ], + "type": "object" + }, + "type": "array" + }, + "summary": { + "additionalProperties": false, + "description": "Executive summary (for summary analysis)", + "properties": { + "averageRating": { + "description": "Average rating across analyzed reviews (1-5)", + "maximum": 5, + "minimum": 1, + "type": "number" + }, + "executiveSummary": { + "description": "2-3 sentence summary of findings", + "minLength": 1, + "type": "string" + }, + "lowConfidence": { + "description": "True when sample size is small (<20 reviews)", + "type": "boolean" + }, + "overallSentiment": { + "description": "Overall sentiment classification", + "enum": [ + "positive", + "neutral", + "negative", + "mixed" + ], + "type": "string" + }, + "ratingDistribution": { + "additionalProperties": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "description": "Rating distribution (e.g., {\"5\": 100, \"4\": 50})", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "sentimentDistribution": { + "additionalProperties": false, + "description": "Sentiment breakdown by percentage", + "properties": { + "negative": { + "description": "Percentage of negative reviews (0-100)", + "maximum": 100, + "minimum": 0, + "type": "number" + }, + "neutral": { + "description": "Percentage of neutral reviews (0-100)", + "maximum": 100, + "minimum": 0, + "type": "number" + }, + "positive": { + "description": "Percentage of positive reviews (0-100)", + "maximum": 100, + "minimum": 0, + "type": "number" + } + }, + "required": [ + "positive", + "neutral", + "negative" + ], + "type": "object" + } + }, + "required": [ + "executiveSummary", + "overallSentiment", + "averageRating", + "sentimentDistribution", + "ratingDistribution" + ], + "type": "object" + }, + "themes": { + "additionalProperties": false, + "description": "Theme analysis (for summary/themes analysis)", + "properties": { + "negative": { + "description": "Negative themes/areas for improvement", + "items": { + "additionalProperties": false, + "properties": { + "exampleQuote": { + "description": "Representative quote illustrating this theme", + "type": "string" + }, + "frequency": { + "description": "How often this theme appears in reviews", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "severity": { + "description": "Severity level (for negative themes only)", + "enum": [ + "low", + "medium", + "high", + "critical" + ], + "type": "string" + }, + "theme": { + "description": "Theme or topic identified (e.g., \"Service Speed\", \"Staff Friendliness\")", + "minLength": 1, + "type": "string" + } + }, + "required": [ + "theme", + "frequency" + ], + "type": "object" + }, + "type": "array" + }, + "positive": { + "description": "Positive themes identified", + "items": { + "additionalProperties": false, + "properties": { + "exampleQuote": { + "description": "Representative quote illustrating this theme", + "type": "string" + }, + "frequency": { + "description": "How often this theme appears in reviews", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "severity": { + "description": "Severity level (for negative themes only)", + "enum": [ + "low", + "medium", + "high", + "critical" + ], + "type": "string" + }, + "theme": { + "description": "Theme or topic identified (e.g., \"Service Speed\", \"Staff Friendliness\")", + "minLength": 1, + "type": "string" + } + }, + "required": [ + "theme", + "frequency" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "positive", + "negative" + ], + "type": "object" + }, + "trends": { + "additionalProperties": false, + "description": "Trends analysis (for trends analysis)", + "properties": { + "currentPeriod": { + "additionalProperties": false, + "description": "Current period summary", + "properties": { + "averageRating": { + "description": "Average rating in current period (1-5)", + "maximum": 5, + "minimum": 1, + "type": "number" + }, + "reviewCount": { + "description": "Number of reviews in current period", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "sentiment": { + "description": "Overall sentiment in current period", + "enum": [ + "positive", + "neutral", + "negative", + "mixed" + ], + "type": "string" + } + }, + "required": [ + "averageRating", + "sentiment", + "reviewCount" + ], + "type": "object" + }, + "direction": { + "description": "Overall trend direction (based on Β±0.2 rating threshold)", + "enum": [ + "improving", + "stable", + "declining" + ], + "type": "string" + }, + "emergingIssues": { + "description": "New issues that emerged", + "items": { + "type": "string" + }, + "type": "array" + }, + "previousPeriod": { + "additionalProperties": false, + "description": "Prior period summary", + "properties": { + "averageRating": { + "description": "Average rating in prior period (1-5)", + "maximum": 5, + "minimum": 1, + "type": "number" + }, + "reviewCount": { + "description": "Number of reviews in prior period", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "sentiment": { + "description": "Overall sentiment in prior period", + "enum": [ + "positive", + "neutral", + "negative", + "mixed" + ], + "type": "string" + } + }, + "required": [ + "averageRating", + "sentiment", + "reviewCount" + ], + "type": "object" + }, + "prominenceChanges": { + "description": "Themes gaining or losing prominence", + "items": { + "additionalProperties": false, + "properties": { + "note": { + "description": "Brief explanation of the change", + "type": "string" + }, + "theme": { + "description": "Theme name", + "minLength": 1, + "type": "string" + }, + "trend": { + "description": "Direction of change", + "enum": [ + "increasing", + "stable", + "decreasing" + ], + "type": "string" + } + }, + "required": [ + "theme", + "trend" + ], + "type": "object" + }, + "type": "array" + }, + "ratingChange": { + "description": "Rating change between periods (current - previous)", + "type": "number" + }, + "resolvedIssues": { + "description": "Issues that were resolved", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "direction", + "previousPeriod", + "currentPeriod", + "emergingIssues", + "resolvedIssues" + ], + "type": "object" + } + }, + "type": "object" + }, + { + "type": "null" + } +] - removed
Output schema / properties / largeDatasetWarning / properties / dateRange / $refRemoved value: -"#/properties/metadata/properties/dateRange" - added
Output schema / properties / largeDatasetWarning / properties / dateRange / additionalPropertiesAdded value: +false - added
Output schema / properties / largeDatasetWarning / properties / dateRange / propertiesAdded value: +{ + "from": { + "description": "Start date (YYYY-MM-DD)", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + }, + "to": { + "description": "End date (YYYY-MM-DD)", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" + } +} - added
Output schema / properties / largeDatasetWarning / properties / dateRange / requiredAdded value: +[ + "from", + "to" +] - added
Output schema / properties / largeDatasetWarning / properties / dateRange / typeAdded value: +"object" - added
Output schema / properties / largeDatasetWarning / properties / estimatedTokens / maximumAdded value: +9007199254740991 - added
Output schema / properties / largeDatasetWarning / properties / locationCount / maximumAdded value: +9007199254740991 - added
Output schema / properties / largeDatasetWarning / properties / options / items / properties / estimatedTokens / maximumAdded value: +9007199254740991 - added
Output schema / properties / largeDatasetWarning / properties / options / items / properties / parameters / propertyNamesAdded value: +{ + "type": "string" +} - added
Output schema / properties / largeDatasetWarning / properties / totalReviewCount / maximumAdded value: +9007199254740991 - added
Output schema / properties / metadata / properties / analyzedReviewCount / maximumAdded value: +9007199254740991 - added
Output schema / properties / metadata / properties / cache / properties / ttl / maximumAdded value: +9007199254740991 - added
Output schema / properties / metadata / properties / locationCount / maximumAdded value: +9007199254740991 - added
Output schema / properties / metadata / properties / totalReviewCount / maximumAdded value: +9007199254740991
- Changed
pinmeto_get_google_reviews6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - removed
Input schema / properties / to / $refRemoved value: -"#/properties/from" - added
Input schema / properties / to / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - added
Input schema / properties / to / typeAdded value: +"string" - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
pinmeto_get_location10 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - changed
Output schema / properties / data / additionalPropertiesPrevious value: -trueNew value: +{} - changed
Output schema / properties / data / properties / address / additionalPropertiesPrevious value: -trueNew value: +{} - changed
Output schema / properties / data / properties / contact / additionalPropertiesPrevious value: -trueNew value: +{} - added
Output schema / properties / data / properties / fb / propertyNamesAdded value: +{ + "type": "string" +} - added
Output schema / properties / data / properties / google / propertyNamesAdded value: +{ + "type": "string" +} - changed
Output schema / properties / data / properties / location / additionalPropertiesPrevious value: -trueNew value: +{} - added
Output schema / properties / data / properties / openHours / propertyNamesAdded value: +{ + "type": "string" +}
- Changed
pinmeto_get_locations4 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / properties / data / items / propertyNamesAdded value: +{ + "type": "string" +}
- Changed
pinmeto_search_locations3 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
12 tool updates
v4.0.0- First observed
pinmeto_get_apple_insights - First observed
pinmeto_get_facebook_brandpage_insights - First observed
pinmeto_get_facebook_insights - First observed
pinmeto_get_facebook_ratings - First observed
pinmeto_get_google_insights - First observed
pinmeto_get_google_keywords - First observed
pinmeto_get_google_ratings - First observed
pinmeto_get_google_review_insights - First observed
pinmeto_get_google_reviews - First observed
pinmeto_get_location - First observed
pinmeto_get_locations - First observed
pinmeto_search_locations
TDQS
Most tools target clearly distinct resources and actions, with useful cross-references between ratings, reviews, and review insights. The only mild ambiguities are google_review_insights vs. google_ratings and facebook_insights vs. facebook_brandpage_insights, though descriptions do provide enough guidance to separate them.
Every tool follows the same pinmeto_get_<resource> pattern with snake_case naming. The lone action variation is search_locations, but it still fits the overall verb_noun convention and remains predictable.
Twelve tools is well-scoped for a location data and platform-insights server. Each tool covers a distinct data area, and there is no obvious redundancy or bloat despite the range of Google, Facebook, and Apple data.
The server provides solid read coverage for locations and platform analytics, but it is entirely read-only with no create, update, or delete operations for locations. Some platform coverage is also uneven, such as Facebook reviews missing despite Google reviews being available.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
MCP server unifying ERPs, CRMs, APIs and knowledge base for Claude, ChatGPT and Gemini.
- PressoOAuthnow.presso
Connect e-commerce and marketing data to AI assistants via MCP.
- ZapierOAuthcom.zapier
Hosted MCP server connecting AI assistants to 9,000+ apps and 40,000+ actions via Zapier.
MCP server for querying and analyzing data from ad platforms, analytics tools, and spreadsheets
Related MCP Servers
- AlicenseAqualityCmaintenanceAn MCP server that enables AI assistants to query databases, execute SQL, and manage Metabase resources like dashboards, cards, and collections through natural language.22MIT
- -licenseNot gradedqualityCmaintenanceAn MCP server that bridges AI assistants with SQL databases, enabling natural language querying across multiple database types with built-in optimization and security.3-
- AlicenseNot gradedqualityCmaintenanceAn MCP server that connects AI assistants to SEO platforms like Google Search Console, GA4, Bing Webmaster Tools, and Adobe Analytics, enabling natural language queries about SEO performance.2,926MIT
- AlicenseNot gradedqualityDmaintenanceA unified MCP server that gives AI assistants direct access to Google Analytics 4, Google Search Console, Google Ads and Google Merchant Center data using OAuth2 user credentials.MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/PinMeTo/pinmeto-location-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server