Skip to main content
Glama
jrubiosainz

Google Drive MCP Server

by jrubiosainz

Foundry Agent + Google Drive (self-hosted MCP)

A working example of a Microsoft Foundry agent that answers natural-language questions about your personal Google Drive — through a small Google Drive MCP server you host yourself on Azure App Service:

"¿Qué documentos tengo en Drive?" "Resume el archivo 'Viaje molón a Japón'." "¿Qué dice mi plan de marketing sobre el presupuesto?"

Built with the new Microsoft Foundry SDKazure-ai-projects 2.x prompt agents + the OpenAI-compatible Responses API — and the Model Context Protocol (MCP).

Because the Google identity lives server-side (a refresh token stored on the App Service), the agent works the same from this CLI and from the Foundry web portal — no localhost, no per-user OAuth.


Why a self-hosted MCP server?

Google publishes a hosted Drive MCP server at drivemcp.googleapis.com. In testing with a personal @gmail.com account it lets you initialize and tools/list, but denies every data-plane call (search_files, list_recent_files, …) with:

The caller does not have permission

…even though the OAuth client is a Web app, both scopes are granted, the Drive API is enabled, and the raw Drive API v3 returns your files with the exact same token (proven by check_drivemcp.py). The hosted MCP is a restricted preview, and nothing you change client-side fixes it for a consumer Google account.

Solution: host a tiny MCP server (webapp/) that speaks the same MCP protocol but calls the plain Drive API v3 (which works). It runs on Azure App Service and holds your Google refresh token in app settings.


Related MCP server: Google Drive MCP Server

Architecture

flowchart LR
    U([You]) -- question --> C[main.py CLI / Foundry portal]
    C -- create agent + run --> FA[Foundry Agent Service]
    FA -- MCP tool call over HTTPS<br/>server_url + ?key=secret --> APP[App Service<br/>Flask MCP server]
    APP -- Drive API v3<br/>refresh token --> DRIVE[(Your Google Drive)]
  1. Foundry agent (agents.create_version + PromptAgentDefinition) has one tool: an MCP tool pointing at your App Service URL, e.g. https://<app>.azurewebsites.net/mcp?key=<shared-secret>.

  2. The App Service (webapp/) implements MCP (initialize, tools/list, tools/call) and exposes three tools: search_files, list_files, get_file_content.

  3. It authenticates the caller with a shared secret in the URL and calls the Drive API v3 using a stored refresh token (exchanged for short-lived access tokens on demand).

  4. Chat happens over the OpenAI-compatible Responses API on a conversation, so multi-turn context is preserved. The service runs the MCP tools and returns the answer.

Two auth hops, both server-to-server:

Hop

Mechanism

Foundry → App Service

Shared secret in the server_url query (?key=…)

App Service → Google

OAuth refresh token (GOOGLE_CLIENT_ID/SECRET/REFRESH_TOKEN app settings)


Prerequisites

  • Python 3.10+ and Azure CLI (az login).

  • An Azure subscription with a Microsoft Foundry project + a deployed chat model (this repo uses gpt-4o-mini). Provisioned here via infra/foundry.bicep.

  • A Google account with files in Drive, and a Google Cloud project where you can enable the Drive API and create a Web OAuth client.


Part 1 — Google Cloud setup

You only need the Drive API (not the hosted MCP service) and a Web OAuth client whose JSON you save as credentials.json.

1.1 Enable the Drive API

gcloud services enable drive.googleapis.com --project=PROJECT_ID

(Console: APIs & Services → Enable APIs and services → Google Drive API.)

Google Auth Platform → Branding: set an app name and support email. Under Audience, choose External and add your own email as a Test user (or Internal if it's a Workspace org). Under Data Access → Add scopes, add:

  • https://www.googleapis.com/auth/drive.readonly

  • https://www.googleapis.com/auth/drive.file

1.3 Create a Web application OAuth client

Google Auth Platform → Clients → Create Client → Application type: Web application. Add the authorized redirect URI:

http://localhost:8765/

Create it and Download JSON → save as credentials.json in the repo root.

If the download button doesn't work, copy the Client ID and Client secret into a credentials.json of this shape:

{
  "web": {
    "client_id": "…apps.googleusercontent.com",
    "project_id": "your-project",
    "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    "token_uri": "https://oauth2.googleapis.com/token",
    "client_secret": "GOCSPX-…",
    "redirect_uris": ["http://localhost:8765/"]
  }
}

Part 2 — Deploy the MCP server to Azure App Service

The Foundry project is already provisioned (infra/foundry.bicep). Now stand up the MCP web app.

Region note: App Service VM quota is regional. If F1/B1 fails with "Operation cannot be completed without additional quota … Total VMs: 0" in your Foundry region, pick another region for the web app (this repo uses westus2). The web app does not need to be co-located with Foundry.

2.1 Provision (one time)

RG=Google-Drive
APP=gdrive-mcp-$RANDOM          # must be globally unique
REGION=westus2

az appservice plan create -g $RG -n gdrive-mcp-plan --is-linux --sku F1 --location $REGION
az webapp create -g $RG -p gdrive-mcp-plan -n $APP --runtime "PYTHON:3.11"
az webapp config set -g $RG -n $APP --startup-file "gunicorn --bind=0.0.0.0:8000 --timeout 600 app:app"
az webapp config appsettings set -g $RG -n $APP --settings SCM_DO_BUILD_DURING_DEPLOYMENT=true
az webapp update -g $RG -n $APP --https-only true

2.2 Set the shared secret

Generate a long random secret and store it as an app setting (the Foundry agent will send it in the URL):

# any long random string; keep a copy for your .env MCP_SERVER_URL
az webapp config appsettings set -g $RG -n $APP --settings MCP_SHARED_SECRET="<your-40-char-secret>"

2.3 Deploy the code

# PowerShell helper (zips webapp/ contents + az webapp deploy):
./scripts/deploy_webapp.ps1 -AppName $APP -ResourceGroup $RG

Verify it's live (no secret needed for health):

curl https://$APP.azurewebsites.net/
# {"status":"ok","server":{"name":"gdrive-mcp-appservice","version":"1.0.0"}}

Part 3 — Connect your Google Drive to the server

3.1 Authenticate to Google (local, one time)

python -m venv .venv
# Windows: .\.venv\Scripts\Activate.ps1   | macOS/Linux: source .venv/bin/activate
pip install -r requirements.txt

python main.py auth      # opens a browser, writes token.json (incl. refresh token)

3.2 Push your Google credentials to the App Service

This reads your local credentials.json + token.json and stores the client id/secret + refresh token as app settings. Secrets go disk → Azure; they are never printed or sent through anything else.

./scripts/set_appservice_secrets.ps1 -AppName <your-app-name> -ResourceGroup Google-Drive

After this the MCP tools can actually read your Drive.


Part 4 — Create the agent and test

Copy the env template and fill it in:

cp .env.example .env        # Windows: copy .env.example .env

Set:

  • PROJECT_ENDPOINT — Foundry project endpoint.

  • MODEL_DEPLOYMENT_NAME — e.g. gpt-4o-mini.

  • MCP_SERVER_URLhttps://<your-app>.azurewebsites.net/mcp?key=<your-secret>.

Then:

az login                                   # so DefaultAzureCredential gets a token

python main.py create-agent                # persists the agent (for the portal)
python main.py ask "¿qué documentos tengo en drive?"
python main.py chat                         # interactive loop

Your signed-in identity needs a Foundry data-plane role (e.g. Azure AI User) on the Foundry account — Owner alone is not enough for data calls.


Part 5 — Use it from the Foundry portal

python main.py create-agent publishes a persistent agent version. Open ai.azure.com → your project → Agentsgdrive-mcp-agentTry in playground, and ask the same questions. Because the Google identity is server-side, no extra sign-in is needed.


Available MCP tools

Tool

Purpose

search_files

Find files by keyword (name + full text)

list_files

List recently modified files

get_file_content

Read a file's text (Docs/Slides→text, Sheets→CSV, PDF extracted, text as-is). Accepts file_id or name

Restrict them with MCP_ALLOWED_TOOLS if you want (e.g. search_files,get_file_content).


Configuration reference

Variable

Where

Required

Default

Description

PROJECT_ENDPOINT

.env

Foundry project endpoint

MODEL_DEPLOYMENT_NAME

.env

Deployed model name (gpt-4o-mini)

MCP_SERVER_URL

.env

https://<app>.azurewebsites.net/mcp?key=<secret>

MCP_SERVER_LABEL

.env

google_drive

Tool label

MCP_ALLOWED_TOOLS

.env

(all)

Comma-separated allow-list

MCP_REQUIRE_APPROVAL

.env

never

never (service runs tools) or always (app auto-approves + logs)

AGENT_NAME

.env

gdrive-mcp-agent

Agent name

MCP_SHARED_SECRET

App Service

Secret the URL ?key= must match

GOOGLE_CLIENT_ID

App Service

From credentials.json (set by script)

GOOGLE_CLIENT_SECRET

App Service

From credentials.json (set by script)

GOOGLE_REFRESH_TOKEN

App Service

From token.json (set by script)

MAX_CONTENT_CHARS

App Service

12000

Truncate file content length


Project layout

foundry-gdrive-mcp-agent/
├── main.py                 # CLI: auth / ask / chat / create-agent
├── check_google.py         # Diagnostic: verify Drive token directly
├── check_drivemcp.py       # Diagnostic: probe Google's hosted Drive MCP
├── requirements.txt        # Agent-side deps (Foundry SDK, Google auth)
├── .env.example
├── infra/
│   └── foundry.bicep       # Foundry account + project + model deployment
├── scripts/
│   ├── deploy_webapp.ps1           # Zip + deploy webapp/ to App Service
│   └── set_appservice_secrets.ps1  # Push Google creds (disk → Azure)
├── src/
│   ├── config.py           # Settings from environment
│   ├── google_auth.py      # Google OAuth 2.0 (obtain/refresh token, `auth` cmd)
│   └── foundry_agent.py    # Foundry prompt agent + MCP tool + approval loop
└── webapp/                 # The self-hosted Google Drive MCP server
    ├── app.py              # Flask wrapper (health + /mcp + shared-secret auth)
    ├── mcp_core.py         # MCP JSON-RPC + Drive API v3 logic (3 tools)
    ├── requirements.txt    # Web app deps (Flask, gunicorn, requests, pypdf)
    └── startup.txt         # gunicorn startup command

Troubleshooting

  • DefaultAzureCredential / data-plane 401–403az login; assign your identity Azure AI User on the Foundry account (Owner is control-plane only).

  • App Service create fails: "Total VMs: 0" → no App Service quota in that region; deploy the web app to another region (e.g. westus2). It's independent of the Foundry region.

  • Health OK but tool calls return "missing Google credentials app settings" → run scripts/set_appservice_secrets.ps1 (Part 3.2).

  • Tool returns "Google token refresh failed" → the refresh token is stale or from a different OAuth client. Delete token.json, re-run python main.py auth (uses the same Web client as credentials.json), then re-run the secrets script.

  • Agent run returns unauthorized / 401 from the app → the ?key= in MCP_SERVER_URL doesn't match MCP_SHARED_SECRET on the App Service. If Foundry strips the query string, move the secret into the URL path instead and add a matching route (advanced).

  • Nothing found for a file you know exists → try get_file_content with the exact name, or search_files with a distinctive keyword; Drive search is fuzzy and list_files shows the most recent items.

  • Package/import errors → this uses the new Foundry projects API (azure-ai-projects>=2.3.0, pulls in openai); not compatible with 1.x. Use a clean venv and pip install -r requirements.txt.

  • Hosted drivemcp.googleapis.com "caller does not have permission" → expected for personal accounts; that's exactly why this repo self-hosts. See Why a self-hosted MCP server?.


Security & limitations

  • Rotate any secret you have pasted anywhere (chat, screenshots). Regenerate the Google client secret in the Cloud Console if it was exposed, then re-run python main.py auth + scripts/set_appservice_secrets.ps1.

  • credentials.json, token.json, .env, webapp_deploy.zip are git-ignored — never commit them. The shared secret lives only in .env and App Service settings.

  • The refresh token grants read access to your Drive; treat App Service settings like passwords. Keep the web app HTTPS-only (set above).

  • Indirect prompt injection: documents can contain hidden instructions. Point the agent only at Drives you trust; set MCP_REQUIRE_APPROVAL=always while experimenting to review each tool call.

  • This is a demo/dev pattern. For production, prefer a managed identity / connection-based credential store and per-user consent rather than a single server-side refresh token.


References

License

MIT

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

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/jrubiosainz/foundry-gdrive-mcp-agent'

If you have feedback or need assistance with the MCP directory API, please join our Discord server