google-drive-files-mcp 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. google_drive_files_mcp-0.3.0/.github/workflows/ci.yml +29 -0
  2. google_drive_files_mcp-0.3.0/.github/workflows/release.yml +36 -0
  3. google_drive_files_mcp-0.3.0/.gitignore +33 -0
  4. google_drive_files_mcp-0.3.0/LICENSE +21 -0
  5. google_drive_files_mcp-0.3.0/PKG-INFO +190 -0
  6. google_drive_files_mcp-0.3.0/README.md +159 -0
  7. google_drive_files_mcp-0.3.0/docs/claude-code.md +23 -0
  8. google_drive_files_mcp-0.3.0/docs/claude-desktop.md +30 -0
  9. google_drive_files_mcp-0.3.0/docs/other-clients.md +32 -0
  10. google_drive_files_mcp-0.3.0/docs/setup-google-oauth.md +56 -0
  11. google_drive_files_mcp-0.3.0/examples/file-into-dated-folder.sh +23 -0
  12. google_drive_files_mcp-0.3.0/pyproject.toml +57 -0
  13. google_drive_files_mcp-0.3.0/server.json +50 -0
  14. google_drive_files_mcp-0.3.0/src/google_drive_files_mcp/__init__.py +2 -0
  15. google_drive_files_mcp-0.3.0/src/google_drive_files_mcp/__main__.py +5 -0
  16. google_drive_files_mcp-0.3.0/src/google_drive_files_mcp/auth.py +88 -0
  17. google_drive_files_mcp-0.3.0/src/google_drive_files_mcp/cli.py +290 -0
  18. google_drive_files_mcp-0.3.0/src/google_drive_files_mcp/client.py +217 -0
  19. google_drive_files_mcp-0.3.0/src/google_drive_files_mcp/config.py +48 -0
  20. google_drive_files_mcp-0.3.0/src/google_drive_files_mcp/server.py +247 -0
  21. google_drive_files_mcp-0.3.0/src/google_drive_files_mcp/sheets.py +270 -0
  22. google_drive_files_mcp-0.3.0/tests/__init__.py +0 -0
  23. google_drive_files_mcp-0.3.0/tests/test_client.py +101 -0
  24. google_drive_files_mcp-0.3.0/tests/test_config.py +45 -0
  25. google_drive_files_mcp-0.3.0/tests/test_sheets.py +93 -0
@@ -0,0 +1,29 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ${{ matrix.os }}
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ os: [ubuntu-latest, macos-latest]
16
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ - uses: actions/setup-python@v5
20
+ with:
21
+ python-version: ${{ matrix.python-version }}
22
+ - name: Install
23
+ run: |
24
+ python -m pip install --upgrade pip
25
+ pip install -e ".[dev]"
26
+ - name: Lint
27
+ run: ruff check src tests
28
+ - name: Test
29
+ run: pytest -v
@@ -0,0 +1,36 @@
1
+ name: Release to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/setup-python@v5
14
+ with:
15
+ python-version: "3.12"
16
+ - run: python -m pip install --upgrade build
17
+ - run: python -m build
18
+ - uses: actions/upload-artifact@v4
19
+ with:
20
+ name: dist
21
+ path: dist/
22
+
23
+ publish:
24
+ needs: build
25
+ runs-on: ubuntu-latest
26
+ environment:
27
+ name: pypi
28
+ url: https://pypi.org/project/google-drive-files-mcp/
29
+ permissions:
30
+ id-token: write
31
+ steps:
32
+ - uses: actions/download-artifact@v4
33
+ with:
34
+ name: dist
35
+ path: dist/
36
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,33 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ *.egg
6
+ dist/
7
+ build/
8
+ .eggs/
9
+
10
+ # Virtual envs
11
+ .venv/
12
+ venv/
13
+ env/
14
+ .env
15
+
16
+ # Tooling
17
+ .pytest_cache/
18
+ .ruff_cache/
19
+ .mypy_cache/
20
+ .coverage
21
+
22
+ # Editors / OS
23
+ .vscode/
24
+ .idea/
25
+ *.swp
26
+ .DS_Store
27
+
28
+ # Credentials — NEVER commit
29
+ credentials.json
30
+ token.json
31
+ client_secret*.json
32
+ *.pem
33
+ *.key
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Zayan Khan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,190 @@
1
+ Metadata-Version: 2.4
2
+ Name: google-drive-files-mcp
3
+ Version: 0.3.0
4
+ Summary: A minimal MCP server and CLI for Google Drive file management (move, upload, organize) and Google Sheets editing.
5
+ Project-URL: Homepage, https://github.com/zayansalman/google-drive-files-mcp
6
+ Project-URL: Repository, https://github.com/zayansalman/google-drive-files-mcp
7
+ Project-URL: Issues, https://github.com/zayansalman/google-drive-files-mcp/issues
8
+ Author: Zayan Khan
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: anthropic,claude,files,google-drive,google-sheets,mcp,model-context-protocol,move,spreadsheet,upload
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Office/Business
21
+ Classifier: Topic :: Software Development :: Libraries
22
+ Requires-Python: >=3.10
23
+ Requires-Dist: google-api-python-client>=2.100.0
24
+ Requires-Dist: google-auth-httplib2>=0.2.0
25
+ Requires-Dist: google-auth-oauthlib>=1.0.0
26
+ Requires-Dist: mcp>=1.0.0
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest>=7.0; extra == 'dev'
29
+ Requires-Dist: ruff>=0.1; extra == 'dev'
30
+ Description-Content-Type: text/markdown
31
+
32
+ # google-drive-files-mcp
33
+
34
+ <!-- mcp-name: io.github.zayansalman/google-drive-files-mcp -->
35
+
36
+ A focused [Model Context Protocol](https://modelcontextprotocol.io) 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.
37
+
38
+ 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.).
39
+
40
+ ## Tools
41
+
42
+ ### Drive — files & folders
43
+ - `drive_search(query, only_folders=False, max_results=20)` — find files/folders (and their IDs).
44
+ - `drive_create_folder(name, parent=None)` — create a folder (`parent` accepts an ID, URL, `root`, or an unambiguous folder name).
45
+ - `drive_move(file, dest_folder, keep_existing_parents=False)` — *true move* (removed from its current folder); `keep_existing_parents=True` adds without removing.
46
+ - `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).
47
+
48
+ ### Google Sheets — read, edit, structure, format
49
+ - `sheets_get_info(spreadsheet)` — list tabs + sizes (call first to learn tab names).
50
+ - `sheets_read(spreadsheet, range_a1, render_option="FORMATTED_VALUE")` — read a range (`FORMULA`/`UNFORMATTED_VALUE` available).
51
+ - `sheets_write(spreadsheet, range_a1, values, value_input_option="USER_ENTERED")` — overwrite a range; returns `before`. `USER_ENTERED` parses numbers and makes `=SUM(..)` a formula; `RAW` writes literally.
52
+ - `sheets_append(spreadsheet, range_a1, values, ...)` — append rows after a table.
53
+ - `sheets_clear(spreadsheet, range_a1)` — clear values (keeps formatting); returns `before`.
54
+ - `sheets_batch_write(spreadsheet, updates, ...)` — write many ranges atomically.
55
+ - `sheets_add_tab` / `sheets_rename_tab` / `sheets_delete_tab` — manage tabs (delete is destructive).
56
+ - `sheets_format(spreadsheet, range_a1, number_format=None, bold=None, background=None)` — number pattern / bold / `#RRGGBB` background.
57
+
58
+ 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.
59
+
60
+ ## Scope warning (read this)
61
+
62
+ 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.
63
+
64
+ ## Install
65
+
66
+ ```bash
67
+ pip install google-drive-files-mcp
68
+ # or: uv tool install google-drive-files-mcp
69
+ ```
70
+
71
+ ## One-time setup (~10 min)
72
+
73
+ 1. [Google Cloud Console](https://console.cloud.google.com/) → create/pick a project.
74
+ 2. Enable the **Drive API** ([library link](https://console.cloud.google.com/apis/library/drive.googleapis.com)) and, for the Sheets tools, the **Sheets API** ([library link](https://console.cloud.google.com/apis/library/sheets.googleapis.com)). (The full `drive` scope already authorizes the Sheets API — no extra consent, just enable the API.)
75
+ 3. 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).
76
+ 4. Credentials → **OAuth client ID** → **Desktop app** → download JSON.
77
+ 5. `google-drive-files-mcp setup --import-credentials ~/Downloads/client_secret_*.json` → consent in the browser.
78
+
79
+ Verify:
80
+ ```bash
81
+ google-drive-files-mcp status
82
+ google-drive-files-mcp search "Reports" --folders
83
+ ```
84
+
85
+ ## Claude Code
86
+
87
+ ```bash
88
+ claude mcp add --scope user google-drive-files google-drive-files-mcp -- serve
89
+ ```
90
+
91
+ > Find my "Q2 Report" doc and move it into the "2026 Reports" folder.
92
+
93
+ ## Claude Desktop
94
+
95
+ ```json
96
+ {
97
+ "mcpServers": {
98
+ "google-drive-files": { "command": "google-drive-files-mcp", "args": ["serve"] }
99
+ }
100
+ }
101
+ ```
102
+
103
+ ## CLI
104
+
105
+ ```bash
106
+ google-drive-files-mcp search "budget" # find a file + its ID
107
+ google-drive-files-mcp search "Reports" --folders # find destination folders
108
+ google-drive-files-mcp mkdir "2026 Reports" # create a folder
109
+ google-drive-files-mcp move <file-url-or-id> "2026 Reports" # move into it (by folder name)
110
+ google-drive-files-mcp move <file-url-or-id> root # move back to My Drive root
111
+ google-drive-files-mcp upload ~/Downloads/report.zip --parent "2026 Reports" # upload a local file
112
+
113
+ # Google Sheets
114
+ google-drive-files-mcp sheet-info <sheet-url-or-id> # list tabs + sizes
115
+ google-drive-files-mcp sheet-read <sheet-url-or-id> "Sheet1!A1:D10" # read a range
116
+ google-drive-files-mcp sheet-write <sheet-url-or-id> "Sheet1!B2:B4" '[[100],[200],[300]]' # set numbers
117
+ google-drive-files-mcp sheet-format <sheet-url-or-id> "Sheet1!B2:B4" --number-format '#,##0.00' --bold
118
+ ```
119
+
120
+ `drive_move` returns the before/after parents so the move is auditable:
121
+ ```json
122
+ { "id": "1Abc…", "name": "Q2 Report", "moved_from": ["0OldFolderId"], "moved_to": "1NewFolderId", "parents_now": ["1NewFolderId"], "web_view_link": "https://docs.google.com/…" }
123
+ ```
124
+
125
+ ## Configuration
126
+
127
+ | Variable | Default | What |
128
+ |---|---|---|
129
+ | `GDRIVE_FILES_MCP_CREDENTIALS` | `~/.config/google-drive-files-mcp/credentials.json` | OAuth client secret |
130
+ | `GDRIVE_FILES_MCP_TOKEN` | `~/.config/google-drive-files-mcp/token.json` | Cached refresh token |
131
+ | `GDRIVE_FILES_MCP_SCOPES` | `https://www.googleapis.com/auth/drive` | OAuth scopes (comma-separated) |
132
+
133
+ ## Safety notes
134
+
135
+ - **True move removes the file from its current folder.** Drive items can have multiple parents; `keep_existing_parents=True` adds without removing.
136
+ - **Folder-name destinations must be unambiguous.** If two folders share a name, `drive_move` refuses and lists the candidates so you can pass an explicit ID.
137
+ - **The before/after parents are returned** on every move so an agent (or you) can verify the result.
138
+
139
+ ## Troubleshooting
140
+
141
+ **`HttpError 403: Google Drive API has not been used in project … or it is disabled`**
142
+ Enable the Drive API on the project that owns your OAuth client: [console.cloud.google.com/apis/library/drive.googleapis.com](https://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.)
143
+
144
+ **`multiple folders named '…'; pass the folder ID/URL instead`**
145
+ 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.
146
+
147
+ **`no folder named '…' found`**
148
+ Create it first (`google-drive-files-mcp mkdir "<name>"`) or pass a folder ID/URL/`root`.
149
+
150
+ **`HttpError 403: insufficientFilePermissions` when moving**
151
+ 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).
152
+
153
+ **`No valid Google token` from Claude Desktop / cron**
154
+ 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.
155
+
156
+ **A move "removed" a file from a shared folder unexpectedly**
157
+ 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`).
158
+
159
+ ## Use it from other clients (Cursor, Cline, Continue, …)
160
+
161
+ Any stdio MCP client works — see [docs/other-clients.md](docs/other-clients.md).
162
+
163
+ ## Authentication — bring your own Google OAuth client
164
+
165
+ 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.
166
+
167
+ - **Why your own client?** Google's restricted scopes (here, the full `drive` scope) 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.
168
+ - **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](docs/setup-google-oauth.md).
169
+ - **Where your token lives:** `~/.config/google-drive-files-mcp/token.json` (mode `0600`). Delete it to revoke locally; revoke fully at [myaccount.google.com/permissions](https://myaccount.google.com/permissions).
170
+ - **No hosted/SaaS option** — everything runs locally; your Drive data never touches a third-party server.
171
+
172
+ ## More guides
173
+
174
+ - [docs/setup-google-oauth.md](docs/setup-google-oauth.md) — full OAuth walkthrough (full-`drive` scope) + common errors
175
+ - [docs/claude-code.md](docs/claude-code.md) · [docs/claude-desktop.md](docs/claude-desktop.md) · [docs/other-clients.md](docs/other-clients.md)
176
+ - [examples/](examples/) — e.g. file a document into a `YYYY-MM` folder
177
+
178
+ ## Related tools
179
+
180
+ Part of a small family of focused, local MCP servers for Google Workspace data the hosted connectors don't expose:
181
+
182
+ - **[gmail-attachments-mcp](https://github.com/zayansalman/gmail-attachments-mcp)** — download Gmail attachment bytes to disk
183
+ - **[google-drive-comments-mcp](https://github.com/zayansalman/google-drive-comments-mcp)** — read comment threads on Docs/Sheets/Slides
184
+ - **google-drive-files-mcp** — move/organize Drive files *(this repo)*
185
+
186
+ They can share one OAuth login or stay isolated — see each repo's setup.
187
+
188
+ ## License
189
+
190
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,159 @@
1
+ # google-drive-files-mcp
2
+
3
+ <!-- mcp-name: io.github.zayansalman/google-drive-files-mcp -->
4
+
5
+ A focused [Model Context Protocol](https://modelcontextprotocol.io) 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.
6
+
7
+ 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.).
8
+
9
+ ## Tools
10
+
11
+ ### Drive — files & folders
12
+ - `drive_search(query, only_folders=False, max_results=20)` — find files/folders (and their IDs).
13
+ - `drive_create_folder(name, parent=None)` — create a folder (`parent` accepts an ID, URL, `root`, or an unambiguous folder name).
14
+ - `drive_move(file, dest_folder, keep_existing_parents=False)` — *true move* (removed from its current folder); `keep_existing_parents=True` adds without removing.
15
+ - `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).
16
+
17
+ ### Google Sheets — read, edit, structure, format
18
+ - `sheets_get_info(spreadsheet)` — list tabs + sizes (call first to learn tab names).
19
+ - `sheets_read(spreadsheet, range_a1, render_option="FORMATTED_VALUE")` — read a range (`FORMULA`/`UNFORMATTED_VALUE` available).
20
+ - `sheets_write(spreadsheet, range_a1, values, value_input_option="USER_ENTERED")` — overwrite a range; returns `before`. `USER_ENTERED` parses numbers and makes `=SUM(..)` a formula; `RAW` writes literally.
21
+ - `sheets_append(spreadsheet, range_a1, values, ...)` — append rows after a table.
22
+ - `sheets_clear(spreadsheet, range_a1)` — clear values (keeps formatting); returns `before`.
23
+ - `sheets_batch_write(spreadsheet, updates, ...)` — write many ranges atomically.
24
+ - `sheets_add_tab` / `sheets_rename_tab` / `sheets_delete_tab` — manage tabs (delete is destructive).
25
+ - `sheets_format(spreadsheet, range_a1, number_format=None, bold=None, background=None)` — number pattern / bold / `#RRGGBB` background.
26
+
27
+ 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.
28
+
29
+ ## Scope warning (read this)
30
+
31
+ 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.
32
+
33
+ ## Install
34
+
35
+ ```bash
36
+ pip install google-drive-files-mcp
37
+ # or: uv tool install google-drive-files-mcp
38
+ ```
39
+
40
+ ## One-time setup (~10 min)
41
+
42
+ 1. [Google Cloud Console](https://console.cloud.google.com/) → create/pick a project.
43
+ 2. Enable the **Drive API** ([library link](https://console.cloud.google.com/apis/library/drive.googleapis.com)) and, for the Sheets tools, the **Sheets API** ([library link](https://console.cloud.google.com/apis/library/sheets.googleapis.com)). (The full `drive` scope already authorizes the Sheets API — no extra consent, just enable the API.)
44
+ 3. 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).
45
+ 4. Credentials → **OAuth client ID** → **Desktop app** → download JSON.
46
+ 5. `google-drive-files-mcp setup --import-credentials ~/Downloads/client_secret_*.json` → consent in the browser.
47
+
48
+ Verify:
49
+ ```bash
50
+ google-drive-files-mcp status
51
+ google-drive-files-mcp search "Reports" --folders
52
+ ```
53
+
54
+ ## Claude Code
55
+
56
+ ```bash
57
+ claude mcp add --scope user google-drive-files google-drive-files-mcp -- serve
58
+ ```
59
+
60
+ > Find my "Q2 Report" doc and move it into the "2026 Reports" folder.
61
+
62
+ ## Claude Desktop
63
+
64
+ ```json
65
+ {
66
+ "mcpServers": {
67
+ "google-drive-files": { "command": "google-drive-files-mcp", "args": ["serve"] }
68
+ }
69
+ }
70
+ ```
71
+
72
+ ## CLI
73
+
74
+ ```bash
75
+ google-drive-files-mcp search "budget" # find a file + its ID
76
+ google-drive-files-mcp search "Reports" --folders # find destination folders
77
+ google-drive-files-mcp mkdir "2026 Reports" # create a folder
78
+ google-drive-files-mcp move <file-url-or-id> "2026 Reports" # move into it (by folder name)
79
+ google-drive-files-mcp move <file-url-or-id> root # move back to My Drive root
80
+ google-drive-files-mcp upload ~/Downloads/report.zip --parent "2026 Reports" # upload a local file
81
+
82
+ # Google Sheets
83
+ google-drive-files-mcp sheet-info <sheet-url-or-id> # list tabs + sizes
84
+ google-drive-files-mcp sheet-read <sheet-url-or-id> "Sheet1!A1:D10" # read a range
85
+ google-drive-files-mcp sheet-write <sheet-url-or-id> "Sheet1!B2:B4" '[[100],[200],[300]]' # set numbers
86
+ google-drive-files-mcp sheet-format <sheet-url-or-id> "Sheet1!B2:B4" --number-format '#,##0.00' --bold
87
+ ```
88
+
89
+ `drive_move` returns the before/after parents so the move is auditable:
90
+ ```json
91
+ { "id": "1Abc…", "name": "Q2 Report", "moved_from": ["0OldFolderId"], "moved_to": "1NewFolderId", "parents_now": ["1NewFolderId"], "web_view_link": "https://docs.google.com/…" }
92
+ ```
93
+
94
+ ## Configuration
95
+
96
+ | Variable | Default | What |
97
+ |---|---|---|
98
+ | `GDRIVE_FILES_MCP_CREDENTIALS` | `~/.config/google-drive-files-mcp/credentials.json` | OAuth client secret |
99
+ | `GDRIVE_FILES_MCP_TOKEN` | `~/.config/google-drive-files-mcp/token.json` | Cached refresh token |
100
+ | `GDRIVE_FILES_MCP_SCOPES` | `https://www.googleapis.com/auth/drive` | OAuth scopes (comma-separated) |
101
+
102
+ ## Safety notes
103
+
104
+ - **True move removes the file from its current folder.** Drive items can have multiple parents; `keep_existing_parents=True` adds without removing.
105
+ - **Folder-name destinations must be unambiguous.** If two folders share a name, `drive_move` refuses and lists the candidates so you can pass an explicit ID.
106
+ - **The before/after parents are returned** on every move so an agent (or you) can verify the result.
107
+
108
+ ## Troubleshooting
109
+
110
+ **`HttpError 403: Google Drive API has not been used in project … or it is disabled`**
111
+ Enable the Drive API on the project that owns your OAuth client: [console.cloud.google.com/apis/library/drive.googleapis.com](https://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.)
112
+
113
+ **`multiple folders named '…'; pass the folder ID/URL instead`**
114
+ 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.
115
+
116
+ **`no folder named '…' found`**
117
+ Create it first (`google-drive-files-mcp mkdir "<name>"`) or pass a folder ID/URL/`root`.
118
+
119
+ **`HttpError 403: insufficientFilePermissions` when moving**
120
+ 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).
121
+
122
+ **`No valid Google token` from Claude Desktop / cron**
123
+ 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.
124
+
125
+ **A move "removed" a file from a shared folder unexpectedly**
126
+ 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`).
127
+
128
+ ## Use it from other clients (Cursor, Cline, Continue, …)
129
+
130
+ Any stdio MCP client works — see [docs/other-clients.md](docs/other-clients.md).
131
+
132
+ ## Authentication — bring your own Google OAuth client
133
+
134
+ 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.
135
+
136
+ - **Why your own client?** Google's restricted scopes (here, the full `drive` scope) 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.
137
+ - **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](docs/setup-google-oauth.md).
138
+ - **Where your token lives:** `~/.config/google-drive-files-mcp/token.json` (mode `0600`). Delete it to revoke locally; revoke fully at [myaccount.google.com/permissions](https://myaccount.google.com/permissions).
139
+ - **No hosted/SaaS option** — everything runs locally; your Drive data never touches a third-party server.
140
+
141
+ ## More guides
142
+
143
+ - [docs/setup-google-oauth.md](docs/setup-google-oauth.md) — full OAuth walkthrough (full-`drive` scope) + common errors
144
+ - [docs/claude-code.md](docs/claude-code.md) · [docs/claude-desktop.md](docs/claude-desktop.md) · [docs/other-clients.md](docs/other-clients.md)
145
+ - [examples/](examples/) — e.g. file a document into a `YYYY-MM` folder
146
+
147
+ ## Related tools
148
+
149
+ Part of a small family of focused, local MCP servers for Google Workspace data the hosted connectors don't expose:
150
+
151
+ - **[gmail-attachments-mcp](https://github.com/zayansalman/gmail-attachments-mcp)** — download Gmail attachment bytes to disk
152
+ - **[google-drive-comments-mcp](https://github.com/zayansalman/google-drive-comments-mcp)** — read comment threads on Docs/Sheets/Slides
153
+ - **google-drive-files-mcp** — move/organize Drive files *(this repo)*
154
+
155
+ They can share one OAuth login or stay isolated — see each repo's setup.
156
+
157
+ ## License
158
+
159
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,23 @@
1
+ # Claude Code integration
2
+
3
+ After `pip install google-drive-files-mcp` and `google-drive-files-mcp setup`:
4
+
5
+ ```bash
6
+ claude mcp add --scope user google-drive-files google-drive-files-mcp -- serve
7
+ ```
8
+
9
+ Verify:
10
+ ```bash
11
+ claude mcp list | grep google-drive-files
12
+ # google-drive-files: google-drive-files-mcp serve - ✓ Connected
13
+ ```
14
+
15
+ In a session:
16
+ > Find my "Q2 Report" doc and move it into the "2026 Reports" folder.
17
+
18
+ Because this tool can move/relocate files, prefer to let it **search first and show you the matches** before moving — `drive_move` returns the before/after parents so every move is auditable.
19
+
20
+ ## Remove
21
+ ```bash
22
+ claude mcp remove google-drive-files
23
+ ```
@@ -0,0 +1,30 @@
1
+ # Claude Desktop integration
2
+
3
+ After installing and running `google-drive-files-mcp setup`, edit Claude Desktop's MCP config:
4
+
5
+ - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
6
+ - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
7
+ - **Linux**: `~/.config/Claude/claude_desktop_config.json`
8
+
9
+ ```json
10
+ {
11
+ "mcpServers": {
12
+ "google-drive-files": {
13
+ "command": "google-drive-files-mcp",
14
+ "args": ["serve"]
15
+ }
16
+ }
17
+ }
18
+ ```
19
+
20
+ If the command isn't on Claude Desktop's `$PATH`, use the absolute path from `which google-drive-files-mcp`.
21
+
22
+ ## Newer Claude Desktop / Cowork builds
23
+ Some builds read MCP config from the unified `~/.claude.json` (shared with Claude Code) rather than `claude_desktop_config.json`. If editing the JSON has no effect after a restart, register via the CLI and relaunch:
24
+
25
+ ```bash
26
+ claude mcp add --scope user google-drive-files google-drive-files-mcp -- serve
27
+ ```
28
+
29
+ ## Verify
30
+ > Create a folder called "Archive 2026" and move my oldest "Draft" doc into it.
@@ -0,0 +1,32 @@
1
+ # Other MCP clients
2
+
3
+ Any stdio-transport MCP client can use `google-drive-files-mcp`:
4
+
5
+ - **Transport**: stdio
6
+ - **Command**: `google-drive-files-mcp` (or the absolute path)
7
+ - **Args**: `["serve"]`
8
+ - **Env** (optional): `GDRIVE_FILES_MCP_CREDENTIALS`, `GDRIVE_FILES_MCP_TOKEN`, `GDRIVE_FILES_MCP_SCOPES`
9
+
10
+ ## Cursor — `~/.cursor/mcp.json`
11
+ ```json
12
+ {
13
+ "mcpServers": {
14
+ "google-drive-files": { "command": "google-drive-files-mcp", "args": ["serve"] }
15
+ }
16
+ }
17
+ ```
18
+
19
+ ## Cline (VS Code)
20
+ MCP settings → **Add MCP server** → stdio. Command `google-drive-files-mcp`, args `serve`.
21
+
22
+ ## Continue.dev — `~/.continue/config.yaml`
23
+ ```yaml
24
+ mcpServers:
25
+ - name: google-drive-files
26
+ command: google-drive-files-mcp
27
+ args:
28
+ - serve
29
+ ```
30
+
31
+ ## One-time auth per machine
32
+ Once `google-drive-files-mcp setup` has cached a token at `~/.config/google-drive-files-mcp/token.json`, every client on that machine/user reuses it — no per-client re-authentication.
@@ -0,0 +1,56 @@
1
+ # Google OAuth setup (~10 minutes)
2
+
3
+ This server **moves and organizes files in your Drive**, so it needs the **full `drive` scope** (read + write + delete on all your Drive files). There is no narrower scope that can change a file's parents. Treat the cached token like a password.
4
+
5
+ You create your own OAuth client; nothing is shipped with the package, and nothing leaves your machine.
6
+
7
+ ## Step 1 — Project
8
+ 1. [Google Cloud Console](https://console.cloud.google.com/) → sign in → project dropdown → **New Project** → name it → **Create** → switch to it.
9
+
10
+ ## Step 2 — Enable the Drive API
11
+ [console.cloud.google.com/apis/library/drive.googleapis.com](https://console.cloud.google.com/apis/library/drive.googleapis.com) → **Enable**.
12
+
13
+ ## Step 3 — OAuth consent screen
14
+ Left nav → **APIs & Services** → **OAuth consent screen**.
15
+
16
+ | You have | Pick | Why |
17
+ |---|---|---|
18
+ | Google Workspace | **Internal** | No verification needed *even for the restricted full-`drive` scope* |
19
+ | Personal Gmail | **External** | Add your address under **Test users** or consent is refused |
20
+
21
+ Fill App name / support email / developer contact. Leave the Scopes page empty. Save.
22
+
23
+ ## Step 4 — OAuth client
24
+ **Credentials → + Create Credentials → OAuth client ID → Desktop app → Create → Download JSON.**
25
+
26
+ ## Step 5 — Hand it to the CLI
27
+ ```bash
28
+ google-drive-files-mcp setup --import-credentials ~/Downloads/client_secret_*.json
29
+ ```
30
+ A browser opens; the consent screen will say **"See, edit, create, and delete all of your Google Drive files"** — that breadth is required to move arbitrary files. The refresh token is cached at `~/.config/google-drive-files-mcp/token.json` (mode `0600`).
31
+
32
+ Verify:
33
+ ```bash
34
+ google-drive-files-mcp status
35
+ google-drive-files-mcp search "Reports" --folders
36
+ ```
37
+
38
+ ## Common errors
39
+
40
+ **`HttpError 403: Google Drive API has not been used in project … or it is disabled`**
41
+ Enable the Drive API (Step 2) on the project that owns your OAuth client, then wait ~1 min and retry.
42
+
43
+ **`Access blocked: This app's request is invalid`**
44
+ Personal Gmail without your address under **Test users**. Add it on the consent screen.
45
+
46
+ **`This app isn't verified`**
47
+ Expected for an unverified personal app. **Advanced → Go to <app> (unsafe)**. Verification only matters for public distribution.
48
+
49
+ **`HttpError 403: insufficientFilePermissions` / `insufficientPermissions` when moving**
50
+ The token was authorized with a narrower scope. Re-authorize with the full scope:
51
+ ```bash
52
+ google-drive-files-mcp setup --reauth
53
+ ```
54
+
55
+ **Browser opened but never returned**
56
+ Firewall blocking the localhost redirect. Re-run `setup` (new port each time) or allow the connection.
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env bash
2
+ # Move a file into a YYYY-MM folder (created if missing) under a parent folder.
3
+ # Handy for filing exports/reports into month buckets.
4
+ #
5
+ # Usage:
6
+ # ./file-into-dated-folder.sh <file-url-or-id> [parent-folder-name-or-id]
7
+ #
8
+ # Assumes google-drive-files-mcp is installed and `setup` has been run once.
9
+
10
+ set -euo pipefail
11
+
12
+ FILE="${1:?usage: file-into-dated-folder.sh <file-url-or-id> [parent]}"
13
+ PARENT="${2:-root}"
14
+ MONTH="$(date +%Y-%m)"
15
+
16
+ # Create (or reuse) the YYYY-MM folder under PARENT, capture its id.
17
+ FOLDER_ID="$(
18
+ google-drive-files-mcp mkdir "${MONTH}" --parent "${PARENT}" \
19
+ | python3 -c 'import sys,json; print(json.load(sys.stdin)["id"])'
20
+ )"
21
+
22
+ google-drive-files-mcp move "${FILE}" "${FOLDER_ID}"
23
+ echo "filed ${FILE} into ${MONTH} (folder ${FOLDER_ID})"