uratmangun commited on
Commit
d33a9bf
·
unverified ·
1 Parent(s): a0b7dc7

✨ feat: initial commit for MCP-Server-Demo

Browse files
Files changed (2) hide show
  1. README.md +28 -4
  2. app.py +189 -17
README.md CHANGED
@@ -1,16 +1,40 @@
1
  ---
2
- title: mcp-test
3
  emoji: 💻
4
  colorFrom: indigo
5
  colorTo: blue
6
  sdk: gradio
7
  sdk_version: 5.33.0
8
  app_file: app.py
9
- pinned: false
10
  license: apache-2.0
11
- short_description: Gradio app for mcp-test
12
  tags:
13
  - mcp-server-track
14
  ---
15
 
16
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: huggingface-mcp
3
  emoji: 💻
4
  colorFrom: indigo
5
  colorTo: blue
6
  sdk: gradio
7
  sdk_version: 5.33.0
8
  app_file: app.py
9
+ pinned: true
10
  license: apache-2.0
11
+ short_description: some huggingface api as a mcp
12
  tags:
13
  - mcp-server-track
14
  ---
15
 
16
+ ## Available MCP Functions
17
+
18
+ This Gradio application exposes the following functions as an MCP server:
19
+
20
+ 1. **`list_my_hf_spaces`**
21
+ * **Description:** Lists all public Hugging Face Spaces for a given username or organization.
22
+ * **Parameters:**
23
+ * `hf_username_or_org` (string): The Hugging Face username or organization name.
24
+ * **Interface Tab:** "List Spaces by User/Org"
25
+
26
+ 2. **`list_my_hf_organizations`**
27
+ * **Description:** Lists the Hugging Face organizations the user (identified by the token) is a member of.
28
+ * **Parameters:**
29
+ * `token` (string, optional): Hugging Face API token. If left blank or not provided, it attempts to use the token from `huggingface-cli login`.
30
+ * **Interface Tab:** "List My Organizations"
31
+
32
+ 3. **`list_organization_spaces`**
33
+ * **Description:** Lists all public Hugging Face Spaces for a given organization.
34
+ * **Parameters:**
35
+ * `org_name` (string): The name of the Hugging Face organization.
36
+ * **Interface Tab:** "List Org Spaces"
37
+
38
+ These functions can be called via the MCP protocol if this Gradio app is configured as an MCP server endpoint.
39
+
40
+ # video demo
app.py CHANGED
@@ -1,28 +1,200 @@
1
  import gradio as gr
2
 
3
- def letter_counter(word, letter):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  """
5
- Count the number of occurrences of a letter in a word or text.
6
 
7
  Args:
8
- word (str): The input text to search through
9
- letter (str): The letter to search for
10
 
11
  Returns:
12
- str: A message indicating how many times the letter appears
 
 
13
  """
14
- word = word.lower()
15
- letter = letter.lower()
16
- count = word.count(letter)
17
- return count
18
-
19
- demo = gr.Interface(
20
- fn=letter_counter,
21
- inputs=[gr.Textbox("strawberry"), gr.Textbox("r")],
22
- outputs=[gr.Number()],
23
- title="Letter Counter",
24
- description="Enter text and a letter to count how many times the letter appears in the text."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  )
26
 
27
  if __name__ == "__main__":
28
- demo.launch(mcp_server=True,share=True)
 
 
 
 
 
1
  import gradio as gr
2
 
3
+ from huggingface_hub import list_spaces, whoami, HfFolder
4
+ from huggingface_hub.hf_api import HfHubHTTPError
5
+
6
+ def list_my_hf_spaces(hf_username_or_org: str):
7
+ """
8
+ Lists all Hugging Face Spaces for a given username or organization.
9
+
10
+ Args:
11
+ hf_username_or_org (str): The Hugging Face username or organization name.
12
+
13
+ Returns:
14
+ list: A list of dictionaries, where each dictionary contains details of a space.
15
+ Suitable for use with gradio.DataFrame. Returns a list with an error
16
+ message if an issue occurs.
17
+ """
18
+ try:
19
+ print(f"Fetching Hugging Face Spaces for user/org: {hf_username_or_org}") # Server-side log
20
+ if not hf_username_or_org or not hf_username_or_org.strip():
21
+ # Return list of lists format for error
22
+ return [["Error", "Username/Organization cannot be empty.", "-", "-", "-", "-"]]
23
+
24
+ spaces_objects = list_spaces(author=hf_username_or_org.strip())
25
+
26
+ if not spaces_objects:
27
+ # Return list of lists format for no spaces found
28
+ return [[f"No spaces found for '{hf_username_or_org}'", "Check username/org or authentication.", "-", "-", "-", "-"]]
29
+
30
+ spaces_data_list_of_lists = []
31
+ for space in spaces_objects:
32
+ row = [
33
+ f"[{space.id}](https://huggingface.co/spaces/{space.id})",
34
+ getattr(space, 'author', 'N/A'),
35
+ str(getattr(space, 'lastModified', 'N/A')),
36
+ str(getattr(space, 'private', 'N/A')),
37
+ str(getattr(space, 'gated', 'N/A')),
38
+ getattr(space, 'sdk', 'N/A')
39
+ ]
40
+ spaces_data_list_of_lists.append(row)
41
+
42
+ return spaces_data_list_of_lists
43
+
44
+ except Exception as e:
45
+ error_message = f"An error occurred: {str(e)}. Ensure correct username/org and HF authentication (huggingface-cli login or HF_TOKEN)."
46
+ print(error_message) # Server-side log
47
+ # Return list of lists format for exception
48
+ return [["Error", error_message, "-", "-", "-", "-"]]
49
+
50
+
51
+ def list_my_hf_organizations(token: str = None):
52
+ """
53
+ Lists organizations the Hugging Face user (identified by the token) is a member of.
54
+
55
+ Args:
56
+ token (str, optional): Hugging Face API token.
57
+ If None or empty, attempts to load token via HfFolder.get_token().
58
+
59
+ Returns:
60
+ list: A list of lists, where each inner list contains an organization name (as a Markdown link).
61
+ Suitable for use with gradio.DataFrame.
62
+ """
63
+ try:
64
+ if not token: # If token param is None or empty
65
+ token = HfFolder.get_token()
66
+ if not token:
67
+ return [["Error: Not logged in", "Please log in using 'huggingface-cli login'."]]
68
+
69
+ print("Fetching organizations for the authenticated user...") # Server-side log
70
+ user_info = whoami(token=token)
71
+
72
+ if not user_info or 'orgs' not in user_info:
73
+ return [["Info", "No organization information found or user data incomplete."]]
74
+
75
+ org_list_from_api = user_info.get('orgs', [])
76
+ if not org_list_from_api:
77
+ return [["Info", "Authenticated user is not a member of any organizations."]]
78
+
79
+ orgs_data = []
80
+ for org_dict in org_list_from_api:
81
+ org_name = org_dict.get('name')
82
+ if org_name:
83
+ org_link = f"[{org_name}](https://huggingface.co/{org_name})"
84
+ orgs_data.append([org_link]) # Store as a list containing the Markdown link
85
+
86
+ if not orgs_data:
87
+ return [["Info", "Found organization entries but no names extracted."]]
88
+ return orgs_data
89
+
90
+ except HfHubHTTPError as e:
91
+ if e.response.status_code == 401:
92
+ error_msg = "Authentication error. Please ensure you are logged in ('huggingface-cli login')."
93
+ else:
94
+ error_msg = f"API Error: {str(e)}"
95
+ print(error_msg) # Server-side log
96
+ return [["Error", error_msg]]
97
+ except Exception as e:
98
+ error_message = f"An unexpected error occurred: {str(e)}"
99
+ print(error_message) # Server-side log
100
+ return [["Error", error_message]]
101
+
102
+
103
+ def list_organization_spaces(org_name: str):
104
  """
105
+ Lists all public Hugging Face Spaces for a given organization.
106
 
107
  Args:
108
+ org_name (str): The name of the Hugging Face organization.
 
109
 
110
  Returns:
111
+ list: A list of lists, where each inner list contains Space details.
112
+ Suitable for use with gradio.DataFrame.
113
+ The Space ID is formatted as a Markdown link.
114
  """
115
+ try:
116
+ if not org_name or not org_name.strip():
117
+ return [["Error", "Organization name cannot be empty.", "-", "-", "-", "-"]]
118
+
119
+ print(f"Fetching Hugging Face Spaces for organization: {org_name.strip()}") # Server-side log
120
+ spaces_objects = list_spaces(author=org_name.strip()) # Use author field for organization
121
+
122
+ if not spaces_objects:
123
+ return [[f"No Spaces found for organization '{org_name.strip()}'", "Organization may not exist or have no public spaces.", "-", "-", "-", "-"]]
124
+
125
+ spaces_data_list_of_lists = []
126
+ for space in spaces_objects:
127
+ row = [
128
+ f"[{space.id}](https://huggingface.co/spaces/{space.id})",
129
+ getattr(space, 'author', 'N/A'),
130
+ str(getattr(space, 'lastModified', 'N/A')),
131
+ str(getattr(space, 'private', 'N/A')),
132
+ str(getattr(space, 'gated', 'N/A')),
133
+ getattr(space, 'sdk', 'N/A')
134
+ ]
135
+ spaces_data_list_of_lists.append(row)
136
+
137
+ return spaces_data_list_of_lists
138
+
139
+ except HfHubHTTPError as e:
140
+ error_msg = f"API Error for organization '{org_name.strip()}': {str(e)}"
141
+ print(error_msg) # Server-side log
142
+ return [["Error", error_msg, "-", "-", "-", "-"]]
143
+ except Exception as e:
144
+ error_message = f"An unexpected error occurred for organization '{org_name.strip()}': {str(e)}"
145
+ print(error_message) # Server-side log
146
+ return [["Error", error_message, "-", "-", "-", "-"]]
147
+
148
+
149
+ # Gradio interface for listing Hugging Face Spaces
150
+ hf_spaces_interface = gr.Interface(
151
+ fn=list_my_hf_spaces,
152
+ inputs=[gr.Textbox(label="Hugging Face Username or Organization", placeholder="e.g., huggingface, stabilityai, or your_username")],
153
+ outputs=[gr.DataFrame(
154
+ headers=["ID", "Author", "Last Modified", "Private", "Gated", "SDK"],
155
+ label="Hugging Face Spaces",
156
+ wrap=True, # Allow text wrapping in cells
157
+ datatype=["markdown", "str", "str", "str", "str", "str"] # Render first column as Markdown
158
+ )],
159
+ title="Hugging Face api as mcp",
160
+ description="Enter a Hugging Face username or organization to list their public Spaces.",
161
+ examples=[["huggingface"], ["stabilityai"], ["gradio"]],
162
+ allow_flagging='never'
163
+ )
164
+
165
+ hf_orgs_interface = gr.Interface(
166
+ fn=list_my_hf_organizations,
167
+ inputs=[gr.Textbox(label="Hugging Face Token (Optional)", placeholder="hf_xxx... or leave blank to use logged-in user", type="password")],
168
+ outputs=[gr.DataFrame(
169
+ headers=["My Organization Name"],
170
+ label="My Hugging Face Organizations",
171
+ wrap=True,
172
+ datatype=["markdown"] # Render column as Markdown
173
+ )],
174
+ title="My Hugging Face Organizations Lister",
175
+ 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.",
176
+ allow_flagging='never'
177
+ )
178
+
179
+
180
+ hf_org_spaces_interface = gr.Interface(
181
+ fn=list_organization_spaces,
182
+ inputs=[gr.Textbox(label="Organization Name", placeholder="e.g., huggingface, stabilityai")],
183
+ outputs=[gr.DataFrame(
184
+ headers=["ID", "Author", "Last Modified", "Private", "Gated", "SDK"],
185
+ label="Organization's Hugging Face Spaces",
186
+ wrap=True,
187
+ datatype=["markdown", "str", "str", "str", "str", "str"]
188
+ )],
189
+ title="List Organization's Spaces",
190
+ description="Enter a public Hugging Face organization name to list their Spaces.",
191
+ examples=[["huggingface"], ["stabilityai"], ["google"]],
192
+ allow_flagging='never'
193
  )
194
 
195
  if __name__ == "__main__":
196
+ tabbed_demo = gr.TabbedInterface(
197
+ [hf_spaces_interface, hf_orgs_interface, hf_org_spaces_interface],
198
+ ["List Spaces by User/Org", "List My Organizations", "List Org Spaces"]
199
+ )
200
+ tabbed_demo.launch(mcp_server=True, share=True)