MCP
Hosted MCP server for any client that takes a URL. Nothing to install.
Connect over MCP →
Agent skill
For agents that run shell commands and read a SKILL.md, with or without MCP.
Install the skill →
REST API
The plain HTTP layer underneath both. For scripts, services and custom tools.
Call the API →
Create a key#
Open QueryInbox, go to Settings → Agent access, and click Create key. The key looks like qi_AbCdEfGh.… and is shown once — copy it before you close the panel. You can mint several keys (one per laptop, one per agent) and revoke each one separately.
MCP#
QueryInbox serves MCP itself at https://queryinbox.com/mcp (Streamable HTTP, no session). One URL and one header are the whole configuration: nothing to install, and changes ship with the app.
Claude Code#
claude mcp add --transport http queryinbox https://queryinbox.com/mcp \
--header "Authorization: Bearer qi_..."Codex#
Codex only reads the bearer token from an environment variable, so export the key first:
export QUERYINBOX_API_KEY=qi_...
codex mcp add queryinbox --url https://queryinbox.com/mcp \
--bearer-token-env-var QUERYINBOX_API_KEYCursor#
Add this to ~/.cursor/mcp.json, or .cursor/mcp.json in a project:
{
"mcpServers": {
"queryinbox": {
"url": "https://queryinbox.com/mcp",
"headers": { "Authorization": "Bearer qi_..." }
}
}
}opencode#
Add a remote server to opencode.json (project) or ~/.config/opencode/opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"queryinbox": {
"type": "remote",
"url": "https://queryinbox.com/mcp",
"headers": { "Authorization": "Bearer {env:QUERYINBOX_API_KEY}" }
}
}
}pi#
MCP is built into pi 0.99.0 and later. The server lands in ~/.pi/agent/mcp.json; add -l to write .pi/mcp.json for the current project instead:
pi mcp add queryinbox --url https://queryinbox.com/mcp \
--header "Authorization=Bearer qi_..."Other remote clients#
Any client that accepts a URL and headers works the same way — new Claude Desktop builds, IDE plugins:
{
"mcpServers": {
"queryinbox": {
"url": "https://queryinbox.com/mcp",
"headers": { "Authorization": "Bearer qi_..." }
}
}
}Clients that only speak stdio#
Bridge the remote endpoint with the community mcp-remote package:
npx -y mcp-remote https://queryinbox.com/mcp \
--header "Authorization: Bearer qi_..."Tools#
| Tool | What it does |
|---|---|
list_resources | List the Search Console properties and Analytics properties this QueryInbox account can read, plus the user's current working set. One call that covers both Google APIs; use it before picking a site or property. |
gsc_api | Run any read-only Google Search Console method. Pass the native method name plus that method's native request fields; everything except method and site is forwarded to Google untouched (POST fields become the JSON body, GET fields the query string). Methods: sites.list, sites.get, sitemaps.list, sitemaps.get, searchanalytics.query, urlInspection.index.inspect. Returns the raw Google payload under data. Search Console data lags 2-3 days. Call api_reference for parameters, and note the URL inspection quota (2,000/day per property). |
ga4_data | Run any read-only Google Analytics Data API method. Pass the native method name plus that method's native request body (dateRanges, dimensions: [{name}], metrics: [{name}], filters, ...); everything except method and property is forwarded untouched. Methods: properties.runReport, properties.batchRunReports, properties.runPivotReport, properties.batchRunPivotReports, properties.runRealtimeReport, properties.checkCompatibility, properties.getMetadata, properties.runFunnelReport (alpha), properties.getPropertyQuotasSnapshot (alpha). Returns the raw Google payload under data. Use properties.getMetadata to discover dimension and metric names. |
ga4_admin | Run any read-only Google Analytics Admin API method: account and property discovery, data streams, key events, conversion events, custom dimensions and custom metrics. These explain what report dimensions and metrics mean (for example which event a keyEvents metric counts). Pass the native method name plus native request fields; everything except method, property and account is forwarded untouched. Returns the raw Google payload under data. |
api_reference | The generated reference for gsc_api, ga4_data and ga4_admin: every available method, its path, parameters, notes and Google's quotas. Call it before an unfamiliar method or when a method name is rejected. |
Agent skill#
For any agent that runs shell commands and reads a SKILL.md. The skill teaches the agent the REST calls that MCP wraps, and the key stays the only secret it needs.
Install#
The skill is served at /skills/queryinbox and its generated method reference at /skills/queryinbox/reference — open them in the browser first if you like, then install both into your harness's skills directory:
# pi
mkdir -p ~/.pi/agent/skills/queryinbox
curl -fsSL https://queryinbox.com/skills/queryinbox \
-o ~/.pi/agent/skills/queryinbox/SKILL.md
curl -fsSL https://queryinbox.com/skills/queryinbox/reference \
-o ~/.pi/agent/skills/queryinbox/reference.md
# Claude Code
mkdir -p ~/.claude/skills/queryinbox
curl -fsSL https://queryinbox.com/skills/queryinbox \
-o ~/.claude/skills/queryinbox/SKILL.md
curl -fsSL https://queryinbox.com/skills/queryinbox/reference \
-o ~/.claude/skills/queryinbox/reference.md
# other harnesses that read the shared skills directory
mkdir -p ~/.agents/skills/queryinbox
curl -fsSL https://queryinbox.com/skills/queryinbox \
-o ~/.agents/skills/queryinbox/SKILL.md
curl -fsSL https://queryinbox.com/skills/queryinbox/reference \
-o ~/.agents/skills/queryinbox/reference.mdUpdating the skill later is the same two curls.
Key storage#
The skill reads QUERYINBOX_API_KEY when set and falls back to a file, so the key keeps working across terminals and GUI-launched agents without touching your shell profile:
mkdir -p ~/.config/queryinbox
printf '%s\n' 'qi_...' > ~/.config/queryinbox/api-key
chmod 600 ~/.config/queryinbox/api-keyPrefer an environment variable? Make it persistent rather than exporting it per shell: macOS/zsh ~/.zshrc, Linux/bash ~/.bashrc, fish set -Ux, Windows PowerShell setx, or your harness's own environment settings (for Claude Code, the env block in ~/.claude/settings.json).
REST API#
MCP is a wrapper around these endpoints, and the skill documents them. There is one route per Google API; method names the endpoint to call and every other field is that endpoint's native request — POST fields become the JSON body, GET fields the query string. Send the key as a bearer token; the site or property selector accepts a full value or a unique substring and is resolved before the call.
curl -s https://queryinbox.com/api/agent/resources \
-H "Authorization: Bearer $QUERYINBOX_API_KEY"
curl -s https://queryinbox.com/api/agent/gsc \
-H "Authorization: Bearer $QUERYINBOX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"method":"searchanalytics.query","site":"example.com",
"startDate":"2026-09-01","endDate":"2026-09-28",
"dimensions":["query"],"rowLimit":20}'
curl -s https://queryinbox.com/api/agent/ga4 \
-H "Authorization: Bearer $QUERYINBOX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"method":"properties.runReport","property":"example.com",
"dateRanges":[{"startDate":"2026-09-01","endDate":"2026-09-28"}],
"dimensions":[{"name":"date"}],
"metrics":[{"name":"sessions"},{"name":"activeUsers"}]}'Also available: POST /api/agent/ga4/admin for property configuration and metadata (data streams, key events, custom dimensions), and POST /api/agent/reference for the full method list with parameters and quotas.
Errors#
| HTTP | Code | Meaning |
|---|---|---|
| 400 | invalid_request | The body is malformed or a required field is missing ( method, or the selector a method needs) |
| 400 | method_not_available | The method is not part of the read-only surface (writes, account configuration, or exports that create state) |
| 401 | invalid_api_key | Key is wrong or revoked — create a new one in Settings |
| 404 | site_not_found, site_ambiguous, property_not_found, property_ambiguous | The selectors matched nothing or several resources; the body lists the candidates |
| 409 | reauth_required | The key is fine, but the underlying Google authorization expired or was revoked. Sign in at QueryInbox again; the response carries a reauthUrl, and the same key keeps working afterwards |
| 429 | rate_limited | More than 120 requests in a minute — back off |
| 429 | google_quota_exceeded | Google's own quota (for example URL inspection's 2,000/day per property) — back off, honoring retryAfter when present |
| 502 | google_error | Google itself failed or rejected the query |
Good to know#
- Read-only. A key can read the Search Console and Analytics read APIs those two scopes cover; a few endpoints are deliberately excluded (account configuration, exports that create state). Nothing is ever written back to Google.
- Keys do not expire on their own. Revoke them in Settings at any time, or use Disconnect Google to remove the Google authorization and every key at once.
- Search Console lags 2–3 days, and the newest day is partial. Analytics reports by the day; a realtime report (
properties.runRealtimeReport) covers the last 30 minutes. - The agent never sees your Google password or tokens — only this key. Revoking the key cuts access immediately.