""" ======================================================================= Název: mcp_vbcz_email_v1.6.py Verze: 1.6 Datum: 2026-06-09 Popis: MCP server pro schránku vladimir.buzalka@buzalka.cz přes Microsoft Graph API (application permissions). Credentials sdílí s EmailMessagingGraph.py (Knihovny/). Tooly: - list_emails — seznam posledních emailů (+ preview) - get_email — plné tělo + metadata emailu - list_attachments — přílohy emailu (název, velikost, typ) - get_attachment — stáhne přílohu na disk, vrátí cestu - create_draft_eml — vygeneruje .eml draft (X-Unsent) k ruční kontrole a odeslání v Outlooku (+ přílohy) - create_event — vytvoří událost v kalendáři (+ připomínka) - create_contact — vytvoří kontakt ve schránce Změny v1.1: + create_draft_eml (generování rozepsaných emailů) Změny v1.2: + create_draft_eml: parametr `attachments` Změny v1.3: * OPRAVA kódování: base64 (cte) + policy.SMTP (CRLF) Změny v1.4: + create_draft_eml: `original_message_id` (forward styl) Změny v1.5: + create_draft_eml: `strip_self_forward` (default True) Změny v1.6: + create_event — zapíše událost do kalendáře schránky (start/end v lokálním čase, časové pásmo, připomínka N minut předem). Vrací id + webLink. Vyžaduje Graph oprávnění Calendars.ReadWrite (application). + create_contact — založí kontakt ve schránce (jméno, e-mail, telefony, firma, funkce, poznámka). Vrací id. Vyžaduje Contacts.ReadWrite (application). + helper _graph_post (POST na Graph). POZN.: e-maily lékařům/CTA se i nadále generují jako .eml drafty (odesílají se přes JNJ server), NE přes tuto schránku. Kalendář a kontakty se píšou do osobní schránky vladimir.buzalka@buzalka.cz. Spuštění: python mcp_vbcz_email_v1.6.py ======================================================================= """ import base64 import mimetypes import sys from datetime import datetime from email.message import EmailMessage from email.policy import SMTP as SMTP_POLICY from functools import lru_cache from pathlib import Path from typing import Optional, Union import msal import requests from mcp.server.fastmcp import FastMCP # ── Konfigurace ──────────────────────────────────────────────────────── TENANT_ID = "7d269944-37a4-43a1-8140-c7517dc426e9" CLIENT_ID = "4b222bfd-78c9-4239-a53f-43006b3ed07f" CLIENT_SECRET = "Txg8Q~MjhocuopxsJyJBhPmDfMxZ2r5WpTFj1dfk" MAILBOX = "vladimir.buzalka@buzalka.cz" AUTHORITY = f"https://login.microsoftonline.com/{TENANT_ID}" SCOPE = ["https://graph.microsoft.com/.default"] GRAPH_BASE = f"https://graph.microsoft.com/v1.0/users/{MAILBOX}" # Výchozí časové pásmo pro události kalendáře (Windows TZ název pro Graph) DEFAULT_TIMEZONE = "Central European Standard Time" DOWNLOADS_DIR = Path(__file__).resolve().parent / "downloads" DOWNLOADS_DIR.mkdir(exist_ok=True) # Výchozí cíl pro generované draft .eml soubory DEFAULT_DRAFT_DIR = Path(r"u:\Dropbox\!!!Days\Downloads Z230") # Výchozí odesílatel + standardní podpis (ICON / Janssen) DEFAULT_FROM = "vbuzalka@its.jnj.com" SIGNATURE_HTML = """
S pozdravem
MUDr. Vladimír BUZALKA
ICON plc
Performing Local Trial Management Services for Janssen – Cilag s.r.o.
Global Clinical Operations
Mobile: +420 775 735 276
Fax: +420 227 012 284
E-mail: vbuzalka@its.jnj.com,
vladimir.buzalka@iconplc.com
From: {_esc(from_name)} '
f'<{_esc(from_addr)}>
'
f'Sent: {_esc(sent)}
'
f'To: {_esc(to_list)}
'
)
if cc_list:
hdr += f'Cc: {_esc(cc_list)}
'
hdr += f'Subject: {_esc(subj)}
" \
+ _esc(orig_content) + ""
return hdr + orig_html
else:
lines = [
"",
"________________________________",
f"From: {from_name} <{from_addr}>",
f"Sent: {sent}",
f"To: {to_list}",
]
if cc_list:
lines.append(f"Cc: {cc_list}")
lines.append(f"Subject: {subj}")
lines.append("")
# pokud je originál HTML, dej aspoň hrubý text (bez tagů)
if orig_type == "html":
import re
txt = re.sub(r"<[^>]+>", "", orig_content)
else:
txt = orig_content
lines.append(txt)
return "\n".join(lines)
@mcp.tool()
def create_draft_eml(
to: str,
subject: str,
body: str,
cc: Optional[str] = None,
attachments: Optional[str] = None,
original_message_id: Optional[str] = None,
strip_self_forward: bool = True,
from_addr: str = DEFAULT_FROM,
body_format: str = "html",
add_signature: bool = True,
filename: Optional[str] = None,
output_dir: Optional[str] = None,
) -> dict:
"""Vygeneruje .eml draft (X-Unsent: 1) připravený k ruční kontrole a
odeslání v Outlooku. Po dvojkliku Outlook otevře rozepsaný email
s předvyplněnými To/CC/Subject/tělem/přílohami — uživatel zkontroluje
a pošle.
- to: příjemce (jeden) nebo více oddělených čárkou
- subject: předmět — libovolný text (diakritika OK), klidně
s prefixem typu "[Připomínka] RE: …"
- body: tělo emailu — JEN vnitřní obsah; u HTML stačí …
, plain text se zalomí dle řádků - cc: kopie, oddělené čárkou (volitelné) - attachments: cesta k souboru nebo více cest oddělených ';' (např. "C:\\a.pdf;C:\\b.docx"). MIME typ se detekuje sám. - original_message_id: message_id původního emailu (z list_emails). Když je zadán, původní email se vloží POD nový text ve forward stylu (oddělovač + From/Sent/To/Subject + tělo) — tj. připomínka nahoře, zachovaný originál pod ní. - strip_self_forward: (default True) když je `original_message_id` email přeposlaný k sobě (FW:), odřízne horní self-forward obal (prázdný forward + duplicitní podpis + FW hlavičku k sobě) a vloží JEN vnitřní skutečně odeslaný originál. Když vnitřní forward nenajde, ocituje celý email (v1.4). - from_addr: odesílatel (default vbuzalka@its.jnj.com) - body_format: 'html' (default) nebo 'text' - add_signature:připojí standardní ICON/Janssen podpis (default True) - filename: vlastní název .eml (default draft_