Skip to main content
Glama

MCP Server Box

MIT License
51
  • Apple
  • Linux
import base64 import os from typing import Any from box_ai_agents_toolkit import ( DocumentFiles, ImageFiles, box_file_download, box_file_text_extract, box_upload_file, ) from mcp.server.fastmcp import Context from box_tools_generic import get_box_client async def box_read_tool(ctx: Context, file_id: str) -> dict[str, Any]: """ Read the text content of a file in Box. Args: file_id (str): The ID of the file to read. return: str: The text content of the file. """ # check if file id isn't a string and convert to a string if not isinstance(file_id, str): file_id = str(file_id) box_client = get_box_client(ctx) response = box_file_text_extract(box_client, file_id) return response async def box_upload_file_from_path_tool( ctx: Context, file_path: str, folder_id: str = "0", new_file_name: str = "", ) -> str: """ Upload a file to Box from a filesystem path. Args: file_path (str): Path on the *server* filesystem to the file to upload. folder_id (str): The ID of the destination folder. Defaults to root ("0"). new_file_name (str): Optional new name to give the file in Box. If empty, uses the original filename. return: str: Information about the uploaded file (ID and name). """ box_client = get_box_client(ctx) try: # Normalize the path and check if file exists file_path_expanded = os.path.expanduser(file_path) if not os.path.isfile(file_path_expanded): return f"Error: file '{file_path}' not found." # Determine the file name to use actual_file_name = new_file_name.strip() or os.path.basename(file_path_expanded) # Determine file extension to detect binary types _, ext = os.path.splitext(actual_file_name) binary_exts = { ".docx", ".pptx", ".xlsx", ".pdf", ".jpg", ".jpeg", ".png", ".gif", } # Read file content as bytes for binary types, else as text if ext.lower() in binary_exts: # Binary file: read raw bytes with open(file_path_expanded, "rb") as f: content = f.read() else: # Text file: read as UTF-8 with open(file_path_expanded, "r", encoding="utf-8") as f: content = f.read() # Upload using toolkit (supports str or bytes) result = box_upload_file(box_client, content, actual_file_name, folder_id) return f"File uploaded successfully. File ID: {result['id']}, Name: {result['name']}" except Exception as e: return f"Error uploading file: {str(e)}" async def box_upload_file_from_content_tool( ctx: Context, content: str | bytes, # Accept both string and bytes file_name: str, folder_id: str = "0", is_base64: bool = False, # New parameter to indicate if content is base64 encoded ) -> str: """ Upload content as a file to Box using the toolkit. Args: content (str | bytes): The content to upload. Can be text or binary data. file_name (str): The name to give the file in Box. folder_id (str): The ID of the destination folder. Defaults to root ("0"). is_base64 (bool): Whether the content is base64 encoded. Defaults to False. """ box_client = get_box_client(ctx) try: # Handle base64 encoded content if is_base64 and isinstance(content, str): content = base64.b64decode(content) # Upload using toolkit result = box_upload_file(box_client, content, file_name, folder_id) return f"File uploaded successfully. File ID: {result['id']}, Name: {result['name']}" except Exception as e: return f"Error uploading file: {str(e)}" async def box_download_file_tool( ctx: Context, file_id: str, save_file: bool = False, save_path: str | None = None ) -> str: """ Download a file from Box and return its content as a string. Supports text files (returns content directly) and images (returns base64-encoded). Other file types will return an error message. Optionally saves the file locally. Args: file_id (str): The ID of the file to download. save_file (bool, optional): Whether to save the file locally. Defaults to False. save_path (str, optional): Path where to save the file. If not provided but save_file is True, uses a temporary directory. Defaults to None. return: str: For text files: content as string. For images: base64-encoded string with metadata. For unsupported files: error message. If save_file is True, includes the path where the file was saved. """ box_client = get_box_client(ctx) # Convert file_id to string if it's not already if not isinstance(file_id, str): file_id = str(file_id) try: # Use the box_api function for downloading saved_path, file_content, mime_type = box_file_download( client=box_client, file_id=file_id, save_file=save_file, save_path=save_path ) # Get file info to include name in response file_info = box_client.files.get_file_by_id(file_id) file_name = file_info.name file_extension = file_name.split(".")[-1].lower() if "." in file_name else "" # Prepare response based on content type response = "" if saved_path: response += f"File saved to: {saved_path}\n\n" # Check if file is a document (text-based file) is_document = ( mime_type and mime_type.startswith("text/") or file_extension in [e.value for e in DocumentFiles] ) # Check if file is an image is_image = ( mime_type and mime_type.startswith("image/") or file_extension in [e.value for e in ImageFiles] ) if is_document: # Text file - return content directly try: content_text = file_content.decode("utf-8") response += ( f"File downloaded successfully: {file_name}\n\n{content_text}" ) except UnicodeDecodeError: # Handle case where file can't be decoded as UTF-8 despite being a "document" response += f"File {file_name} is a document but couldn't be decoded as text. It may be in a binary format." elif is_image: # Image file - return base64 encoded base64_data = base64.b64encode(file_content).decode("utf-8") response += f"Image downloaded successfully: {file_name}\nMIME type: {mime_type}\nBase64 encoded data:\n{base64_data}" else: # Unsupported file type for content display (but still saved if requested) if not saved_path: response += f"File {file_name} has unsupported type ({mime_type or 'unknown'}). Only text and image files are supported for content display." else: response += f"File {file_name} has unsupported type ({mime_type or 'unknown'}) for content display, but was saved successfully." return response except Exception as e: return f"Error downloading file: {str(e)}"

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/box-community/mcp-server-box'

If you have feedback or need assistance with the MCP directory API, please join our Discord server