Claude Workspace Ops MCP
Provides tools for inspecting and organizing a Google Drive workspace: searching and reading files, listing folder contents, finding duplicates, classifying documents, proposing organization plans, and applying approved plans to create folders, rename files, and move files within an app-owned root folder.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Claude Workspace Ops MCPInspect my Google Drive and propose a tidy-up plan for approval"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Claude Workspace Ops MCP
A Python MCP server for AI-assisted Google Drive organization. Claude can inspect a workspace and propose how to tidy it; deterministic Python and an explicit human approval decide what actually happens.
The interesting part is not that Claude can propose a folder structure. It's that a compromised model operating through the MCP interface cannot authorize an unsafe write, and the tests prove it rather than assert it. An attacker who already controls the operator's own terminal session is a different threat and sits outside that boundary — see Threat-model boundaries.
Python 3.11+ · MCP · Google Drive API · OAuth drive.file · Anthropic API
· Pydantic · SQLite · pytest · ruff · mypy
┌────────────── model trust zone ──────────────┐ ┌──── human trust zone ────┐
│ inspect ▶ propose ▶ deterministic validation│ │ cwops approve (TTY only) │
└───────────────────────┬──────────────────────┘ └────────────┬─────────────┘
│ no MCP tool can approve │
└──────────▶ apply_proposal ◀───────────┘
│ single-use · plan-hash bound · expiring
▼
Google Drive + append-only audit logNon-interactive approval fails closed: cwops approve refuses to run when
stdin is not a terminal, --yes included, so a shell-capable agent cannot
manufacture a human decision.
Engineering highlights
Designed and built solo — the MCP server, the Drive and Anthropic integrations, the validator, the approval gate, the storage layer, the fakes and the test suite. Third-party runtime code is limited to the MCP SDK, the Google and Anthropic clients, Pydantic and SQLite.
MCP server — nine typed tools; the published JSON Schema is derived from Pydantic models and pinned by a golden-snapshot test, so a contract change is a reviewed diff. stdio transport, with all logging on stderr so a stray print cannot corrupt the JSON-RPC stream.
Google Drive API integration — installed-app OAuth flow, bounded jittered retry, escaped query values, and a 404 that is never retried.
Least-privilege scope —
drive.fileis hard-coded; a stored token carrying anything broader is rejected at load time.Deterministic validation — pure functions over a fetched snapshot. Unknown IDs, ungranted targets, path separators, cycles and anything outside the app-owned root are rejected, never repaired.
Proposal / dry-run workflow — plans are stored, hashed, previewed in plain language, and re-validated against live Drive state at apply time.
Approval outside the MCP/model trust zone — an approval row is created by one CLI command in a separate process; no tool creates one.
TTY-enforced approval boundary — that CLI fails closed without an interactive terminal, and
--yescannot bypass the check.Plan-hash binding, expiry, single use — approvals are tied to a SHA-256 of the exact operation list, TTL-limited, and claimed by one atomic guarded
UPDATE, with an explicit lifecycle state (none · active · consumed · expired · superseded).Append-only audit log — one row per tool call and per CLI action, with correlation IDs, reason codes on refusal, and secret scrubbing on the way in.
Duplicate detection — checksum-exact vs. metadata-heuristic, with Google-native files reported as unscannable rather than silently unique.
Fakes at the Protocol seams — a fake Drive and a fake organizer make the entire suite deterministic and offline. No mocking library, no network.
Related MCP server: MCP Google Drive Server
Validated against real Google Drive
The gates are not only exercised against the fakes. A full end-to-end run with
CWOPS_DRIVE_BACKEND=google against a live Google account:
Check | Result |
OAuth consent | granted |
Files this app created | reachable |
An unrelated pre-existing Drive file | not reachable — outside the grant |
Workspace seeded | 6 files |
Duplicate detection | the exact duplicate pair found by checksum |
| 11 operations — 5 folder creations + 6 moves |
Approval | given by a human, through |
| executed the exact hash-bound plan it was approved for |
Outcome | 11/11 operations succeeded; 6 files organized into 5 folders |
Duplicate pair | both copies preserved — nothing was deleted |
Destructive actions | none occurred; none exist to call |
Audit trail | distinct |
The TTY boundary was verified against the installed Windows CLI as well: a
non-interactive invocation is refused with approval_not_interactive, while a
real terminal reaches the proposal lookup normally.
The three claims this project makes
1. Least privilege is structural, not procedural.
The only OAuth scope requested is drive.file — Google's one non-sensitive
Drive scope. It grants per-file access to files this app created or that the
user explicitly opened/shared with it. The rest of the user's Drive is not
"forbidden", it is invisible: a request for an ungranted file returns 404,
not 403. There is no configuration option to widen this, and a stored token that
somehow carries a broader scope is rejected at load
time as a configuration error.
2. The model advises; deterministic code decides. Claude is consulted in exactly two places, and it answers in a schema that cannot express an unsafe action. It returns folder names and file assignments — there is no field for "rename", "delete", or "put this outside the workspace". Deterministic code then compiles that draft into operations whose parent folder comes from configuration, never from the model, and re-validates every one.
3. Approval lives in a different trust zone than the agent.
An approval record is created only by cwops approve — a CLI command in a
separate process that refuses to run without an interactive terminal, --yes
included. No MCP tool creates one, and a shell-capable agent gets a pipe rather
than a TTY, so an agent driving this server has no code path to approval. It can
ask; it cannot produce.
Try it in 30 seconds, with no Google account
git clone https://github.com/Shineoverthemoon/claude-workspace-ops-mcp
cd claude-workspace-ops-mcp
python -m venv .venv && .venv/bin/pip install -e ".[dev]" # Windows: .venv\Scripts\pip
cwops democwops demo runs the entire pipeline against an in-memory Drive and an offline
organizer, narrating each gate: what the app can see, deterministic duplicate
detection, a proposed plan, a dry run, a real run refused for lack of
approval, a human approval, a successful run, a replay refused because
approvals are single-use, and the resulting audit trail.
It is also a test (test_demo_runs_the_whole_pipeline_offline), so the
walkthrough in docs/demo.md cannot rot.
========================================================================
5. Real run WITHOUT approval (must be refused)
========================================================================
Refused: [approval_required] Proposal prop_241cb99db035 has no human
approval. Run: cwops approve prop_241cb99db035
Drive mutations so far: 0The tools
Nine tools. Eight are read-only. One can write.
Tool | Model? | Writes? |
| no | no |
| no | no |
| no | no |
| no | no |
| yes | no |
| yes | no |
| no | no |
| no | no |
| no | yes — the only one |
apply_proposal defaults to dry_run=true. A real run additionally requires
CWOPS_ALLOW_MUTATIONS=true and an unconsumed, unexpired approval bound to
that exact plan.
There is no delete, trash, overwrite, permission or sharing capability anywhere in this server. Only create-folder, rename and move exist, and all three are reversible. That is a deliberate MVP boundary, not an oversight — see Deliberate limits.
Duplicate detection is honest about what it can't know
checksum— exact match on Drive'smd5Checksum+ size. Trustworthy.metadata— normalized title + size + MIME type. Always labelledheuristic.
Google-native Docs/Sheets/Slides have no checksum at all. Rather than
silently treating them as unique, they are reported in a separate unscannable
list with the reason. The metadata strategy exists precisely to catch the
copies that checksum structurally cannot.
Running it against your own Google Drive
cp .env.example .env # then edit
cwops auth # browser consent, drive.file only
cwops workspace init # creates the app-owned root folder
# -> prints CWOPS_ROOT_FOLDER_ID to paste into .env
cwops workspace seed # optional: demo files, incl. an exact duplicate pairYou need a Google Cloud project with the Drive API enabled and an OAuth client
ID of type "Desktop app", downloaded as client_secret.json. That file and the
token it produces stay on your machine — both are gitignored, and neither
belongs in a commit.
Because drive.file is non-sensitive, the sensitive/restricted-scope
verification review does not apply — the practical payoff of keeping the
authorization surface narrow.
Scope and publishing status are separate concerns, though. While the OAuth app's
publishing status is Testing, Google issues refresh tokens with a limited
lifetime (currently 7 days), so you will periodically need to re-run
cwops auth. Publishing to production has its own requirements.
To bring an existing file under the app's control, either move it into the
workspace folder or open it with this app; then cwops grant <file_id|url>
verifies and records the grant. Programmatic file-picking (Google Picker) is
deliberately deferred — the GrantSource.PICKER value already exists so adding
it later needs no schema change.
Wiring it into an MCP client
{
"mcpServers": {
"workspace-ops": {
"command": "C:\\Projects\\claude-workspace-ops-mcp\\.venv\\Scripts\\cwops-mcp.exe",
"env": {
"CWOPS_DRIVE_BACKEND": "google",
"CWOPS_AI_BACKEND": "claude",
"CWOPS_ROOT_FOLDER_ID": "<from workspace init>",
"CWOPS_ALLOW_MUTATIONS": "true"
}
}
}
}Transport is stdio, so stdout carries the JSON-RPC stream. Every log line
goes to stderr as single-line JSON with a correlation ID; a stray print()
would corrupt the protocol.
Where Claude is used — and where it deliberately isn't
Concern | Handled by |
Classifying an ambiguous document | Claude ( |
Suggesting a folder taxonomy | Claude |
Everything else | Deterministic Python |
"Everything else" means: authorization, workspace containment, grant checks, name policy, duplicate detection, plan compilation, approval, execution ordering, retry, and audit. None of it consults a model, and none of it can be influenced by one.
Claude's output is treated as untrusted input. File names and contents are attacker-controllable, so a persuasive document could talk the model into suggesting something hostile. The system prompt says to ignore embedded instructions — but that is noise reduction, not the defence. The defence is that the validator rejects the result afterwards regardless of what the model was persuaded to say.
tests/test_ai_boundary.py demonstrates this with an organizer that returns
deliberately hostile plans.
Architecture
src/cwops/
config.py env vars; drive.file scope hard-coded; fails fast
logging.py structured JSON to stderr + secret scrubbing
models.py the MCP contract (Pydantic -> published JSON Schema)
clock.py injectable time, so TTLs are tested not slept through
container.py dependency wiring: real backends vs. offline fakes
workspace.py read-side ops; keeps the grant ledger honest
provision.py CLI-only workspace bootstrap (2nd of 2 write sites)
server.py MCP wiring only
cli.py the human half of the approval gate
drive/ DriveClient Protocol · OAuth · Google impl · retry · fake
ai/ Organizer Protocol · Claude impl · prompts · fake
rules/ naming · duplicates · validate (pure functions, no I/O)
store/ SQLite: proposals · approvals · grants · audit
tools/ read (8 read-only) · organize · apply (the write path)Two Protocol seams — DriveClient and Organizer — are what let every safety
gate be built and fully tested before any real Google or Anthropic code
existed, and what let the whole system run offline today.
Full data flow and trust zones: docs/architecture.md. The invariants and the threat model: docs/safety-model.md.
Testing
pytest # 248 passed, 1 skipped, ~5s, no network
ruff check . && mypy # both clean (mypy's configured scope: src/cwops)
pytest --cov=cwops # 89% overall; rules/ 96-100%Suite | What it proves |
| No tool can create an approval · single-use · TTL · plan-hash binding · tampering invalidates · operator switch · world-changed detection · approval lifecycle state |
| Approval refused without an interactive terminal, |
| 23 adversarial plans from a JSON fixture — hallucinated IDs, path traversal, cycles, escapes — all rejected |
| A hostile organizer cannot cause an unsafe operation |
| Zero mutating calls across every read tool and every dry run — asserted against the fake's call log, plus a source-level check that only |
| Exact vs. heuristic; Google-native files unscannable, not "unique"; output is deterministic |
| Backoff bounded and jittered; 404 never retried; Drive query values escaped against injection |
| Only |
| One row per call; refusals recorded; no secret can reach the table |
| Golden snapshot of the published MCP contract |
No test touches the network. Two fakes at the Protocol seams make that possible without mocking libraries.
Deliberate limits
Documented as scope, not omissions:
No destructive operations. No delete, trash, overwrite, permissions or sharing. Everything the MVP can do is reversible.
No Google Picker. Existing files come under management by being moved into the workspace or opened with the app. The
pickergrant source is reserved.No Shared Drives, no multi-user, no concurrent proposals across processes.
No undo journal. Rename and move are reversible in principle; a one-command rollback is not built.
stdio transport only. No HTTP/SSE.
A partially-invalid plan is trimmed, not rejected. Rejected operations are dropped and shown in full — with reason codes — in the proposal, the preview, and the audit log, so the human approves an explicit list. A plan with nothing left cannot be approved at all.
Threat-model boundaries
Stated plainly, because a safety argument with no stated limits is marketing. Full version in docs/safety-model.md.
The operator is trusted. Anyone who can type at the operator's terminal can approve anything. The TTY requirement raises the bar to "can allocate a PTY"; it is not a defence against something that already owns your session.
The MCP client is assumed to be the intended one. The server does not authenticate its caller.
The SQLite file is a local, single-user trust boundary, not a tamper-proof ledger: write access to it means write access to approvals. The audit log is append-only by convention, not cryptographically chained.
drive.filedoes not protect files already granted. A file you opened with this app is genuinely reachable — which is why workspace containment is a separate control, tested separately.Prompt injection is mitigated structurally, not by prompting. The system prompt says to ignore embedded instructions, but the actual defence is that the validator rejects whatever the model was persuaded to produce.
Secrets
.env, client_secret*.json, *token.json and *.db are gitignored. The
Anthropic SDK reads ANTHROPIC_API_KEY from the environment directly; no
credential is ever passed through this code. The audit log and every log line
are scrubbed on the way out — test_audit.py asserts that a credential passed
in by mistake cannot reach the database.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Give Claude only the Google Drive files you choose. Every action logged.
Personal CRM for Claude. Contacts live as plain-text files in your own Google Drive.
- AurentiaOAuthfr.aurentia
Your Aurentia workspace — projects, CRM, tasks, deliverables — in Claude, Cursor or any MCP client.
- platform7nOAuthtech.p7n
Connect Claude to your Platform7n workspaces — chat, links, and tasks. One-click OAuth.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables Claude to manage Google Drive files and folders through natural language commands. Supports creating folders, moving/renaming files, retrieving file metadata, and listing folder contents with secure OAuth authentication.-
- FlicenseNot gradedqualityNot gradedmaintenanceConnects AI assistants like Claude to Google Drive, enabling them to browse, read, search, create, and edit files and folders using Google's official API with secure authentication.-
- AlicenseNot gradedqualityDmaintenanceEnables Claude to intelligently organize files by scanning folders, detecting duplicates, suggesting meaningful names, and moving files into logical folders.MIT
- FlicenseNot gradedqualityDmaintenanceEnables managing Google Drive files, Docs, and Sheets through natural language via Claude Code, with tools for listing, searching, editing, and formatting documents and spreadsheets.-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Shineoverthemoon/claude-workspace-ops-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server