diff --git a/doc/connections/GOOGLE-WORKSPACE.md b/doc/connections/GOOGLE-WORKSPACE.md index 74187eee43..98b256a4d8 100644 --- a/doc/connections/GOOGLE-WORKSPACE.md +++ b/doc/connections/GOOGLE-WORKSPACE.md @@ -159,6 +159,40 @@ operations. Write profiles add only the reviewed write operations for their app; destructive or unreviewed tools do not become available merely because Google adds them upstream. +### Service-specific minimum scopes (2026-09-30) + +Docs, Sheets, and Slides request only their service's read-only scope in the +read profile and its read/write scope in the write profile. They do not also +request `drive.readonly` or `drive.file`: those are authorization alternatives, +not additional requirements. Drive and Workspace Search retain their separate +Drive permissions. Calendar write requests `calendar.calendarlist.readonly` +and `calendar.events`; the latter also authorizes `suggest_time`. Calendar read +retains `calendar.events.freebusy` alongside list/event read-only access. + +References: Google's [Docs read](https://developers.google.com/workspace/docs/api/reference/mcp/tools_list/read_doc) +and [update](https://developers.google.com/workspace/docs/api/reference/mcp/tools_list/update_doc), +[Sheets read](https://developers.google.com/workspace/sheets/api/reference/mcp/tools_list/get_spreadsheet) +and [update](https://developers.google.com/workspace/sheets/api/reference/mcp/tools_list/update_values), +[Slides read](https://developers.google.com/workspace/slides/api/reference/mcp/tools_list/read_presentation) +and [update](https://developers.google.com/workspace/slides/api/reference/mcp/tools_list/update_presentation), +and [Calendar suggest_time](https://developers.google.com/workspace/calendar/api/v3/reference/mcp/tools_list/suggest_time). + +The write scopes support editing existing accessible files by ID. `drive.file` +is a valid narrower alternative for app-authorized files, but would require a +different per-file authorization workflow. Read-only profiles remain separate; +the project-wide union is not the scope set requested by every connection. + +Deploy with the matching Cloud broker registry and test fresh grants in staging +before production. Signed authorization and refresh requests use exact scope +sets, so mixed versions fail closed. The broker rejects old broader grants and +refresh responses without explicit scope evidence for these reduced profiles. +Reconnect affected connections; do not relabel or globally revoke existing +tokens. Customer-owned methods request the same reduced sets on new consent; +previously issued grants are not retroactively narrowed. The 21-scope integration +union is unchanged by these profile-level reductions. Console must still keep +Drive/free-busy entries required by other profiles and separately used identity +scopes. Fresh provider proof is a release requirement, not implied by unit tests. + ### Google Chat scope reduction (2026-09-22) `chat.read` requests only `chat.spaces.readonly` and `chat.messages.readonly`. diff --git a/packages/shared/src/app-definitions.test.ts b/packages/shared/src/app-definitions.test.ts index 9333e1c196..fea1cde846 100644 --- a/packages/shared/src/app-definitions.test.ts +++ b/packages/shared/src/app-definitions.test.ts @@ -71,7 +71,7 @@ const GOOGLE_WORKSPACE_PROFILE_EXPECTATIONS = [ serverUrl: "https://docsmcp.googleapis.com/mcp/v1", capability: "read", riskTier: "S3", - scopes: [googleScope("drive.readonly"), googleScope("documents.readonly")], + scopes: [googleScope("documents.readonly")], writeTools: [], }, { @@ -80,11 +80,7 @@ const GOOGLE_WORKSPACE_PROFILE_EXPECTATIONS = [ serverUrl: "https://docsmcp.googleapis.com/mcp/v1", capability: "write", riskTier: "S4", - scopes: [ - googleScope("drive.readonly"), - googleScope("drive.file"), - googleScope("documents"), - ], + scopes: [googleScope("documents")], writeTools: ["update_doc"], }, { @@ -93,10 +89,7 @@ const GOOGLE_WORKSPACE_PROFILE_EXPECTATIONS = [ serverUrl: "https://sheetsmcp.googleapis.com/mcp/v1", capability: "read", riskTier: "S3", - scopes: [ - googleScope("drive.readonly"), - googleScope("spreadsheets.readonly"), - ], + scopes: [googleScope("spreadsheets.readonly")], writeTools: [], }, { @@ -105,11 +98,7 @@ const GOOGLE_WORKSPACE_PROFILE_EXPECTATIONS = [ serverUrl: "https://sheetsmcp.googleapis.com/mcp/v1", capability: "write", riskTier: "S4", - scopes: [ - googleScope("drive.readonly"), - googleScope("drive.file"), - googleScope("spreadsheets"), - ], + scopes: [googleScope("spreadsheets")], writeTools: [ "update_spreadsheet", "update_values", @@ -123,10 +112,7 @@ const GOOGLE_WORKSPACE_PROFILE_EXPECTATIONS = [ serverUrl: "https://slidesmcp.googleapis.com/mcp/v1", capability: "read", riskTier: "S3", - scopes: [ - googleScope("drive.readonly"), - googleScope("presentations.readonly"), - ], + scopes: [googleScope("presentations.readonly")], writeTools: [], }, { @@ -135,11 +121,7 @@ const GOOGLE_WORKSPACE_PROFILE_EXPECTATIONS = [ serverUrl: "https://slidesmcp.googleapis.com/mcp/v1", capability: "write", riskTier: "S4", - scopes: [ - googleScope("drive.readonly"), - googleScope("drive.file"), - googleScope("presentations"), - ], + scopes: [googleScope("presentations")], writeTools: ["update_presentation"], }, { @@ -163,7 +145,6 @@ const GOOGLE_WORKSPACE_PROFILE_EXPECTATIONS = [ riskTier: "S4", scopes: [ googleScope("calendar.calendarlist.readonly"), - googleScope("calendar.events.freebusy"), googleScope("calendar.events"), ], writeTools: [ diff --git a/packages/shared/src/app-definitions/google-calendar.json b/packages/shared/src/app-definitions/google-calendar.json index b8b00444c1..ab9e93999d 100644 --- a/packages/shared/src/app-definitions/google-calendar.json +++ b/packages/shared/src/app-definitions/google-calendar.json @@ -129,7 +129,6 @@ "serverUrl": "https://calendarmcp.googleapis.com/mcp/v1", "scopesHint": [ "https://www.googleapis.com/auth/calendar.calendarlist.readonly", - "https://www.googleapis.com/auth/calendar.events.freebusy", "https://www.googleapis.com/auth/calendar.events" ] }, @@ -165,7 +164,6 @@ "metadataUrl": "https://accounts.google.com/.well-known/openid-configuration", "scopesHint": [ "https://www.googleapis.com/auth/calendar.calendarlist.readonly", - "https://www.googleapis.com/auth/calendar.events.freebusy", "https://www.googleapis.com/auth/calendar.events" ], "oauthAuthorizationParams": { diff --git a/packages/shared/src/app-definitions/google-docs.json b/packages/shared/src/app-definitions/google-docs.json index bb6eb24a18..71a66e01f7 100644 --- a/packages/shared/src/app-definitions/google-docs.json +++ b/packages/shared/src/app-definitions/google-docs.json @@ -52,7 +52,6 @@ "defaults": { "serverUrl": "https://docsmcp.googleapis.com/mcp/v1", "scopesHint": [ - "https://www.googleapis.com/auth/drive.readonly", "https://www.googleapis.com/auth/documents.readonly" ] }, @@ -86,7 +85,6 @@ "tokenEndpoint": "https://oauth2.googleapis.com/token", "metadataUrl": "https://accounts.google.com/.well-known/openid-configuration", "scopesHint": [ - "https://www.googleapis.com/auth/drive.readonly", "https://www.googleapis.com/auth/documents.readonly" ], "oauthAuthorizationParams": { @@ -127,8 +125,6 @@ "defaults": { "serverUrl": "https://docsmcp.googleapis.com/mcp/v1", "scopesHint": [ - "https://www.googleapis.com/auth/drive.readonly", - "https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/documents" ] }, @@ -163,8 +159,6 @@ "tokenEndpoint": "https://oauth2.googleapis.com/token", "metadataUrl": "https://accounts.google.com/.well-known/openid-configuration", "scopesHint": [ - "https://www.googleapis.com/auth/drive.readonly", - "https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/documents" ], "oauthAuthorizationParams": { diff --git a/packages/shared/src/app-definitions/google-sheets.json b/packages/shared/src/app-definitions/google-sheets.json index 83e0ef0d31..de87b58007 100644 --- a/packages/shared/src/app-definitions/google-sheets.json +++ b/packages/shared/src/app-definitions/google-sheets.json @@ -53,7 +53,6 @@ "defaults": { "serverUrl": "https://sheetsmcp.googleapis.com/mcp/v1", "scopesHint": [ - "https://www.googleapis.com/auth/drive.readonly", "https://www.googleapis.com/auth/spreadsheets.readonly" ] }, @@ -87,7 +86,6 @@ "tokenEndpoint": "https://oauth2.googleapis.com/token", "metadataUrl": "https://accounts.google.com/.well-known/openid-configuration", "scopesHint": [ - "https://www.googleapis.com/auth/drive.readonly", "https://www.googleapis.com/auth/spreadsheets.readonly" ], "oauthAuthorizationParams": { @@ -128,8 +126,6 @@ "defaults": { "serverUrl": "https://sheetsmcp.googleapis.com/mcp/v1", "scopesHint": [ - "https://www.googleapis.com/auth/drive.readonly", - "https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/spreadsheets" ] }, @@ -164,8 +160,6 @@ "tokenEndpoint": "https://oauth2.googleapis.com/token", "metadataUrl": "https://accounts.google.com/.well-known/openid-configuration", "scopesHint": [ - "https://www.googleapis.com/auth/drive.readonly", - "https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/spreadsheets" ], "oauthAuthorizationParams": { diff --git a/packages/shared/src/app-definitions/google-slides.json b/packages/shared/src/app-definitions/google-slides.json index ccde0900e2..289366009d 100644 --- a/packages/shared/src/app-definitions/google-slides.json +++ b/packages/shared/src/app-definitions/google-slides.json @@ -52,7 +52,6 @@ "defaults": { "serverUrl": "https://slidesmcp.googleapis.com/mcp/v1", "scopesHint": [ - "https://www.googleapis.com/auth/drive.readonly", "https://www.googleapis.com/auth/presentations.readonly" ] }, @@ -86,7 +85,6 @@ "tokenEndpoint": "https://oauth2.googleapis.com/token", "metadataUrl": "https://accounts.google.com/.well-known/openid-configuration", "scopesHint": [ - "https://www.googleapis.com/auth/drive.readonly", "https://www.googleapis.com/auth/presentations.readonly" ], "oauthAuthorizationParams": { @@ -127,8 +125,6 @@ "defaults": { "serverUrl": "https://slidesmcp.googleapis.com/mcp/v1", "scopesHint": [ - "https://www.googleapis.com/auth/drive.readonly", - "https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/presentations" ] }, @@ -163,8 +159,6 @@ "tokenEndpoint": "https://oauth2.googleapis.com/token", "metadataUrl": "https://accounts.google.com/.well-known/openid-configuration", "scopesHint": [ - "https://www.googleapis.com/auth/drive.readonly", - "https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/presentations" ], "oauthAuthorizationParams": { diff --git a/packages/shared/src/google-workspace-connectors.ts b/packages/shared/src/google-workspace-connectors.ts index 7f0d42b496..5800309de1 100644 --- a/packages/shared/src/google-workspace-connectors.ts +++ b/packages/shared/src/google-workspace-connectors.ts @@ -18,14 +18,14 @@ export const GOOGLE_WORKSPACE_CONNECTOR_PROFILES: Readonly