1010import os
1111import uuid
1212from pathlib import Path
13- from typing import Optional , Dict
13+ from typing import NamedTuple , Optional , Dict
1414from datetime import datetime , timedelta
1515
1616logger = logging .getLogger (__name__ )
2121# Storage directory - configurable via WORKSPACE_ATTACHMENT_DIR env var
2222# Uses absolute path to avoid creating tmp/ in arbitrary working directories (see #327)
2323_default_dir = str (Path .home () / ".workspace-mcp" / "attachments" )
24- STORAGE_DIR = Path (os .getenv ("WORKSPACE_ATTACHMENT_DIR" , _default_dir ))
24+ STORAGE_DIR = Path (os .getenv ("WORKSPACE_ATTACHMENT_DIR" , _default_dir )). expanduser (). resolve ()
2525STORAGE_DIR .mkdir (parents = True , exist_ok = True )
2626
2727
28+ class SavedAttachment (NamedTuple ):
29+ """Result of saving an attachment: provides both the UUID and the absolute file path."""
30+
31+ file_id : str
32+ path : str
33+
34+
2835class AttachmentStorage :
2936 """Manages temporary storage of email attachments."""
3037
@@ -37,17 +44,17 @@ def save_attachment(
3744 base64_data : str ,
3845 filename : Optional [str ] = None ,
3946 mime_type : Optional [str ] = None ,
40- ) -> str :
47+ ) -> SavedAttachment :
4148 """
42- Save an attachment to local disk and return the absolute file path .
49+ Save an attachment to local disk.
4350
4451 Args:
4552 base64_data: Base64-encoded attachment data
4653 filename: Original filename (optional)
4754 mime_type: MIME type (optional)
4855
4956 Returns:
50- Absolute file path where the attachment was saved
57+ SavedAttachment with file_id (UUID) and path (absolute file path)
5158 """
5259 # Generate unique file ID for metadata tracking
5360 file_id = str (uuid .uuid4 ())
@@ -104,7 +111,7 @@ def save_attachment(
104111 "expires_at" : expires_at ,
105112 }
106113
107- return str (file_path )
114+ return SavedAttachment ( file_id = file_id , path = str (file_path ) )
108115
109116 def get_attachment_path (self , file_id : str ) -> Optional [Path ]:
110117 """
@@ -213,7 +220,6 @@ def get_attachment_url(file_id: str) -> str:
213220 Returns:
214221 Full URL to access the attachment
215222 """
216- import os
217223 from core .config import WORKSPACE_MCP_PORT , WORKSPACE_MCP_BASE_URI
218224
219225 # Use external URL if set (for reverse proxy scenarios)
0 commit comments