CHAN9IJI commited on
Commit
1c61ef6
Β·
verified Β·
1 Parent(s): b2f33c1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +273 -40
app.py CHANGED
@@ -2,6 +2,8 @@ import gradio as gr
2
  from huggingface_hub import InferenceClient
3
  import json
4
  import asyncio
 
 
5
  from typing import Optional, Dict, Any, List
6
 
7
 
@@ -12,6 +14,7 @@ class MCPContextManager:
12
  self.context = []
13
  self.tools = {}
14
  self.resources = {}
 
15
 
16
  def add_context(self, role: str, content: str, metadata: Optional[Dict] = None):
17
  """Add context entry following MCP specification"""
@@ -42,6 +45,10 @@ class MCPContextManager:
42
  "content": content
43
  }
44
 
 
 
 
 
45
  def get_context_window(self, max_tokens: int = 4096) -> List[Dict]:
46
  """Get context window within token limits"""
47
  return self.context[-10:] # Simple implementation
@@ -70,15 +77,40 @@ class MCPContextManager:
70
  return json.dumps({
71
  "context": self.context,
72
  "tools": self.get_available_tools(),
73
- "resources": list(self.resources.keys())
 
74
  }, indent=2)
75
 
76
 
77
  # Initialize MCP Manager
78
  mcp_manager = MCPContextManager()
79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
 
81
- # Register example MCP tools
82
  async def calculator_handler(args):
83
  """Calculator tool handler"""
84
  operation = args.get("operation")
@@ -120,7 +152,97 @@ async def web_search_handler(args):
120
  return f"Search results for: {query} (MCP tool simulation)"
121
 
122
 
123
- # Register tools with MCP manager
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  mcp_manager.register_tool(
125
  name="calculator",
126
  description="Perform basic arithmetic operations",
@@ -164,6 +286,50 @@ mcp_manager.register_tool(
164
  handler=web_search_handler
165
  )
166
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
 
168
  def respond(
169
  message,
@@ -220,7 +386,7 @@ def respond(
220
  def call_mcp_tool(tool_name: str, arguments_json: str):
221
  """Interface for calling MCP tools from UI"""
222
  try:
223
- arguments = json.loads(arguments_json)
224
  result = asyncio.run(mcp_manager.call_tool(tool_name, arguments))
225
  return json.dumps({"success": True, "result": result}, indent=2)
226
  except Exception as e:
@@ -238,6 +404,11 @@ def get_mcp_tools_list():
238
  return json.dumps(tools, indent=2)
239
 
240
 
 
 
 
 
 
241
  """
242
  Enhanced Gradio interface with Model Context Protocol (MCP) support
243
  """
@@ -246,7 +417,7 @@ chatbot = gr.ChatInterface(
246
  type="messages",
247
  additional_inputs=[
248
  gr.Textbox(
249
- value="You are a friendly AI assistant with access to Model Context Protocol (MCP) tools. You can use tools like calculator, memory storage, and web search to help users.",
250
  label="System message",
251
  lines=3
252
  ),
@@ -263,9 +434,9 @@ chatbot = gr.ChatInterface(
263
  ],
264
  )
265
 
266
- with gr.Blocks(title="AI Chat with MCP Support") as demo:
267
- gr.Markdown("# πŸ€– AI Chatbot with Model Context Protocol (MCP)")
268
- gr.Markdown("Enhanced with MCP for context management, tool usage, and resource handling")
269
 
270
  with gr.Tabs():
271
  with gr.Tab("πŸ’¬ Chat"):
@@ -275,23 +446,47 @@ with gr.Blocks(title="AI Chat with MCP Support") as demo:
275
 
276
  with gr.Tab("πŸ› οΈ MCP Tools"):
277
  gr.Markdown("### Available MCP Tools")
278
- tools_display = gr.JSON(label="Registered Tools")
279
- refresh_tools_btn = gr.Button("Refresh Tools List")
 
 
 
 
 
 
 
 
 
 
 
 
 
280
 
281
- gr.Markdown("### Call MCP Tool")
282
  with gr.Row():
283
  tool_name_input = gr.Textbox(label="Tool Name", placeholder="calculator")
284
- tool_args_input = gr.Textbox(
285
  label="Arguments (JSON)",
286
- placeholder='{"operation": "add", "a": 5, "b": 3}',
287
- lines=3
 
288
  )
289
- call_tool_btn = gr.Button("Call Tool")
290
- tool_result = gr.JSON(label="Tool Result")
 
 
 
291
 
292
- refresh_tools_btn.click(
293
- fn=get_mcp_tools_list,
294
- outputs=tools_display
 
 
 
 
 
 
 
295
  )
296
 
297
  call_tool_btn.click(
@@ -300,42 +495,79 @@ with gr.Blocks(title="AI Chat with MCP Support") as demo:
300
  outputs=tool_result
301
  )
302
 
 
 
 
 
 
 
 
 
 
 
 
 
 
303
  with gr.Tab("πŸ“‹ MCP Context"):
304
  gr.Markdown("### Export MCP Context")
305
  gr.Markdown("View and export the current context window managed by MCP")
306
- export_btn = gr.Button("Export Context")
307
- context_display = gr.Code(language="json", label="MCP Context")
308
 
309
- export_btn.click(
310
- fn=export_mcp_context,
311
- outputs=context_display
312
- )
313
 
314
  with gr.Tab("ℹ️ About MCP"):
315
  gr.Markdown("""
316
  ### Model Context Protocol (MCP)
317
 
318
- MCP is a protocol for managing context, tools, and resources in AI applications.
 
 
 
 
 
 
 
 
319
 
320
- **Features:**
321
- - πŸ”§ **Tool Integration**: Register and call tools dynamically
322
- - πŸ’Ύ **Context Management**: Maintain conversation history and context
323
- - πŸ“¦ **Resource Handling**: Store and retrieve resources (files, data, etc.)
324
- - πŸ”Œ **Extensible**: Easy to add new tools and capabilities
 
 
325
 
326
- **Available Tools:**
327
- 1. **Calculator**: Perform arithmetic operations
328
- 2. **Memory**: Store and retrieve information
329
- 3. **Web Search**: Search for information (simulated)
330
 
331
- **Example Tool Call:**
332
  ```json
333
  {
334
- "tool": "calculator",
335
  "arguments": {
336
- "operation": "add",
337
- "a": 10,
338
- "b": 5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
339
  }
340
  }
341
  ```
@@ -344,3 +576,4 @@ with gr.Blocks(title="AI Chat with MCP Support") as demo:
344
 
345
  if __name__ == "__main__":
346
  demo.launch()
 
 
2
  from huggingface_hub import InferenceClient
3
  import json
4
  import asyncio
5
+ import subprocess
6
+ import os
7
  from typing import Optional, Dict, Any, List
8
 
9
 
 
14
  self.context = []
15
  self.tools = {}
16
  self.resources = {}
17
+ self.mcp_servers = {}
18
 
19
  def add_context(self, role: str, content: str, metadata: Optional[Dict] = None):
20
  """Add context entry following MCP specification"""
 
45
  "content": content
46
  }
47
 
48
+ def register_mcp_server(self, server_name: str, config: Dict):
49
+ """Register an MCP server configuration"""
50
+ self.mcp_servers[server_name] = config
51
+
52
  def get_context_window(self, max_tokens: int = 4096) -> List[Dict]:
53
  """Get context window within token limits"""
54
  return self.context[-10:] # Simple implementation
 
77
  return json.dumps({
78
  "context": self.context,
79
  "tools": self.get_available_tools(),
80
+ "resources": list(self.resources.keys()),
81
+ "mcp_servers": list(self.mcp_servers.keys())
82
  }, indent=2)
83
 
84
 
85
  # Initialize MCP Manager
86
  mcp_manager = MCPContextManager()
87
 
88
+ # Register MCP Servers (from your config)
89
+ mcp_manager.register_mcp_server("postgres-full", {
90
+ "command": "npx",
91
+ "args": [
92
+ "-y",
93
+ "mcp-postgres-full-access",
94
+ "postgresql://neondb_owner:npg_oGg8yphr6FeZ@ep-summer-art-a1jpcb05-pooler.ap-southeast-1.aws.neon.tech/neondb?sslmode=require&channel_binding=require"
95
+ ],
96
+ "env": {
97
+ "TRANSACTION_TIMEOUT_MS": "60000",
98
+ "MAX_CONCURRENT_TRANSACTIONS": "5",
99
+ "PG_STATEMENT_TIMEOUT_MS": "30000"
100
+ }
101
+ })
102
+
103
+ mcp_manager.register_mcp_server("filesystem", {
104
+ "command": "npx",
105
+ "args": [
106
+ "-y",
107
+ "@modelcontextprotocol/server-filesystem",
108
+ "C:\\Users\\CHAN\\Documents\\PROJECTS"
109
+ ]
110
+ })
111
+
112
 
113
+ # MCP Tool Handlers
114
  async def calculator_handler(args):
115
  """Calculator tool handler"""
116
  operation = args.get("operation")
 
152
  return f"Search results for: {query} (MCP tool simulation)"
153
 
154
 
155
+ async def git_command_handler(args):
156
+ """Git command execution handler"""
157
+ command = args.get("command", "")
158
+ repo_path = args.get("repo_path", os.getcwd())
159
+
160
+ try:
161
+ # Security: Only allow specific safe git commands
162
+ allowed_commands = ["status", "log", "branch", "diff", "commit", "push", "pull", "add"]
163
+ cmd_parts = command.split()
164
+
165
+ if not cmd_parts or cmd_parts[0] not in allowed_commands:
166
+ return {"error": "Command not allowed or invalid"}
167
+
168
+ # Execute git command
169
+ result = subprocess.run(
170
+ ["git"] + cmd_parts,
171
+ cwd=repo_path,
172
+ capture_output=True,
173
+ text=True,
174
+ timeout=30
175
+ )
176
+
177
+ return {
178
+ "stdout": result.stdout,
179
+ "stderr": result.stderr,
180
+ "returncode": result.returncode,
181
+ "success": result.returncode == 0
182
+ }
183
+ except subprocess.TimeoutExpired:
184
+ return {"error": "Command timed out"}
185
+ except Exception as e:
186
+ return {"error": str(e)}
187
+
188
+
189
+ async def postgres_query_handler(args):
190
+ """PostgreSQL query handler (simulated - would connect to your Neon DB)"""
191
+ query = args.get("query", "")
192
+ operation = args.get("operation", "SELECT")
193
+
194
+ # Note: In production, this would actually connect to your Neon PostgreSQL
195
+ # using the connection string from mcp_servers
196
+ return {
197
+ "message": f"Would execute {operation} query: {query}",
198
+ "note": "Connect to: postgresql://neondb_owner@ep-summer-art-a1jpcb05-pooler.ap-southeast-1.aws.neon.tech/neondb",
199
+ "status": "simulated"
200
+ }
201
+
202
+
203
+ async def filesystem_handler(args):
204
+ """Filesystem operations handler"""
205
+ operation = args.get("operation") # read, write, list, search
206
+ path = args.get("path", "")
207
+ content = args.get("content", "")
208
+
209
+ base_path = r"C:\Users\CHAN\Documents\PROJECTS"
210
+ full_path = os.path.join(base_path, path)
211
+
212
+ try:
213
+ if operation == "read":
214
+ if os.path.exists(full_path):
215
+ with open(full_path, 'r', encoding='utf-8') as f:
216
+ return {"content": f.read(), "success": True}
217
+ return {"error": "File not found", "success": False}
218
+
219
+ elif operation == "list":
220
+ if os.path.exists(full_path):
221
+ items = os.listdir(full_path)
222
+ return {"items": items, "success": True}
223
+ return {"error": "Directory not found", "success": False}
224
+
225
+ elif operation == "write":
226
+ with open(full_path, 'w', encoding='utf-8') as f:
227
+ f.write(content)
228
+ return {"message": "File written successfully", "success": True}
229
+
230
+ elif operation == "search":
231
+ pattern = args.get("pattern", "")
232
+ results = []
233
+ for root, dirs, files in os.walk(full_path if os.path.isdir(full_path) else base_path):
234
+ for file in files:
235
+ if pattern.lower() in file.lower():
236
+ results.append(os.path.join(root, file))
237
+ return {"results": results, "count": len(results), "success": True}
238
+
239
+ return {"error": "Invalid operation", "success": False}
240
+
241
+ except Exception as e:
242
+ return {"error": str(e), "success": False}
243
+
244
+
245
+ # Register all tools with MCP manager
246
  mcp_manager.register_tool(
247
  name="calculator",
248
  description="Perform basic arithmetic operations",
 
286
  handler=web_search_handler
287
  )
288
 
289
+ mcp_manager.register_tool(
290
+ name="git",
291
+ description="Execute git commands (status, log, commit, push, pull, add, branch, diff)",
292
+ parameters={
293
+ "type": "object",
294
+ "properties": {
295
+ "command": {"type": "string", "description": "Git command (e.g., 'status', 'commit -am \"message\"', 'push')"},
296
+ "repo_path": {"type": "string", "description": "Repository path (optional)"}
297
+ },
298
+ "required": ["command"]
299
+ },
300
+ handler=git_command_handler
301
+ )
302
+
303
+ mcp_manager.register_tool(
304
+ name="postgres",
305
+ description="Execute PostgreSQL queries on Neon database",
306
+ parameters={
307
+ "type": "object",
308
+ "properties": {
309
+ "query": {"type": "string"},
310
+ "operation": {"type": "string", "enum": ["SELECT", "INSERT", "UPDATE", "DELETE", "CREATE", "ALTER"]}
311
+ },
312
+ "required": ["query"]
313
+ },
314
+ handler=postgres_query_handler
315
+ )
316
+
317
+ mcp_manager.register_tool(
318
+ name="filesystem",
319
+ description="Perform filesystem operations (read, write, list, search)",
320
+ parameters={
321
+ "type": "object",
322
+ "properties": {
323
+ "operation": {"type": "string", "enum": ["read", "write", "list", "search"]},
324
+ "path": {"type": "string"},
325
+ "content": {"type": "string"},
326
+ "pattern": {"type": "string"}
327
+ },
328
+ "required": ["operation", "path"]
329
+ },
330
+ handler=filesystem_handler
331
+ )
332
+
333
 
334
  def respond(
335
  message,
 
386
  def call_mcp_tool(tool_name: str, arguments_json: str):
387
  """Interface for calling MCP tools from UI"""
388
  try:
389
+ arguments = json.loads(arguments_json) if arguments_json else {}
390
  result = asyncio.run(mcp_manager.call_tool(tool_name, arguments))
391
  return json.dumps({"success": True, "result": result}, indent=2)
392
  except Exception as e:
 
404
  return json.dumps(tools, indent=2)
405
 
406
 
407
+ def get_mcp_servers():
408
+ """Get configured MCP servers"""
409
+ return json.dumps(mcp_manager.mcp_servers, indent=2)
410
+
411
+
412
  """
413
  Enhanced Gradio interface with Model Context Protocol (MCP) support
414
  """
 
417
  type="messages",
418
  additional_inputs=[
419
  gr.Textbox(
420
+ value="You are a powerful AI assistant with MCP tools including: Git operations, PostgreSQL database access (Neon), filesystem operations, calculator, memory, and web search.",
421
  label="System message",
422
  lines=3
423
  ),
 
434
  ],
435
  )
436
 
437
+ with gr.Blocks(title="AI Chat with Full MCP Support") as demo:
438
+ gr.Markdown("# πŸ€– AI Chatbot with Full Model Context Protocol (MCP)")
439
+ gr.Markdown("✨ Connected to PostgreSQL (Neon), Filesystem, Git, and more!")
440
 
441
  with gr.Tabs():
442
  with gr.Tab("πŸ’¬ Chat"):
 
446
 
447
  with gr.Tab("πŸ› οΈ MCP Tools"):
448
  gr.Markdown("### Available MCP Tools")
449
+ tools_display = gr.Code(language="json", label="Registered Tools")
450
+ refresh_tools_btn = gr.Button("πŸ”„ Refresh Tools List")
451
+
452
+ gr.Markdown("### 🎯 Quick Actions")
453
+ with gr.Row():
454
+ with gr.Column():
455
+ gr.Markdown("**Git Commands**")
456
+ git_cmd = gr.Textbox(label="Git Command", placeholder="status")
457
+ git_btn = gr.Button("Execute Git")
458
+
459
+ with gr.Column():
460
+ gr.Markdown("**Filesystem**")
461
+ fs_operation = gr.Dropdown(["list", "read", "search"], label="Operation")
462
+ fs_path = gr.Textbox(label="Path", placeholder="PROJECTS")
463
+ fs_btn = gr.Button("Execute FS")
464
 
465
+ gr.Markdown("### πŸ”§ Custom Tool Call")
466
  with gr.Row():
467
  tool_name_input = gr.Textbox(label="Tool Name", placeholder="calculator")
468
+ tool_args_input = gr.Code(
469
  label="Arguments (JSON)",
470
+ value='{"operation": "add", "a": 5, "b": 3}',
471
+ language="json",
472
+ lines=5
473
  )
474
+ call_tool_btn = gr.Button("▢️ Call Tool")
475
+ tool_result = gr.Code(language="json", label="Tool Result", lines=10)
476
+
477
+ # Event handlers
478
+ refresh_tools_btn.click(fn=get_mcp_tools_list, outputs=tools_display)
479
 
480
+ git_btn.click(
481
+ fn=lambda cmd: call_mcp_tool("git", json.dumps({"command": cmd})),
482
+ inputs=[git_cmd],
483
+ outputs=tool_result
484
+ )
485
+
486
+ fs_btn.click(
487
+ fn=lambda op, path: call_mcp_tool("filesystem", json.dumps({"operation": op, "path": path})),
488
+ inputs=[fs_operation, fs_path],
489
+ outputs=tool_result
490
  )
491
 
492
  call_tool_btn.click(
 
495
  outputs=tool_result
496
  )
497
 
498
+ with gr.Tab("🌐 MCP Servers"):
499
+ gr.Markdown("### Configured MCP Servers")
500
+ servers_display = gr.Code(language="json", label="MCP Server Configuration")
501
+ refresh_servers_btn = gr.Button("πŸ”„ Refresh Servers")
502
+
503
+ refresh_servers_btn.click(fn=get_mcp_servers, outputs=servers_display)
504
+
505
+ gr.Markdown("""
506
+ #### Connected Servers:
507
+ - **postgres-full**: Neon PostgreSQL Database
508
+ - **filesystem**: Local file system access (C:\\Users\\CHAN\\Documents\\PROJECTS)
509
+ """)
510
+
511
  with gr.Tab("πŸ“‹ MCP Context"):
512
  gr.Markdown("### Export MCP Context")
513
  gr.Markdown("View and export the current context window managed by MCP")
514
+ export_btn = gr.Button("πŸ“₯ Export Context")
515
+ context_display = gr.Code(language="json", label="MCP Context", lines=15)
516
 
517
+ export_btn.click(fn=export_mcp_context, outputs=context_display)
 
 
 
518
 
519
  with gr.Tab("ℹ️ About MCP"):
520
  gr.Markdown("""
521
  ### Model Context Protocol (MCP)
522
 
523
+ This AI assistant is powered by MCP with full access to:
524
+
525
+ #### πŸ—„οΈ Database Access
526
+ - **PostgreSQL (Neon)**: Full database operations
527
+ - Connection: `ep-summer-art-a1jpcb05-pooler.ap-southeast-1.aws.neon.tech`
528
+
529
+ #### πŸ“ Filesystem Access
530
+ - **Root**: `C:\\Users\\CHAN\\Documents\\PROJECTS`
531
+ - Operations: read, write, list, search
532
 
533
+ #### πŸ”§ Available Tools:
534
+ 1. **Git**: Execute git commands (status, commit, push, pull, etc.)
535
+ 2. **PostgreSQL**: Query and manage your Neon database
536
+ 3. **Filesystem**: Read/write files, list directories, search
537
+ 4. **Calculator**: Perform arithmetic operations
538
+ 5. **Memory**: Store and retrieve session data
539
+ 6. **Web Search**: Search for information
540
 
541
+ #### πŸ“– Example Commands:
 
 
 
542
 
543
+ **Git:**
544
  ```json
545
  {
546
+ "tool": "git",
547
  "arguments": {
548
+ "command": "status"
549
+ }
550
+ }
551
+ ```
552
+
553
+ **Filesystem:**
554
+ ```json
555
+ {
556
+ "tool": "filesystem",
557
+ "arguments": {
558
+ "operation": "list",
559
+ "path": "PROJECTS"
560
+ }
561
+ }
562
+ ```
563
+
564
+ **PostgreSQL:**
565
+ ```json
566
+ {
567
+ "tool": "postgres",
568
+ "arguments": {
569
+ "query": "SELECT * FROM users LIMIT 10",
570
+ "operation": "SELECT"
571
  }
572
  }
573
  ```
 
576
 
577
  if __name__ == "__main__":
578
  demo.launch()
579
+