Eddyhzd commited on
Commit
7952316
·
1 Parent(s): a513f18
Files changed (1) hide show
  1. app.py +63 -118
app.py CHANGED
@@ -1,145 +1,90 @@
 
 
 
 
 
1
  import asyncio
2
- from typing import Optional
3
  from contextlib import AsyncExitStack
4
 
5
- from mcp import ClientSession, StdioServerParameters
6
- from mcp.client.stdio import stdio_client
7
 
8
- from anthropic import Anthropic
9
- import os
 
 
 
 
10
 
11
- class MCPClient:
12
  def __init__(self):
13
- # Initialize session and client objects
14
- self.session: Optional[ClientSession] = None
 
 
 
 
 
 
 
 
 
15
  self.exit_stack = AsyncExitStack()
16
- self.anthropic = Anthropic(api_key=os.environ.get("CLE_API_ANTHROPIC"))
17
-
18
- async def connect_to_server(self, server_script_path: str):
19
- """Connect to an MCP server
20
 
21
- Args:
22
- server_script_path: Path to the server script (.py or .js)
23
- """
24
- is_python = server_script_path.endswith('.py')
25
- is_js = server_script_path.endswith('.js')
26
- if not (is_python or is_js):
27
- raise ValueError("Server script must be a .py or .js file")
28
-
29
  command = "python" if is_python else "node"
 
30
  server_params = StdioServerParameters(
31
  command=command,
32
- args=[server_script_path],
33
- env=None
34
  )
35
 
36
  stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))
37
  self.stdio, self.write = stdio_transport
38
- self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write))
39
 
 
40
  await self.session.initialize()
41
 
42
- # List available tools
43
  response = await self.session.list_tools()
44
- tools = response.tools
45
- print("\nConnected to server with tools:", [tool.name for tool in tools])
46
-
47
- async def process_query(self, query: str) -> str:
48
- """Process a query using Claude and available tools"""
49
- messages = [
50
- {
51
- "role": "user",
52
- "content": query
53
- }
54
- ]
55
-
56
- response = await self.session.list_tools()
57
- available_tools = [{
58
  "name": tool.name,
59
  "description": tool.description,
60
  "input_schema": tool.inputSchema
61
  } for tool in response.tools]
62
-
63
- # Initial Claude API call
64
- response = self.anthropic.messages.create(
65
- model="claude-3-5-sonnet-20241022",
66
- max_tokens=1000,
67
- messages=messages,
68
- tools=available_tools
69
- )
70
-
71
- # Process response and handle tool calls
72
- tool_results = []
73
- final_text = []
74
-
75
- for content in response.content:
76
- if content.type == 'text':
77
- final_text.append(content.text)
78
- elif content.type == 'tool_use':
79
- tool_name = content.name
80
- tool_args = content.input
81
-
82
- # Execute tool call
83
- result = await self.session.call_tool(tool_name, tool_args)
84
- tool_results.append({"call": tool_name, "result": result})
85
- final_text.append(f"[Calling tool {tool_name} with args {tool_args}]")
86
-
87
- # Continue conversation with tool results
88
- if hasattr(content, 'text') and content.text:
89
- messages.append({
90
- "role": "assistant",
91
- "content": content.text
92
- })
93
- messages.append({
94
- "role": "user",
95
- "content": result.content
96
- })
97
-
98
- # Get next response from Claude
99
- response = self.anthropic.messages.create(
100
- model="claude-3-5-sonnet-20241022",
101
- max_tokens=1000,
102
- messages=messages,
103
- )
104
-
105
- final_text.append(response.content[0].text)
106
-
107
- return "\n".join(final_text)
108
-
109
- async def chat_loop(self):
110
- """Run an interactive chat loop"""
111
- print("\nMCP Client Started!")
112
- print("Type your queries or 'quit' to exit.")
113
 
114
- while True:
115
- try:
116
- query = input("\nQuery: ").strip()
117
-
118
- if query.lower() == 'quit':
119
- break
120
-
121
- response = await self.process_query(query)
122
- print("\n" + response)
123
-
124
- except Exception as e:
125
- print(f"\nError: {str(e)}")
 
 
126
 
127
- async def cleanup(self):
128
- """Clean up resources"""
129
- await self.exit_stack.aclose()
 
 
 
 
 
 
 
 
 
 
 
130
 
131
- async def main():
132
- if len(sys.argv) < 2:
133
- print("Usage: python client.py mcp_server.py")
134
- sys.exit(1)
135
-
136
- client = MCPClient()
137
- try:
138
- await client.connect_to_server(sys.argv[1])
139
- await client.chat_loop()
140
- finally:
141
- await client.cleanup()
142
 
143
- if __name__ == "__main__":
144
- import sys
145
- asyncio.run(main())
 
1
+ import gradio as gr
2
+ from openai import OpenAI
3
+ import os
4
+ from mcp import ClientSession, StdioServerParameters
5
+ from mcp.client.stdio import stdio_client
6
  import asyncio
 
7
  from contextlib import AsyncExitStack
8
 
9
+ cle_api = os.environ.get("CLE_API_MISTRAL")
 
10
 
11
+ # Initialisation du client Mistral (API compatible OpenAI)
12
+ clientLLM = OpenAI(api_key=cle_api, base_url="https://api.mistral.ai/v1")
13
+
14
+
15
+ loop = asyncio.new_event_loop()
16
+ asyncio.set_event_loop(loop)
17
 
18
+ class MCPClientWrapper:
19
  def __init__(self):
20
+ self.session = None
21
+ self.exit_stack = None
22
+ self.tools = []
23
+
24
+ def connect(self, server_path: str) -> str:
25
+ return loop.run_until_complete(self._connect(server_path))
26
+
27
+ async def _connect(self, server_path: str) -> str:
28
+ if self.exit_stack:
29
+ await self.exit_stack.aclose()
30
+
31
  self.exit_stack = AsyncExitStack()
 
 
 
 
32
 
33
+ is_python = server_path.endswith('.py')
 
 
 
 
 
 
 
34
  command = "python" if is_python else "node"
35
+
36
  server_params = StdioServerParameters(
37
  command=command,
38
+ args=[server_path],
39
+ env={"PYTHONIOENCODING": "utf-8", "PYTHONUNBUFFERED": "1"}
40
  )
41
 
42
  stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))
43
  self.stdio, self.write = stdio_transport
 
44
 
45
+ self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write))
46
  await self.session.initialize()
47
 
 
48
  response = await self.session.list_tools()
49
+ self.tools = [{
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  "name": tool.name,
51
  "description": tool.description,
52
  "input_schema": tool.inputSchema
53
  } for tool in response.tools]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
+ tool_names = [tool["name"] for tool in self.tools]
56
+ return f"Connected to MCP server. Available tools: {', '.join(tool_names)}"
57
+
58
+ clientMCP = MCPClientWrapper()
59
+ clientMCP.connect("mcp_server.py")
60
+ print(clientMCP.tools)
61
+
62
+ # Chatbot : simple écho Fonction chatbot reliée à Mistral
63
+ def chatbot(message, history):
64
+ # Préparer l’historique dans le format de Mistral
65
+ messages = []
66
+ for user_msg, bot_msg in history:
67
+ messages.append({"role": "user", "content": user_msg})
68
+ messages.append({"role": "assistant", "content": bot_msg})
69
 
70
+ messages.append({"role": "user", "content": message})
71
+
72
+ # Appel API Mistral
73
+ response = clientLLM.chat.completions.create(
74
+ model="mistral-small-latest",
75
+ messages=messages,
76
+ tools=clientMCP.tools
77
+ )
78
+
79
+ bot_reply = response.choices[0].message.content.strip()
80
+ history.append(("Vous: " + message, "Bot: " + bot_reply))
81
+ return history, history
82
+
83
+ with gr.Blocks() as demo:
84
 
85
+ chatbot_ui = gr.Chatbot(label="ChatBot")
86
+ msg = gr.Textbox(placeholder="Écrivez un message...")
87
+
88
+ msg.submit(chatbot, [msg, chatbot_ui], [chatbot_ui, chatbot_ui])
 
 
 
 
 
 
 
89
 
90
+ demo.launch(debug=True)