Google Cloud Spanner MCP server
Endpoint: https://spanner.googleapis.com/mcp · Authentication: Sign in with OAuth
Manages Spanner instances and databases, reads schema DDL, and runs SQL queries and commits. Requires Google Cloud credentials through OAuth.
How do I authenticate?
Add the endpoint in your client, start Connect or Sign in, approve the requested scopes, and return to the client. OAuth discovery finds the authorization server; client registration requirements vary by provider. Follow the provider guidance and client setup below.
Authentication and connection guideConnection specification
- Remote endpoint
https://spanner.googleapis.com/mcp- Browser access
- Not yet measured
- Declared MCP transport
- Streamable HTTP
- Live-validated MCP transport
- Streamable HTTP — Observed by the latest catalog validation
- Declared authentication
- OAuth 2.1
- Detected authentication
- OAuth 2.1 detected or retained from publisher evidence
- Protocol lifecycle
- Stateful MCP · 2025-11-25
- Authorization server
https://accounts.google.com/- Category
- Databases
Product documentation · Official listing documentation
Provider guidance
- Initialization and tool listing succeeded without credentials in the 2026-10-20 audit; tool calls require Google Cloud credentials. Google OAuth clients are pre-registered in a Google Cloud project; the server does not advertise Dynamic Client Registration.
More Databases MCP servers · Browse all MCP servers · Test this endpoint in the MCP Playground
Connect it
Live-validated endpoint: https://spanner.googleapis.com/mcp · Streamable HTTP. Registration requirements not verified: The OAuth authorization and app-registration requirements for this exact endpoint have not been verified. A compatible client will request authorization, but follow the publisher documentation and do not guess client credentials or callbacks.
Agent prompt for Claude Code or Codex
Add the Google Cloud Spanner MCP server to my MCP client configuration and verify that it works. What it is: Manages Spanner instances and databases, reads schema DDL, and runs SQL queries and commits. Requires Google Cloud credentials through OAuth. Server URL: https://spanner.googleapis.com/mcp Transport: Streamable HTTP (remote MCP server, no local install). Authentication: OAuth 2.1. Registration requirements not verified: The OAuth authorization and app-registration requirements for this exact endpoint have not been verified. A compatible client will request authorization, but follow the publisher documentation and do not guess client credentials or callbacks. Tools (16, as last observed by mcptest): commit, create_database, create_instance, create_session, execute_sql, execute_sql_readonly, get_config, get_database_ddl, get_instance, get_operation, get_query_plan, list_configs, list_databases, list_instances, update_database_schema, update_instance. Reference: https://mcptest.io/servers/google-spanner/ Steps: 1. Work out which MCP client I use (Claude Code, Codex, Cursor, VS Code or another) and add the server under the name "google-spanner" in that client's MCP configuration, user scope unless I ask otherwise. Claude Code: claude mcp add --transport http --scope user 'google-spanner' 'https://spanner.googleapis.com/mcp' Other clients: use the setup for that client on the reference page. 2. Never write a credential value into a file that could be committed; reference an environment variable or the client's secret store, and ask me for any value you need. 3. Verify: connect to the server and call tools/list. Confirm the tools above are listed, and report any sign-in step I still have to complete.
Claude Code setup
Run in a terminal. This user-scoped entry is available across projects.
claude mcp add --transport http --scope user 'google-spanner' 'https://spanner.googleapis.com/mcp'- After adding the server, open Claude Code, run /mcp, select the server, and follow the browser flow to authenticate.
Codex CLI setup
Run in a terminal; Codex stores the entry in ~/.codex/config.toml.
codex mcp add 'google-spanner' --url 'https://spanner.googleapis.com/mcp'
codex mcp login 'google-spanner'Cursor setup
Add to .cursor/mcp.json for this project, or ~/.cursor/mcp.json for all projects.
{
"mcpServers": {
"google-spanner": {
"url": "https://spanner.googleapis.com/mcp"
}
}
}VS Code setup
Add to .vscode/mcp.json, or run “MCP: Open User Configuration” for a private user-level entry.
{
"servers": {
"google-spanner": {
"type": "http",
"url": "https://spanner.googleapis.com/mcp"
}
}
}Claude setup
Add the endpoint above in Claude:
- Customize > Connectors > Add custom connector
- Team/Enterprise: Organization settings > Connectors > Add > Custom > Web
Claude Desktop setup
Add the endpoint above in Claude Desktop:
- Remote: Customize > Connectors (same as claude.ai)
- Local: Settings > Developer > Edit Config, or Settings > Extensions for .mcpb files
~/Library/Application Support/Claude/claude_desktop_config.json(macOS) or%APPDATA%\Claude\claude_desktop_config.json(Windows), local servers only
ChatGPT setup
Add the endpoint above in ChatGPT:
- ChatGPT web: Plugins > Add custom MCP server, then configure authentication and accept the risk warning
Windsurf setup
Add the endpoint above in Windsurf:
~/.config/devin/mcp_config.json(%APPDATA%\devin\mcp_config.jsonon Windows),serverUrlorurl- Cascade panel > ... > MCPs > Open MCP config file
Gemini CLI setup
Add the endpoint above in Gemini CLI:
gemini mcp add --transport http <name> <url>~/.gemini/settings.json(user) or.gemini/settings.json(project),mcpServers
MCP SDK setup
Add the endpoint above in MCP SDK:
- Programmatic:
new Client(...).connect(new StreamableHTTPClientTransport(url))
Notes for every client
- Publisher evidence (reviewed 2026-10-20): https://docs.cloud.google.com/spanner/docs/use-spanner-mcp
- Provider guidance: Initialization and tool listing succeeded without credentials in the 2026-10-20 audit; tool calls require Google Cloud credentials. Google OAuth clients are pre-registered in a Google Cloud project; the server does not advertise Dynamic Client Registration.
Client compatibility
| Client | Status | Why |
|---|---|---|
| Claude Code | Supported | Claude Code supports Streamable HTTP servers and OAuth sign-in. |
| Codex | Supported | Codex supports Streamable HTTP servers and OAuth sign-in. |
| Cursor | Supported | Cursor supports Streamable HTTP servers and OAuth sign-in. |
| VS Code | Supported | VS Code supports Streamable HTTP servers and OAuth sign-in. |
| Claude | Supported | Claude supports Streamable HTTP servers and OAuth sign-in. |
| Claude Desktop | Supported | Claude Desktop supports Streamable HTTP servers and OAuth sign-in. |
| ChatGPT | Partial | Stateful routing needs operational care: ChatGPT can preserve MCP sessions, but the deployment must route a session consistently and retain its state. |
| Windsurf | Partial | Windsurf's documentation does not state support for OAuth sign-in. |
| Gemini CLI | Supported | Gemini CLI supports Streamable HTTP servers and OAuth sign-in. |
| MCP SDK | Supported | MCP SDK supports Streamable HTTP servers and OAuth sign-in. |
Computed from this server's validated transport, protocol and authentication against documented client support. Checks the catalog has not observed are not counted.
Latest validation evidence
- Validation status
- Online when last tested
- Validation checked at
- Oct 26, 2026 at 11:06 AM
- Validation detail
- Negotiated stateful MCP 2025-11-25 at https://spanner.googleapis.com/mcp; detected transport streamable-http; authentication oauth
Tool inventory
What the catalog validator observed on at https://spanner.googleapis.com/mcp without credentials. The live server may have changed since; connect in the Playground for the current list.
Tools provided by Google Cloud Spanner 16
Some details were sanitized for public display.
commitoutputSchema declaredCommit a transaction in a given session. * If commit is finalizing the result of a DML statement then commit request should include latest precommit_token returned by execute_sql tool. * If response to commit includes another precommit_token then issue another commit call to finalize the transaction with the latest precommit_token.
Input
precommitToken: any, session: string, transactionId: stringprecommitToken: anyrequiredRequired. You must include the precommit token with the highest sequence number received in this transaction attempt. Failing to do so results in a `FailedPrecondition` error.
session: stringrequiredRequired. The session in which the transaction to be committed is running.
transactionId: stringrequiredRequired. The transaction in which to commit. Commit a previously-started transaction.
create_databaseoutputSchema declaredCreate a Spanner database in a given instance.
Input
createStatement: string, databaseDialect?: string, encryptionConfig?: any, extraStatements?: array, parent: string, protoDescriptors?: stringcreateStatement: stringrequiredRequired. A `CREATE DATABASE` statement, which specifies the ID of the new database. The database ID must conform to the regular expression `a-z*[a-z0-9]` and be between 2 and 30 characters in length. If the database ID is a reserved word or if it contains a hyphen, the database ID must be enclosed in backticks (`` ` ``).
databaseDialect?: stringoptionalOptional. The dialect of the Cloud Spanner Database.
encryptionConfig?: anyoptionalOptional. The encryption configuration for the database. If this field is not specified, Cloud Spanner will encrypt/decrypt all data at rest using Google default encryption.
extraStatements?: arrayoptionalOptional. A list of DDL statements to run inside the newly created database. Statements can create tables, indexes, etc. These statements execute atomically with the creation of the database: if there is an error in any statement, the database is not created.
parent: stringrequiredRequired. The name of the instance that will serve the new database. Values are of the form `projects//instances/`.
protoDescriptors?: stringoptionalOptional. Proto descriptors used by `CREATE/ALTER PROTO BUNDLE` statements in 'extra_statements'. Contains a protobuf-serialized [`google.protobuf.FileDescriptorSet`]([REDACTED URI] descriptor set. To generate it, [install]([REDACTED URI] and run `protoc` with --include_imports and --descriptor_set_out. For example, to generate for moon/shot/app.proto, run ``` $protoc --proto_path=/app_path --proto_path=/lib_path \ --include_imports \ --descriptor_set_out=descriptors.data \ moon/shot/app.pr
create_instanceoutputSchema declaredCreate a Spanner instance in a given project.
Input
instance: any, instanceId: string, parent: stringinstance: anyrequiredRequired. The instance to create. The name may be omitted, but if specified must be `/instances/`.
instanceId: stringrequiredRequired. The ID of the instance to create. Valid identifiers are of the form `a-z*[a-z0-9]` and must be between 2 and 64 characters in length.
parent: stringrequiredRequired. The name of the project in which to create the instance. Values are of the form `projects/`.
create_sessionoutputSchema declaredCreate a session in a given database for query executions using execute_sql tool. * A session provides transactional context and should be reused across operations if possible. * If a session expires (e.g., returning NOT_FOUND), call create_session tool to get a new one. * Treat the create_session tool call that results as part of running execute_sql_readonly tool as a read-only operation.
Input
database: string, fineGrainedAccessRole?: stringdatabase: stringrequiredRequired. The database in which the new session is created. Format: `projects/{project}/instances/{instance}/databases/{database}`
fineGrainedAccessRole?: stringoptionalOptional. The fine grained access role of the session. All operations performed using the session will be performed with the fine grained access role.
execute_sqloutputSchema declaredExecute SQL statement using a given session. * Requires an active session. Reuse existing sessions if possible. If a session expires, call create_session to get a new one. * **CRITICAL:** To prevent SQL injection vulnerabilities and improve performance, ALWAYS use the `parameters` argument to pass any dynamic values into your SQL query. Do NOT embed variables directly into the `sql` string. * Use placeholders in the `sql` string and provide values in the `parameters` list: * For GoogleSQL: Use named placeholders (e.g., `@my_param`). * For PostgreSQL: Use positional placeholders (e.g., `$1`, `$
Input
existingTransactionId?: string, parameters?: array, readOnlyTransaction?: boolean, readWriteTransaction?: boolean, seqno?: string, session: string, singleUseTransaction?: boolean, sql: stringexistingTransactionId?: stringoptionalUse an existing transaction.
parameters?: arrayoptionalOptional. The SQL query parameters.
readOnlyTransaction?: booleanoptionalBegin a new read-only transaction.
readWriteTransaction?: booleanoptionalBegin a new read-write transaction.
seqno?: stringoptionalOptional. Sequence number of the request within a transaction. The sequence number must be monotonically increasing within the transaction. If a request arrives for the first time with an out-of-order sequence number, the transaction can be aborted.
session: stringrequiredRequired. The session in which the SQL query is executed. Format: `projects/{project}/instances/{instance}/databases/{database}/sessions/{session}`
singleUseTransaction?: booleanoptionalUse a single use transaction for query execution.
sql: stringrequiredRequired. The SQL query to execute.
execute_sql_readonlyoutputSchema declaredExecute SQL query statement using a given session in a read-only transaction. * Requires an active session. Reuse existing sessions if possible. If a session expires, call create_session tool to get a new one. Treat create_session tool invocation made as part of execute_sql_readonly as a read-only operation. * **CRITICAL:** To prevent SQL injection vulnerabilities and improve performance, ALWAYS use the `parameters` argument to pass any dynamic values into your SQL query. Do NOT embed variables directly into the `sql` string. * Use placeholders in the `sql` string and provide values in the `pa
Input
existingTransactionId?: string, parameters?: array, readOnlyTransaction?: boolean, readWriteTransaction?: boolean, seqno?: string, session: string, singleUseTransaction?: boolean, sql: stringexistingTransactionId?: stringoptionalUse an existing transaction.
parameters?: arrayoptionalOptional. The SQL query parameters.
readOnlyTransaction?: booleanoptionalBegin a new read-only transaction.
readWriteTransaction?: booleanoptionalBegin a new read-write transaction.
seqno?: stringoptionalOptional. Sequence number of the request within a transaction. The sequence number must be monotonically increasing within the transaction. If a request arrives for the first time with an out-of-order sequence number, the transaction can be aborted.
session: stringrequiredRequired. The session in which the SQL query is executed. Format: `projects/{project}/instances/{instance}/databases/{database}/sessions/{session}`
singleUseTransaction?: booleanoptionalUse a single use transaction for query execution.
sql: stringrequiredRequired. The SQL query to execute.
get_configoutputSchema declaredGet information about a specific Spanner instance configuration.
Input
name: stringname: stringrequiredRequired. The name of the requested instance configuration. Values are of the form `projects//instanceConfigs/`.
get_database_ddloutputSchema declaredGet database schema for a given database.
Input
database: stringdatabase: stringrequiredRequired. The database whose schema we wish to get. Values are of the form `projects//instances//databases/`
get_instanceoutputSchema declaredGet information about a Spanner instance
Input
fieldMask?: string, name: stringfieldMask?: stringoptionalIf field_mask is present, specifies the subset of Instance fields that should be returned. If absent, all Instance fields are returned.
name: stringrequiredRequired. The name of the requested instance. Values are of the form `projects//instances/`.
get_operationoutputSchema declaredGet status of a long-running operation. * Long running operation may take several minutes to complete. get_operation tool can be used to poll the status of a long running operation.
Input
name?: stringname?: stringoptionalThe name of the operation resource.
get_query_planoutputSchema declaredRetrieves the execution plan (query plan) for a Spanner SQL query. This tool does NOT execute the query itself, making it safe and efficient to run even on large datasets or write operations. Use this tool to understand index usage, join algorithms, and execution cost before executing the query. Queries may include parameter placeholders (e.g., `@param_name` for GoogleSQL or `$1` for PostgreSQL), but there is no need to provide or bind parameter values when requesting the query plan. * **Example (GoogleSQL):** ``` sql: "SELECT * FROM Users WHERE UserId = @user_id" ``` * **Example (PostgreSQL):
Input
session: string, sql: stringsession: stringrequiredRequired. The session in which the SQL query is executed. Format: `projects/{project}/instances/{instance}/databases/{database}/sessions/{session}`
sql: stringrequiredRequired. The SQL query to get the plan for.
list_configsoutputSchema declaredList instance configs in a given project. * `page_size` defaults to 10 if not specified. * Response may include next_page_token to fetch additional configs using list_configs tool with page_token set.
Input
pageSize?: integer, pageToken?: string, parent: stringpageSize?: integeroptionalNumber of instance configurations to be returned in the response. If 0 or less, defaults to the server's maximum allowed page size.
pageToken?: stringoptionalIf non-empty, `page_token` should contain a next_page_token from a previous ListInstanceConfigsResponse.
parent: stringrequiredRequired. The name of the project for which a list of supported instance configurations is requested. Values are of the form `projects/`.
list_databasesoutputSchema declaredList Spanner databases in a given spanner instance. * Response may include next_page_token to fetch additional databases using list_databases tool with page_token set.
Input
pageSize?: integer, pageToken?: string, parent: stringpageSize?: integeroptionalNumber of databases to be returned in the response. If 0 or less, defaults to the server's maximum allowed page size.
pageToken?: stringoptionalIf non-empty, `page_token` should contain a next_page_token from a previous ListDatabasesResponse.
parent: stringrequiredRequired. The instance whose databases should be listed. Values are of the form `projects//instances/`.
list_instancesoutputSchema declaredList Spanner instances in a given project. * `page_size` defaults to 10 if not specified. * Response may include next_page_token to fetch additional instances using list_instances tool with page_token set.
Input
filter?: string, instanceDeadline?: string, pageSize?: integer, pageToken?: string, parent: stringfilter?: stringoptionalAn expression for filtering the results of the request. Filter rules are case insensitive. The fields eligible for filtering are: * `name` * `display_name` * `labels.key` where key is the name of a label Some examples of using filters are: * `name:*` --> The instance has a name. * `name:Howl` --> The instance's name contains the string "howl". * `name:HOWL` --> Equivalent to above. * `NAME:howl` --> Equivalent to above. * `labels.env:*` --> The instance has the label "env". * `labels.env:dev` --> The instance has the label "env" and the value of the label contains the string "dev". * `name:how
instanceDeadline?: stringoptionalDeadline used while retrieving metadata for instances. Instances whose metadata cannot be retrieved within this deadline will be added to unreachable in ListInstancesResponse.
pageSize?: integeroptionalNumber of instances to be returned in the response. If 0 or less, defaults to the server's maximum allowed page size.
pageToken?: stringoptionalIf non-empty, `page_token` should contain a next_page_token from a previous ListInstancesResponse.
parent: stringrequiredRequired. The name of the project for which a list of instances is requested. Values are of the form `projects/`.
update_database_schemaoutputSchema declaredUpdate schema for a given database.
Input
database: string, operationId?: string, protoDescriptors?: string, statements: arraydatabase: stringrequiredRequired. The database to update.
operationId?: stringoptionalIf empty, the new update request is assigned an automatically-generated operation ID. Otherwise, `operation_id` is used to construct the name of the resulting Operation. Specifying an explicit operation ID simplifies determining whether the statements were executed in the event that the UpdateDatabaseDdl call is replayed, or the return value is otherwise lost: the database and `operation_id` fields can be combined to form the `name` of the resulting longrunning.Operation: `/operations/`. `operation_id` should be unique within the database, and must be a valid identifier: `a-z*`. Note that auto
protoDescriptors?: stringoptionalOptional. Proto descriptors used by CREATE/ALTER PROTO BUNDLE statements. Contains a protobuf-serialized [google.protobuf.FileDescriptorSet]([REDACTED URI] To generate it, [install]([REDACTED URI] and run `protoc` with --include_imports and --descriptor_set_out. For example, to generate for moon/shot/app.proto, run ``` $protoc --proto_path=/app_path --proto_path=/lib_path \ --include_imports \ --descriptor_set_out=descriptors.data \ moon/shot/app.proto ``` For more details, see protobuffer
statements: arrayrequiredRequired. DDL statements to be applied to the database.
update_instanceoutputSchema declaredUpdate a Spanner instance. * While updating an instance always include instance name and config.
Input
fieldMask: string, instance: anyfieldMask: stringrequiredRequired. A mask specifying which fields in Instance should be updated. The field mask must always be specified; this prevents any future fields in Instance from being erased accidentally by clients that do not know about them.
instance: anyrequiredRequired. The instance to update, which must always include the instance name. Otherwise, only fields mentioned in field_mask need be included.