Ava2lon commited on
Commit
99d5f49
·
verified ·
1 Parent(s): bac782e

Upload 213 files

Browse files
N8N_ENDPOINTS.md CHANGED
@@ -866,6 +866,8 @@ These are not business API operations:
866
  | `/whisper/` | Whisper Gradio interface. |
867
  | `/editor/` | FFmpeg editor Gradio interface. |
868
  | `/mcp/` | MCP Streamable HTTP transport; use an MCP client rather than a normal REST request. |
 
 
869
  | `/docs` | Root FastAPI Swagger UI when `ENABLE_API_DOCS=true`. |
870
  | `/redoc` | Root FastAPI ReDoc UI when `ENABLE_API_DOCS=true`. |
871
  | `/openapi.json` | Root renderer OpenAPI schema when `ENABLE_API_DOCS=true`. |
 
866
  | `/whisper/` | Whisper Gradio interface. |
867
  | `/editor/` | FFmpeg editor Gradio interface. |
868
  | `/mcp/` | MCP Streamable HTTP transport; use an MCP client rather than a normal REST request. |
869
+ | `/dashboard/gradio_api/mcp/` | Gradio-native MCP transport for documented dashboard actions. |
870
+ | `/mcp-health` | MCP transport discovery and custom tool count. |
871
  | `/docs` | Root FastAPI Swagger UI when `ENABLE_API_DOCS=true`. |
872
  | `/redoc` | Root FastAPI ReDoc UI when `ENABLE_API_DOCS=true`. |
873
  | `/openapi.json` | Root renderer OpenAPI schema when `ENABLE_API_DOCS=true`. |
README.md CHANGED
@@ -21,6 +21,7 @@ One Hugging Face Docker Space containing the five original applications.
21
  | Whisper operator | `/whisper/` |
22
  | FFmpeg editor | `/editor/` |
23
  | MCP Streamable HTTP | `/mcp/` |
 
24
 
25
  The rendering API remains available at the Space root. `GET /apps` returns the
26
  mounted application paths.
@@ -43,6 +44,16 @@ Connect an MCP client to:
43
  https://<space-subdomain>.hf.space/mcp/
44
  ```
45
 
 
 
 
 
 
 
 
 
 
 
46
  Every FastAPI application endpoint is exposed as a separate MCP tool. Tool
47
  arguments use a consistent transport wrapper:
48
 
 
21
  | Whisper operator | `/whisper/` |
22
  | FFmpeg editor | `/editor/` |
23
  | MCP Streamable HTTP | `/mcp/` |
24
+ | Gradio-native MCP | `/dashboard/gradio_api/mcp/` |
25
 
26
  The rendering API remains available at the Space root. `GET /apps` returns the
27
  mounted application paths.
 
44
  https://<space-subdomain>.hf.space/mcp/
45
  ```
46
 
47
+ This is the custom MCP server and exposes every FastAPI endpoint. The renderer
48
+ dashboard also exposes its documented Gradio actions through Gradio-native MCP:
49
+
50
+ ```text
51
+ https://<space-subdomain>.hf.space/dashboard/gradio_api/mcp/
52
+ ```
53
+
54
+ Use `GET /mcp-health` in a browser or HTTP client to verify both advertised
55
+ transport URLs and the generated custom tool count.
56
+
57
  Every FastAPI application endpoint is exposed as a separate MCP tool. Tool
58
  arguments use a consistent transport wrapper:
59
 
app.py CHANGED
@@ -61,6 +61,7 @@ async def studio_apps():
61
  "whisper": "/whisper/",
62
  "editor": "/editor/",
63
  "mcp": "/mcp/",
 
64
  "mcp_tools": len(mcp_tool_catalog),
65
  }
66
 
@@ -82,6 +83,17 @@ mcp, mcp_tool_catalog = create_mcp_server(
82
  mcp_http_app = mcp.streamable_http_app()
83
 
84
 
 
 
 
 
 
 
 
 
 
 
 
85
  @asynccontextmanager
86
  async def studio_lifespan(root_app):
87
  async with AsyncExitStack() as stack:
 
61
  "whisper": "/whisper/",
62
  "editor": "/editor/",
63
  "mcp": "/mcp/",
64
+ "gradio_mcp": "/dashboard/gradio_api/mcp/",
65
  "mcp_tools": len(mcp_tool_catalog),
66
  }
67
 
 
83
  mcp_http_app = mcp.streamable_http_app()
84
 
85
 
86
+ @app.get("/mcp-health", include_in_schema=False)
87
+ async def mcp_health():
88
+ return {
89
+ "status": "ok",
90
+ "custom_mcp_url": "/mcp/",
91
+ "gradio_mcp_url": "/dashboard/gradio_api/mcp/",
92
+ "custom_tool_count": len(mcp_tool_catalog),
93
+ "transports": ["streamable-http"],
94
+ }
95
+
96
+
97
  @asynccontextmanager
98
  async def studio_lifespan(root_app):
99
  async with AsyncExitStack() as stack:
renderer_app.py CHANGED
@@ -374,6 +374,7 @@ app = gr.mount_gradio_app(
374
  create_dashboard(),
375
  path="/dashboard",
376
  root_path="/dashboard",
 
377
  )
378
 
379
 
 
374
  create_dashboard(),
375
  path="/dashboard",
376
  root_path="/dashboard",
377
+ mcp_server=True,
378
  )
379
 
380
 
requirements.renderer.txt CHANGED
@@ -1,8 +1,9 @@
1
  fastapi>=0.115.0
2
  uvicorn[standard]>=0.30.0
3
- gradio>=5.49,<6
4
  huggingface_hub<1.0
5
- pydantic>=2.7.0
 
6
  python-multipart>=0.0.9
7
  psutil>=5.9.8
8
  pytest>=8.2.0
 
1
  fastapi>=0.115.0
2
  uvicorn[standard]>=0.30.0
3
+ gradio[mcp]==5.49.1
4
  huggingface_hub<1.0
5
+ pydantic>=2.11,<2.12
6
+ mcp==1.10.1
7
  python-multipart>=0.0.9
8
  psutil>=5.9.8
9
  pytest>=8.2.0
requirements.txt CHANGED
@@ -10,19 +10,19 @@ google-auth>=2.29.0
10
  google-auth-httplib2>=0.2.0
11
  google-auth-oauthlib>=1.2.0
12
  google-generativeai>=0.7.2
13
- gradio>=5.49,<6
14
  httplib2>=0.22.0
15
  huggingface_hub<1.0
16
  httpx>=0.27.0
17
  imageio>=2.34.0
18
  imageio-ffmpeg>=0.4.9
19
  moviepy==1.0.3
20
- mcp>=1.28.1,<2
21
  numpy>=1.26.0
22
  onnxruntime
23
  phonemizer
24
  psutil>=5.9.8
25
- pydantic>=2.7.0
26
  pytest>=8.2.0
27
  pytest-cov>=5.0.0
28
  pysrt>=1.1.2
 
10
  google-auth-httplib2>=0.2.0
11
  google-auth-oauthlib>=1.2.0
12
  google-generativeai>=0.7.2
13
+ gradio[mcp]==5.49.1
14
  httplib2>=0.22.0
15
  huggingface_hub<1.0
16
  httpx>=0.27.0
17
  imageio>=2.34.0
18
  imageio-ffmpeg>=0.4.9
19
  moviepy==1.0.3
20
+ mcp==1.10.1
21
  numpy>=1.26.0
22
  onnxruntime
23
  phonemizer
24
  psutil>=5.9.8
25
+ pydantic>=2.11,<2.12
26
  pytest>=8.2.0
27
  pytest-cov>=5.0.0
28
  pysrt>=1.1.2
tests/test_ui_routing.py CHANGED
@@ -31,6 +31,14 @@ class UIRoutingTests(unittest.TestCase):
31
  self.assertEqual(response.status_code, 200)
32
  self.assertIn("/dashboard", response.text)
33
 
 
 
 
 
 
 
 
 
34
 
35
  if __name__ == "__main__":
36
  unittest.main()
 
31
  self.assertEqual(response.status_code, 200)
32
  self.assertIn("/dashboard", response.text)
33
 
34
+ def test_mcp_discovery_reports_both_transports(self) -> None:
35
+ response = self.client.get("/mcp-health")
36
+ self.assertEqual(response.status_code, 200)
37
+ payload = response.json()
38
+ self.assertEqual(payload["custom_mcp_url"], "/mcp/")
39
+ self.assertEqual(payload["gradio_mcp_url"], "/dashboard/gradio_api/mcp/")
40
+ self.assertGreater(payload["custom_tool_count"], 0)
41
+
42
 
43
  if __name__ == "__main__":
44
  unittest.main()