# SEO and warehouse servers: Search Console, BigQuery and Snowflake

Checked on 2026-11-01, BigQuery again on 2026-11-06. Admin-side drafts (the BigQuery deny policy, the Snowflake role, user defaults, warehouse and security integration) are in [../assets/read-only-snippets.md](../assets/read-only-snippets.md).

## Google Search Console

Server and status

- No Google MCP server as of 2026-11-01.
- Preferred route: the Search Console bulk data export to BigQuery, read through BigQuery MCP with `execute_sql_readonly`.

Bulk export facts

- Default dataset `searchconsole`; tables `searchdata_site_impression` (property aggregation), `searchdata_url_impression` (URL aggregation) and `ExportLog`.
- `data_date` is Pacific Time. Keys repeat, so always aggregate.
- `search_type` holds `web`, `image`, `video`, `news`, `discover` and `googleNews`. The Performance report defaults to Search type: Web, so filter on `search_type = 'web'` before comparing totals.
- Anonymized queries are flagged and have null or empty query text; no server can recover them.
- No backfill: export starts on the setup day, so earlier history stays in the API or UI. The first export lands within 48 hours.
- The export's Google-managed service account (shown on the setup page) needs BigQuery Job User and BigQuery Data Editor on the project. Storage and query costs apply.
- Moving rows to BigQuery does not make query-level data complete, and search clicks are not analytics sessions.

Community route: open-gsc-mcp (unofficial, MIT)

- `auth login --read-only` grants reads only.
- `GSC_ENABLE_WRITES` defaults to 1; 0 removes `submit_sitemap`, `delete_sitemap`, `add_site` and `delete_site`.
- The token file is owner-only (`GSC_TOKEN_FILE` sets its path); `auth logout` revokes.
- A write-scope token from an earlier login is still accepted, so revoke the old grant first, then log in with `--read-only` (failure F03).
- Pin the version (article example: 1.4.0) and keep the client JSON outside the repository.

API facts (article research)

- `webmasters.readonly` reads; `webmasters` reads and writes.
- Search Analytics dates are Pacific Time and include both ends; request `data_state` final for stable comparisons.
- At most 50,000 rows per day per search type. Rows come back in click order for ordinary queries, so sorting a partial result by impressions does not find every high-impression query.

T1 and T3

- Export route: `list_dataset_ids` shows `searchconsole` and only approved datasets. T3 sums clicks from `searchdata_site_impression` where `search_type = 'web'` for a final week of `data_date` (Pacific Time) and compares them with the Performance report set to Search type: Web for the same dates.
- Community route: `list_sites` returns the exact `site_url` (`sc-domain:example.com` for a Domain property, `https://www.example.com/` for URL-prefix); T3 runs `query_search_analytics` with `data_state` final and search type web.

## BigQuery

Server and status

- Google-managed remote server `https://bigquery.googleapis.com/mcp` (Streamable HTTP), enabled whenever the BigQuery API is enabled, which is automatic on new projects (page updated 2026-10-29).
- Tools: `list_dataset_ids`, `list_table_ids`, `get_dataset_info`, `get_table_info`, `execute_sql_readonly`, `execute_sql` and `cancel_job`. Google's tool pages mark `execute_sql` and `cancel_job` Read Only Hint false and Destructive Hint true, although the setup page still says only `execute_sql` is not read-only.

Auth and who can connect

- Roles: MCP Tool User, BigQuery Job User and BigQuery Data Viewer. Google recommends a separate agent identity.
- OAuth scope `https://www.googleapis.com/auth/bigquery`.
- Client setup uses a Web application OAuth client. claude.ai redirect `https://claude.ai/api/mcp/auth_callback` (plus `https://claude.ai` as a JavaScript origin); Claude Code inherits the same custom connector; ChatGPT needs ChatGPT Business and redirect `https://chatgpt.com/connector_platform_oauth_redirect`. Custom redirect URIs are not supported.

Read-only layer

- An IAM deny policy on `mcp.googleapis.com/tools.call` for `principalSet://goog/public:all` with the condition `api.getAttribute('mcp.googleapis.com/tool.isReadOnly', false) == false`, created with `gcloud iam policies create ... --kind=denypolicies` at the project, folder or organization (page updated 2026-10-26).
- Data Viewer on approved datasets only; queries through `execute_sql_readonly`.
- Denied tools still appear in `tools/list`, so T2 shows `execute_sql` and `cancel_job`, and T4 must prove the denial. The deny policy does not cover non-Google MCP servers.

Limits and meters

- 3,000 rows per result and three minutes of processing by default (failure F11).
- Record the job (billing) project separately from the data project.
- `execute_sql_readonly` has no maximum bytes billed. It takes `dryRun`, `jobTimeoutMs`, `timeoutMs` and `labels`; prose pages use snake_case and the schema camelCase, so use the client's tool schema. Dry run first, set a job timeout and a label, and agree a budget.
- A project quota is a backstop, not a per-query cap, and a custom per-user quota applies to every user and service account in the project alike. For a budget of its own, give the agent its own job project.

Alternative

- MCP Toolbox for Databases is Google's open-source, self-run option for narrow business tools. Google pages link the repository under two names: use the one Google's MCP catalog links. Designing such a server belongs to warehouse-and-internal-mcp.

## Snowflake

Server and status

- Managed server URL `https://<account_url>/api/v2/databases/{database}/schemas/{schema}/mcp-servers/{name}`. Hostnames use hyphens instead of underscores.
- Tool types: `CORTEX_AGENT_RUN`, `CODING_AGENT`, `CORTEX_SEARCH_SERVICE_QUERY`, `CORTEX_ANALYST_MESSAGE`, `SYSTEM_EXECUTE_SQL` and `GENERIC` (procedures and functions; review their execution rights).
- `Snowflake-Labs/mcp` (package `snowflake-labs-mcp`) is deprecated in favour of the managed server (scanner S02).

Auth and who can connect

- Snowflake OAuth by default, External OAuth optional, no dynamic client registration.
- OAuth sessions run as the connecting user's `DEFAULT_ROLE`. A client can name another role only with a `session:role:<role>` scope, and clients such as Claude request `session:role:all`, which also means the default role. So `MCP_READER` must be the user's default role, and each user needs a `DEFAULT_WAREHOUSE`, or sessions fail to initialise. Setting the default role changes it in every Snowflake session for that user, and users can change their own default role back: a dedicated MCP user per person that holds only `MCP_READER` avoids both.
- Server access does not grant tool access: each tool needs its own grant plus the underlying privileges.
- Redirect URIs: Snowflake's public-client example uses `https://claude.ai/api/mcp/auth_callback`; its connector note mentions a localhost URI for the desktop app; ChatGPT shows its URI during connector creation. Use the exact URI the client displays, and `OAUTH_ALTERNATE_REDIRECT_URIS` when a client needs several.
- Security integration draft for the admin: `OAUTH_USE_SECONDARY_ROLES = NONE` and `ALLOWED_ROLES_LIST` limited to the MCP role, plus the user defaults and a dedicated warehouse with a cost guard (`assets/read-only-snippets.md`).

Read-only layer

- The SQL execution tool with `read_only: true` (the default), and a SELECT-only `MCP_READER` that is the user's default role and the only role in `ALLOWED_ROLES_LIST`, with no secondary roles.
- Prefer a Cortex Analyst tool over a semantic view to raw SQL: answers follow the governed definitions.

Limits and meters

- Protocol revision 2025-11-25; 50 tools per server; SQL and generic tool responses truncate at 250 KB; recursion depth 10.
- An agent can run many queries: give it a dedicated XSMALL warehouse with `AUTO_SUSPEND = 60`, a `STATEMENT_TIMEOUT_IN_SECONDS` and a resource monitor.
- MCP server objects are not replicated in failover groups; OAuth integrations are.

Traps

- A network policy blocks remote connectors: the token request fails with `invalid_client`, the same error as a wrong client ID or secret (failure F13). Allow the client provider's outbound IP ranges, or choose another route.
- The session always runs as the user's `DEFAULT_ROLE`; `ALLOWED_ROLES_LIST` only limits which roles may connect. T1 must show `MCP_READER` (failure F14).
