import gradio as gr from huggingface_hub import list_spaces, whoami, HfFolder from huggingface_hub.hf_api import HfHubHTTPError def list_my_hf_spaces(hf_username_or_org: str): """ Lists all Hugging Face Spaces for a given username or organization. Args: hf_username_or_org (str): The Hugging Face username or organization name. Returns: list: A list of dictionaries, where each dictionary contains details of a space. Suitable for use with gradio.DataFrame. Returns a list with an error message if an issue occurs. """ try: print(f"Fetching Hugging Face Spaces for user/org: {hf_username_or_org}") # Server-side log if not hf_username_or_org or not hf_username_or_org.strip(): # Return list of lists format for error return [["Error", "Username/Organization cannot be empty.", "-", "-", "-", "-"]] spaces_objects = list_spaces(author=hf_username_or_org.strip()) if not spaces_objects: # Return list of lists format for no spaces found return [[f"No spaces found for '{hf_username_or_org}'", "Check username/org or authentication.", "-", "-", "-", "-"]] spaces_data_list_of_lists = [] for space in spaces_objects: row = [ f"[{space.id}](https://huggingface.co/spaces/{space.id})", getattr(space, 'author', 'N/A'), str(getattr(space, 'lastModified', 'N/A')), str(getattr(space, 'private', 'N/A')), str(getattr(space, 'gated', 'N/A')), getattr(space, 'sdk', 'N/A') ] spaces_data_list_of_lists.append(row) return spaces_data_list_of_lists except Exception as e: error_message = f"An error occurred: {str(e)}. Ensure correct username/org and HF authentication (huggingface-cli login or HF_TOKEN)." print(error_message) # Server-side log # Return list of lists format for exception return [["Error", error_message, "-", "-", "-", "-"]] def list_my_hf_organizations(token: str = None): """ Lists organizations the Hugging Face user (identified by the token) is a member of. Args: token (str, optional): Hugging Face API token. If None or empty, attempts to load token via HfFolder.get_token(). Returns: list: A list of lists, where each inner list contains an organization name (as a Markdown link). Suitable for use with gradio.DataFrame. """ try: if not token: # If token param is None or empty token = HfFolder.get_token() if not token: return [["Error: Not logged in", "Please log in using 'huggingface-cli login'."]] print("Fetching organizations for the authenticated user...") # Server-side log user_info = whoami(token=token) if not user_info or 'orgs' not in user_info: return [["Info", "No organization information found or user data incomplete."]] org_list_from_api = user_info.get('orgs', []) if not org_list_from_api: return [["Info", "Authenticated user is not a member of any organizations."]] orgs_data = [] for org_dict in org_list_from_api: org_name = org_dict.get('name') if org_name: org_link = f"[{org_name}](https://huggingface.co/{org_name})" orgs_data.append([org_link]) # Store as a list containing the Markdown link if not orgs_data: return [["Info", "Found organization entries but no names extracted."]] return orgs_data except HfHubHTTPError as e: if e.response.status_code == 401: error_msg = "Authentication error. Please ensure you are logged in ('huggingface-cli login')." else: error_msg = f"API Error: {str(e)}" print(error_msg) # Server-side log return [["Error", error_msg]] except Exception as e: error_message = f"An unexpected error occurred: {str(e)}" print(error_message) # Server-side log return [["Error", error_message]] def list_organization_spaces(org_name: str): """ Lists all public Hugging Face Spaces for a given organization. Args: org_name (str): The name of the Hugging Face organization. Returns: list: A list of lists, where each inner list contains Space details. Suitable for use with gradio.DataFrame. The Space ID is formatted as a Markdown link. """ try: if not org_name or not org_name.strip(): return [["Error", "Organization name cannot be empty.", "-", "-", "-", "-"]] print(f"Fetching Hugging Face Spaces for organization: {org_name.strip()}") # Server-side log spaces_objects = list_spaces(author=org_name.strip()) # Use author field for organization if not spaces_objects: return [[f"No Spaces found for organization '{org_name.strip()}'", "Organization may not exist or have no public spaces.", "-", "-", "-", "-"]] spaces_data_list_of_lists = [] for space in spaces_objects: row = [ f"[{space.id}](https://huggingface.co/spaces/{space.id})", getattr(space, 'author', 'N/A'), str(getattr(space, 'lastModified', 'N/A')), str(getattr(space, 'private', 'N/A')), str(getattr(space, 'gated', 'N/A')), getattr(space, 'sdk', 'N/A') ] spaces_data_list_of_lists.append(row) return spaces_data_list_of_lists except HfHubHTTPError as e: error_msg = f"API Error for organization '{org_name.strip()}': {str(e)}" print(error_msg) # Server-side log return [["Error", error_msg, "-", "-", "-", "-"]] except Exception as e: error_message = f"An unexpected error occurred for organization '{org_name.strip()}': {str(e)}" print(error_message) # Server-side log return [["Error", error_message, "-", "-", "-", "-"]] # Gradio interface for listing Hugging Face Spaces hf_spaces_interface = gr.Interface( fn=list_my_hf_spaces, inputs=[gr.Textbox(label="Hugging Face Username or Organization", placeholder="e.g., huggingface, stabilityai, or your_username")], outputs=[gr.DataFrame( headers=["ID", "Author", "Last Modified", "Private", "Gated", "SDK"], label="Hugging Face Spaces", wrap=True, # Allow text wrapping in cells datatype=["markdown", "str", "str", "str", "str", "str"] # Render first column as Markdown )], title="Hugging Face api as mcp", description="Enter a Hugging Face username or organization to list their public Spaces.", examples=[["huggingface"], ["stabilityai"], ["gradio"]], allow_flagging='never' ) hf_orgs_interface = gr.Interface( fn=list_my_hf_organizations, inputs=[gr.Textbox(label="Hugging Face Token (Optional)", placeholder="hf_xxx... or leave blank to use logged-in user", type="password")], outputs=[gr.DataFrame( headers=["My Organization Name"], label="My Hugging Face Organizations", wrap=True, datatype=["markdown"] # Render column as Markdown )], title="My Hugging Face Organizations Lister", description="Lists the Hugging Face organizations you are a member of. Requires you to be logged in via 'huggingface-cli login'. Get your token from [here](https://huggingface.co/settings/tokens). Click 'Submit' to refresh.", allow_flagging='never' ) hf_org_spaces_interface = gr.Interface( fn=list_organization_spaces, inputs=[gr.Textbox(label="Organization Name", placeholder="e.g., huggingface, stabilityai")], outputs=[gr.DataFrame( headers=["ID", "Author", "Last Modified", "Private", "Gated", "SDK"], label="Organization's Hugging Face Spaces", wrap=True, datatype=["markdown", "str", "str", "str", "str", "str"] )], title="List Organization's Spaces", description="Enter a public Hugging Face organization name to list their Spaces.", examples=[["huggingface"], ["stabilityai"], ["google"]], allow_flagging='never' ) if __name__ == "__main__": tabbed_demo = gr.TabbedInterface( [hf_spaces_interface, hf_orgs_interface, hf_org_spaces_interface], ["List Spaces by User/Org", "List My Organizations", "List Org Spaces"] ) tabbed_demo.launch(mcp_server=True, share=True)