mgokg commited on
Commit
0b463c5
·
verified ·
1 Parent(s): c4f8ee5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +33 -16
app.py CHANGED
@@ -8,14 +8,15 @@ from mcp import ClientSession, StdioServerParameters
8
  from mcp.client.stdio import stdio_client
9
 
10
  # 1. Konfiguration des MCP-Servers via STDIO-Bridge
11
- # Dies löst das SSE-Problem, indem npx mcp-remote die Kommunikation übernimmt [3].
12
  server_params = StdioServerParameters(
13
  command="npx",
14
  args=[
 
15
  "mcp-remote",
16
  "https://mgokg-db-timetable-api.hf.space/gradio_api/mcp/",
17
  "--transport",
18
- "streamable-http"
19
  ]
20
  )
21
 
@@ -27,12 +28,13 @@ async def generate(input_text):
27
 
28
  model = "gemini-2.0-flash"
29
 
30
- # 2. Aufbau der MCP-Session [4, 5]
 
31
  async with stdio_client(server_params) as (read, write):
32
  async with ClientSession(read, write) as session:
33
  await session.initialize()
34
 
35
- # MCP-Tools abrufen und in Gemini-Format konvertieren [5, 6]
36
  mcp_tools_data = await session.list_tools()
37
  mcp_declarations = [
38
  {
@@ -43,7 +45,9 @@ async def generate(input_text):
43
  for tool in mcp_tools_data.tools
44
  ]
45
 
46
- # 3. Kombination der Tools: Google Search + DB-Timetable [5, 7]
 
 
47
  tools = [
48
  types.Tool(google_search=types.GoogleSearch()),
49
  types.Tool(function_declarations=mcp_declarations)
@@ -58,20 +62,33 @@ async def generate(input_text):
58
  config=types.GenerateContentConfig(tools=tools, temperature=0.4)
59
  )
60
 
61
- # 4. Agentic Loop: Bearbeitung von Tool-Calls (z.B. db_timetable_api_ui_wrapper) [8, 9]
62
  turn_count = 0
 
 
63
  while response.function_calls and turn_count < 5:
64
  turn_count += 1
65
- contents.append(response.candidates.content)
 
 
 
66
  tool_responses = []
67
 
68
  for fc in response.function_calls:
69
  try:
70
- # Ausführung des MCP-Tools [9]
71
  tool_result = await session.call_tool(fc.name, fc.args)
72
 
73
- # Ergebnis formatieren (Erfolg oder Fehler) [9]
74
- result_data = tool_result.content.text if not tool_result.isError else tool_result.content.text
 
 
 
 
 
 
 
 
75
  tool_responses.append(types.Part.from_function_response(
76
  name=fc.name, response={"result": result_data}
77
  ))
@@ -82,16 +99,17 @@ async def generate(input_text):
82
 
83
  contents.append(types.Content(role="user", parts=tool_responses))
84
 
85
- # Nächster Modell-Aufruf mit den Tool-Ergebnissen [10, 11]
86
  response = await client.aio.models.generate_content(
87
  model=model, contents=contents, config=types.GenerateContentConfig(tools=tools)
88
  )
89
 
90
  return response.text, ""
91
 
92
- # 5. Gradio UI Integration [12]
93
- def ui_wrapper(input_text):
94
- return asyncio.run(generate(input_text))
 
95
 
96
  if __name__ == '__main__':
97
  with gr.Blocks() as demo:
@@ -105,8 +123,7 @@ if __name__ == '__main__':
105
  inputs=input_textbox,
106
  outputs=[output_textbox, input_textbox]
107
  )
108
- demo.launch(show_error=True)
109
-
110
 
111
 
112
  """
 
8
  from mcp.client.stdio import stdio_client
9
 
10
  # 1. Konfiguration des MCP-Servers via STDIO-Bridge
11
+ # FIX: Changed transport from 'streamable-http' to 'http-first' based on error log
12
  server_params = StdioServerParameters(
13
  command="npx",
14
  args=[
15
+ "-y", # Auto-confirm installation if needed
16
  "mcp-remote",
17
  "https://mgokg-db-timetable-api.hf.space/gradio_api/mcp/",
18
  "--transport",
19
+ "http-first"
20
  ]
21
  )
22
 
 
28
 
29
  model = "gemini-2.0-flash"
30
 
31
+ # 2. Aufbau der MCP-Session
32
+ # Note: This context manager keeps the connection open only during the generation
33
  async with stdio_client(server_params) as (read, write):
34
  async with ClientSession(read, write) as session:
35
  await session.initialize()
36
 
37
+ # MCP-Tools abrufen und in Gemini-Format konvertieren
38
  mcp_tools_data = await session.list_tools()
39
  mcp_declarations = [
40
  {
 
45
  for tool in mcp_tools_data.tools
46
  ]
47
 
48
+ # 3. Kombination der Tools
49
+ # Using function_declarations disables Automatic Function Calling (AFC),
50
+ # which is what we want because we handle the loop manually below.
51
  tools = [
52
  types.Tool(google_search=types.GoogleSearch()),
53
  types.Tool(function_declarations=mcp_declarations)
 
62
  config=types.GenerateContentConfig(tools=tools, temperature=0.4)
63
  )
64
 
65
+ # 4. Agentic Loop: Bearbeitung von Tool-Calls
66
  turn_count = 0
67
+
68
+ # Note: response.function_calls is a helper property in the SDK
69
  while response.function_calls and turn_count < 5:
70
  turn_count += 1
71
+
72
+ # FIX: response.candidates is a list. Must access index 0.
73
+ contents.append(response.candidates[0].content)
74
+
75
  tool_responses = []
76
 
77
  for fc in response.function_calls:
78
  try:
79
+ # Ausführung des MCP-Tools
80
  tool_result = await session.call_tool(fc.name, fc.args)
81
 
82
+ # Ergebnis formatieren
83
+ # Check if content is a list (standard MCP) or text
84
+ if hasattr(tool_result.content, 'text'):
85
+ # Some implementations might differ, standardizing to string
86
+ result_data = tool_result.content.text
87
+ elif isinstance(tool_result.content, list):
88
+ result_data = "\n".join([item.text for item in tool_result.content if hasattr(item, 'text')])
89
+ else:
90
+ result_data = str(tool_result.content)
91
+
92
  tool_responses.append(types.Part.from_function_response(
93
  name=fc.name, response={"result": result_data}
94
  ))
 
99
 
100
  contents.append(types.Content(role="user", parts=tool_responses))
101
 
102
+ # Nächster Modell-Aufruf mit den Tool-Ergebnissen
103
  response = await client.aio.models.generate_content(
104
  model=model, contents=contents, config=types.GenerateContentConfig(tools=tools)
105
  )
106
 
107
  return response.text, ""
108
 
109
+ # 5. Gradio UI Integration
110
+ # FIX: Made this async and removed asyncio.run() to prevent Event Loop conflicts
111
+ async def ui_wrapper(input_text):
112
+ return await generate(input_text)
113
 
114
  if __name__ == '__main__':
115
  with gr.Blocks() as demo:
 
123
  inputs=input_textbox,
124
  outputs=[output_textbox, input_textbox]
125
  )
126
+ demo.launch(show_error=True, ssr_mode=False)
 
127
 
128
 
129
  """