google-drive-files-mcp
A focused Model Context Protocol server (and standalone CLI) for Google Drive file management (move, upload, organize) and Google Sheets editing (update cells, append rows, edit tabs, format). Fourteen granular, single-purpose tools — each one an explicit operation, with writes returning before/after so nothing is silently overwritten.
Built because the hosted Google Drive connectors can search, read, and copy files, but cannot move them (copy duplicates a file with a new ID rather than relocating it), cannot reliably upload a real binary (their inline-content API needs the bytes embedded as base64, which breaks for large/binary files), and cannot edit spreadsheet contents. This server adds a true move, a resumable upload from a local path, folder creation, and a full set of Google Sheets value/structure/format edits — for any MCP client (Claude Code, Claude Desktop, Cursor, Cline, etc.).
Tools
Drive — files & folders
drive_search(query, only_folders=False, max_results=20)— find files/folders (and their IDs).drive_create_folder(name, parent=None)— create a folder (parentaccepts an ID, URL,root, or an unambiguous folder name).drive_move(file, dest_folder, keep_existing_parents=False)— true move (removed from its current folder);keep_existing_parents=Trueadds without removing.drive_upload_file(local_path, parent=None, name=None, mime_type=None)— upload a local file (any type, incl. large binaries) via a resumable media upload. Stored as-is (no Google-format conversion).
Google Sheets — read, edit, structure, format
sheets_get_info(spreadsheet)— list tabs + sizes (call first to learn tab names).sheets_read(spreadsheet, range_a1, render_option="FORMATTED_VALUE")— read a range (FORMULA/UNFORMATTED_VALUEavailable).sheets_write(spreadsheet, range_a1, values, value_input_option="USER_ENTERED")— overwrite a range; returnsbefore.USER_ENTEREDparses numbers and makes=SUM(..)a formula;RAWwrites literally.sheets_append(spreadsheet, range_a1, values, ...)— append rows after a table.sheets_clear(spreadsheet, range_a1)— clear values (keeps formatting); returnsbefore.sheets_batch_write(spreadsheet, updates, ...)— write many ranges atomically.sheets_add_tab/sheets_rename_tab/sheets_delete_tab— manage tabs (delete is destructive).sheets_format(spreadsheet, range_a1, number_format=None, bold=None, background=None)— number pattern / bold /#RRGGBBbackground.
No rename/copy/trash/delete of files (copy already exists in the hosted Drive connector); destructive Sheets ops (sheets_clear, sheets_delete_tab) are their own explicit tools so you control exactly when they run.
Scope warning (read this)
Moving an existing arbitrary file requires the full drive scope — read/write/delete on all your Drive files. There is no narrower scope that can change a file's parents (drive.file only covers files the app itself created). This tool is therefore far more powerful than a read-only connector. Treat its cached token like a password (stored 0600), and prefer an isolated OAuth client/token rather than sharing one with read-only tools.
Install
pip install google-drive-files-mcp
# or: uv tool install google-drive-files-mcp
One-time setup (~10 min)
- Google Cloud Console → create/pick a project.
- Enable the Drive API (library link) and, for the Sheets tools, the Sheets API (library link). (The full
drivescope already authorizes the Sheets API — no extra consent, just enable the API.) - OAuth consent screen → Internal (Workspace; no verification needed even for the restricted full-drive scope) or External + add yourself as a test user (personal Gmail).
- Credentials → OAuth client ID → Desktop app → download JSON.
google-drive-files-mcp setup --import-credentials ~/Downloads/client_secret_*.json→ consent in the browser.
Verify:
google-drive-files-mcp status
google-drive-files-mcp search "Reports" --folders
Claude Code
claude mcp add --scope user google-drive-files google-drive-files-mcp -- serve
Find my "Q2 Report" doc and move it into the "2026 Reports" folder.
Claude Desktop
{
"mcpServers": {
"google-drive-files": { "command": "google-drive-files-mcp", "args": ["serve"] }
}
}
CLI
google-drive-files-mcp search "budget" # find a file + its ID
google-drive-files-mcp search "Reports" --folders # find destination folders
google-drive-files-mcp mkdir "2026 Reports" # create a folder
google-drive-files-mcp move <file-url-or-id> "2026 Reports" # move into it (by folder name)
google-drive-files-mcp move <file-url-or-id> root # move back to My Drive root
google-drive-files-mcp upload ~/Downloads/report.zip --parent "2026 Reports" # upload a local file
# Google Sheets
google-drive-files-mcp sheet-info <sheet-url-or-id> # list tabs + sizes
google-drive-files-mcp sheet-read <sheet-url-or-id> "Sheet1!A1:D10" # read a range
google-drive-files-mcp sheet-write <sheet-url-or-id> "Sheet1!B2:B4" '[[100],[200],[300]]' # set numbers
google-drive-files-mcp sheet-format <sheet-url-or-id> "Sheet1!B2:B4" --number-format '#,##0.00' --bold
drive_move returns the before/after parents so the move is auditable:
{ "id": "1Abc…", "name": "Q2 Report", "moved_from": ["0OldFolderId"], "moved_to": "1NewFolderId", "parents_now": ["1NewFolderId"], "web_view_link": "https://docs.google.com/…" }
Configuration
| Variable | Default | What |
|---|---|---|
GDRIVE_FILES_MCP_CREDENTIALS |
~/.config/google-drive-files-mcp/credentials.json |
OAuth client secret |
GDRIVE_FILES_MCP_TOKEN |
~/.config/google-drive-files-mcp/token.json |
Cached refresh token |
GDRIVE_FILES_MCP_SCOPES |
https://www.googleapis.com/auth/drive |
OAuth scopes (comma-separated) |
Safety notes
- True move removes the file from its current folder. Drive items can have multiple parents;
keep_existing_parents=Trueadds without removing. - Folder-name destinations must be unambiguous. If two folders share a name,
drive_moverefuses and lists the candidates so you can pass an explicit ID. - The before/after parents are returned on every move so an agent (or you) can verify the result.
Troubleshooting
HttpError 403: Google Drive API has not been used in project … or it is disabled
Enable the Drive API on the project that owns your OAuth client: console.cloud.google.com/apis/library/drive.googleapis.com → Enable, then wait ~1 min and retry. (This is the single most common first-run error.)
multiple folders named '…'; pass the folder ID/URL instead
Two or more of your folders share that name, so a name is ambiguous. Run google-drive-files-mcp search "<name>" --folders to get the IDs and pass the exact one.
no folder named '…' found
Create it first (google-drive-files-mcp mkdir "<name>") or pass a folder ID/URL/root.
HttpError 403: insufficientFilePermissions when moving
Either the token lacks the full drive scope — re-authorize with google-drive-files-mcp setup --reauth — or you don't have edit rights on the file/destination (you can't move a file someone else owns unless they've granted you edit access).
No valid Google token from Claude Desktop / cron
The first consent needs a browser. Run google-drive-files-mcp setup once in a terminal; later headless runs reuse and auto-refresh the cached token.
A move "removed" a file from a shared folder unexpectedly
A true move removes the item from its current parent(s). If you meant to also keep it where it was, use keep_existing_parents=true (CLI --keep).
Use it from other clients (Cursor, Cline, Continue, …)
Any stdio MCP client works — see docs/other-clients.md.
Authentication — bring your own Google OAuth client
There are no API keys and no shipped secrets. The server authenticates to your Google account with an OAuth client you create, and caches a refresh token locally. The author has zero access to your data.
- Why your own client? Google's restricted scopes (here, the full
drivescope) can't be redistributed in a shared app, and an unverified shared app is capped at 100 users. "Bring your own OAuth client" is the standard pattern for personal-data MCP servers. - What you need: a free Google Cloud project, the Drive API enabled, an OAuth consent screen, and a Desktop OAuth client. Full walkthrough → docs/setup-google-oauth.md.
- Where your token lives:
~/.config/google-drive-files-mcp/token.json(mode0600). Delete it to revoke locally; revoke fully at myaccount.google.com/permissions. - No hosted/SaaS option — everything runs locally; your Drive data never touches a third-party server.
More guides
- docs/setup-google-oauth.md — full OAuth walkthrough (full-
drivescope) + common errors - docs/claude-code.md · docs/claude-desktop.md · docs/other-clients.md
- examples/ — e.g. file a document into a
YYYY-MMfolder
Related tools
Part of a small family of focused, local MCP servers for Google Workspace data the hosted connectors don't expose:
- gmail-attachments-mcp — download Gmail attachment bytes to disk
- google-drive-comments-mcp — read comment threads on Docs/Sheets/Slides
- google-drive-files-mcp — move/organize Drive files (this repo)
They can share one OAuth login or stay isolated — see each repo's setup.
License
MIT. See LICENSE.
Release files for google-drive-files-mcp 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| google_drive_files_mcp-0.3.0.tar.gz | 22.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| google_drive_files_mcp-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 45.0 kB
Release files / google_drive_files_mcp-0.3.0.tar.gz
| Download URL | google_drive_files_mcp-0.3.0.tar.gz |
|---|---|
| Size | 22.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
43cfae4c656b77d505f5f9c7d72f522575d1bfbe0e5f2e93bebc39c653908f3e
|
|
BLAKE2b-256 checksum How to use checksums |
03c35fd3a5fd8f64a17368196d5c4e83a88b2b2534281d03e640420e6edc1ecb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / google_drive_files_mcp-0.3.0-py3-none-any.whl
| Download URL | google_drive_files_mcp-0.3.0-py3-none-any.whl |
|---|---|
| Size | 22.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
596e33acb2c9a1b2938d16075f032195b485b7d044f3f04df7872133d274edad
|
|
BLAKE2b-256 checksum How to use checksums |
a5d51905030798f66876320edf92851cde3b61c1fa01d3ffa2f8bb1c8da1b7fa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|