ryoshimu commited on
Commit
317ab4b
·
1 Parent(s): 0bbd02b
Files changed (3) hide show
  1. Dockerfile +1 -1
  2. app.py +69 -189
  3. requirements.txt +1 -3
Dockerfile CHANGED
@@ -12,4 +12,4 @@ COPY . .
12
 
13
  EXPOSE 7860
14
 
15
- CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
 
12
 
13
  EXPOSE 7860
14
 
15
+ CMD ["python", "app.py"]
app.py CHANGED
@@ -1,201 +1,81 @@
1
- """FastMCP sample MCP server implementation with a Gradio configuration UI."""
2
- import json
3
- import os
4
- from pathlib import Path
5
- from typing import List, Tuple
6
-
7
  import gradio as gr
8
- import uvicorn
9
- from fastmcp import FastMCP
10
- from starlette.responses import JSONResponse
11
-
12
- mcp = FastMCP(name="Sample MCP Server", version="0.1.0")
13
-
14
- AVAILABLE_TOOLS = [
15
- {
16
- "name": "echo",
17
- "description": "Return the provided text unchanged.",
18
- }
19
- ]
20
-
21
- SERVER_DESCRIPTION = "Sample FastMCP server deployed to Hugging Face Spaces."
22
 
23
-
24
- @mcp.tool(name="echo")
25
- async def echo(text: str) -> str:
26
- """Return the provided text unchanged."""
 
 
 
 
 
 
27
  return text
28
 
29
-
30
- @mcp.custom_route("/", methods=["GET"])
31
- async def health_check(_request) -> JSONResponse:
32
- """Basic health-check endpoint for Hugging Face Spaces."""
33
- return JSONResponse(
34
- {
35
- "status": "ok",
36
- "message": "Sample MCP server is running with FastMCP.",
37
- "ui_path": "/gradio",
38
- }
39
- )
40
-
41
-
42
- def _default_space_url() -> str:
43
- """Best-effort default Space URL for Hugging Face deployments."""
44
- explicit_url = os.getenv("SPACE_URL")
45
- if explicit_url:
46
- return explicit_url.rstrip("/")
47
- space_host = os.getenv("SPACE_HOST")
48
- if space_host:
49
- prefix = "" if space_host.startswith("http") else "https://"
50
- return f"{prefix}{space_host}".rstrip("/")
51
- space_id = os.getenv("SPACE_ID")
52
- if space_id:
53
- space_slug = space_id.replace("/", "-")
54
- return f"https://{space_slug}.hf.space"
55
- return "http://localhost:7860"
56
-
57
-
58
- def _available_tools_table() -> List[List[str]]:
59
- """Return tool metadata for display in the Gradio UI."""
60
- return [[tool["name"], tool["description"]] for tool in AVAILABLE_TOOLS]
61
-
62
-
63
- def build_configuration(
64
- space_url: str, server_name: str, server_description: str
65
- ) -> Tuple[str, str, str, str]:
66
- """Build connection details for MCP clients."""
67
- base_url = (space_url or "").strip() or _default_space_url()
68
- base_url = base_url.rstrip("/")
69
- endpoint = f"{base_url}/mcp"
70
- resolved_name = (server_name or "").strip() or mcp.name
71
- resolved_description = (server_description or "").strip() or SERVER_DESCRIPTION
72
-
73
- servers_json = json.dumps(
74
- {
75
- "version": 1,
76
- "servers": [
77
- {
78
- "name": resolved_name,
79
- "url": endpoint,
80
- "type": "http",
81
- "description": resolved_description,
82
- }
83
- ],
84
- },
85
- indent=2,
86
- )
87
-
88
- chatgpt_steps = "\n".join(
89
- [
90
- "1. Open ChatGPT and navigate to Settings -> Developer -> Model Context Protocol.",
91
- f"2. Choose 'Add server' and paste `{endpoint}` into the URL field.",
92
- "3. Save the configuration to enable the tools listed below.",
93
- ]
94
- )
95
-
96
- script_dir = Path(__file__).resolve().parent
97
- client_script = (
98
- "client.py" if (script_dir / "client.py").exists() else "clinet.py"
99
- )
100
- client_command = f"python {client_script} --url {endpoint}"
101
-
102
- return endpoint, servers_json, chatgpt_steps, client_command
103
-
104
-
105
- with gr.Blocks(title="MCP Server Configurator", theme=gr.themes.Soft()) as demo:
106
- gr.Markdown(
107
- (
108
- "# MCP Server Configuration Helper\n"
109
- "Generate ready-to-use connection details for MCP-compatible clients."
110
- )
111
- )
112
- with gr.Row():
113
- space_url_input = gr.Textbox(
114
- label="Space base URL",
115
- value=_default_space_url(),
116
- placeholder="https://username-space.hf.space",
117
- )
118
- server_name_input = gr.Textbox(
119
- label="Server name",
120
- value=mcp.name,
121
- placeholder="Sample MCP Server",
122
- )
123
- server_description_input = gr.Textbox(
124
- label="Server description",
125
- value=SERVER_DESCRIPTION,
126
- placeholder="Brief description shown to clients.",
127
- )
128
- generate_button = gr.Button("Generate configuration", variant="primary")
129
-
130
- endpoint_output = gr.Textbox(
131
- label="MCP endpoint",
132
- interactive=False,
133
- )
134
- servers_json_output = gr.Code(
135
- label="servers.json entry",
136
- language="json",
137
- )
138
- chatgpt_output = gr.Markdown()
139
- available_tools_output = gr.Dataframe(
140
- headers=["Tool", "Description"],
141
- value=_available_tools_table(),
142
- interactive=False,
143
- label="Available tools",
144
- )
145
- client_command_output = gr.Textbox(
146
- label="FastMCP client command",
147
- interactive=False,
148
- value="",
149
- )
150
-
151
- generate_button.click(
152
- build_configuration,
153
- inputs=[space_url_input, server_name_input, server_description_input],
154
- outputs=[
155
- endpoint_output,
156
- servers_json_output,
157
- chatgpt_output,
158
- client_command_output,
159
- ],
160
- queue=False,
161
- )
162
-
163
- demo.load(
164
- build_configuration,
165
- inputs=[space_url_input, server_name_input, server_description_input],
166
- outputs=[
167
- endpoint_output,
168
- servers_json_output,
169
- chatgpt_output,
170
- client_command_output,
171
- ],
172
- queue=False,
173
- )
174
-
175
- app = mcp.http_app()
176
- gr.mount_gradio_app(app, demo, path="/gradio")
177
- def your_function(param1: str, param2: int) -> str:
178
- """
179
- 関数の説明をここに書きます。
180
 
181
  Args:
182
- param1: パラメータ1の説明
183
- param2: パラメータ2の説明
184
 
185
  Returns:
186
- 戻り値の説明
187
  """
188
- # 関数の処理
189
- return result
190
 
191
- # インターフェース作成
192
- demo = gr.Interface(
193
- fn=your_function,
194
- inputs=["text", "number"],
195
- outputs="text"
196
- )
 
 
 
 
197
 
198
- # 重要:mcp_server=True 追加!
199
- demo.launch(mcp_server=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
  if __name__ == "__main__":
201
- uvicorn.run("app:app", host="0.0.0.0", port=7860, reload=False)
 
1
+ """Gradio MCP server implementation for Hugging Face Spaces."""
 
 
 
 
 
2
  import gradio as gr
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
+ # MCP対応のツール関数を定義(型ヒントとdocstringが必須)
5
+ def echo(text: str) -> str:
6
+ """Return the provided text unchanged.
7
+
8
+ Args:
9
+ text: The text to echo back
10
+
11
+ Returns:
12
+ The same text that was provided
13
+ """
14
  return text
15
 
16
+ def reverse_text(text: str) -> str:
17
+ """Reverse the provided text.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
  Args:
20
+ text: The text to reverse
 
21
 
22
  Returns:
23
+ The reversed text
24
  """
25
+ return text[::-1]
 
26
 
27
+ def count_words(text: str) -> int:
28
+ """Count the number of words in the text.
29
+
30
+ Args:
31
+ text: The text to count words in
32
+
33
+ Returns:
34
+ The number of words in the text
35
+ """
36
+ return len(text.split())
37
 
38
+ # Gradioインターフェース作成
39
+ with gr.Blocks(title="MCP Sample Server", theme=gr.themes.Soft()) as demo:
40
+ gr.Markdown(
41
+ """
42
+ # MCP Sample Server
43
+ This Space provides MCP-compatible tools that can be used with Claude.ai and other MCP clients.
44
+
45
+ ## Available Tools:
46
+ - **echo**: Returns the provided text unchanged
47
+ - **reverse_text**: Reverses the provided text
48
+ - **count_words**: Counts the number of words in the text
49
+
50
+ ## How to connect:
51
+ 1. Go to https://huggingface.co/settings/mcp
52
+ 2. Set up your MCP client (Claude.ai)
53
+ 3. Click the MCP badge on this Space and select "Add to MCP tools"
54
+ 4. The tools will be available in your MCP client
55
+ """
56
+ )
57
+
58
+ with gr.Tab("Echo Tool"):
59
+ with gr.Row():
60
+ echo_input = gr.Textbox(label="Input Text", placeholder="Enter text to echo")
61
+ echo_output = gr.Textbox(label="Output", interactive=False)
62
+ echo_btn = gr.Button("Echo")
63
+ echo_btn.click(echo, inputs=echo_input, outputs=echo_output)
64
+
65
+ with gr.Tab("Reverse Tool"):
66
+ with gr.Row():
67
+ reverse_input = gr.Textbox(label="Input Text", placeholder="Enter text to reverse")
68
+ reverse_output = gr.Textbox(label="Reversed Text", interactive=False)
69
+ reverse_btn = gr.Button("Reverse")
70
+ reverse_btn.click(reverse_text, inputs=reverse_input, outputs=reverse_output)
71
+
72
+ with gr.Tab("Word Count Tool"):
73
+ with gr.Row():
74
+ count_input = gr.Textbox(label="Input Text", placeholder="Enter text to count words")
75
+ count_output = gr.Number(label="Word Count", interactive=False)
76
+ count_btn = gr.Button("Count Words")
77
+ count_btn.click(count_words, inputs=count_input, outputs=count_output)
78
+
79
+ # 重要: mcp_server=True を指定してMCPサーバーとして公開
80
  if __name__ == "__main__":
81
+ demo.launch(mcp_server=True)
requirements.txt CHANGED
@@ -1,3 +1 @@
1
- fastmcp==2.12.4
2
- gradio==4.44.0
3
- uvicorn[standard]==0.30.1
 
1
+ gradio[mcp]>=5.0.0