Gmail-SAP-MCP-Assistant
Provides tools for interacting with Gmail, including searching messages using native search syntax, reading full messages with body/headers/attachments, sending emails, creating drafts, moving messages to trash, marking read/unread, listing labels, and fetching attachment bytes.
Provides read-only tools for browsing SAP business data, including listing and searching Business Partners, viewing individual partners, and reading email addresses on file. Also supports querying Sales Orders, Billing Documents, and Product data via the SAP OData API.
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., "@Gmail-SAP-MCP-AssistantSearch my inbox for the latest purchase order confirmation from SAP and summarize it"
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.
Gmail + SAP MCP Assistant
A Streamlit application that lets you read and manage Gmail, browse SAP Business Partner / Sales / Billing / Product data, and ask an AI assistant natural-language questions about your inbox (and SAP records) — all through a single Model Context Protocol (MCP) server.
Streamlit UI (app.py)
│
┌───────────────┴───────────────┐
▼ ▼
Gmail / SAP / Admin tabs Ai tab
(direct button click) EmailAssistant (ai_agent.py)
│ → Mistral LLM decides which
│ tool(s) to call, if any
│ │
└───────────────┬────────────────┘
▼
MCPClient (mcp_client.py) — one persistent
background event loop for every call, either path
│
│ Streamable HTTP transport
▼
FastMCP server (server.py) — dispatches
the tool call by name
│
┌────────────────┴────────────────┐
▼ ▼
GmailService SAPService
(gmail_service.py) (sap_service.py)
│ │
▼ ▼
Gmail API SAP OData API
(OAuth credentials) (API key, sandbox)The UI never talks to Gmail or SAP directly — every action, whether it's a
button click or something the AI assistant decided to do, goes through the
same MCPClient → FastMCP server → service layer path. This keeps a single,
auditable boundary between the app and the two external systems.
Request flow
There are two ways a request enters the system, and they converge at
MCPClient.
1. Direct UI action (Gmail / SAP / Admin tabs)
You click a button (e.g. "Search" in the Gmail tab).
app.pycalls a method directly on the sharedMCPClientinstance, e.g.mcp_client.gmail_search_messages(query, max_results).MCPClientschedules that coroutine on its dedicated background event loop and blocks until it completes (_loop.run(...)inmcp_client.py) — this is what keeps the MCP session safe across Streamlit's rerun-per-interaction model.The FastMCP server (
server.py) receives the tool call over Streamable HTTP and dispatches it to the matching function, e.g.gmail_search_messages().That function calls into
GmailService(gmail_service.py) orSAPService(sap_service.py), which makes the real network call — the Gmail API (OAuth) or the SAP OData API (API key) — and returns parsed, plain-dict results.The result travels back up: MCP server →
MCPClient._unwrap()→app.py, which stores it inst.session_stateand renders it.
Errors at any layer (MCPToolError, MCPConnectionError, or anything
unexpected) are caught centrally by run_action() in app.py and shown
as an st.error, so a failed call never crashes the UI.
2. AI Assistant question (Ai tab)
This is the same pipeline with a decision loop in front of it:
Your question (plus chat history) goes to
EmailAssistant.ask()inai_agent.py, which builds a system prompt viaprompts.py(injected with today's/tomorrow's dates) and sends it to Mistral along with theTOOLSschema.Mistral decides whether it needs a tool. If so,
ai_agent.pyruns the call through the sameMCPClientinstance used by the manual tabs —EmailAssistantnever talks to Gmail/SAP itself — and feeds the JSON result back into the conversation.Steps 1–2 repeat (search, then maybe read a specific message, then maybe another search) up to
MISTRAL_MAX_STEPStimes (default 12).Once Mistral has enough information, it stops calling tools and returns a final natural-language answer, which
app.pyrenders in the chat — with the full tool-call trace available in a collapsible "Tool calls used" expander for debugging.
The agent's tool list is deliberately narrow (read-only Gmail/SAP lookups), so no matter what you ask it, it cannot send, delete, or modify anything. Only the manual flows in the Gmail tab can do that, and each of those requires an explicit confirmation step before the destructive action fires.
3. App startup (once per process)
get_mcp_client() in app.py is wrapped in @st.cache_resource, so it
runs exactly once: it creates the MCPClient, calls .connect(), which
starts the background thread + event loop and opens the Streamable HTTP
session to the FastMCP server. That session stays alive for the life of
the Streamlit process — it is not recreated on every rerun.
Features
Gmail (via the "Gmail" tab)
List / search messages using Gmail's native search syntax
Read a full message (body, headers, attachments)
Send email, create drafts, move messages to Trash (each gated behind an explicit confirmation step in the UI)
Mark messages read/unread, list labels, fetch attachment bytes
SAP (via the "SAP" tab)
Check configuration / connectivity to the SAP OData sandbox
List and search Business Partners, view a single partner
List email addresses on file
(Read-only by default — see SAP writes below)
AI Assistant (via the "Ai" tab)
A Mistral-powered agent (ai_agent.py / EmailAssistant) that answers
natural-language questions such as:
"Summarize today's important emails"
"Find emails containing attachments"
"Do I have any interviews scheduled tomorrow?"
"Summarize emails from the last 7 days"
The agent is intentionally read-only: it can only call
gmail_search_messages, gmail_read_message, and gmail_list_messages
(plus the read-only SAP lookups described in prompts.py). It has no
tool for sending, replying to, or deleting anything, and the system
prompt explicitly instructs it to say so if asked — every fact in its
answers must trace back to an actual tool result, never an invented one.
Administration tab
Live MCP connection status, the list of tools the server currently exposes, and the last-fetched Gmail/SAP configuration — useful for verifying the server is reachable and correctly configured.
Project layout
File | Responsibility |
| Streamlit UI — tabs for AI, Gmail, SAP, and Admin |
| Streamlit-safe MCP client (single persistent background event loop; see the module docstring for why) |
| Agent loop: sends the user's question + tool results to Mistral until it produces a final answer |
| System prompt: tool permissions, date context, Gmail search syntax reference, answer-style guidance |
| FastMCP server exposing Gmail and SAP operations as MCP tools |
| Gmail API wrapper: OAuth flow, message parsing, send/draft/delete/label operations |
| SAP OData wrapper: Business Partner, Sales Order, Billing Document, Product reads (writes implemented but disabled by default) |
| Python dependencies |
Prerequisites
Python 3.10+
A Google Cloud project with the Gmail API enabled and an OAuth Desktop app client (
credentials.json)Access to an SAP OData sandbox (e.g. the SAP Business Accelerator Hub) with an API key, if you want the SAP tab/tools to work
A Mistral API key, if you want the AI Assistant tab to work
Setup
Install dependencies
python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -r requirements.txtGmail OAuth credentials
Download your OAuth client's
credentials.jsonfrom Google Cloud Console and place it atcredentials/credentials.json(or pointGMAIL_CREDENTIALS_FILEat a different path). The first time the server calls a Gmail tool, it opens a browser window for you to authorize; the resulting token is written tocredentials/token.json.Environment variables
Create a
.envfile in the project root:# --- MCP server --- MCP_SERVER_HOST=127.0.0.1 MCP_SERVER_PORT=8000 LOG_LEVEL=INFO # --- MCP client (Streamlit side) --- MCP_SERVER_URL=http://127.0.0.1:8000/mcp MCP_CONNECT_TIMEOUT_SECONDS=20 MCP_CALL_TIMEOUT_SECONDS=60 # --- Gmail --- GMAIL_CREDENTIALS_FILE=credentials/credentials.json GMAIL_TOKEN_FILE=credentials/token.json # --- SAP --- SAP_MODE=sandbox SAP_BASE_URL=https://sandbox.api.sap.com/s4hanacloud/sap/opu/odata/sap/API_BUSINESS_PARTNER SAP_API_KEY=your-sap-api-key SAP_VERIFY_SSL=true SAP_WRITE_ENABLED=false SAP_TIMEOUT_SECONDS=30 # --- AI Assistant --- MISTRAL_API_KEY=your-mistral-api-key MISTRAL_MODEL=mistral-large-latest MISTRAL_MAX_STEPS=12Every variable has a sane default except the credentials/API keys themselves — see the top of each
*_service.py/*_client.pyfile for the exact fallback values.Run the MCP server
python server.pyThis starts the FastMCP server on
MCP_SERVER_HOST:MCP_SERVER_PORTusing the Streamable HTTP transport.Run the Streamlit app (in a second terminal)
streamlit run app.pyOpen the URL Streamlit prints (typically
http://localhost:8501).
SAP writes
SAPService already implements create_business_partner and
update_business_partner against SAP's OData write endpoints, but the
corresponding MCP tools are commented out in server.py and the calls
are hard-gated behind SAP_WRITE_ENABLED=true in sap_service.py. To
enable them:
Set
SAP_WRITE_ENABLED=truein.env.Uncomment the
sap_create_business_partner/sap_update_business_partnertool definitions inserver.py.Restart the MCP server.
Until then, all SAP access is read-only regardless of the flag.
Safety notes
The AI Assistant can only read Gmail — it has no send/delete/modify tool, enforced both in
ai_agent.py'sTOOLSlist and in the system prompt inprompts.py.Sending email, creating drafts, and deleting/trashing messages in the Gmail tab each require an explicit confirmation checkbox or a "search → open → confirm" flow before the destructive action fires.
SAP writes are off by default (
SAP_WRITE_ENABLED=false) and the tools that would perform them aren't even registered on the MCP server unless you opt in.
Troubleshooting
"Could not connect to the MCP server" — make sure
server.pyis running andMCP_SERVER_URLin your.envmatches its host/port.Gmail OAuth errors mentioning a stale/invalid token — delete the file at
GMAIL_TOKEN_FILEand retry; the app will re-run the OAuth flow.SAP requests failing with HTTP errors — some SAP sandbox tenants don't have every OData service (e.g.
API_SALES_ORDER_SRV,API_BILLING_DOCUMENT_SRV) activated by default; check the error body against your API catalog."AI assistant is not available" —
MISTRAL_API_KEYis missing or empty in.env.
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
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
MCP server exposing the Backtest360 engine API as tools for AI agents.
MCP server for Gainium — manage trading bots, deals, and balances via AI assistants
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/suryanandan1/Gmail-SAP-Connection-With-MCP-Agent'
If you have feedback or need assistance with the MCP directory API, please join our Discord server