Google Drive MCP Server

Google Drive MCP Server

Self-hosted MCP server enabling Foundry agents to search, list, and read Google Drive files via the Drive API with server-side OAuth authentication.

Category
Visit Server

README

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.


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.)

1.2 OAuth consent screen

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

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured