Gmail-SAP-MCP-Assistant
Gmail + SAP MCP 어시스턴트
Gmail을 읽고 관리하고, SAP 비즈니스 파트너/영업/빌링/제품 데이터를 탐색하며, 받은 편지함(및 SAP 레코드)에 대해 자연어로 질문할 수 있는 AI 어시스턴트를 제공하는 Streamlit 애플리케이션입니다. 이 모든 것은 단일 Model Context Protocol(MCP) 서버를 통해 이루어집니다.
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)UI는 Gmail이나 SAP에 직접 연결되지 않습니다. 버튼 클릭이든 AI 어시스턴트가 결정한 작업이든 모든 작업은 동일한 MCPClient → FastMCP 서버 → 서비스 계층 경로를 거칩니다. 이를 통해 앱과 두 외부 시스템 사이에 단일하고 감사 가능한 경계가 유지됩니다.
요청 흐름
요청이 시스템에 유입되는 방법은 두 가지가 있으며, 이는 MCPClient에서 수렴됩니다.
1. 직접 UI 작업 (Gmail / SAP / 관리 탭)
버튼(예: Gmail 탭의 "검색")을 클릭합니다.
app.py는 공유MCPClient인스턴스의 메서드(예:mcp_client.gmail_search_messages(query, max_results))를 직접 호출합니다.MCPClient는 해당 코루틴을 전용 백그라운드 이벤트 루프에 예약하고 완료될 때까지 차단합니다(mcp_client.py의_loop.run(...)). 이는 Streamlit의 상호 작용당 재실행 모델에서 MCP 세션을 안전하게 유지하는 방법입니다.FastMCP 서버(
server.py)는 Streamable HTTP를 통해 도구 호출을 수신하고gmail_search_messages()와 같은 일치하는 함수로 디스패치합니다.해당 함수는
GmailService(gmail_service.py) 또는SAPService(sap_service.py)를 호출하여 실제 네트워크 호출(Gmail API(OAuth) 또는 SAP OData API(API 키))을 수행하고 구문 분석된 일반 사전 결과를 반환합니다.결과는 MCP 서버 →
MCPClient._unwrap()→app.py순서로 다시 전달되며,app.py는 이를st.session_state에 저장하고 렌더링합니다.
모든 계층의 오류(MCPToolError, MCPConnectionError 또는 예기치 않은 모든 것)는 app.py의 run_action()에서 중앙 집중식으로 포착되어 st.error로 표시되므로 실패한 호출로 인해 UI가 중단되지 않습니다.
2. AI 어시스턴트 질문 (Ai 탭)
이것은 앞에 결정 루프가 있는 동일한 파이프라인입니다.
질문(및 채팅 기록)은
ai_agent.py의EmailAssistant.ask()로 전송됩니다.prompts.py를 통해 시스템 프롬프트(오늘/내일 날짜가 주입됨)를 만들고TOOLS스키마와 함께 Mistral로 보냅니다.Mistral은 도구가 필요한지 결정합니다. 필요한 경우
ai_agent.py는 수동 탭에서 사용하는 동일한MCPClient인스턴스를 통해 호출을 실행하고(EmailAssistant는 자체적으로 Gmail/SAP에 직접 연결하지 않음) JSON 결과를 대화에 다시 공급합니다.1~2단계는
MISTRAL_MAX_STEPS(기본값 12)까지 반복됩니다(검색 후 특정 메시지 읽기, 그 다음 다른 검색 등).Mistral이 충분한 정보를 얻으면 도구 호출을 중지하고 최종 자연어 답변을 반환하며,
app.py는 이를 채팅에 렌더링합니다. 전체 도구 호출 추적은 디버깅을 위해 접을 수 있는 "사용된 도구 호출" 확장 영역에서 볼 수 있습니다.
에이전트의 도구 목록은 의도적으로 제한되어 있으므로(읽기 전용 Gmail/SAP 조회) 무엇을 요청하든 보내기, 삭제 또는 수정할 수 없습니다. Gmail 탭의 수동 흐름만이 이를 수행할 수 있으며, 각각은 파괴적인 작업이 실행되기 전에 명시적인 확인 단계를 거쳐야 합니다.
3. 앱 시작 (프로세스당 한 번)
app.py의 get_mcp_client()는 @st.cache_resource로 래핑되어 정확히 한 번만 실행됩니다. MCPClient를 만들고 .connect()를 호출하여 백그라운드 스레드와 이벤트 루프를 시작하고 FastMCP 서버에 대한 Streamable HTTP 세션을 엽니다. 이 세션은 Streamlit 프로세스가 살아있는 동안 유지되며 재실행할 때마다 다시 생성되지 않습니다.
기능
Gmail ("Gmail" 탭)
Gmail 고유 검색 구문을 사용한 메시지 목록/검색
전체 메시지 읽기(본문, 헤더, 첨부 파일)
이메일 보내기, 임시 보관함 만들기, 메시지 휴지통으로 이동(각각 UI에서 명시적인 확인 단계를 거쳐야 함)
읽음/읽지 않음 표시, 라벨 나열, 첨부 파일 바이트 가져오기
SAP ("SAP" 탭)
SAP OData 샌드박스 구성/연결 확인
비즈니스 파트너 목록 및 검색, 단일 파트너 보기
등록된 이메일 주소 나열
(기본적으로 읽기 전용 — 아래 SAP 쓰기 참조)
AI 어시스턴트 ("Ai" 탭)
다음과 같은 자연어 질문에 답하는 Mistral 기반 에이전트(ai_agent.py / EmailAssistant):
"오늘 중요한 이메일 요약해 줘"
"첨부 파일이 있는 이메일 찾아줘"
"내일 면접 일정 있어?"
"지난 7일 동안의 이메일 요약해 줘"
에이전트는 의도적으로 읽기 전용입니다. gmail_search_messages, gmail_read_message, gmail_list_messages(및 prompts.py에 설명된 읽기 전용 SAP 조회)만 호출할 수 있습니다. 보내기, 답장, 삭제를 위한 도구는 없으며 시스템 프롬프트는 요청 시 이를 명시적으로 말하도록 지시합니다. 답변의 모든 사실은 실제 도구 결과에 근거해야 하며 절대 허구가 될 수 없습니다.
관리 탭
실시간 MCP 연결 상태, 서버가 현재 노출하는 도구 목록, 마지막으로 가져온 Gmail/SAP 구성을 보여줍니다. 서버 연결 가능 여부와 올바른 구성 여부를 확인하는 데 유용합니다.
프로젝트 구조
파일 | 설명 |
| Streamlit UI — AI, Gmail, SAP, 관리 탭 |
| Streamlit 안전 MCP 클라이언트(단일 영구 백그라운드 이벤트 루프, 이유는 모듈 docstring 참조) |
| 에이전트 루프: 최종 답변이 나올 때까지 사용자 질문 + 도구 결과를 Mistral로 전송 |
| 시스템 프롬프트: 도구 권한, 날짜 컨텍스트, Gmail 검색 구문 참조, 답변 스타일 지침 |
| Gmail 및 SAP 작업을 MCP 도구로 노출하는 FastMCP 서버 |
| Gmail API 래퍼: OAuth 흐름, 메시지 구문 분석, 보내기/임시 보관/삭제/라벨 작업 |
| SAP OData 래퍼: 비즈니스 파트너, 판매 주문, 빌링 문서, 제품 읽기(쓰기는 구현되어 있지만 기본적으로 비활성화됨) |
| Python 종속성 |
사전 요구 사항
Python 3.10 이상
Gmail API가 활성화되고 OAuth 데스크톱 앱 클라이언트(
credentials.json)가 있는 Google Cloud 프로젝트SAP 탭/도구를 사용하려면 API 키가 있는 SAP OData 샌드박스(예: SAP Business Accelerator Hub)에 대한 액세스 권한
AI 어시스턴트 탭을 사용하려면 Mistral API 키
설정
종속성 설치
python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -r requirements.txtGmail OAuth 자격 증명
Google Cloud 콘솔에서 OAuth 클라이언트의
credentials.json을 다운로드하여credentials/credentials.json에 배치합니다(또는GMAIL_CREDENTIALS_FILE을 다른 경로로 지정). 서버가 Gmail 도구를 처음 호출하면 브라우저 창이 열려 권한을 부여하라는 메시지가 표시되고, 생성된 토큰은credentials/token.json에 기록됩니다.환경 변수
프로젝트 루트에
.env파일을 만듭니다.# --- 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=12자격 증명/API 키 자체를 제외한 모든 변수에는 합리적인 기본값이 있습니다. 정확한 대체 값은 각
*_service.py/*_client.py파일의 상단을 참조하세요.MCP 서버 실행
python server.py이렇게 하면 Streamable HTTP 전송을 사용하여
MCP_SERVER_HOST:MCP_SERVER_PORT에서 FastMCP 서버가 시작됩니다.Streamlit 앱 실행 (두 번째 터미널에서)
streamlit run app.pyStreamlit이 출력하는 URL(일반적으로
http://localhost:8501)을 엽니다.
SAP 쓰기
SAPService는 이미 SAP OData 쓰기 엔드포인트에 대한 create_business_partner 및 update_business_partner를 구현하지만 해당 MCP 도구는 server.py에서 주석 처리되어 있으며 sap_service.py에서 SAP_WRITE_ENABLED=true로 하드 게이트됩니다. 이를 활성화하려면:
.env에서SAP_WRITE_ENABLED=true를 설정합니다.server.py에서sap_create_business_partner/sap_update_business_partner도구 정의의 주석을 해제합니다.MCP 서버를 다시 시작합니다.
그 전까지는 플래그와 관계없이 모든 SAP 액세스는 읽기 전용입니다.
안전 참고 사항
AI 어시스턴트는 Gmail을 읽기만 할 수 있습니다. 보내기/삭제/수정 도구가 없으며, 이는
ai_agent.py의TOOLS목록과prompts.py의 시스템 프롬프트 모두에 적용됩니다.Gmail 탭에서 이메일 보내기, 임시 보관함 만들기, 메시지 삭제/휴지통 이동은 파괴적인 작업이 실행되기 전에 명시적인 확인 확인란 또는 "검색 → 열기 → 확인" 흐름을 거쳐야 합니다.
SAP 쓰기는 기본적으로 비활성화되어 있으며(
SAP_WRITE_ENABLED=false) 이를 수행할 도구는 옵트인하지 않는 한 MCP 서버에 등록조차 되지 않습니다.
문제 해결
"MCP 서버에 연결할 수 없습니다" —
server.py가 실행 중이고.env의MCP_SERVER_URL이 호스트/포트와 일치하는지 확인하세요.오래되었거나 잘못된 토큰을 언급하는 Gmail OAuth 오류 —
GMAIL_TOKEN_FILE의 파일을 삭제하고 다시 시도하세요. 앱이 OAuth 흐름을 다시 실행합니다.HTTP 오류로 인한 SAP 요청 실패 — 일부 SAP 샌드박스 테넌트는 모든 OData 서비스(예:
API_SALES_ORDER_SRV,API_BILLING_DOCUMENT_SRV)가 기본적으로 활성화되어 있지 않습니다. API 카탈로그에서 오류 본문을 확인하세요."AI 어시스턴트를 사용할 수 없습니다" —
.env에MISTRAL_API_KEY가 없거나 비어 있습니다.
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