Skip to content

Commit 15606cd

Browse files
added mcp way to communicate
1 parent 68079ab commit 15606cd

1 file changed

Lines changed: 123 additions & 1 deletion

File tree

src/sap_cloud_sdk/outputmanagement/clients/email_client.py

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,4 +274,126 @@ def send_email(
274274
return output_requests_client.send_output_request(output_request)
275275

276276
except Exception as e:
277-
raise Exception(f"Failed to send email via destination '{destination_name}': {str(e)}") from e
277+
raise Exception(f"Failed to send email via destination '{destination_name}': {str(e)}") from e
278+
279+
async def send_email_with_mcp(
280+
self,
281+
tool_name: str,
282+
notification_template_key: str,
283+
to_emails: List[str],
284+
business_document: Dict[str, Any],
285+
cc_email: Optional[str] = None,
286+
attachment_url: Optional[str] = None,
287+
mcp_tool: Any = None,
288+
sender_provider_subaccount_id: Optional[str] = None
289+
) -> Dict[str, Any]:
290+
"""
291+
Create an output request and invoke MCP tool with traceparent and sender_provider_subaccount_id.
292+
293+
This method first generates an output request using the provided parameters, then invokes
294+
the specified MCP tool with the output request as the body, along with traceparent for
295+
distributed tracing and sender_provider_subaccount_id for multi-tenancy support.
296+
297+
Args:
298+
tool_name: Name of the MCP tool to invoke
299+
notification_template_key: Template key for the notification
300+
to_emails: List of recipient email addresses
301+
business_document: Business document data
302+
cc_email: Optional CC email address
303+
attachment_url: Optional attachment URL
304+
mcp_tool: The MCP tool instance to invoke
305+
sender_provider_subaccount_id: Optional sender provider subaccount ID (defaults to env var)
306+
307+
Returns:
308+
Result from the MCP tool invocation
309+
310+
Raises:
311+
Exception: If the MCP tool invocation fails
312+
313+
Example:
314+
```python
315+
import asyncio
316+
from sap_cloud_sdk.outputmanagement.clients.email_client import EmailClient
317+
318+
async def send_with_mcp():
319+
client = EmailClient()
320+
321+
result = await client.send_email_with_output_request_and_mcp_async(
322+
tool_name="send_output_request",
323+
notification_template_key="PO_APPROVAL_NOTIFICATION",
324+
to_emails=["finance@company.com"],
325+
business_document={
326+
"PurchaseOrder": {
327+
"orderId": "PO-12345",
328+
"vendor": "ACME Corp",
329+
"total": 1500.00
330+
}
331+
},
332+
mcp_tool=my_mcp_tool,
333+
sender_provider_subaccount_id="my-subaccount-id"
334+
)
335+
return result
336+
337+
result = asyncio.run(send_with_mcp())
338+
```
339+
"""
340+
import logging
341+
import os
342+
343+
logger = logging.getLogger(__name__)
344+
345+
try:
346+
logger.info("Creating output request for MCP tool '%s'", tool_name)
347+
348+
# Create the output request
349+
output_request = self.create_output_request(
350+
notification_template_key=notification_template_key,
351+
to=to_emails,
352+
business_document=business_document,
353+
cc=[cc_email] if cc_email else None,
354+
template_language="en",
355+
attachment_urls=[attachment_url] if attachment_url else None
356+
)
357+
358+
logger.info("Output request created successfully")
359+
360+
# Convert output request to dict for MCP payload
361+
payload = output_request.model_dump(by_alias=True, exclude_none=True)
362+
363+
# Get sender_provider_subaccount_id from parameter or environment variable
364+
subaccount_id = sender_provider_subaccount_id or os.getenv("APPFND_CONHOS_SUBACCOUNTID")
365+
366+
if not subaccount_id:
367+
logger.warning("sender_provider_subaccount_id not provided and APPFND_CONHOS_SUBACCOUNTID env var not set")
368+
369+
logger.info("Invoking MCP tool '%s' with body, traceparent, and sender_provider_subaccount_id", tool_name)
370+
371+
# Generate traceparent for distributed tracing
372+
import uuid
373+
trace_id = uuid.uuid4().hex # 32 hex chars
374+
parent_id = uuid.uuid4().hex[:16] # 16 hex chars
375+
traceparent = f"00-{trace_id}-{parent_id}-01"
376+
377+
# Prepare the invocation payload
378+
invocation_payload = {
379+
"body": payload,
380+
"traceparent": traceparent,
381+
"sender_provider_subaccount_id": subaccount_id
382+
}
383+
384+
# Log the payload before invoking
385+
logger.info("MCP tool '%s' invocation payload: %s", tool_name, invocation_payload)
386+
387+
# Validate that mcp_tool is provided
388+
if mcp_tool is None:
389+
raise ValueError("mcp_tool parameter is required")
390+
391+
# Use ainvoke for async invocation
392+
result = await mcp_tool.ainvoke(invocation_payload)
393+
logger.info("MCP tool '%s' executed successfully", tool_name)
394+
logger.info("Result from MCP tool '%s': %s", tool_name, result)
395+
return result
396+
397+
except Exception as e:
398+
logger.error("Failed to invoke MCP tool '%s': %s", tool_name, str(e))
399+
raise Exception(f"MCP tool invocation failed: {str(e)}") from e

0 commit comments

Comments
 (0)