Agent access

Let an AI agent read the Search Console and Analytics data of your own QueryInbox account. Access is read-only, uses a key you create and can revoke at any time, and never exposes your Google credentials to the agent.

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#

bash
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:

bash
export QUERYINBOX_API_KEY=qi_...
codex mcp add queryinbox --url https://queryinbox.com/mcp \
  --bearer-token-env-var QUERYINBOX_API_KEY

Cursor#

Add this to ~/.cursor/mcp.json, or .cursor/mcp.json in a project:

json
{
  "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:

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:

shell
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:

json
{
  "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:

bash
npx -y mcp-remote https://queryinbox.com/mcp \
  --header "Authorization: Bearer qi_..."

Tools#

ToolWhat it does
list_resourcesList 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_apiRun 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_dataRun 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_adminRun 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_referenceThe 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:

shell
# 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.md

Updating 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:

bash
mkdir -p ~/.config/queryinbox
printf '%s\n' 'qi_...' > ~/.config/queryinbox/api-key
chmod 600 ~/.config/queryinbox/api-key

Prefer 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.

bash
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#

HTTPCodeMeaning
400invalid_requestThe body is malformed or a required field is missing ( method, or the selector a method needs)
400method_not_availableThe method is not part of the read-only surface (writes, account configuration, or exports that create state)
401invalid_api_keyKey is wrong or revoked — create a new one in Settings
404site_not_found, site_ambiguous, property_not_found, property_ambiguousThe selectors matched nothing or several resources; the body lists the candidates
409reauth_requiredThe 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
429rate_limitedMore than 120 requests in a minute — back off
429google_quota_exceededGoogle's own quota (for example URL inspection's 2,000/day per property) — back off, honoring retryAfter when present
502google_errorGoogle 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.