@@ -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