abidlabs HF Staff commited on
Commit
7476735
Β·
verified Β·
1 Parent(s): 0f85802

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +149 -0
app.py ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import httpx
3
+ import json
4
+ from huggingface_hub import HfApi
5
+ import random
6
+
7
+ def find_endpoints(openapi_spec_url, api_base_url, methods):
8
+ print(f"Finding endpoints for {openapi_spec_url} with methods {methods}")
9
+ if openapi_spec_url.startswith(("http://", "https://")):
10
+ response = httpx.get(openapi_spec_url)
11
+ response.raise_for_status()
12
+ content = response.text
13
+ else:
14
+ raise gr.Error("Invalid URL for OpenAPI spec")
15
+
16
+ try:
17
+ spec = json.loads(content)
18
+ except json.JSONDecodeError as e:
19
+ raise gr.Error("Invalid JSON for OpenAPI spec")
20
+
21
+ api_paths = spec.get("paths", {})
22
+ if not api_paths:
23
+ raise gr.Error("No valid paths found in the OpenAPI specification")
24
+
25
+ valid_api_paths = []
26
+ for path, path_item in api_paths.items():
27
+ for method, operation in path_item.items():
28
+ if methods and method.lower() not in [m.lower() for m in methods]:
29
+ continue
30
+ valid_api_paths.append({
31
+ "path": path,
32
+ "method": method.upper(),
33
+ })
34
+
35
+ return gr.JSON(valid_api_paths, label=f"πŸ” {len(valid_api_paths)} endpoints found")
36
+
37
+ def update_bottom(oauth_token: gr.OAuthToken | None):
38
+ if oauth_token:
39
+ return "Click the πŸš€ Launch button to create a new MCP Space", gr.Button(interactive=True)
40
+ else:
41
+ return gr.skip()
42
+
43
+ gradio_app_code = """
44
+ import gradio as gr
45
+
46
+ gr.load_openapi(
47
+ openapi_spec=\"{}\",
48
+ base_url=\"{}\",
49
+ methods={},
50
+ ).launch(mcp_server=True)
51
+ """
52
+
53
+ def create_hf_space(token, app_code):
54
+ """
55
+ Create a new Hugging Face Space with optional app.py file
56
+
57
+ Args:
58
+ token (str): Your Hugging Face API token
59
+ app_code (str): String content for the app.py file
60
+
61
+ Returns:
62
+ SpaceInfo: Information about the created space
63
+ """
64
+
65
+ api = HfApi(token=token)
66
+ user_info = api.whoami()
67
+ username = user_info["name"]
68
+ space_name = f"{username}/openapi-to-mcp-{random.randint(100000, 999999)}"
69
+
70
+ try:
71
+ gr.Info("Creating space...")
72
+ space_info = api.create_repo(
73
+ repo_id=space_name,
74
+ repo_type="space",
75
+ private=False,
76
+ space_sdk="gradio"
77
+ )
78
+ print(f"Space created: {space_info}")
79
+
80
+ api.upload_file(
81
+ path_or_fileobj=app_code.encode('utf-8'),
82
+ path_in_repo="app.py",
83
+ repo_id=space_name,
84
+ repo_type="space",
85
+ commit_message="Add app.py"
86
+ )
87
+ print(f"App.py uploaded to {space_name}")
88
+
89
+ space_url = f"https://huggingface.co/spaces/{space_name}"
90
+ gr.Success(f"πŸš€ Your space is available at: <a href='{space_url}' target='_blank'>{space_url}</a>")
91
+ return space_info
92
+
93
+ except Exception as e:
94
+ gr.Error(f"❌ Error creating space: {str(e)}")
95
+
96
+
97
+ def launch_mcp_server(openapi_spec_url, api_base_url, methods, oauth_token: gr.OAuthToken | None):
98
+ if oauth_token:
99
+ create_hf_space(
100
+ oauth_token.token,
101
+ gradio_app_code.format(
102
+ openapi_spec_url,
103
+ api_base_url,
104
+ methods
105
+ )
106
+ )
107
+ else:
108
+ pass
109
+
110
+ with gr.Blocks(theme="ocean") as demo:
111
+ gr.Markdown("## OpenAPI βžͺ MCP")
112
+ gr.Markdown("""
113
+ This is a tool that converts an OpenAPI spec to a MCP server that you can launch as a Space and then use with any MCP Client (e.g. ChatGPT, Claude, Cursor, Cline).
114
+ """)
115
+ with gr.Row():
116
+ with gr.Column():
117
+ openapi_spec_url = gr.Textbox(label="OpenAPI Spec URL", value="https://petstore3.swagger.io/api/v3/openapi.json")
118
+ api_base_url = gr.Textbox(label="API Base URL", value="https://petstore3.swagger.io/api/v3/")
119
+ methods = gr.CheckboxGroup(label="Methods", choices=["GET", "POST", "PUT", "DELETE"], value=["GET", "POST", "PUT", "DELETE"])
120
+ find_endpoints_button = gr.Button("πŸ” Find Endpoints")
121
+ with gr.Column():
122
+ endpoints = gr.JSON(label="πŸ” endpoints found", value=[], max_height=400)
123
+ message = gr.Markdown("_Note:_ you must be signed in through your Hugging Face account to launch the MCP Server")
124
+ with gr.Row():
125
+ login_button = gr.LoginButton()
126
+ launch_button = gr.Button("πŸš€ Launch MCP Server", variant="primary", interactive=False)
127
+
128
+ gr.on(
129
+ [demo.load, find_endpoints_button.click],
130
+ find_endpoints,
131
+ inputs=[openapi_spec_url, api_base_url, methods],
132
+ outputs=endpoints,
133
+ )
134
+
135
+ gr.on(
136
+ [demo.load],
137
+ update_bottom,
138
+ inputs=None,
139
+ outputs=[message, launch_button]
140
+ )
141
+
142
+ gr.on(
143
+ [launch_button.click],
144
+ launch_mcp_server,
145
+ inputs=[openapi_spec_url, api_base_url, methods],
146
+ outputs=None
147
+ )
148
+
149
+ demo.launch()