Google Drive — Tool Reference
Browse, read, and create files in the Google Drive files and folders you pick
Your AI assistant discovers and invokes these tools through the
MCP Server's meta tools —
it calls execute_tool with the tool name and arguments below.
# copy_file write
Copy a granted Drive file into a granted destination folder. BOTH ids must be reachable by this toolkit, and both are checked before anything is copied; a read-only destination is refused with that reason. Folders cannot be copied. The original is untouched. Pass an `idempotency_key` to make a retry safe. `account` is required: a write names the Google account it acts under rather than inferring one.
Full description
Copy one granted Drive file into a granted destination folder.
Both ends are checked before anything is copied, and both are Google's
decision rather than a Toolforest record: the source and the destination
are each fetched under the toolkit's `drive.file` credential, so an id that
was never picked for this account and was never created by these tools is a
Drive 404 surfaced as NotFoundError. A destination Drive reports as
`canAddChildren: false` is refused with that reason.
Args:
resource_id: Drive id of the granted file to copy.
parent_folder_id: Drive id of the granted folder to put the copy in.
name: Optional name for the copy; Drive names it if omitted.
idempotency_key: Optional key making a retry safe; see the field.
account: REQUIRED Google account (email) to write as; a mutation
never infers it. See the field for why.
Returns:
CopyFileResult describing the NEW file as Drive returned it — its own
id, resulting owner and My Drive / Shared Drive location — alongside the
source id and name, and `outcome` saying whether this call created the
copy, found it under a previously used key, or recovered it after an
unclear answer.
The source is not modified, moved or removed in any way; a copy is added at
the destination and that is the only change. Folders are refused up front:
Drive's copy operation does not copy folders, and this tool does not
simulate one by walking a folder's contents — under `drive.file` it cannot
see them.
An `idempotency_key` that matches a resource an earlier call already
created short-circuits BEFORE the checks above: nothing is copied, so
NEITHER the source nor the destination is read, and neither one's
permissions are consulted. The key decides what comes back in that case,
not `resource_id` — which is why `source_name` is null there.
The match must also be something a copy could BE. A key names one resource
across all four creating tools rather than one per tool, so it can match a
folder `create_folder` made; a folder is not a copy Drive could have
produced, so that is refused with the conflict named rather than returned as
this call's copy. Nothing is copied on that path either.
A copy is a NEW file, so it starts out granted to this toolkit and carries
the same `appProperties.sourceApp` tag as anything else created here. Note
that a copy of a Google Doc, Sheet or Slides file is still Google-native
and still cannot be handed to google_docs / google_sheets / google_slides
without being picked there first — Drive grants do not cross OAuth clients. | Parameter | Type | Required | Description |
|---|---|---|---|
resource_id | string | Yes | Drive id of the file to copy. It must be granted to this toolkit for this account — picked in the Toolforest picker, or created by these tools. Folders cannot be copied; Drive's copy operation covers files only. |
parent_folder_id | string | Yes | Drive id of the granted folder to place the COPY in. Required: this toolkit never picks a destination for you, and the copy is never placed beside the original by default. |
name | string | null | No | Name for the copy. Omit to let Drive name it, which yields "Copy of <original>" for a My Drive file. |
idempotency_key | string | null | No | Optional caller-chosen key that makes this creation safe to retry. Send a UUID. When set, the tool first looks for a resource an earlier call already created under the SAME key and returns that one instead of creating a second (`outcome` says which happened); the key is also stamped on whatever is created, and used to reconcile a request whose answer was lost in flight. The key is the identity: reusing one with different arguments returns the ORIGINAL resource unchanged rather than creating or updating anything. Omit it and no deduplication happens at all — a retry after an unclear outcome can create a second copy, which the error on that path says explicitly. Keys are matched only against resources this toolkit created for this Google account, never against picked files. A key whose resource has since been trashed does not match. One key names ONE resource across all four creating tools — it is not scoped per tool — so a key first used elsewhere can match here; when the resource it names is not the kind this tool returns (a folder to create_file, a Doc to upload_file, a spreadsheet to a `document` create), the call is REFUSED naming the conflict rather than handing back a resource mislabelled as what you asked for, and nothing is created. One caveat on the guarantee: the match is a Drive search-index query on appProperties, and Google documents no read-your-writes freshness for it — a retry issued immediately after a create may not see it yet and can still duplicate, so leave a moment between the two. |
account | string | Yes | Google account to write as (email, e.g. "alice.work@company.com"). REQUIRED, and deliberately not inferred: a mutation names the account it acts under, because a destination granted under more than one connected account would otherwise be written under a default the caller never chose, putting the new resource's ownership and provenance on the wrong account. Call list_accounts to see which accounts are connected, and pass the one whose grant covers the destination. Read tools take the same parameter as an optional override. |
Parameter schema (JSON)
{
"description": "Parameters for copy_file.",
"properties": {
"resource_id": {
"description": "Drive id of the file to copy. It must be granted to this toolkit for this account — picked in the Toolforest picker, or created by these tools. Folders cannot be copied; Drive's copy operation covers files only.",
"minLength": 1,
"title": "Resource Id",
"type": "string"
},
"parent_folder_id": {
"description": "Drive id of the granted folder to place the COPY in. Required: this toolkit never picks a destination for you, and the copy is never placed beside the original by default.",
"minLength": 1,
"title": "Parent Folder Id",
"type": "string"
},
"name": {
"anyOf": [
{
"maxLength": 255,
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Name for the copy. Omit to let Drive name it, which yields \"Copy of <original>\" for a My Drive file.",
"title": "Name"
},
"idempotency_key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional caller-chosen key that makes this creation safe to retry. Send a UUID. When set, the tool first looks for a resource an earlier call already created under the SAME key and returns that one instead of creating a second (`outcome` says which happened); the key is also stamped on whatever is created, and used to reconcile a request whose answer was lost in flight. The key is the identity: reusing one with different arguments returns the ORIGINAL resource unchanged rather than creating or updating anything. Omit it and no deduplication happens at all — a retry after an unclear outcome can create a second copy, which the error on that path says explicitly. Keys are matched only against resources this toolkit created for this Google account, never against picked files. A key whose resource has since been trashed does not match. One key names ONE resource across all four creating tools — it is not scoped per tool — so a key first used elsewhere can match here; when the resource it names is not the kind this tool returns (a folder to create_file, a Doc to upload_file, a spreadsheet to a `document` create), the call is REFUSED naming the conflict rather than handing back a resource mislabelled as what you asked for, and nothing is created. One caveat on the guarantee: the match is a Drive search-index query on appProperties, and Google documents no read-your-writes freshness for it — a retry issued immediately after a create may not see it yet and can still duplicate, so leave a moment between the two.",
"title": "Idempotency Key"
},
"account": {
"description": "Google account to write as (email, e.g. \"alice.work@company.com\"). REQUIRED, and deliberately not inferred: a mutation names the account it acts under, because a destination granted under more than one connected account would otherwise be written under a default the caller never chose, putting the new resource's ownership and provenance on the wrong account. Call list_accounts to see which accounts are connected, and pass the one whose grant covers the destination. Read tools take the same parameter as an optional override.",
"minLength": 1,
"title": "Account",
"type": "string"
}
},
"required": [
"resource_id",
"parent_folder_id",
"account"
],
"title": "CopyFileParams",
"type": "object",
"additionalProperties": false
} Result schema (JSON)
{
"description": "Result of copy_file.",
"properties": {
"resource_id": {
"description": "Drive file id of the resource, usable as `resource_id` on the other Google Drive tools for this same account.",
"title": "Resource Id",
"type": "string"
},
"name": {
"default": "",
"description": "The resource's name in Drive.",
"title": "Name",
"type": "string"
},
"mime_type": {
"default": "",
"description": "Drive MIME type of the resource.",
"title": "Mime Type",
"type": "string"
},
"is_folder": {
"default": false,
"description": "True for a Drive folder.",
"title": "Is Folder",
"type": "boolean"
},
"is_google_native": {
"default": false,
"description": "True for Google-native editor types (Docs, Sheets, Slides and the other application/vnd.google-apps.* types, folders included). Native files have no downloadable bytes: download_file refuses them, and only Docs, Sheets and Slides can be export_file'd.",
"title": "Is Google Native",
"type": "boolean"
},
"size_bytes": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Size in bytes as reported by Drive. Null means no usable size came back — Drive omits it for folders and for Google-native files — and never stands in for zero bytes.",
"title": "Size Bytes"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "RFC 3339 creation time from Drive.",
"title": "Created Time"
},
"modified_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "RFC 3339 last-modified time from Drive.",
"title": "Modified Time"
},
"location": {
"description": "`shared_drive` when Drive returns a `driveId` for the resulting resource, otherwise `my_drive`. Read from the create response, so it is where the resource actually landed.",
"enum": [
"my_drive",
"shared_drive"
],
"title": "Location",
"type": "string"
},
"drive_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Shared drive id, present only for shared-drive resources.",
"title": "Drive Id"
},
"parents": {
"description": "Parent folder ids as reported by Drive for the resulting resource. A parent id here is not itself a grant.",
"items": {
"type": "string"
},
"title": "Parents",
"type": "array"
},
"web_view_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Drive UI link, when Drive returns one.",
"title": "Web View Link"
},
"owners": {
"description": "Owner email addresses as Drive reports them for the RESULT. Drive does not populate owners for shared-drive items, so this is empty there rather than absent — it is not a claim that the resource is unowned.",
"items": {
"type": "string"
},
"title": "Owners",
"type": "array"
},
"capabilities": {
"additionalProperties": {
"type": "boolean"
},
"description": "Drive's `capabilities` for the resulting resource, limited to the boolean flags Drive returned; any non-boolean entry is dropped, and the map is empty when Drive returned none. `canAddChildren` on a created folder is Google's answer to whether more can be created inside it.",
"title": "Capabilities",
"type": "object"
},
"source_app_tag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Value of `appProperties.sourceApp` on the resource. Creation stamps the same tag the Toolforest picker writes, so a created resource and a picked one describe their origin identically. The tag is provenance, not the reason the resource is listed: list_granted_resources applies no `sourceApp` filter, and a created resource appears there because the toolkit's `drive.file` scope makes what it created visible to its own file listing. `registered_via` stays null on created resources, and is how the two are told apart there.",
"title": "Source App Tag"
},
"account": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Google account that served this request, as reported by Drive for the credential used. Null when that lookup failed — which does not affect whether the write happened. Compare it with `account_requested` to confirm the write landed where it was aimed.",
"title": "Account"
},
"account_requested": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The `account` this call named. Never null on a write result: the write tools require `account` rather than falling back to a default connected account.",
"title": "Account Requested"
},
"source_resource_id": {
"description": "The `resource_id` this call was asked to copy. It is echoed from the request, so on an `already_existed` outcome it names the file you asked about rather than the one the earlier call copied — the key, not the source, decides what comes back.",
"title": "Source Resource Id",
"type": "string"
},
"source_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Name of the source file in Drive. Null on an `already_existed` outcome: the idempotency key matched before the source was ever fetched, so no name was read. It is never an empty string standing in for an unread name.",
"title": "Source Name"
},
"outcome": {
"description": "`created` — this call created the resource. `already_existed` — an `idempotency_key` was supplied and matched a resource an earlier call had already created, AND that resource is of the kind this tool returns, so this call created nothing and every field below describes that earlier resource. (A match of a different kind is an error, not this outcome.) `recovered` — this call's request reached Google but its answer was lost, and the idempotency lookup afterwards found a resource of the kind this tool returns, proving the request had committed. (As with `already_existed`, a match of a different kind is reported as an unresolved outcome, never as this one.) Only `already_existed` means nothing was written by this call.",
"enum": [
"created",
"already_existed",
"recovered"
],
"title": "Outcome",
"type": "string"
},
"idempotency_key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The `idempotency_key` this call used, or null when none was supplied. Send the same one to retry safely — subject to the search-index freshness caveat on the parameter of the same name.",
"title": "Idempotency Key"
}
},
"required": [
"resource_id",
"location",
"source_resource_id",
"outcome"
],
"title": "CopyFileResult",
"type": "object"
} # create_file write
Create an EMPTY Google Doc, Sheet or Slides file in a granted destination folder and return its id and link. `parent_folder_id` is required; a read-only parent is refused before anything is created. Drive creates the resource — the google_docs / google_sheets / google_slides toolkits fill in its content, after the file is picked there (Drive grants do not cross OAuth clients). Pass an `idempotency_key` to make a retry safe. `account` is required: a write names the Google account it acts under rather than inferring one.
Full description
Create an empty Google Doc, Sheet or Slides file in a granted folder.
The destination is validated before anything is created: it is fetched
under the toolkit's `drive.file` credential, so a folder id that was never
picked for this account and was never created by these tools is a Drive 404
surfaced as NotFoundError, and a folder Drive reports as
`canAddChildren: false` is refused with that reason.
Args:
name: Name for the new file.
parent_folder_id: Drive id of the granted folder to create it in.
file_type: `document`, `spreadsheet` or `presentation`.
idempotency_key: Optional key making a retry safe; see the field.
account: REQUIRED Google account (email) to write as; a mutation
never infers it. See the field for why.
Returns:
CreateFileResult describing the file as Drive returned it — resulting
owner and My Drive / Shared Drive location included — plus the
`content_toolkit` that edits this type and `outcome` saying whether this
call created it, found it under a previously used key, or recovered it
after an unclear answer.
The file is created EMPTY and stays empty: this toolkit creates Drive
resources and does not author document content, and there is no `content`
parameter here for that reason. Writing into it is the matching toolkit's
job (google_docs, google_sheets, google_slides).
**Handing it over is not automatic.** Google scopes `drive.file` per OAuth
client and this toolkit has its own, so a file created here is granted to
Google Drive and not to google_docs / google_sheets / google_slides. Those
toolkits will report the id as not found until the user selects the file in
their picker as well. The `resource_id` and the Drive link are valid
regardless, and the other Google Drive tools on this account can use the id
immediately.
Like the other creating tools, this only ever adds a file; it does not
check for or replace a same-named file in the destination, which under
`drive.file` it could not see anyway.
An `idempotency_key` that matches a resource an earlier call already
created short-circuits BEFORE the checks above: nothing is created, so
the destination is never read and its permissions are never consulted.
The key decides what comes back in that case, not the other arguments.
The match must also BE the kind of resource this tool returns. A key names
one resource across all four creating tools rather than one per tool, so it
can match something another tool made; when it does and this tool could not
describe that resource truthfully, the call is refused with the conflict
named — nothing is created then either, and no mislabelled resource is
handed back. | Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Name for the new file, as it will appear in Drive. |
parent_folder_id | string | Yes | Drive id of the granted folder to create the file IN. Required: this toolkit never picks a destination for you and has no default location. Use list_granted_resources with `grant_type=folder`. |
file_type | "document" | "spreadsheet" | "presentation" | Yes | Which Google-native file to create: `document` (Google Docs), `spreadsheet` (Google Sheets) or `presentation` (Google Slides). The file is created EMPTY — Drive creates resources, it does not author content. To upload bytes of any other type, use upload_file. |
idempotency_key | string | null | No | Optional caller-chosen key that makes this creation safe to retry. Send a UUID. When set, the tool first looks for a resource an earlier call already created under the SAME key and returns that one instead of creating a second (`outcome` says which happened); the key is also stamped on whatever is created, and used to reconcile a request whose answer was lost in flight. The key is the identity: reusing one with different arguments returns the ORIGINAL resource unchanged rather than creating or updating anything. Omit it and no deduplication happens at all — a retry after an unclear outcome can create a second copy, which the error on that path says explicitly. Keys are matched only against resources this toolkit created for this Google account, never against picked files. A key whose resource has since been trashed does not match. One key names ONE resource across all four creating tools — it is not scoped per tool — so a key first used elsewhere can match here; when the resource it names is not the kind this tool returns (a folder to create_file, a Doc to upload_file, a spreadsheet to a `document` create), the call is REFUSED naming the conflict rather than handing back a resource mislabelled as what you asked for, and nothing is created. One caveat on the guarantee: the match is a Drive search-index query on appProperties, and Google documents no read-your-writes freshness for it — a retry issued immediately after a create may not see it yet and can still duplicate, so leave a moment between the two. |
account | string | Yes | Google account to write as (email, e.g. "alice.work@company.com"). REQUIRED, and deliberately not inferred: a mutation names the account it acts under, because a destination granted under more than one connected account would otherwise be written under a default the caller never chose, putting the new resource's ownership and provenance on the wrong account. Call list_accounts to see which accounts are connected, and pass the one whose grant covers the destination. Read tools take the same parameter as an optional override. |
Parameter schema (JSON)
{
"description": "Parameters for create_file.",
"properties": {
"name": {
"description": "Name for the new file, as it will appear in Drive.",
"maxLength": 255,
"minLength": 1,
"title": "Name",
"type": "string"
},
"parent_folder_id": {
"description": "Drive id of the granted folder to create the file IN. Required: this toolkit never picks a destination for you and has no default location. Use list_granted_resources with `grant_type=folder`.",
"minLength": 1,
"title": "Parent Folder Id",
"type": "string"
},
"file_type": {
"description": "Which Google-native file to create: `document` (Google Docs), `spreadsheet` (Google Sheets) or `presentation` (Google Slides). The file is created EMPTY — Drive creates resources, it does not author content. To upload bytes of any other type, use upload_file.",
"enum": [
"document",
"spreadsheet",
"presentation"
],
"title": "File Type",
"type": "string"
},
"idempotency_key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional caller-chosen key that makes this creation safe to retry. Send a UUID. When set, the tool first looks for a resource an earlier call already created under the SAME key and returns that one instead of creating a second (`outcome` says which happened); the key is also stamped on whatever is created, and used to reconcile a request whose answer was lost in flight. The key is the identity: reusing one with different arguments returns the ORIGINAL resource unchanged rather than creating or updating anything. Omit it and no deduplication happens at all — a retry after an unclear outcome can create a second copy, which the error on that path says explicitly. Keys are matched only against resources this toolkit created for this Google account, never against picked files. A key whose resource has since been trashed does not match. One key names ONE resource across all four creating tools — it is not scoped per tool — so a key first used elsewhere can match here; when the resource it names is not the kind this tool returns (a folder to create_file, a Doc to upload_file, a spreadsheet to a `document` create), the call is REFUSED naming the conflict rather than handing back a resource mislabelled as what you asked for, and nothing is created. One caveat on the guarantee: the match is a Drive search-index query on appProperties, and Google documents no read-your-writes freshness for it — a retry issued immediately after a create may not see it yet and can still duplicate, so leave a moment between the two.",
"title": "Idempotency Key"
},
"account": {
"description": "Google account to write as (email, e.g. \"alice.work@company.com\"). REQUIRED, and deliberately not inferred: a mutation names the account it acts under, because a destination granted under more than one connected account would otherwise be written under a default the caller never chose, putting the new resource's ownership and provenance on the wrong account. Call list_accounts to see which accounts are connected, and pass the one whose grant covers the destination. Read tools take the same parameter as an optional override.",
"minLength": 1,
"title": "Account",
"type": "string"
}
},
"required": [
"name",
"parent_folder_id",
"file_type",
"account"
],
"title": "CreateFileParams",
"type": "object",
"additionalProperties": false
} Result schema (JSON)
{
"description": "Result of create_file.",
"properties": {
"resource_id": {
"description": "Drive file id of the resource, usable as `resource_id` on the other Google Drive tools for this same account.",
"title": "Resource Id",
"type": "string"
},
"name": {
"default": "",
"description": "The resource's name in Drive.",
"title": "Name",
"type": "string"
},
"mime_type": {
"default": "",
"description": "Drive MIME type of the resource.",
"title": "Mime Type",
"type": "string"
},
"is_folder": {
"default": false,
"description": "True for a Drive folder.",
"title": "Is Folder",
"type": "boolean"
},
"is_google_native": {
"default": false,
"description": "True for Google-native editor types (Docs, Sheets, Slides and the other application/vnd.google-apps.* types, folders included). Native files have no downloadable bytes: download_file refuses them, and only Docs, Sheets and Slides can be export_file'd.",
"title": "Is Google Native",
"type": "boolean"
},
"size_bytes": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Size in bytes as reported by Drive. Null means no usable size came back — Drive omits it for folders and for Google-native files — and never stands in for zero bytes.",
"title": "Size Bytes"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "RFC 3339 creation time from Drive.",
"title": "Created Time"
},
"modified_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "RFC 3339 last-modified time from Drive.",
"title": "Modified Time"
},
"location": {
"description": "`shared_drive` when Drive returns a `driveId` for the resulting resource, otherwise `my_drive`. Read from the create response, so it is where the resource actually landed.",
"enum": [
"my_drive",
"shared_drive"
],
"title": "Location",
"type": "string"
},
"drive_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Shared drive id, present only for shared-drive resources.",
"title": "Drive Id"
},
"parents": {
"description": "Parent folder ids as reported by Drive for the resulting resource. A parent id here is not itself a grant.",
"items": {
"type": "string"
},
"title": "Parents",
"type": "array"
},
"web_view_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Drive UI link, when Drive returns one.",
"title": "Web View Link"
},
"owners": {
"description": "Owner email addresses as Drive reports them for the RESULT. Drive does not populate owners for shared-drive items, so this is empty there rather than absent — it is not a claim that the resource is unowned.",
"items": {
"type": "string"
},
"title": "Owners",
"type": "array"
},
"capabilities": {
"additionalProperties": {
"type": "boolean"
},
"description": "Drive's `capabilities` for the resulting resource, limited to the boolean flags Drive returned; any non-boolean entry is dropped, and the map is empty when Drive returned none. `canAddChildren` on a created folder is Google's answer to whether more can be created inside it.",
"title": "Capabilities",
"type": "object"
},
"source_app_tag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Value of `appProperties.sourceApp` on the resource. Creation stamps the same tag the Toolforest picker writes, so a created resource and a picked one describe their origin identically. The tag is provenance, not the reason the resource is listed: list_granted_resources applies no `sourceApp` filter, and a created resource appears there because the toolkit's `drive.file` scope makes what it created visible to its own file listing. `registered_via` stays null on created resources, and is how the two are told apart there.",
"title": "Source App Tag"
},
"account": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Google account that served this request, as reported by Drive for the credential used. Null when that lookup failed — which does not affect whether the write happened. Compare it with `account_requested` to confirm the write landed where it was aimed.",
"title": "Account"
},
"account_requested": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The `account` this call named. Never null on a write result: the write tools require `account` rather than falling back to a default connected account.",
"title": "Account Requested"
},
"file_type": {
"description": "The requested Google-native file type.",
"enum": [
"document",
"spreadsheet",
"presentation"
],
"title": "File Type",
"type": "string"
},
"outcome": {
"description": "`created` — this call created the resource. `already_existed` — an `idempotency_key` was supplied and matched a resource an earlier call had already created, AND that resource is of the kind this tool returns, so this call created nothing and every field below describes that earlier resource. (A match of a different kind is an error, not this outcome.) `recovered` — this call's request reached Google but its answer was lost, and the idempotency lookup afterwards found a resource of the kind this tool returns, proving the request had committed. (As with `already_existed`, a match of a different kind is reported as an unresolved outcome, never as this one.) Only `already_existed` means nothing was written by this call.",
"enum": [
"created",
"already_existed",
"recovered"
],
"title": "Outcome",
"type": "string"
},
"idempotency_key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The `idempotency_key` this call used, or null when none was supplied. Send the same one to retry safely — subject to the search-index freshness caveat on the parameter of the same name.",
"title": "Idempotency Key"
},
"content_toolkit": {
"description": "The Toolforest toolkit that edits this file type's content: google_docs, google_sheets or google_slides. `resource_id` is the id those toolkits call a document / spreadsheet / presentation id, so it can be passed straight across. READ THE CAVEAT: Google grants `drive.file` access per OAuth client, and this toolkit has its own client, so the grant on a file created here does NOT carry over to those toolkits. Until the file is also selected in that toolkit's own Toolforest picker, it will answer 'not found' for this id. The id and the link are correct either way, and the file is immediately usable in the Drive UI and through the other Google Drive tools on this account.",
"title": "Content Toolkit",
"type": "string"
}
},
"required": [
"resource_id",
"location",
"file_type",
"outcome",
"content_toolkit"
],
"title": "CreateFileResult",
"type": "object"
} # create_folder write
Create a new folder inside a granted destination folder. `parent_folder_id` is required — there is no default location and no inference from context. A parent Drive reports as read-only (`canAddChildren` false) is refused before anything is created. Pass an `idempotency_key` to make a retry safe. `account` is required: a write names the Google account it acts under rather than inferring one. Creates only: this tool never moves, renames or removes anything.
Full description
Create a folder inside a Drive folder this toolkit has been granted.
The parent is validated before anything is created: it is fetched under the
toolkit's `drive.file` credential, so a folder id that was never picked in
the Toolforest picker for this account and was never created by these tools
is a Drive 404 surfaced as NotFoundError. If Drive reports
`capabilities.canAddChildren: false` for it, this refuses with that reason
— approving a folder in the picker registers it as a destination and does
not grant permission to write in it.
Args:
name: Name for the new folder.
parent_folder_id: Drive id of the granted folder to create it inside.
idempotency_key: Optional key making a retry safe; see the field.
account: REQUIRED Google account (email) to write as; a mutation
never infers it. See the field for why.
Returns:
CreateFolderResult describing the folder as Drive returned it —
including the resulting owner and My Drive / Shared Drive location
rather than an assumption that the creating account owns it — plus
`outcome` saying whether this call created it, found it under a
previously used key, or recovered it after an unclear answer.
The new folder appears in list_granted_resources and can be used as a
destination by the other write tools straight away — that follows from the
`drive.file` scope, under which anything this toolkit created is visible to
its own listing. It is also stamped with the same `appProperties.sourceApp`
tag the picker writes, which records where it came from rather than making
it listable.
An `idempotency_key` that matches a resource an earlier call already
created short-circuits BEFORE the checks above: nothing is created, so
the destination is never read and its permissions are never consulted.
The key decides what comes back in that case, not the other arguments.
The match must also BE the kind of resource this tool returns. A key names
one resource across all four creating tools rather than one per tool, so it
can match something another tool made; when it does and this tool could not
describe that resource truthfully, the call is refused with the conflict
named — nothing is created then either, and no mislabelled resource is
handed back.
Two things it does NOT do. It does not merge with, or check for, a folder
of the same name already in the parent: Drive permits same-named siblings,
and under `drive.file` this toolkit cannot see a granted folder's existing
contents to check (approving a folder is not a read grant over it), so no
such check could be honest. Only `idempotency_key` prevents a duplicate,
and only against a folder these tools created under that same key. And it
never removes or relocates anything — the folder is added, nothing else
changes. | Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Name for the new folder, as it will appear in Drive. |
parent_folder_id | string | Yes | Drive id of the folder to create the new folder INSIDE. Required: this toolkit never picks a destination for you and has no default location. It must be a folder granted to this toolkit for this account — one approved in the Toolforest picker, or one these tools created — and one Drive reports as writable. Use list_granted_resources with `grant_type=folder` to see them and their `can_add_children`. |
idempotency_key | string | null | No | Optional caller-chosen key that makes this creation safe to retry. Send a UUID. When set, the tool first looks for a resource an earlier call already created under the SAME key and returns that one instead of creating a second (`outcome` says which happened); the key is also stamped on whatever is created, and used to reconcile a request whose answer was lost in flight. The key is the identity: reusing one with different arguments returns the ORIGINAL resource unchanged rather than creating or updating anything. Omit it and no deduplication happens at all — a retry after an unclear outcome can create a second copy, which the error on that path says explicitly. Keys are matched only against resources this toolkit created for this Google account, never against picked files. A key whose resource has since been trashed does not match. One key names ONE resource across all four creating tools — it is not scoped per tool — so a key first used elsewhere can match here; when the resource it names is not the kind this tool returns (a folder to create_file, a Doc to upload_file, a spreadsheet to a `document` create), the call is REFUSED naming the conflict rather than handing back a resource mislabelled as what you asked for, and nothing is created. One caveat on the guarantee: the match is a Drive search-index query on appProperties, and Google documents no read-your-writes freshness for it — a retry issued immediately after a create may not see it yet and can still duplicate, so leave a moment between the two. |
account | string | Yes | Google account to write as (email, e.g. "alice.work@company.com"). REQUIRED, and deliberately not inferred: a mutation names the account it acts under, because a destination granted under more than one connected account would otherwise be written under a default the caller never chose, putting the new resource's ownership and provenance on the wrong account. Call list_accounts to see which accounts are connected, and pass the one whose grant covers the destination. Read tools take the same parameter as an optional override. |
Parameter schema (JSON)
{
"description": "Parameters for create_folder.",
"properties": {
"name": {
"description": "Name for the new folder, as it will appear in Drive.",
"maxLength": 255,
"minLength": 1,
"title": "Name",
"type": "string"
},
"parent_folder_id": {
"description": "Drive id of the folder to create the new folder INSIDE. Required: this toolkit never picks a destination for you and has no default location. It must be a folder granted to this toolkit for this account — one approved in the Toolforest picker, or one these tools created — and one Drive reports as writable. Use list_granted_resources with `grant_type=folder` to see them and their `can_add_children`.",
"minLength": 1,
"title": "Parent Folder Id",
"type": "string"
},
"idempotency_key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional caller-chosen key that makes this creation safe to retry. Send a UUID. When set, the tool first looks for a resource an earlier call already created under the SAME key and returns that one instead of creating a second (`outcome` says which happened); the key is also stamped on whatever is created, and used to reconcile a request whose answer was lost in flight. The key is the identity: reusing one with different arguments returns the ORIGINAL resource unchanged rather than creating or updating anything. Omit it and no deduplication happens at all — a retry after an unclear outcome can create a second copy, which the error on that path says explicitly. Keys are matched only against resources this toolkit created for this Google account, never against picked files. A key whose resource has since been trashed does not match. One key names ONE resource across all four creating tools — it is not scoped per tool — so a key first used elsewhere can match here; when the resource it names is not the kind this tool returns (a folder to create_file, a Doc to upload_file, a spreadsheet to a `document` create), the call is REFUSED naming the conflict rather than handing back a resource mislabelled as what you asked for, and nothing is created. One caveat on the guarantee: the match is a Drive search-index query on appProperties, and Google documents no read-your-writes freshness for it — a retry issued immediately after a create may not see it yet and can still duplicate, so leave a moment between the two.",
"title": "Idempotency Key"
},
"account": {
"description": "Google account to write as (email, e.g. \"alice.work@company.com\"). REQUIRED, and deliberately not inferred: a mutation names the account it acts under, because a destination granted under more than one connected account would otherwise be written under a default the caller never chose, putting the new resource's ownership and provenance on the wrong account. Call list_accounts to see which accounts are connected, and pass the one whose grant covers the destination. Read tools take the same parameter as an optional override.",
"minLength": 1,
"title": "Account",
"type": "string"
}
},
"required": [
"name",
"parent_folder_id",
"account"
],
"title": "CreateFolderParams",
"type": "object",
"additionalProperties": false
} Result schema (JSON)
{
"description": "Result of create_folder.",
"properties": {
"resource_id": {
"description": "Drive file id of the resource, usable as `resource_id` on the other Google Drive tools for this same account.",
"title": "Resource Id",
"type": "string"
},
"name": {
"default": "",
"description": "The resource's name in Drive.",
"title": "Name",
"type": "string"
},
"mime_type": {
"default": "",
"description": "Drive MIME type of the resource.",
"title": "Mime Type",
"type": "string"
},
"is_folder": {
"default": false,
"description": "True for a Drive folder.",
"title": "Is Folder",
"type": "boolean"
},
"is_google_native": {
"default": false,
"description": "True for Google-native editor types (Docs, Sheets, Slides and the other application/vnd.google-apps.* types, folders included). Native files have no downloadable bytes: download_file refuses them, and only Docs, Sheets and Slides can be export_file'd.",
"title": "Is Google Native",
"type": "boolean"
},
"size_bytes": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Size in bytes as reported by Drive. Null means no usable size came back — Drive omits it for folders and for Google-native files — and never stands in for zero bytes.",
"title": "Size Bytes"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "RFC 3339 creation time from Drive.",
"title": "Created Time"
},
"modified_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "RFC 3339 last-modified time from Drive.",
"title": "Modified Time"
},
"location": {
"description": "`shared_drive` when Drive returns a `driveId` for the resulting resource, otherwise `my_drive`. Read from the create response, so it is where the resource actually landed.",
"enum": [
"my_drive",
"shared_drive"
],
"title": "Location",
"type": "string"
},
"drive_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Shared drive id, present only for shared-drive resources.",
"title": "Drive Id"
},
"parents": {
"description": "Parent folder ids as reported by Drive for the resulting resource. A parent id here is not itself a grant.",
"items": {
"type": "string"
},
"title": "Parents",
"type": "array"
},
"web_view_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Drive UI link, when Drive returns one.",
"title": "Web View Link"
},
"owners": {
"description": "Owner email addresses as Drive reports them for the RESULT. Drive does not populate owners for shared-drive items, so this is empty there rather than absent — it is not a claim that the resource is unowned.",
"items": {
"type": "string"
},
"title": "Owners",
"type": "array"
},
"capabilities": {
"additionalProperties": {
"type": "boolean"
},
"description": "Drive's `capabilities` for the resulting resource, limited to the boolean flags Drive returned; any non-boolean entry is dropped, and the map is empty when Drive returned none. `canAddChildren` on a created folder is Google's answer to whether more can be created inside it.",
"title": "Capabilities",
"type": "object"
},
"source_app_tag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Value of `appProperties.sourceApp` on the resource. Creation stamps the same tag the Toolforest picker writes, so a created resource and a picked one describe their origin identically. The tag is provenance, not the reason the resource is listed: list_granted_resources applies no `sourceApp` filter, and a created resource appears there because the toolkit's `drive.file` scope makes what it created visible to its own file listing. `registered_via` stays null on created resources, and is how the two are told apart there.",
"title": "Source App Tag"
},
"account": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Google account that served this request, as reported by Drive for the credential used. Null when that lookup failed — which does not affect whether the write happened. Compare it with `account_requested` to confirm the write landed where it was aimed.",
"title": "Account"
},
"account_requested": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The `account` this call named. Never null on a write result: the write tools require `account` rather than falling back to a default connected account.",
"title": "Account Requested"
},
"outcome": {
"description": "`created` — this call created the resource. `already_existed` — an `idempotency_key` was supplied and matched a resource an earlier call had already created, AND that resource is of the kind this tool returns, so this call created nothing and every field below describes that earlier resource. (A match of a different kind is an error, not this outcome.) `recovered` — this call's request reached Google but its answer was lost, and the idempotency lookup afterwards found a resource of the kind this tool returns, proving the request had committed. (As with `already_existed`, a match of a different kind is reported as an unresolved outcome, never as this one.) Only `already_existed` means nothing was written by this call.",
"enum": [
"created",
"already_existed",
"recovered"
],
"title": "Outcome",
"type": "string"
},
"idempotency_key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The `idempotency_key` this call used, or null when none was supplied. Send the same one to retry safely — subject to the search-index freshness caveat on the parameter of the same name.",
"title": "Idempotency Key"
}
},
"required": [
"resource_id",
"location",
"outcome"
],
"title": "CreateFolderResult",
"type": "object"
} # download_file read
Download a granted non-Google file's bytes as base64, up to 3 MiB. Use for uploaded files (PDF, images, CSV, zip). Google Docs/Sheets/Slides have no downloadable bytes — use export_file for those; the remaining native types (folders, Forms, Drawings, Sites) have no content route at all. Oversized files are refused, never truncated.
Full description
Download the bytes of one granted, non-Google-native Drive file.
Access is Google's decision: the request runs under the toolkit's
`drive.file` credential, so a file that was never picked in the Toolforest
picker for this account and was never created by Toolforest returns a
Drive 404, surfaced as NotFoundError.
Args:
resource_id: Drive file id of a non-Google-native file.
account: Google account override (email); omit for the default account.
Returns:
DownloadFileResult with the file's complete content base64-encoded in
`data`, its decoded length, MIME type, and the account that served the
call.
Two refusals, both errors rather than partial results. Any Google-native
file (anything `application/vnd.google-apps.*`) is refused, because those
have no stored bytes to fetch — and the refusal points only where that
type can actually go: a Doc, Sheet or Slides file is sent to export_file
with its available formats, while a folder, Form, Drawing or Site is told
that export_file refuses it too, since it handles only those three. A file
whose size exceeds 3 MiB is refused before any bytes are fetched when
Drive reports its size, and after the fetch when Drive reports none; the
content is never truncated to fit. The 3 MiB ceiling exists because the
response travels inline through Lambda's 6 MB payload limit and base64
inflates bytes by a third. | Parameter | Type | Required | Description |
|---|---|---|---|
resource_id | string | Yes | Drive file id of a NON-Google-native file (an uploaded PDF, image, CSV, zip and so on). Google Docs/Sheets/Slides have no downloadable bytes — use export_file for those. Folders, Forms, Drawings and Sites have neither downloadable nor exportable bytes; only get_file_metadata works on them. |
account | string | null | No | Optional Google account override (email, e.g. "alice.work@company.com"). Omit to use the user's default connected Google account for this MCP client. Call list_accounts to see which accounts are connected. |
Parameter schema (JSON)
{
"description": "Parameters for download_file.",
"properties": {
"resource_id": {
"description": "Drive file id of a NON-Google-native file (an uploaded PDF, image, CSV, zip and so on). Google Docs/Sheets/Slides have no downloadable bytes — use export_file for those. Folders, Forms, Drawings and Sites have neither downloadable nor exportable bytes; only get_file_metadata works on them.",
"minLength": 1,
"title": "Resource Id",
"type": "string"
},
"account": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional Google account override (email, e.g. \"alice.work@company.com\"). Omit to use the user's default connected Google account for this MCP client. Call list_accounts to see which accounts are connected.",
"title": "Account"
}
},
"required": [
"resource_id"
],
"title": "DownloadFileParams",
"type": "object",
"additionalProperties": false
} Result schema (JSON)
{
"description": "Result of download_file.",
"properties": {
"resource_id": {
"description": "Drive file id of the downloaded file.",
"title": "Resource Id",
"type": "string"
},
"name": {
"default": "",
"description": "The file's name in Drive.",
"title": "Name",
"type": "string"
},
"mime_type": {
"default": "",
"description": "Drive MIME type of the downloaded bytes.",
"title": "Mime Type",
"type": "string"
},
"size_bytes": {
"description": "Length in bytes of the decoded content returned in `data`.",
"title": "Size Bytes",
"type": "integer"
},
"encoding": {
"const": "base64",
"default": "base64",
"description": "Encoding of `data`: standard base64 (RFC 4648 §4).",
"title": "Encoding",
"type": "string"
},
"data": {
"description": "The file's complete content, base64-encoded. Never truncated: a file larger than the inline limit is refused with an error instead of being partially returned.",
"title": "Data",
"type": "string"
},
"location": {
"description": "`shared_drive` when Drive returns a `driveId` for the file, otherwise `my_drive`.",
"enum": [
"my_drive",
"shared_drive"
],
"title": "Location",
"type": "string"
},
"account": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Google account that served this request, as reported by Drive for the credential used. Null when that lookup failed.",
"title": "Account"
},
"account_requested": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The `account` override passed to this call, or null when the toolkit's default connected account was used.",
"title": "Account Requested"
}
},
"required": [
"resource_id",
"size_bytes",
"data",
"location"
],
"title": "DownloadFileResult",
"type": "object"
} # export_file read
Export a granted Google Doc, Sheet or Slides file to PDF, DOCX, XLSX, PPTX, CSV, TSV, ODF, HTML, EPUB, Markdown or plain text and return it as base64, up to 3 MiB. CSV/TSV of a Sheet cover the first sheet only. Oversized exports are refused, never truncated.
Full description
Export one granted Google Docs, Sheets or Slides file to another format.
Access is Google's decision: the export runs under the toolkit's
`drive.file` credential, so a file that was never picked in the Toolforest
picker for this account and was never created by Toolforest returns a
Drive 404, surfaced as NotFoundError.
Args:
resource_id: Drive file id of a Google Doc, Sheet or Slides file.
export_format: Target format; see the field description for which
formats Drive offers per source type.
account: Google account override (email); omit for the default account.
Returns:
ExportFileResult with the exported bytes base64-encoded in `data`,
their decoded length, the MIME type Drive exported to, a suggested
filename, and the account that served the call.
Three things this tool does not do, each an error rather than a surprise
in the output. It does not export uploaded (non-native) files — those are
refused with a pointer to download_file. It does not export the
Google-native types outside Docs, Sheets and Slides (Forms, Drawings,
Sites, folders); those are refused too. And it never truncates: an export
whose bytes exceed 3 MiB is refused after Drive produces it, because Drive
does not report an export's size in advance. The 3 MiB ceiling exists
because the response travels inline through Lambda's 6 MB payload limit
and base64 inflates bytes by a third.
One conversion caveat comes from Drive itself: exporting a Google Sheet as
`csv` or `tsv` yields only the FIRST sheet of the spreadsheet. Use `xlsx`
or `ods` to keep every sheet. | Parameter | Type | Required | Description |
|---|---|---|---|
resource_id | string | Yes | Drive file id of a granted Google Doc, Sheet or Slides presentation. Uploaded (non-native) files are not exported — use download_file for those. |
export_format | "pdf" | "docx" | "odt" | "rtf" | "txt" | "html" | "epub" | "md" | "xlsx" | "ods" | "csv" | "tsv" | "pptx" | "odp" | Yes | Target format. Google Docs: pdf, docx, odt, rtf, txt, html, epub, md. Google Sheets: pdf, xlsx, ods, csv, tsv. Google Slides: pdf, pptx, odp, txt. A format Drive does not offer for the source type is rejected before the export is attempted. |
account | string | null | No | Optional Google account override (email, e.g. "alice.work@company.com"). Omit to use the user's default connected Google account for this MCP client. Call list_accounts to see which accounts are connected. |
Parameter schema (JSON)
{
"description": "Parameters for export_file.",
"properties": {
"resource_id": {
"description": "Drive file id of a granted Google Doc, Sheet or Slides presentation. Uploaded (non-native) files are not exported — use download_file for those.",
"minLength": 1,
"title": "Resource Id",
"type": "string"
},
"export_format": {
"description": "Target format. Google Docs: pdf, docx, odt, rtf, txt, html, epub, md. Google Sheets: pdf, xlsx, ods, csv, tsv. Google Slides: pdf, pptx, odp, txt. A format Drive does not offer for the source type is rejected before the export is attempted.",
"enum": [
"pdf",
"docx",
"odt",
"rtf",
"txt",
"html",
"epub",
"md",
"xlsx",
"ods",
"csv",
"tsv",
"pptx",
"odp"
],
"title": "Export Format",
"type": "string"
},
"account": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional Google account override (email, e.g. \"alice.work@company.com\"). Omit to use the user's default connected Google account for this MCP client. Call list_accounts to see which accounts are connected.",
"title": "Account"
}
},
"required": [
"resource_id",
"export_format"
],
"title": "ExportFileParams",
"type": "object",
"additionalProperties": false
} Result schema (JSON)
{
"description": "Result of export_file.",
"properties": {
"resource_id": {
"description": "Drive file id of the exported resource.",
"title": "Resource Id",
"type": "string"
},
"name": {
"default": "",
"description": "The source file's name in Drive.",
"title": "Name",
"type": "string"
},
"source_mime_type": {
"default": "",
"description": "Google-native MIME type of the source file.",
"title": "Source Mime Type",
"type": "string"
},
"export_format": {
"description": "The requested target format.",
"title": "Export Format",
"type": "string"
},
"export_mime_type": {
"description": "MIME type Drive was asked to export to.",
"title": "Export Mime Type",
"type": "string"
},
"suggested_filename": {
"description": "The source name with the format's extension appended; path separators and control characters are replaced with underscores, and a name left empty by that cleaning becomes `export`. A suggestion only — this tool writes nothing anywhere.",
"title": "Suggested Filename",
"type": "string"
},
"size_bytes": {
"description": "Length in bytes of the decoded exported content in `data`.",
"title": "Size Bytes",
"type": "integer"
},
"encoding": {
"const": "base64",
"default": "base64",
"description": "Encoding of `data`: standard base64 (RFC 4648 §4).",
"title": "Encoding",
"type": "string"
},
"data": {
"description": "The complete exported content, base64-encoded. Never truncated: an export over the inline limit is refused with an error instead of being partially returned.",
"title": "Data",
"type": "string"
},
"location": {
"description": "`shared_drive` when Drive returns a `driveId` for the source file, otherwise `my_drive`.",
"enum": [
"my_drive",
"shared_drive"
],
"title": "Location",
"type": "string"
},
"account": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Google account that served this request, as reported by Drive for the credential used. Null when that lookup failed.",
"title": "Account"
},
"account_requested": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The `account` override passed to this call, or null when the toolkit's default connected account was used.",
"title": "Account Requested"
}
},
"required": [
"resource_id",
"export_format",
"export_mime_type",
"suggested_filename",
"size_bytes",
"data",
"location"
],
"title": "ExportFileResult",
"type": "object"
} # get_file_metadata read
Get name, MIME type, size, timestamps, owners, Drive capabilities, My Drive vs Shared Drive location and account provenance for one granted Drive resource. A resource id that has not been granted to this toolkit is refused by Google rather than fetched.
Full description
Describe one Drive file or folder that this toolkit has been granted.
Access is decided by Google: the request runs under the toolkit's
`drive.file` credential, so a resource id that was never picked in the
Toolforest picker for this account and was never created by Toolforest
under this OAuth client returns a Drive 404, surfaced here as
NotFoundError. Passing an id found some other way does not widen access.
Args:
resource_id: Drive file or folder id.
account: Google account override (email); omit for the default account.
Returns:
GetFileMetadataResult with the resource's name, MIME type, size,
timestamps, parents, owners, Drive capabilities, whether it lives in
My Drive or a Shared Drive, and which Google account served the call.
Two fields carry caveats worth reading before relying on them: `owners` is
empty for shared-drive items because Drive does not populate it there, and
`size_bytes` is null wherever Drive reports no size (folders, shortcuts)
rather than reporting zero. For a folder, this describes the folder only —
it says nothing about the files inside it, which the folder's approval
does not grant. | Parameter | Type | Required | Description |
|---|---|---|---|
resource_id | string | Yes | Drive file or folder id, from list_granted_resources or from a Toolforest-created resource. An id that has not been granted to this toolkit for this account is refused by Google, not fetched. |
account | string | null | No | Optional Google account override (email, e.g. "alice.work@company.com"). Omit to use the user's default connected Google account for this MCP client. Call list_accounts to see which accounts are connected. |
Parameter schema (JSON)
{
"description": "Parameters for get_file_metadata.",
"properties": {
"resource_id": {
"description": "Drive file or folder id, from list_granted_resources or from a Toolforest-created resource. An id that has not been granted to this toolkit for this account is refused by Google, not fetched.",
"minLength": 1,
"title": "Resource Id",
"type": "string"
},
"account": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional Google account override (email, e.g. \"alice.work@company.com\"). Omit to use the user's default connected Google account for this MCP client. Call list_accounts to see which accounts are connected.",
"title": "Account"
}
},
"required": [
"resource_id"
],
"title": "GetFileMetadataParams",
"type": "object",
"additionalProperties": false
} Result schema (JSON)
{
"description": "Result of get_file_metadata.",
"properties": {
"resource_id": {
"description": "Drive file id of the resource.",
"title": "Resource Id",
"type": "string"
},
"name": {
"default": "",
"description": "The resource's name in Drive.",
"title": "Name",
"type": "string"
},
"mime_type": {
"default": "",
"description": "Drive MIME type of the resource.",
"title": "Mime Type",
"type": "string"
},
"is_folder": {
"default": false,
"description": "True for a Drive folder. A granted folder is registered as a creation destination; its existing contents are not reachable through it, and whether creation is actually permitted is Drive's `capabilities.canAddChildren`, reported in `capabilities` below.",
"title": "Is Folder",
"type": "boolean"
},
"is_google_native": {
"default": false,
"description": "True for Google-native editor types (Docs, Sheets, Slides, and the other application/vnd.google-apps.* types, folders included). Native files have no downloadable bytes, so download_file refuses them all. Only Docs, Sheets and Slides have an alternative: export_file. The rest (folders, Forms, Drawings, Sites) have no content route through this toolkit at all.",
"title": "Is Google Native",
"type": "boolean"
},
"size_bytes": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Size in bytes as reported by Drive. Null means no usable size came back — Drive omits it for folders and shortcuts, and an unparseable value lands here too. It never stands in for zero bytes.",
"title": "Size Bytes"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "RFC 3339 creation time from Drive.",
"title": "Created Time"
},
"modified_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "RFC 3339 last-modified time from Drive.",
"title": "Modified Time"
},
"location": {
"description": "`shared_drive` when Drive returns a `driveId` for the resource, otherwise `my_drive`.",
"enum": [
"my_drive",
"shared_drive"
],
"title": "Location",
"type": "string"
},
"drive_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Shared drive id, present only for shared-drive resources.",
"title": "Drive Id"
},
"shared": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"description": "Drive's `shared` flag, when Drive reports it.",
"title": "Shared"
},
"trashed": {
"default": false,
"description": "True when the resource is in the Drive trash.",
"title": "Trashed",
"type": "boolean"
},
"parents": {
"description": "Parent folder ids as reported by Drive. A parent id here is not itself a grant.",
"items": {
"type": "string"
},
"title": "Parents",
"type": "array"
},
"owners": {
"description": "Owner email addresses. Drive does not populate owners for shared-drive items, so this is empty there rather than absent.",
"items": {
"type": "string"
},
"title": "Owners",
"type": "array"
},
"capabilities": {
"additionalProperties": {
"type": "boolean"
},
"description": "Drive's `capabilities` for this resource, limited to the boolean flags Drive returned (e.g. canDownload, canEdit, canAddChildren); any non-boolean entry is dropped. Empty when Drive returned none. These are Google's answers for the credential that served the call.",
"title": "Capabilities",
"type": "object"
},
"web_view_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Drive UI link, when Drive returns one.",
"title": "Web View Link"
},
"file_extension": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Drive's `fileExtension`, present only for uploaded binary files.",
"title": "File Extension"
},
"md5_checksum": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Drive's `md5Checksum`, present only for binary content stored in Drive.",
"title": "Md5 Checksum"
},
"source_app_tag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Value of `appProperties.sourceApp`, written both on creation and on picker registration; see `registered_via` to tell them apart.",
"title": "Source App Tag"
},
"registered_via": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Value of `appProperties.registeredVia` (`picker` for picker-registered resources); null otherwise.",
"title": "Registered Via"
},
"account": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Google account that served this request, as reported by Drive for the credential used. Null when that lookup failed.",
"title": "Account"
},
"account_requested": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The `account` override passed to this call, or null when the toolkit's default connected account was used.",
"title": "Account Requested"
}
},
"required": [
"resource_id",
"location"
],
"title": "GetFileMetadataResult",
"type": "object"
} # list_accounts read
List the Google accounts the user has connected for Google Drive. Returns each account's email, name, and whether it's the current default for this MCP client. Use when the user mentions "my work drive" / "my personal drive" or asks which accounts are available — then pass `account=<email>` to target a non-default account. `account=<email>` works on every OTHER Google Drive tool; this one takes no parameters and always answers for the current user.
Full description
Return the user's connected Google accounts for the Google Drive toolkit.
Returns:
ListAccountsResult with one entry per connected Google account: its
opaque account id, email, display name (when the backend has one), and
a flag marking which account is the default for this user + MCP client.
An empty `accounts` list means the backend answered and nothing is
connected — it is never how an unreachable backend is reported.
Raises:
ProviderError: the accounts backend could not answer — it failed, or
the call was still in flight when this invocation's bound expired.
Returning an empty list here would make "nothing is connected"
indistinguishable from "we could not find out", so it raises
instead. The distinction is real elsewhere too: the auth-failure
path keeps it as `None` vs `[]` internally and words its message
accordingly.
Drive grants are per account and per OAuth client: a file picked under one
connected account is not reachable under another. When more than one
account is connected, call this first and then pass `account=<email>` to
the other Google Drive tools. No parameters.
Parameter schema (JSON)
{
"description": "Parameters for list_accounts.",
"properties": {},
"title": "ListAccountsParams",
"type": "object",
"additionalProperties": false
} Result schema (JSON)
{
"$defs": {
"ConnectedAccount": {
"description": "A single connected Google account.",
"properties": {
"account_id": {
"default": "",
"description": "Stable opaque identifier for this connected account. Empty when the accounts backend did not supply one.",
"title": "Account Id",
"type": "string"
},
"email": {
"default": "",
"description": "The account's Google email address.",
"title": "Email",
"type": "string"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Display name for the account, when the backend has one.",
"title": "Name"
},
"is_default": {
"default": false,
"description": "True for the account used when a tool is called without an `account` override. The default is per user + MCP client + toolkit.",
"title": "Is Default",
"type": "boolean"
}
},
"title": "ConnectedAccount",
"type": "object"
}
},
"description": "Result of list_accounts.",
"properties": {
"accounts": {
"description": "One entry per Google account connected to the Google Drive toolkit. Empty means the accounts backend answered and listed nothing: no account is connected for this MCP client. An empty list is never returned for a backend that could not answer — that raises an error instead, so an empty result can be read as \"nothing connected\" without a second check.",
"items": {
"$ref": "#/$defs/ConnectedAccount"
},
"title": "Accounts",
"type": "array"
}
},
"title": "ListAccountsResult",
"type": "object"
} # list_granted_resources read
List the Drive resources this toolkit can reach: files picked in the Toolforest picker, folders approved as creation destinations, and resources Toolforest created. Filter by grant type and account. Each entry carries Drive's own capabilities (`can_download`, `can_edit`, `can_add_children`), so a read-only folder is visible as one. This is not a Drive search — nothing outside the granted set is returned, and an approved folder's existing contents are not listed.
Full description
List the Drive resources granted to this toolkit for one Google account.
The listing is a Drive `files.list` made with the toolkit's own
`drive.file` credential. Google, not Toolforest, decides what that
credential can reach: only the resources the user selected in the picker
under this OAuth client and the resources Toolforest created under it. So
there is no Toolforest-side grant record that could drift from Google's,
and no way to reach the rest of the user's Drive from here. This call
returns that reachable set narrowed by the filters below and split into
pages.
What a folder entry means: approving a folder registers it as a place to
CREATE files, not access to what is already in it. Approved folders are
listed; the files inside them are not, and a file inside an approved
folder appears only when that file was itself picked or created by
Toolforest. Registration is also not permission: `grant_type` is decided
by MIME type alone, so a folder the user may only read is still labelled
`destination_folder`. Whether creation will actually work is Drive's
answer, returned per resource as `can_add_children`.
Args:
grant_type: `file`, `folder`, or `all` (default).
include_trashed: include trashed resources (default False).
page_size: 1-100, default 50.
page_token: `next_page_token` from a previous call.
account: Google account override (email); omit for the default account.
Returns:
ListGrantedResourcesResult with one entry per granted resource on this
page, `has_more`/`next_page_token` straight from Drive's own paging,
and the account that served the request.
Both filters are compiled into the Drive query rather than applied to a
page after it is formed, so a page is never returned short because of
them, and `has_more` reflects the same filtered query. | Parameter | Type | Required | Description |
|---|---|---|---|
grant_type | "all" | "file" | "folder" | No | Which grants to return. `file` returns non-folder resources; `folder` returns folders — those approved as creation destinations and those Toolforest created, whether or not this credential may actually create in them (`can_add_children` on each entry is Drive's answer to that); `all` (default) returns both. The filter is part of the Drive query, so pages are not thinned after the fact. Default: "all" |
include_trashed | boolean | No | Include resources currently in the Drive trash. Default False. Applied inside the Drive query, not after paging. Default: false |
page_size | integer | No | Maximum resources per page (1-100, default 50). Drive may return fewer than requested and still have more pages — use `has_more`, not the page length, to decide whether to continue. Default: 50 |
page_token | string | null | No | `next_page_token` from a previous call, to fetch the next page of the SAME query. Re-send the same filters alongside it. |
account | string | null | No | Optional Google account override (email, e.g. "alice.work@company.com"). Omit to use the user's default connected Google account for this MCP client. Call list_accounts to see which accounts are connected. |
Parameter schema (JSON)
{
"description": "Parameters for list_granted_resources.",
"properties": {
"grant_type": {
"default": "all",
"description": "Which grants to return. `file` returns non-folder resources; `folder` returns folders — those approved as creation destinations and those Toolforest created, whether or not this credential may actually create in them (`can_add_children` on each entry is Drive's answer to that); `all` (default) returns both. The filter is part of the Drive query, so pages are not thinned after the fact.",
"enum": [
"all",
"file",
"folder"
],
"title": "Grant Type",
"type": "string"
},
"include_trashed": {
"default": false,
"description": "Include resources currently in the Drive trash. Default False. Applied inside the Drive query, not after paging.",
"title": "Include Trashed",
"type": "boolean"
},
"page_size": {
"default": 50,
"description": "Maximum resources per page (1-100, default 50). Drive may return fewer than requested and still have more pages — use `has_more`, not the page length, to decide whether to continue.",
"maximum": 100,
"minimum": 1,
"title": "Page Size",
"type": "integer"
},
"page_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "`next_page_token` from a previous call, to fetch the next page of the SAME query. Re-send the same filters alongside it.",
"title": "Page Token"
},
"account": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional Google account override (email, e.g. \"alice.work@company.com\"). Omit to use the user's default connected Google account for this MCP client. Call list_accounts to see which accounts are connected.",
"title": "Account"
}
},
"title": "ListGrantedResourcesParams",
"type": "object",
"additionalProperties": false
} Result schema (JSON)
{
"$defs": {
"GrantedResource": {
"description": "One Drive resource this toolkit has been granted.",
"properties": {
"resource_id": {
"description": "Drive file id, usable as `resource_id` on the other tools.",
"title": "Resource Id",
"type": "string"
},
"name": {
"default": "",
"description": "The resource's name in Drive.",
"title": "Name",
"type": "string"
},
"mime_type": {
"default": "",
"description": "Drive MIME type of the resource.",
"title": "Mime Type",
"type": "string"
},
"grant_type": {
"description": "`source_file` — a non-folder resource covered by the grant. `destination_folder` — a folder registered as a creation destination. The label is derived from the resource's MIME type alone: it records what the folder was registered AS, not that creating in it will succeed. A folder the user may only read lands here too, and Drive's own answer for this credential is `can_add_children` — check it before treating an entry as writable. Either way a `destination_folder` entry does NOT make the files already inside that folder reachable, and this tool does not list them.",
"enum": [
"source_file",
"destination_folder"
],
"title": "Grant Type",
"type": "string"
},
"size_bytes": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Size in bytes as reported by Drive. Null means no usable size came back — Drive omits it for folders and shortcuts, and an unparseable value lands here too. It never stands in for zero bytes.",
"title": "Size Bytes"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "RFC 3339 creation time from Drive.",
"title": "Created Time"
},
"modified_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "RFC 3339 last-modified time from Drive.",
"title": "Modified Time"
},
"location": {
"description": "`shared_drive` when Drive returns a `driveId` for the resource, otherwise `my_drive`.",
"enum": [
"my_drive",
"shared_drive"
],
"title": "Location",
"type": "string"
},
"drive_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Shared drive id, present only for shared-drive resources.",
"title": "Drive Id"
},
"parents": {
"description": "Parent folder ids as reported by Drive. A parent id here is not itself a grant: it is only usable by these tools when that folder was separately picked or created by Toolforest.",
"items": {
"type": "string"
},
"title": "Parents",
"type": "array"
},
"web_view_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Drive UI link, when Drive returns one.",
"title": "Web View Link"
},
"owners": {
"description": "Owner email addresses. Drive does not populate owners for shared-drive items, so this is empty there rather than absent.",
"items": {
"type": "string"
},
"title": "Owners",
"type": "array"
},
"can_download": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"description": "Drive's `capabilities.canDownload` for this resource. False means Google reports that this credential may not fetch the resource's content, so download_file / export_file are expected to fail for it even though the grant exists. Null when Drive did not report the capability.",
"title": "Can Download"
},
"can_edit": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"description": "Drive's `capabilities.canEdit` for this resource: whether this credential may modify it. Null when Drive did not report the capability. False is why update_file_content refuses a file it can otherwise read; the creating tools do not consult it, because creating a NEW resource is governed by the destination folder's `can_add_children` instead.",
"title": "Can Edit"
},
"can_add_children": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"description": "Drive's `capabilities.canAddChildren` for this resource: whether this credential may create children inside it. Drive documents it as always false for anything that is not a folder, so it is only informative on a `destination_folder` entry; null when Drive did not report the capability at all. False on a `destination_folder` means the folder is registered as a creation destination but Google will refuse creation in it — the registration does not override Drive's own permissions, and create_folder, upload_file, create_file and copy_file refuse such a destination up front rather than attempting the write. Null is not read as false: a capability Drive declined to report leaves the decision to Google.",
"title": "Can Add Children"
},
"trashed": {
"default": false,
"description": "True when the resource is in the Drive trash.",
"title": "Trashed",
"type": "boolean"
},
"source_app_tag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Value of `appProperties.sourceApp` on the resource, which Toolforest writes both when it creates a resource and when the picker registers one. Its presence therefore does not by itself distinguish created from picked; see `registered_via`.",
"title": "Source App Tag"
},
"registered_via": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Value of `appProperties.registeredVia`, set to `picker` on resources registered through the Toolforest picker. Null on resources Toolforest created, and on resources granted before this property was written.",
"title": "Registered Via"
}
},
"required": [
"resource_id",
"grant_type",
"location"
],
"title": "GrantedResource",
"type": "object"
}
},
"description": "Result of list_granted_resources.",
"properties": {
"resources": {
"items": {
"$ref": "#/$defs/GrantedResource"
},
"title": "Resources",
"type": "array"
},
"has_more": {
"default": false,
"description": "True when Drive returned a page token for this query, i.e. more results remain. No client-side filtering happens after the page is formed, so this is Drive's own answer for the same query.",
"title": "Has More",
"type": "boolean"
},
"next_page_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Pass back as `page_token` to fetch the next page.",
"title": "Next Page Token"
},
"account": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Google account that served this request, as reported by Drive for the credential used. Null when that lookup failed.",
"title": "Account"
},
"account_requested": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The `account` override passed to this call, or null when the toolkit's default connected account was used.",
"title": "Account Requested"
}
},
"title": "ListGrantedResourcesResult",
"type": "object"
} # share_file write
Enable anyone-with-link reader access for one granted Drive file, preserving its format and bytes. Requires account and explicit reader role; returns observed permission and available links. Does not verify anonymous downloads.
Full description
Enable anyone-with-link reader access for one granted Drive file. Requires explicit `account` and `link_sharing_role="reader"`. Access uses this toolkit's own drive.file grant pool, not Docs/Sheets/Slides grants. Folders and shortcuts are refused; only this file's permission is created, without changing its content, MIME type, parents or other permissions. Reuses an existing link-only reader permission after inspecting all pages. Any other anyone permission (including public writer or discoverable reader) is refused without modifying it. Google may reject new sharing because of account permissions or organization policy. Serialize sharing operations on a file: Drive does not support concurrent permission changes. A create is not replayed after an ambiguous failure. Such failures and failures of subsequent verification say that sharing may already have changed. Retry to inspect current permissions before another create. Returns the observed permission and Drive's available view/download links. Permission inspection does not verify anonymous access: restrictions may prevent downloads. `anonymous_access_verified` is always false. Verify a signed-out download against the original bytes separately.
| Parameter | Type | Required | Description |
|---|---|---|---|
file_id | string | Yes | File picked or created under this Drive OAuth client and account. Folders and shortcuts are refused. |
account | string | Yes | Google account to write as (email, e.g. "alice.work@company.com"). REQUIRED, and deliberately not inferred: a mutation names the account it acts under, because a destination granted under more than one connected account would otherwise be written under a default the caller never chose, putting the new resource's ownership and provenance on the wrong account. Call list_accounts to see which accounts are connected, and pass the one whose grant covers the destination. Read tools take the same parameter as an optional override. |
link_sharing_role | string | Yes | Required explicit request for anyone-with-link reader access. Public editing and commenting are unsupported. |
Parameter schema (JSON)
{
"properties": {
"file_id": {
"description": "File picked or created under this Drive OAuth client and account. Folders and shortcuts are refused.",
"minLength": 1,
"pattern": "^[A-Za-z0-9_-]+$",
"title": "File Id",
"type": "string"
},
"account": {
"description": "Google account to write as (email, e.g. \"alice.work@company.com\"). REQUIRED, and deliberately not inferred: a mutation names the account it acts under, because a destination granted under more than one connected account would otherwise be written under a default the caller never chose, putting the new resource's ownership and provenance on the wrong account. Call list_accounts to see which accounts are connected, and pass the one whose grant covers the destination. Read tools take the same parameter as an optional override.",
"minLength": 1,
"title": "Account",
"type": "string"
},
"link_sharing_role": {
"const": "reader",
"description": "Required explicit request for anyone-with-link reader access. Public editing and commenting are unsupported.",
"title": "Link Sharing Role",
"type": "string"
}
},
"required": [
"file_id",
"account",
"link_sharing_role"
],
"title": "ShareFileParams",
"type": "object",
"additionalProperties": false
} Result schema (JSON)
{
"$defs": {
"LinkPermission": {
"properties": {
"id": {
"description": "Permission ID observed in Drive's permissions list.",
"title": "Id",
"type": "string"
},
"type": {
"const": "anyone",
"title": "Type",
"type": "string"
},
"role": {
"const": "reader",
"title": "Role",
"type": "string"
},
"allow_file_discovery": {
"const": false,
"description": "Drive reports this permission as link-only, not discoverable through search.",
"title": "Allow File Discovery",
"type": "boolean"
}
},
"required": [
"id",
"type",
"role",
"allow_file_discovery"
],
"title": "LinkPermission",
"type": "object"
}
},
"properties": {
"file_id": {
"title": "File Id",
"type": "string"
},
"account_requested": {
"title": "Account Requested",
"type": "string"
},
"outcome": {
"enum": [
"created",
"already_shared"
],
"title": "Outcome",
"type": "string"
},
"permission": {
"$ref": "#/$defs/LinkPermission"
},
"web_view_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Drive's webViewLink, when returned; may contain a resource key.",
"title": "Web View Link"
},
"web_content_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Drive's webContentLink for downloading stored bytes, when returned. Download restrictions may still apply.",
"title": "Web Content Link"
},
"anonymous_access_verified": {
"const": false,
"default": false,
"description": "Always false: this tool inspects authenticated Drive permissions; it does not attempt a signed-out download or verify original bytes.",
"title": "Anonymous Access Verified",
"type": "boolean"
}
},
"required": [
"file_id",
"account_requested",
"outcome",
"permission"
],
"title": "ShareFileResult",
"type": "object"
} # update_file_content write
Replace the entire content of one granted NON-Google file with base64 bytes, up to 3 MiB. Requires `confirm_overwrite=true`: the previous content is destroyed and these tools cannot restore it. Google Docs, Sheets and Slides are refused — use the google_docs / google_sheets / google_slides toolkits to edit those. Reports the replaced content's size and MD5, when Drive reports them, so you can see what was overwritten. `account` is required: a write names the Google account it acts under rather than inferring one.
Full description
Replace the whole content of one granted, non-Google-native Drive file.
Access is Google's decision: the file is fetched and then updated under the
toolkit's `drive.file` credential, so an id that was never picked for this
account and was never created by these tools is a Drive 404 surfaced as
NotFoundError. If Drive reports `capabilities.canEdit: false` for the file,
this refuses before sending any bytes.
Args:
resource_id: Drive id of the granted non-native file to overwrite.
content: The new complete content, base64-encoded.
confirm_overwrite: Must be true; see the field.
mime_type: MIME type of the new bytes; omit to keep the current one.
account: REQUIRED Google account (email) to write as; a mutation
never infers it. See the field for why.
Returns:
UpdateFileContentResult describing the file after the update, plus
`previous_size_bytes` and `previous_md5_checksum` identifying the
content that was replaced.
**This is the one destructive operation in the toolkit, and it is bounded
to this single file.** It replaces that file's content in place; it does
not touch the file's name, parents, sharing or any other resource, and
nothing here trashes, moves or deletes anything. The previous content is
gone as far as these tools are concerned — Drive's own revision history is
outside what this toolkit reads or restores — which is why
`confirm_overwrite` has no default.
Google-native files (Docs, Sheets, Slides, and also folders, Forms,
Drawings and Sites) are refused. That is this toolkit's deliberate
boundary, not a report about what Drive's API can be made to do: replacing
a Google Doc's content means a format conversion, and document content
belongs to google_docs / google_sheets / google_slides, which edit those
files structurally instead of overwriting them wholesale. What IS supported
here is exactly what upload_file stores: uploaded binary or text files —
PDFs, images, CSVs, JSON, zips, plain text and so on — replaced byte for
byte with what you send.
Re-sending the same bytes is harmless: the file ends in the same state, so
unlike the creating tools this one needs no idempotency key and has none.
That is also what the error says when the update's outcome is unclear —
a request whose answer was lost, or one still in flight when this
invocation ran out of time, is reported as "may or may not have been
replaced", never as an unchanged file. | Parameter | Type | Required | Description |
|---|---|---|---|
resource_id | string | Yes | Drive id of the file whose content is REPLACED. It must be granted to this toolkit for this account — picked in the Toolforest picker, or created by these tools — and must not be a Google-native file (Doc, Sheet, Slides, folder, Form, Drawing, Site); those are refused. |
content | string | Yes | The file's new complete content, base64-encoded (standard base64, RFC 4648 §4). This REPLACES the whole file — there is no append or patch mode. Decoded content over 3145728 bytes is refused before anything is sent. |
confirm_overwrite | boolean | Yes | Must be true. The existing content of this file is destroyed and this toolkit has no tool that can bring it back — Drive keeps revision history, but restoring from it is not something these tools do. Required explicitly so an overwrite is never the accidental result of a defaulted parameter. |
mime_type | string | null | No | MIME type of the new bytes. Omit to keep the file's current MIME type, which is what you want when replacing a file with a newer version of the same format. |
account | string | Yes | Google account to write as (email, e.g. "alice.work@company.com"). REQUIRED, and deliberately not inferred: a mutation names the account it acts under, because a destination granted under more than one connected account would otherwise be written under a default the caller never chose, putting the new resource's ownership and provenance on the wrong account. Call list_accounts to see which accounts are connected, and pass the one whose grant covers the destination. Read tools take the same parameter as an optional override. |
Parameter schema (JSON)
{
"description": "Parameters for update_file_content.",
"properties": {
"resource_id": {
"description": "Drive id of the file whose content is REPLACED. It must be granted to this toolkit for this account — picked in the Toolforest picker, or created by these tools — and must not be a Google-native file (Doc, Sheet, Slides, folder, Form, Drawing, Site); those are refused.",
"minLength": 1,
"title": "Resource Id",
"type": "string"
},
"content": {
"description": "The file's new complete content, base64-encoded (standard base64, RFC 4648 §4). This REPLACES the whole file — there is no append or patch mode. Decoded content over 3145728 bytes is refused before anything is sent.",
"title": "Content",
"type": "string"
},
"confirm_overwrite": {
"description": "Must be true. The existing content of this file is destroyed and this toolkit has no tool that can bring it back — Drive keeps revision history, but restoring from it is not something these tools do. Required explicitly so an overwrite is never the accidental result of a defaulted parameter.",
"title": "Confirm Overwrite",
"type": "boolean"
},
"mime_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "MIME type of the new bytes. Omit to keep the file's current MIME type, which is what you want when replacing a file with a newer version of the same format.",
"title": "Mime Type"
},
"account": {
"description": "Google account to write as (email, e.g. \"alice.work@company.com\"). REQUIRED, and deliberately not inferred: a mutation names the account it acts under, because a destination granted under more than one connected account would otherwise be written under a default the caller never chose, putting the new resource's ownership and provenance on the wrong account. Call list_accounts to see which accounts are connected, and pass the one whose grant covers the destination. Read tools take the same parameter as an optional override.",
"minLength": 1,
"title": "Account",
"type": "string"
}
},
"required": [
"resource_id",
"content",
"confirm_overwrite",
"account"
],
"title": "UpdateFileContentParams",
"type": "object",
"additionalProperties": false
} Result schema (JSON)
{
"description": "Result of update_file_content.",
"properties": {
"resource_id": {
"description": "Drive file id of the resource, usable as `resource_id` on the other Google Drive tools for this same account.",
"title": "Resource Id",
"type": "string"
},
"name": {
"default": "",
"description": "The resource's name in Drive.",
"title": "Name",
"type": "string"
},
"mime_type": {
"default": "",
"description": "Drive MIME type of the resource.",
"title": "Mime Type",
"type": "string"
},
"is_folder": {
"default": false,
"description": "True for a Drive folder.",
"title": "Is Folder",
"type": "boolean"
},
"is_google_native": {
"default": false,
"description": "True for Google-native editor types (Docs, Sheets, Slides and the other application/vnd.google-apps.* types, folders included). Native files have no downloadable bytes: download_file refuses them, and only Docs, Sheets and Slides can be export_file'd.",
"title": "Is Google Native",
"type": "boolean"
},
"size_bytes": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Size in bytes as reported by Drive. Null means no usable size came back — Drive omits it for folders and for Google-native files — and never stands in for zero bytes.",
"title": "Size Bytes"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "RFC 3339 creation time from Drive.",
"title": "Created Time"
},
"modified_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "RFC 3339 last-modified time from Drive.",
"title": "Modified Time"
},
"location": {
"description": "`shared_drive` when Drive returns a `driveId` for the resulting resource, otherwise `my_drive`. Read from the create response, so it is where the resource actually landed.",
"enum": [
"my_drive",
"shared_drive"
],
"title": "Location",
"type": "string"
},
"drive_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Shared drive id, present only for shared-drive resources.",
"title": "Drive Id"
},
"parents": {
"description": "Parent folder ids as reported by Drive for the resulting resource. A parent id here is not itself a grant.",
"items": {
"type": "string"
},
"title": "Parents",
"type": "array"
},
"web_view_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Drive UI link, when Drive returns one.",
"title": "Web View Link"
},
"owners": {
"description": "Owner email addresses as Drive reports them for the RESULT. Drive does not populate owners for shared-drive items, so this is empty there rather than absent — it is not a claim that the resource is unowned.",
"items": {
"type": "string"
},
"title": "Owners",
"type": "array"
},
"capabilities": {
"additionalProperties": {
"type": "boolean"
},
"description": "Drive's `capabilities` for the resulting resource, limited to the boolean flags Drive returned; any non-boolean entry is dropped, and the map is empty when Drive returned none. `canAddChildren` on a created folder is Google's answer to whether more can be created inside it.",
"title": "Capabilities",
"type": "object"
},
"source_app_tag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Value of `appProperties.sourceApp` on the resource. Creation stamps the same tag the Toolforest picker writes, so a created resource and a picked one describe their origin identically. The tag is provenance, not the reason the resource is listed: list_granted_resources applies no `sourceApp` filter, and a created resource appears there because the toolkit's `drive.file` scope makes what it created visible to its own file listing. `registered_via` stays null on created resources, and is how the two are told apart there.",
"title": "Source App Tag"
},
"account": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Google account that served this request, as reported by Drive for the credential used. Null when that lookup failed — which does not affect whether the write happened. Compare it with `account_requested` to confirm the write landed where it was aimed.",
"title": "Account"
},
"account_requested": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The `account` this call named. Never null on a write result: the write tools require `account` rather than falling back to a default connected account.",
"title": "Account Requested"
},
"md5_checksum": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Drive's `md5Checksum` for the NEW stored bytes, when Drive reports one.",
"title": "Md5 Checksum"
},
"previous_size_bytes": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Size in bytes of the content that was replaced, as Drive reported it just before the update. Null when Drive reported no usable size; never a stand-in for zero bytes.",
"title": "Previous Size Bytes"
},
"previous_md5_checksum": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Drive's `md5Checksum` for the content that was replaced, read just before the update. Null when Drive reported none. It identifies what was overwritten; it does not restore it.",
"title": "Previous Md5 Checksum"
}
},
"required": [
"resource_id",
"location"
],
"title": "UpdateFileContentResult",
"type": "object"
} # upload_file write
Upload base64 bytes as a NEW file inside a granted destination folder, up to 3 MiB. `parent_folder_id` is required; a read-only parent is refused before anything is sent, and so is oversized content. This always creates a new file — it never replaces an existing one (use update_file_content for that), and Drive permits same-named siblings. Pass an `idempotency_key` to make a retry safe. `account` is required: a write names the Google account it acts under rather than inferring one.
Full description
Upload bytes as a new Drive file inside a granted destination folder.
The destination is validated before anything is sent: it is fetched under
the toolkit's `drive.file` credential, so a folder id that was never picked
for this account and was never created by these tools is a Drive 404
surfaced as NotFoundError, and a folder Drive reports as
`canAddChildren: false` is refused with that reason.
Args:
name: Name for the new file.
parent_folder_id: Drive id of the granted folder to upload into.
content: File content, base64-encoded.
mime_type: MIME type to store the bytes as (default
`application/octet-stream`).
idempotency_key: Optional key making a retry safe; see the field.
account: REQUIRED Google account (email) to write as; a mutation
never infers it. See the field for why.
Returns:
UploadFileResult describing the stored file as Drive returned it —
resulting owner, My Drive / Shared Drive location, size and
`md5_checksum` — plus `outcome` saying whether this call created it,
found it under a previously used key, or recovered it after an unclear
answer.
Three refusals, all of them with nothing on the wire. Content that is not
valid base64 is refused. Content decoding to more than 3 MiB is refused —
the ceiling exists because the bytes travel inline through Lambda's 6 MB
REQUEST payload and base64 inflates them by a third — and is never
truncated to fit. A Google-native `mime_type` is refused, because this tool
uploads bytes as they are and does not ask Drive to convert them; use
create_file to make a Doc, Sheet or Slides file.
An `idempotency_key` that matches a resource an earlier call already
created short-circuits BEFORE the checks above: nothing is created, so
the destination is never read and its permissions are never consulted.
The key decides what comes back in that case, not the other arguments.
The match must also BE the kind of resource this tool returns. A key names
one resource across all four creating tools rather than one per tool, so it
can match something another tool made; when it does and this tool could not
describe that resource truthfully, the call is refused with the conflict
named — nothing is created then either, and no mislabelled resource is
handed back.
This tool only ever ADDS a file. It does not overwrite, replace or trash
anything: Drive allows two files with the same name in one folder and will
simply hold both. There is deliberately no `overwrite` or `rename` conflict
mode, because under `drive.file` this toolkit cannot see a granted folder's
existing contents — approving a folder is a creation destination, not a
read grant — so any conflict check it offered would cover only the subset
of that folder these tools happen to have created, and silently miss the
rest. Replacing content is update_file_content's job, against a file id you
name explicitly. | Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Name for the new file, as it will appear in Drive. |
parent_folder_id | string | Yes | Drive id of the granted folder to upload INTO. Required: this toolkit never picks a destination for you and has no default location. Use list_granted_resources with `grant_type=folder`. |
content | string | Yes | The file's complete content, base64-encoded (standard base64, RFC 4648 §4). Decoded content over 3145728 bytes is refused before anything is sent — content is never truncated to fit. |
mime_type | string | No | MIME type to store the bytes as, e.g. `application/pdf`, `text/csv`, `image/png`. Defaults to `application/octet-stream`. The bytes are stored as given: this tool does NOT ask Drive to convert them into a Google Doc, Sheet or Slides file, so passing a Google-native MIME type here is refused rather than silently storing an unusable file. Use create_file for a native document. Default: "application/octet-stream" |
idempotency_key | string | null | No | Optional caller-chosen key that makes this creation safe to retry. Send a UUID. When set, the tool first looks for a resource an earlier call already created under the SAME key and returns that one instead of creating a second (`outcome` says which happened); the key is also stamped on whatever is created, and used to reconcile a request whose answer was lost in flight. The key is the identity: reusing one with different arguments returns the ORIGINAL resource unchanged rather than creating or updating anything. Omit it and no deduplication happens at all — a retry after an unclear outcome can create a second copy, which the error on that path says explicitly. Keys are matched only against resources this toolkit created for this Google account, never against picked files. A key whose resource has since been trashed does not match. One key names ONE resource across all four creating tools — it is not scoped per tool — so a key first used elsewhere can match here; when the resource it names is not the kind this tool returns (a folder to create_file, a Doc to upload_file, a spreadsheet to a `document` create), the call is REFUSED naming the conflict rather than handing back a resource mislabelled as what you asked for, and nothing is created. One caveat on the guarantee: the match is a Drive search-index query on appProperties, and Google documents no read-your-writes freshness for it — a retry issued immediately after a create may not see it yet and can still duplicate, so leave a moment between the two. |
account | string | Yes | Google account to write as (email, e.g. "alice.work@company.com"). REQUIRED, and deliberately not inferred: a mutation names the account it acts under, because a destination granted under more than one connected account would otherwise be written under a default the caller never chose, putting the new resource's ownership and provenance on the wrong account. Call list_accounts to see which accounts are connected, and pass the one whose grant covers the destination. Read tools take the same parameter as an optional override. |
Parameter schema (JSON)
{
"description": "Parameters for upload_file.",
"properties": {
"name": {
"description": "Name for the new file, as it will appear in Drive.",
"maxLength": 255,
"minLength": 1,
"title": "Name",
"type": "string"
},
"parent_folder_id": {
"description": "Drive id of the granted folder to upload INTO. Required: this toolkit never picks a destination for you and has no default location. Use list_granted_resources with `grant_type=folder`.",
"minLength": 1,
"title": "Parent Folder Id",
"type": "string"
},
"content": {
"description": "The file's complete content, base64-encoded (standard base64, RFC 4648 §4). Decoded content over 3145728 bytes is refused before anything is sent — content is never truncated to fit.",
"title": "Content",
"type": "string"
},
"mime_type": {
"default": "application/octet-stream",
"description": "MIME type to store the bytes as, e.g. `application/pdf`, `text/csv`, `image/png`. Defaults to `application/octet-stream`. The bytes are stored as given: this tool does NOT ask Drive to convert them into a Google Doc, Sheet or Slides file, so passing a Google-native MIME type here is refused rather than silently storing an unusable file. Use create_file for a native document.",
"minLength": 1,
"title": "Mime Type",
"type": "string"
},
"idempotency_key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional caller-chosen key that makes this creation safe to retry. Send a UUID. When set, the tool first looks for a resource an earlier call already created under the SAME key and returns that one instead of creating a second (`outcome` says which happened); the key is also stamped on whatever is created, and used to reconcile a request whose answer was lost in flight. The key is the identity: reusing one with different arguments returns the ORIGINAL resource unchanged rather than creating or updating anything. Omit it and no deduplication happens at all — a retry after an unclear outcome can create a second copy, which the error on that path says explicitly. Keys are matched only against resources this toolkit created for this Google account, never against picked files. A key whose resource has since been trashed does not match. One key names ONE resource across all four creating tools — it is not scoped per tool — so a key first used elsewhere can match here; when the resource it names is not the kind this tool returns (a folder to create_file, a Doc to upload_file, a spreadsheet to a `document` create), the call is REFUSED naming the conflict rather than handing back a resource mislabelled as what you asked for, and nothing is created. One caveat on the guarantee: the match is a Drive search-index query on appProperties, and Google documents no read-your-writes freshness for it — a retry issued immediately after a create may not see it yet and can still duplicate, so leave a moment between the two.",
"title": "Idempotency Key"
},
"account": {
"description": "Google account to write as (email, e.g. \"alice.work@company.com\"). REQUIRED, and deliberately not inferred: a mutation names the account it acts under, because a destination granted under more than one connected account would otherwise be written under a default the caller never chose, putting the new resource's ownership and provenance on the wrong account. Call list_accounts to see which accounts are connected, and pass the one whose grant covers the destination. Read tools take the same parameter as an optional override.",
"minLength": 1,
"title": "Account",
"type": "string"
}
},
"required": [
"name",
"parent_folder_id",
"content",
"account"
],
"title": "UploadFileParams",
"type": "object",
"additionalProperties": false
} Result schema (JSON)
{
"description": "Result of upload_file.",
"properties": {
"resource_id": {
"description": "Drive file id of the resource, usable as `resource_id` on the other Google Drive tools for this same account.",
"title": "Resource Id",
"type": "string"
},
"name": {
"default": "",
"description": "The resource's name in Drive.",
"title": "Name",
"type": "string"
},
"mime_type": {
"default": "",
"description": "Drive MIME type of the resource.",
"title": "Mime Type",
"type": "string"
},
"is_folder": {
"default": false,
"description": "True for a Drive folder.",
"title": "Is Folder",
"type": "boolean"
},
"is_google_native": {
"default": false,
"description": "True for Google-native editor types (Docs, Sheets, Slides and the other application/vnd.google-apps.* types, folders included). Native files have no downloadable bytes: download_file refuses them, and only Docs, Sheets and Slides can be export_file'd.",
"title": "Is Google Native",
"type": "boolean"
},
"size_bytes": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Size in bytes as reported by Drive. Null means no usable size came back — Drive omits it for folders and for Google-native files — and never stands in for zero bytes.",
"title": "Size Bytes"
},
"created_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "RFC 3339 creation time from Drive.",
"title": "Created Time"
},
"modified_time": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "RFC 3339 last-modified time from Drive.",
"title": "Modified Time"
},
"location": {
"description": "`shared_drive` when Drive returns a `driveId` for the resulting resource, otherwise `my_drive`. Read from the create response, so it is where the resource actually landed.",
"enum": [
"my_drive",
"shared_drive"
],
"title": "Location",
"type": "string"
},
"drive_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Shared drive id, present only for shared-drive resources.",
"title": "Drive Id"
},
"parents": {
"description": "Parent folder ids as reported by Drive for the resulting resource. A parent id here is not itself a grant.",
"items": {
"type": "string"
},
"title": "Parents",
"type": "array"
},
"web_view_link": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Drive UI link, when Drive returns one.",
"title": "Web View Link"
},
"owners": {
"description": "Owner email addresses as Drive reports them for the RESULT. Drive does not populate owners for shared-drive items, so this is empty there rather than absent — it is not a claim that the resource is unowned.",
"items": {
"type": "string"
},
"title": "Owners",
"type": "array"
},
"capabilities": {
"additionalProperties": {
"type": "boolean"
},
"description": "Drive's `capabilities` for the resulting resource, limited to the boolean flags Drive returned; any non-boolean entry is dropped, and the map is empty when Drive returned none. `canAddChildren` on a created folder is Google's answer to whether more can be created inside it.",
"title": "Capabilities",
"type": "object"
},
"source_app_tag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Value of `appProperties.sourceApp` on the resource. Creation stamps the same tag the Toolforest picker writes, so a created resource and a picked one describe their origin identically. The tag is provenance, not the reason the resource is listed: list_granted_resources applies no `sourceApp` filter, and a created resource appears there because the toolkit's `drive.file` scope makes what it created visible to its own file listing. `registered_via` stays null on created resources, and is how the two are told apart there.",
"title": "Source App Tag"
},
"account": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Google account that served this request, as reported by Drive for the credential used. Null when that lookup failed — which does not affect whether the write happened. Compare it with `account_requested` to confirm the write landed where it was aimed.",
"title": "Account"
},
"account_requested": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The `account` this call named. Never null on a write result: the write tools require `account` rather than falling back to a default connected account.",
"title": "Account Requested"
},
"outcome": {
"description": "`created` — this call created the resource. `already_existed` — an `idempotency_key` was supplied and matched a resource an earlier call had already created, AND that resource is of the kind this tool returns, so this call created nothing and every field below describes that earlier resource. (A match of a different kind is an error, not this outcome.) `recovered` — this call's request reached Google but its answer was lost, and the idempotency lookup afterwards found a resource of the kind this tool returns, proving the request had committed. (As with `already_existed`, a match of a different kind is reported as an unresolved outcome, never as this one.) Only `already_existed` means nothing was written by this call.",
"enum": [
"created",
"already_existed",
"recovered"
],
"title": "Outcome",
"type": "string"
},
"idempotency_key": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The `idempotency_key` this call used, or null when none was supplied. Send the same one to retry safely — subject to the search-index freshness caveat on the parameter of the same name.",
"title": "Idempotency Key"
},
"md5_checksum": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Drive's `md5Checksum` for the stored bytes, when Drive reports one. Compare it against the MD5 of what you sent to confirm the upload is byte-identical.",
"title": "Md5 Checksum"
}
},
"required": [
"resource_id",
"location",
"outcome"
],
"title": "UploadFileResult",
"type": "object"
}