garibong commited on
Commit
4da0167
Β·
1 Parent(s): 41329d5

fix: resolve MCP tool name validation error

Browse files
Files changed (1) hide show
  1. app.py +104 -68
app.py CHANGED
@@ -135,12 +135,109 @@ def scan_code(code: str, severity_threshold: str = "MEDIUM") -> str:
135
  return format_results_markdown(results)
136
 
137
 
138
- def load_sample(sample_name: str) -> str:
139
- """Load sample vulnerable code."""
140
- return SAMPLE_CODES.get(sample_name, "")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
 
142
 
143
  # MCP Tool - gr.Interface for MCP server exposure
 
144
  mcp_interface = gr.Interface(
145
  fn=scan_code,
146
  inputs=[
@@ -151,75 +248,14 @@ mcp_interface = gr.Interface(
151
  label="severity_threshold"
152
  )
153
  ],
154
- outputs=gr.Textbox(label="Scan Results"),
155
  title="Security Scanner",
156
  description="Scan Python code for security vulnerabilities and get beginner-friendly explanations.",
157
- api_name="scan_security"
158
  )
159
 
160
- # Full UI with Blocks
161
- with gr.Blocks(
162
- title="πŸ”’ Simple Security Scanner",
163
- theme=gr.themes.Soft()
164
- ) as blocks_demo:
165
- gr.Markdown("""
166
- # πŸ”’ Simple Security Scanner
167
-
168
- **Scans Python code for security vulnerabilities and provides beginner-friendly explanations.**
169
-
170
- Also available as an MCP (Model Context Protocol) server.
171
- """)
172
-
173
- with gr.Row():
174
- with gr.Column(scale=2):
175
- code_input = gr.Code(
176
- label="Python Code Input",
177
- language="python",
178
- lines=15,
179
- )
180
-
181
- with gr.Row():
182
- severity_dropdown = gr.Dropdown(
183
- choices=["LOW", "MEDIUM", "HIGH", "CRITICAL"],
184
- value="MEDIUM",
185
- label="Minimum Severity",
186
- scale=1
187
- )
188
- scan_btn = gr.Button("πŸ” Scan", variant="primary", scale=2)
189
-
190
- with gr.Column(scale=1):
191
- gr.Markdown("### πŸ“ Sample Code")
192
- for name in SAMPLE_CODES.keys():
193
- sample_btn = gr.Button(name, size="sm")
194
- sample_btn.click(
195
- fn=lambda n=name: load_sample(n),
196
- outputs=code_input
197
- )
198
-
199
- output = gr.Markdown(label="Scan Results")
200
-
201
- scan_btn.click(
202
- fn=scan_code,
203
- inputs=[code_input, severity_dropdown],
204
- outputs=output
205
- )
206
-
207
- gr.Markdown("""
208
- ---
209
- ### πŸ› οΈ Use as MCP Server
210
-
211
- Connect with Claude Desktop or other MCP clients:
212
- ```json
213
- {
214
- "mcpServers": {
215
- "security-scanner": {
216
- "command": "npx",
217
- "args": ["mcp-remote", "https://mcp-1st-birthday-simple-security-scanner.hf.space/gradio_api/mcp/sse"]
218
- }
219
- }
220
- }
221
- ```
222
- """)
223
 
224
  # Combine: TabbedInterface for both UI and MCP
225
  demo = gr.TabbedInterface(
 
135
  return format_results_markdown(results)
136
 
137
 
138
+ # Sample loader functions - use named functions instead of lambda
139
+ def load_sample_sql_injection():
140
+ """Load SQL Injection sample code."""
141
+ return SAMPLE_CODES["SQL Injection"]
142
+
143
+
144
+ def load_sample_hardcoded_secret():
145
+ """Load Hardcoded Secret sample code."""
146
+ return SAMPLE_CODES["Hardcoded Secret"]
147
+
148
+
149
+ def load_sample_path_traversal():
150
+ """Load Path Traversal sample code."""
151
+ return SAMPLE_CODES["Path Traversal"]
152
+
153
+
154
+ def load_sample_insecure_deserialization():
155
+ """Load Insecure Deserialization sample code."""
156
+ return SAMPLE_CODES["Insecure Deserialization"]
157
+
158
+
159
+ # Mapping of sample names to loader functions
160
+ SAMPLE_LOADERS = {
161
+ "SQL Injection": load_sample_sql_injection,
162
+ "Hardcoded Secret": load_sample_hardcoded_secret,
163
+ "Path Traversal": load_sample_path_traversal,
164
+ "Insecure Deserialization": load_sample_insecure_deserialization,
165
+ }
166
+
167
+
168
+ # Full UI with Blocks (not exposed to MCP)
169
+ def create_blocks_ui():
170
+ """Create the Blocks UI - separated to avoid MCP exposure."""
171
+ with gr.Blocks(
172
+ title="πŸ”’ Simple Security Scanner",
173
+ theme=gr.themes.Soft()
174
+ ) as blocks_demo:
175
+ gr.Markdown("""
176
+ # πŸ”’ Simple Security Scanner
177
+
178
+ **Scans Python code for security vulnerabilities and provides beginner-friendly explanations.**
179
+
180
+ Also available as an MCP (Model Context Protocol) server.
181
+ """)
182
+
183
+ with gr.Row():
184
+ with gr.Column(scale=2):
185
+ code_input = gr.Code(
186
+ label="Python Code Input",
187
+ language="python",
188
+ lines=15,
189
+ )
190
+
191
+ with gr.Row():
192
+ severity_dropdown = gr.Dropdown(
193
+ choices=["LOW", "MEDIUM", "HIGH", "CRITICAL"],
194
+ value="MEDIUM",
195
+ label="Minimum Severity",
196
+ scale=1
197
+ )
198
+ scan_btn = gr.Button("πŸ” Scan", variant="primary", scale=2)
199
+
200
+ with gr.Column(scale=1):
201
+ gr.Markdown("### πŸ“ Sample Code")
202
+ for name, loader_fn in SAMPLE_LOADERS.items():
203
+ sample_btn = gr.Button(name, size="sm")
204
+ sample_btn.click(
205
+ fn=loader_fn,
206
+ outputs=code_input,
207
+ api_name=False # Do not expose to MCP
208
+ )
209
+
210
+ output = gr.Markdown(label="Scan Results")
211
+
212
+ scan_btn.click(
213
+ fn=scan_code,
214
+ inputs=[code_input, severity_dropdown],
215
+ outputs=output,
216
+ api_name=False # Do not expose to MCP
217
+ )
218
+
219
+ gr.Markdown("""
220
+ ---
221
+ ### πŸ› οΈ Use as MCP Server
222
+
223
+ Connect with Claude Desktop or other MCP clients:
224
+ ```json
225
+ {
226
+ "mcpServers": {
227
+ "security-scanner": {
228
+ "command": "npx",
229
+ "args": ["mcp-remote", "https://mcp-1st-birthday-simple-security-scanner.hf.space/gradio_api/mcp/sse"]
230
+ }
231
+ }
232
+ }
233
+ ```
234
+ """)
235
+
236
+ return blocks_demo
237
 
238
 
239
  # MCP Tool - gr.Interface for MCP server exposure
240
+ # Tool name must match pattern: ^[a-zA-Z0-9_-]{1,64}$
241
  mcp_interface = gr.Interface(
242
  fn=scan_code,
243
  inputs=[
 
248
  label="severity_threshold"
249
  )
250
  ],
251
+ outputs=gr.Textbox(label="results"),
252
  title="Security Scanner",
253
  description="Scan Python code for security vulnerabilities and get beginner-friendly explanations.",
254
+ api_name="scan_code" # MCP tool name: only alphanumeric, underscore, hyphen allowed
255
  )
256
 
257
+ # Create UI
258
+ blocks_demo = create_blocks_ui()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
 
260
  # Combine: TabbedInterface for both UI and MCP
261
  demo = gr.TabbedInterface(