VotreNomUtilisateurboscherj commited on
Commit
064fc28
·
1 Parent(s): 54e3dbf

chore(pre-commit): apply autofixes

Browse files
.pre-commit-config.yaml ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v4.6.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ - id: check-merge-conflict
9
+
10
+ - repo: https://github.com/Yelp/detect-secrets
11
+ rev: v1.5.0
12
+ hooks:
13
+ - id: detect-secrets
14
+ args: ["--baseline", ".secrets.baseline"]
.secrets.baseline ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "version": "1.5.0",
3
+ "plugins_used": [
4
+ {
5
+ "name": "ArtifactoryDetector"
6
+ },
7
+ {
8
+ "name": "AWSKeyDetector"
9
+ },
10
+ {
11
+ "name": "AzureStorageKeyDetector"
12
+ },
13
+ {
14
+ "name": "Base64HighEntropyString",
15
+ "limit": 4.5
16
+ },
17
+ {
18
+ "name": "BasicAuthDetector"
19
+ },
20
+ {
21
+ "name": "CloudantDetector"
22
+ },
23
+ {
24
+ "name": "DiscordBotTokenDetector"
25
+ },
26
+ {
27
+ "name": "GitHubTokenDetector"
28
+ },
29
+ {
30
+ "name": "GitLabTokenDetector"
31
+ },
32
+ {
33
+ "name": "HexHighEntropyString",
34
+ "limit": 3.0
35
+ },
36
+ {
37
+ "name": "IbmCloudIamDetector"
38
+ },
39
+ {
40
+ "name": "IbmCosHmacDetector"
41
+ },
42
+ {
43
+ "name": "IPPublicDetector"
44
+ },
45
+ {
46
+ "name": "JwtTokenDetector"
47
+ },
48
+ {
49
+ "name": "KeywordDetector",
50
+ "keyword_exclude": ""
51
+ },
52
+ {
53
+ "name": "MailchimpDetector"
54
+ },
55
+ {
56
+ "name": "NpmDetector"
57
+ },
58
+ {
59
+ "name": "OpenAIDetector"
60
+ },
61
+ {
62
+ "name": "PrivateKeyDetector"
63
+ },
64
+ {
65
+ "name": "PypiTokenDetector"
66
+ },
67
+ {
68
+ "name": "SendGridDetector"
69
+ },
70
+ {
71
+ "name": "SlackDetector"
72
+ },
73
+ {
74
+ "name": "SoftlayerDetector"
75
+ },
76
+ {
77
+ "name": "SquareOAuthDetector"
78
+ },
79
+ {
80
+ "name": "StripeDetector"
81
+ },
82
+ {
83
+ "name": "TelegramBotTokenDetector"
84
+ },
85
+ {
86
+ "name": "TwilioKeyDetector"
87
+ }
88
+ ],
89
+ "filters_used": [
90
+ {
91
+ "path": "detect_secrets.filters.allowlist.is_line_allowlisted"
92
+ },
93
+ {
94
+ "path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies",
95
+ "min_level": 2
96
+ },
97
+ {
98
+ "path": "detect_secrets.filters.heuristic.is_indirect_reference"
99
+ },
100
+ {
101
+ "path": "detect_secrets.filters.heuristic.is_likely_id_string"
102
+ },
103
+ {
104
+ "path": "detect_secrets.filters.heuristic.is_lock_file"
105
+ },
106
+ {
107
+ "path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string"
108
+ },
109
+ {
110
+ "path": "detect_secrets.filters.heuristic.is_potential_uuid"
111
+ },
112
+ {
113
+ "path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign"
114
+ },
115
+ {
116
+ "path": "detect_secrets.filters.heuristic.is_sequential_string"
117
+ },
118
+ {
119
+ "path": "detect_secrets.filters.heuristic.is_swagger_file"
120
+ },
121
+ {
122
+ "path": "detect_secrets.filters.heuristic.is_templated_secret"
123
+ }
124
+ ],
125
+ "results": {},
126
+ "generated_at": "2025-09-27T13:56:05Z"
127
+ }
.vscode/launch.json CHANGED
@@ -12,4 +12,4 @@
12
  "console": "integratedTerminal"
13
  }
14
  ]
15
- }
 
12
  "console": "integratedTerminal"
13
  }
14
  ]
15
+ }
mcp_architecture_diagram.txt CHANGED
@@ -52,4 +52,4 @@
52
  | - No network overhead - Authentication |
53
  +------------------------------------------------------+
54
 
55
- ```
 
52
  | - No network overhead - Authentication |
53
  +------------------------------------------------------+
54
 
55
+ ```
mcp_chatbot.py CHANGED
@@ -21,7 +21,7 @@ class MCP_ChatBot:
21
  async def process_query(self, query):
22
  messages = [{'role':'user', 'content':query}]
23
  response = self.anthropic.messages.create(max_tokens = 2024,
24
- model = 'claude-3-7-sonnet-20250219',
25
  tools = self.available_tools, # tools exposed to the LLM
26
  messages = messages)
27
  process_query = True
@@ -46,7 +46,7 @@ class MCP_ChatBot:
46
  #result = execute_tool(tool_name, tool_args): not anymore needed
47
  # tool invocation through the client session
48
  result = await self.session.call_tool(tool_name, arguments=tool_args)
49
- messages.append({"role": "user",
50
  "content": [
51
  {
52
  "type": "tool_result",
@@ -56,9 +56,9 @@ class MCP_ChatBot:
56
  ]
57
  })
58
  response = self.anthropic.messages.create(max_tokens = 2024,
59
- model = 'claude-3-7-sonnet-20250219',
60
  tools = self.available_tools,
61
- messages = messages)
62
 
63
  if(len(response.content) == 1 and response.content[0].type == "text"):
64
  print(response.content[0].text)
 
21
  async def process_query(self, query):
22
  messages = [{'role':'user', 'content':query}]
23
  response = self.anthropic.messages.create(max_tokens = 2024,
24
+ model = 'claude-3-7-sonnet-20250219',
25
  tools = self.available_tools, # tools exposed to the LLM
26
  messages = messages)
27
  process_query = True
 
46
  #result = execute_tool(tool_name, tool_args): not anymore needed
47
  # tool invocation through the client session
48
  result = await self.session.call_tool(tool_name, arguments=tool_args)
49
+ messages.append({"role": "user",
50
  "content": [
51
  {
52
  "type": "tool_result",
 
56
  ]
57
  })
58
  response = self.anthropic.messages.create(max_tokens = 2024,
59
+ model = 'claude-3-7-sonnet-20250219',
60
  tools = self.available_tools,
61
+ messages = messages)
62
 
63
  if(len(response.content) == 1 and response.content[0].type == "text"):
64
  print(response.content[0].text)
mcp_chatbot_L7.py CHANGED
@@ -19,7 +19,7 @@ class MCP_ChatBot:
19
  self.anthropic = Anthropic()
20
  # Tools list required for Anthropic API
21
  self.available_tools = []
22
- # Prompts list for quick display
23
  self.available_prompts = []
24
  # Sessions dict maps tool/prompt names or resource URIs to MCP client sessions
25
  self.sessions = {}
@@ -35,8 +35,8 @@ class MCP_ChatBot:
35
  ClientSession(read, write)
36
  )
37
  await session.initialize()
38
-
39
-
40
  try:
41
  # List available tools
42
  response = await session.list_tools()
@@ -47,7 +47,7 @@ class MCP_ChatBot:
47
  "description": tool.description,
48
  "input_schema": tool.inputSchema
49
  })
50
-
51
  # List available prompts
52
  prompts_response = await session.list_prompts()
53
  if prompts_response and prompts_response.prompts:
@@ -64,10 +64,10 @@ class MCP_ChatBot:
64
  for resource in resources_response.resources:
65
  resource_uri = str(resource.uri)
66
  self.sessions[resource_uri] = session
67
-
68
  except Exception as e:
69
  print(f"Error {e}")
70
-
71
  except Exception as e:
72
  print(f"Error connecting to {server_name}: {e}")
73
 
@@ -76,28 +76,28 @@ class MCP_ChatBot:
76
  with open("server_config_L7.json", "r") as file:
77
  data = json.load(file)
78
  servers = data.get("mcpServers", {})
79
- print(f"Debug - servers: {servers}")
80
 
81
  for server_name, server_config in servers.items():
82
  await self.connect_to_server(server_name, server_config)
83
  except Exception as e:
84
  print(f"Error loading server config: {e}")
85
  raise
86
-
87
  async def process_query(self, query):
88
  messages = [{'role':'user', 'content':query}]
89
-
90
  while True:
91
  response = self.anthropic.messages.create(
92
  max_tokens = 2024,
93
- model = 'claude-3-7-sonnet-20250219',
94
  tools = self.available_tools,
95
  messages = messages
96
  )
97
-
98
  assistant_content = []
99
  has_tool_use = False
100
-
101
  for content in response.content:
102
  if content.type == 'text':
103
  print(content.text)
@@ -106,16 +106,16 @@ class MCP_ChatBot:
106
  has_tool_use = True
107
  assistant_content.append(content)
108
  messages.append({'role':'assistant', 'content':assistant_content})
109
-
110
  # Get session and call tool
111
  session = self.sessions.get(content.name)
112
  if not session:
113
  print(f"Tool '{content.name}' not found.")
114
  break
115
-
116
  result = await session.call_tool(content.name, arguments=content.input)
117
  messages.append({
118
- "role": "user",
119
  "content": [
120
  {
121
  "type": "tool_result",
@@ -124,25 +124,25 @@ class MCP_ChatBot:
124
  }
125
  ]
126
  })
127
-
128
  # Exit loop if no tool was used
129
  if not has_tool_use:
130
  break
131
 
132
  async def get_resource(self, resource_uri):
133
  session = self.sessions.get(resource_uri)
134
-
135
  # Fallback for papers URIs - try any papers resource session
136
  if not session and resource_uri.startswith("papers://"):
137
  for uri, sess in self.sessions.items():
138
  if uri.startswith("papers://"):
139
  session = sess
140
  break
141
-
142
  if not session:
143
  print(f"Resource '{resource_uri}' not found.")
144
  return
145
-
146
  try:
147
  result = await session.read_resource(uri=resource_uri)
148
  if result and result.contents:
@@ -153,13 +153,13 @@ class MCP_ChatBot:
153
  print("No content available.")
154
  except Exception as e:
155
  print(f"Error: {e}")
156
-
157
  async def list_prompts(self):
158
  """List all available prompts."""
159
  if not self.available_prompts:
160
  print("No prompts available.")
161
  return
162
-
163
  print("\nAvailable prompts:")
164
  for prompt in self.available_prompts:
165
  print(f"- {prompt['name']}: {prompt['description']}")
@@ -168,19 +168,19 @@ class MCP_ChatBot:
168
  for arg in prompt['arguments']:
169
  arg_name = arg.name if hasattr(arg, 'name') else arg.get('name', '')
170
  print(f" - {arg_name}")
171
-
172
  async def execute_prompt(self, prompt_name, args):
173
  """Execute a prompt with the given arguments."""
174
  session = self.sessions.get(prompt_name)
175
  if not session:
176
  print(f"Prompt '{prompt_name}' not found.")
177
  return
178
-
179
  try:
180
  result = await session.get_prompt(prompt_name, arguments=args)
181
  if result and result.messages:
182
  prompt_content = result.messages[0].content
183
-
184
  # Extract text from content (handles different formats)
185
  if isinstance(prompt_content, str):
186
  text = prompt_content
@@ -188,14 +188,14 @@ class MCP_ChatBot:
188
  text = prompt_content.text
189
  else:
190
  # Handle list of content items
191
- text = " ".join(item.text if hasattr(item, 'text') else str(item)
192
  for item in prompt_content)
193
-
194
  print(f"\nExecuting prompt '{prompt_name}'...")
195
  await self.process_query(text)
196
  except Exception as e:
197
  print(f"Error: {e}")
198
-
199
  async def chat_loop(self):
200
  print("\nMCP Chatbot Started 7!")
201
  print("Type your queries or 'quit' to exit.")
@@ -203,19 +203,19 @@ class MCP_ChatBot:
203
  print("Use @<topic> to search papers in that topic")
204
  print("Use /prompts to list available prompts")
205
  print("Use /prompt <name> <arg1=value1> to execute a prompt")
206
-
207
  while True:
208
  try:
209
  query = input("\nQuery: ").strip()
210
  if not query:
211
  continue
212
-
213
  if query.lower() == 'quit':
214
  break
215
-
216
  # Check for @resource syntax first
217
  if query.startswith('@'):
218
- # Remove @ sign
219
  topic = query[1:]
220
  if topic == "folders":
221
  resource_uri = "papers://folders"
@@ -223,38 +223,38 @@ class MCP_ChatBot:
223
  resource_uri = f"papers://{topic}"
224
  await self.get_resource(resource_uri)
225
  continue
226
-
227
  # Check for /command syntax
228
  if query.startswith('/'):
229
  parts = query.split()
230
  command = parts[0].lower()
231
-
232
  if command == '/prompts':
233
  await self.list_prompts()
234
  elif command == '/prompt':
235
  if len(parts) < 2:
236
  print("Usage: /prompt <name> <arg1=value1> <arg2=value2>")
237
  continue
238
-
239
  prompt_name = parts[1]
240
  args = {}
241
-
242
  # Parse arguments
243
  for arg in parts[2:]:
244
  if '=' in arg:
245
  key, value = arg.split('=', 1)
246
  args[key] = value
247
-
248
  await self.execute_prompt(prompt_name, args)
249
  else:
250
  print(f"Unknown command: {command}")
251
  continue
252
-
253
  await self.process_query(query)
254
-
255
  except Exception as e:
256
  print(f"\nError: {str(e)}")
257
-
258
  async def cleanup(self):
259
  await self.exit_stack.aclose()
260
 
@@ -269,4 +269,4 @@ async def main():
269
 
270
 
271
  if __name__ == "__main__":
272
- asyncio.run(main())
 
19
  self.anthropic = Anthropic()
20
  # Tools list required for Anthropic API
21
  self.available_tools = []
22
+ # Prompts list for quick display
23
  self.available_prompts = []
24
  # Sessions dict maps tool/prompt names or resource URIs to MCP client sessions
25
  self.sessions = {}
 
35
  ClientSession(read, write)
36
  )
37
  await session.initialize()
38
+
39
+
40
  try:
41
  # List available tools
42
  response = await session.list_tools()
 
47
  "description": tool.description,
48
  "input_schema": tool.inputSchema
49
  })
50
+
51
  # List available prompts
52
  prompts_response = await session.list_prompts()
53
  if prompts_response and prompts_response.prompts:
 
64
  for resource in resources_response.resources:
65
  resource_uri = str(resource.uri)
66
  self.sessions[resource_uri] = session
67
+
68
  except Exception as e:
69
  print(f"Error {e}")
70
+
71
  except Exception as e:
72
  print(f"Error connecting to {server_name}: {e}")
73
 
 
76
  with open("server_config_L7.json", "r") as file:
77
  data = json.load(file)
78
  servers = data.get("mcpServers", {})
79
+ print(f"Debug - servers: {servers}")
80
 
81
  for server_name, server_config in servers.items():
82
  await self.connect_to_server(server_name, server_config)
83
  except Exception as e:
84
  print(f"Error loading server config: {e}")
85
  raise
86
+
87
  async def process_query(self, query):
88
  messages = [{'role':'user', 'content':query}]
89
+
90
  while True:
91
  response = self.anthropic.messages.create(
92
  max_tokens = 2024,
93
+ model = 'claude-3-7-sonnet-20250219',
94
  tools = self.available_tools,
95
  messages = messages
96
  )
97
+
98
  assistant_content = []
99
  has_tool_use = False
100
+
101
  for content in response.content:
102
  if content.type == 'text':
103
  print(content.text)
 
106
  has_tool_use = True
107
  assistant_content.append(content)
108
  messages.append({'role':'assistant', 'content':assistant_content})
109
+
110
  # Get session and call tool
111
  session = self.sessions.get(content.name)
112
  if not session:
113
  print(f"Tool '{content.name}' not found.")
114
  break
115
+
116
  result = await session.call_tool(content.name, arguments=content.input)
117
  messages.append({
118
+ "role": "user",
119
  "content": [
120
  {
121
  "type": "tool_result",
 
124
  }
125
  ]
126
  })
127
+
128
  # Exit loop if no tool was used
129
  if not has_tool_use:
130
  break
131
 
132
  async def get_resource(self, resource_uri):
133
  session = self.sessions.get(resource_uri)
134
+
135
  # Fallback for papers URIs - try any papers resource session
136
  if not session and resource_uri.startswith("papers://"):
137
  for uri, sess in self.sessions.items():
138
  if uri.startswith("papers://"):
139
  session = sess
140
  break
141
+
142
  if not session:
143
  print(f"Resource '{resource_uri}' not found.")
144
  return
145
+
146
  try:
147
  result = await session.read_resource(uri=resource_uri)
148
  if result and result.contents:
 
153
  print("No content available.")
154
  except Exception as e:
155
  print(f"Error: {e}")
156
+
157
  async def list_prompts(self):
158
  """List all available prompts."""
159
  if not self.available_prompts:
160
  print("No prompts available.")
161
  return
162
+
163
  print("\nAvailable prompts:")
164
  for prompt in self.available_prompts:
165
  print(f"- {prompt['name']}: {prompt['description']}")
 
168
  for arg in prompt['arguments']:
169
  arg_name = arg.name if hasattr(arg, 'name') else arg.get('name', '')
170
  print(f" - {arg_name}")
171
+
172
  async def execute_prompt(self, prompt_name, args):
173
  """Execute a prompt with the given arguments."""
174
  session = self.sessions.get(prompt_name)
175
  if not session:
176
  print(f"Prompt '{prompt_name}' not found.")
177
  return
178
+
179
  try:
180
  result = await session.get_prompt(prompt_name, arguments=args)
181
  if result and result.messages:
182
  prompt_content = result.messages[0].content
183
+
184
  # Extract text from content (handles different formats)
185
  if isinstance(prompt_content, str):
186
  text = prompt_content
 
188
  text = prompt_content.text
189
  else:
190
  # Handle list of content items
191
+ text = " ".join(item.text if hasattr(item, 'text') else str(item)
192
  for item in prompt_content)
193
+
194
  print(f"\nExecuting prompt '{prompt_name}'...")
195
  await self.process_query(text)
196
  except Exception as e:
197
  print(f"Error: {e}")
198
+
199
  async def chat_loop(self):
200
  print("\nMCP Chatbot Started 7!")
201
  print("Type your queries or 'quit' to exit.")
 
203
  print("Use @<topic> to search papers in that topic")
204
  print("Use /prompts to list available prompts")
205
  print("Use /prompt <name> <arg1=value1> to execute a prompt")
206
+
207
  while True:
208
  try:
209
  query = input("\nQuery: ").strip()
210
  if not query:
211
  continue
212
+
213
  if query.lower() == 'quit':
214
  break
215
+
216
  # Check for @resource syntax first
217
  if query.startswith('@'):
218
+ # Remove @ sign
219
  topic = query[1:]
220
  if topic == "folders":
221
  resource_uri = "papers://folders"
 
223
  resource_uri = f"papers://{topic}"
224
  await self.get_resource(resource_uri)
225
  continue
226
+
227
  # Check for /command syntax
228
  if query.startswith('/'):
229
  parts = query.split()
230
  command = parts[0].lower()
231
+
232
  if command == '/prompts':
233
  await self.list_prompts()
234
  elif command == '/prompt':
235
  if len(parts) < 2:
236
  print("Usage: /prompt <name> <arg1=value1> <arg2=value2>")
237
  continue
238
+
239
  prompt_name = parts[1]
240
  args = {}
241
+
242
  # Parse arguments
243
  for arg in parts[2:]:
244
  if '=' in arg:
245
  key, value = arg.split('=', 1)
246
  args[key] = value
247
+
248
  await self.execute_prompt(prompt_name, args)
249
  else:
250
  print(f"Unknown command: {command}")
251
  continue
252
+
253
  await self.process_query(query)
254
+
255
  except Exception as e:
256
  print(f"\nError: {str(e)}")
257
+
258
  async def cleanup(self):
259
  await self.exit_stack.aclose()
260
 
 
269
 
270
 
271
  if __name__ == "__main__":
272
+ asyncio.run(main())
mcp_chatbot_v2.py CHANGED
@@ -74,7 +74,7 @@ class MCP_ChatBot:
74
  async def process_query(self, query):
75
  messages = [{'role':'user', 'content':query}]
76
  response = self.anthropic.messages.create(max_tokens = 2024,
77
- model = 'claude-3-7-sonnet-20250219',
78
  tools = self.available_tools,
79
  messages = messages)
80
  process_query = True
@@ -99,7 +99,7 @@ class MCP_ChatBot:
99
  # Call a tool
100
  session = self.tool_to_session[tool_name] # new
101
  result = await session.call_tool(tool_name, arguments=tool_args)
102
- messages.append({"role": "user",
103
  "content": [
104
  {
105
  "type": "tool_result",
@@ -109,9 +109,9 @@ class MCP_ChatBot:
109
  ]
110
  })
111
  response = self.anthropic.messages.create(max_tokens = 2024,
112
- model = 'claude-3-7-sonnet-20250219',
113
  tools = self.available_tools,
114
- messages = messages)
115
 
116
  if(len(response.content) == 1 and response.content[0].type == "text"):
117
  print(response.content[0].text)
@@ -148,10 +148,10 @@ async def main():
148
  # the mcp clients and sessions are not initialized using "with"
149
  # like in the previous lesson
150
  # so the cleanup should be manually handled
151
- await chatbot.connect_to_servers() # new!
152
  await chatbot.chat_loop()
153
  finally:
154
- await chatbot.cleanup() #new!
155
 
156
 
157
  if __name__ == "__main__":
 
74
  async def process_query(self, query):
75
  messages = [{'role':'user', 'content':query}]
76
  response = self.anthropic.messages.create(max_tokens = 2024,
77
+ model = 'claude-3-7-sonnet-20250219',
78
  tools = self.available_tools,
79
  messages = messages)
80
  process_query = True
 
99
  # Call a tool
100
  session = self.tool_to_session[tool_name] # new
101
  result = await session.call_tool(tool_name, arguments=tool_args)
102
+ messages.append({"role": "user",
103
  "content": [
104
  {
105
  "type": "tool_result",
 
109
  ]
110
  })
111
  response = self.anthropic.messages.create(max_tokens = 2024,
112
+ model = 'claude-3-7-sonnet-20250219',
113
  tools = self.available_tools,
114
+ messages = messages)
115
 
116
  if(len(response.content) == 1 and response.content[0].type == "text"):
117
  print(response.content[0].text)
 
148
  # the mcp clients and sessions are not initialized using "with"
149
  # like in the previous lesson
150
  # so the cleanup should be manually handled
151
+ await chatbot.connect_to_servers() # new!
152
  await chatbot.chat_loop()
153
  finally:
154
+ await chatbot.cleanup() #new!
155
 
156
 
157
  if __name__ == "__main__":
mcp_chatbot_v3.py CHANGED
@@ -17,7 +17,7 @@ class MCP_ChatBot:
17
  self.anthropic = Anthropic()
18
  # Tools list required for Anthropic API
19
  self.available_tools = []
20
- # Prompts list for quick display
21
  self.available_prompts = []
22
  # Sessions dict maps tool/prompt names or resource URIs to MCP client sessions
23
  self.sessions = {}
@@ -33,8 +33,8 @@ class MCP_ChatBot:
33
  ClientSession(read, write)
34
  )
35
  await session.initialize()
36
-
37
-
38
  try:
39
  # List available tools
40
  response = await session.list_tools()
@@ -45,7 +45,7 @@ class MCP_ChatBot:
45
  "description": tool.description,
46
  "input_schema": tool.inputSchema
47
  })
48
-
49
  # List available prompts
50
  prompts_response = await session.list_prompts()
51
  if prompts_response and prompts_response.prompts:
@@ -62,10 +62,10 @@ class MCP_ChatBot:
62
  for resource in resources_response.resources:
63
  resource_uri = str(resource.uri)
64
  self.sessions[resource_uri] = session
65
-
66
  except Exception as e:
67
  print(f"Error {e}")
68
-
69
  except Exception as e:
70
  print(f"Error connecting to {server_name}: {e}")
71
 
@@ -79,21 +79,21 @@ class MCP_ChatBot:
79
  except Exception as e:
80
  print(f"Error loading server config: {e}")
81
  raise
82
-
83
  async def process_query(self, query):
84
  messages = [{'role':'user', 'content':query}]
85
-
86
  while True:
87
  response = self.anthropic.messages.create(
88
  max_tokens = 2024,
89
- model = 'claude-3-7-sonnet-20250219',
90
  tools = self.available_tools,
91
  messages = messages
92
  )
93
-
94
  assistant_content = []
95
  has_tool_use = False
96
-
97
  for content in response.content:
98
  if content.type == 'text':
99
  print(content.text)
@@ -102,16 +102,16 @@ class MCP_ChatBot:
102
  has_tool_use = True
103
  assistant_content.append(content)
104
  messages.append({'role':'assistant', 'content':assistant_content})
105
-
106
  # Get session and call tool
107
  session = self.sessions.get(content.name)
108
  if not session:
109
  print(f"Tool '{content.name}' not found.")
110
  break
111
-
112
  result = await session.call_tool(content.name, arguments=content.input)
113
  messages.append({
114
- "role": "user",
115
  "content": [
116
  {
117
  "type": "tool_result",
@@ -120,25 +120,25 @@ class MCP_ChatBot:
120
  }
121
  ]
122
  })
123
-
124
  # Exit loop if no tool was used
125
  if not has_tool_use:
126
  break
127
 
128
  async def get_resource(self, resource_uri):
129
  session = self.sessions.get(resource_uri)
130
-
131
  # Fallback for papers URIs - try any papers resource session
132
  if not session and resource_uri.startswith("papers://"):
133
  for uri, sess in self.sessions.items():
134
  if uri.startswith("papers://"):
135
  session = sess
136
  break
137
-
138
  if not session:
139
  print(f"Resource '{resource_uri}' not found.")
140
  return
141
-
142
  try:
143
  result = await session.read_resource(uri=resource_uri)
144
  if result and result.contents:
@@ -149,13 +149,13 @@ class MCP_ChatBot:
149
  print("No content available.")
150
  except Exception as e:
151
  print(f"Error: {e}")
152
-
153
  async def list_prompts(self):
154
  """List all available prompts."""
155
  if not self.available_prompts:
156
  print("No prompts available.")
157
  return
158
-
159
  print("\nAvailable prompts:")
160
  for prompt in self.available_prompts:
161
  print(f"- {prompt['name']}: {prompt['description']}")
@@ -164,19 +164,19 @@ class MCP_ChatBot:
164
  for arg in prompt['arguments']:
165
  arg_name = arg.name if hasattr(arg, 'name') else arg.get('name', '')
166
  print(f" - {arg_name}")
167
-
168
  async def execute_prompt(self, prompt_name, args):
169
  """Execute a prompt with the given arguments."""
170
  session = self.sessions.get(prompt_name)
171
  if not session:
172
  print(f"Prompt '{prompt_name}' not found.")
173
  return
174
-
175
  try:
176
  result = await session.get_prompt(prompt_name, arguments=args)
177
  if result and result.messages:
178
  prompt_content = result.messages[0].content
179
-
180
  # Extract text from content (handles different formats)
181
  if isinstance(prompt_content, str):
182
  text = prompt_content
@@ -184,14 +184,14 @@ class MCP_ChatBot:
184
  text = prompt_content.text
185
  else:
186
  # Handle list of content items
187
- text = " ".join(item.text if hasattr(item, 'text') else str(item)
188
  for item in prompt_content)
189
-
190
  print(f"\nExecuting prompt '{prompt_name}'...")
191
  await self.process_query(text)
192
  except Exception as e:
193
  print(f"Error: {e}")
194
-
195
  async def chat_loop(self):
196
  print("\nMCP Chatbot Started!")
197
  print("Type your queries or 'quit' to exit.")
@@ -199,19 +199,19 @@ class MCP_ChatBot:
199
  print("Use @<topic> to search papers in that topic")
200
  print("Use /prompts to list available prompts")
201
  print("Use /prompt <name> <arg1=value1> to execute a prompt")
202
-
203
  while True:
204
  try:
205
  query = input("\nQuery: ").strip()
206
  if not query:
207
  continue
208
-
209
  if query.lower() == 'quit':
210
  break
211
-
212
  # Check for @resource syntax first
213
  if query.startswith('@'):
214
- # Remove @ sign
215
  topic = query[1:]
216
  if topic == "folders":
217
  resource_uri = "papers://folders"
@@ -219,38 +219,38 @@ class MCP_ChatBot:
219
  resource_uri = f"papers://{topic}"
220
  await self.get_resource(resource_uri)
221
  continue
222
-
223
  # Check for /command syntax
224
  if query.startswith('/'):
225
  parts = query.split()
226
  command = parts[0].lower()
227
-
228
  if command == '/prompts':
229
  await self.list_prompts()
230
  elif command == '/prompt':
231
  if len(parts) < 2:
232
  print("Usage: /prompt <name> <arg1=value1> <arg2=value2>")
233
  continue
234
-
235
  prompt_name = parts[1]
236
  args = {}
237
-
238
  # Parse arguments
239
  for arg in parts[2:]:
240
  if '=' in arg:
241
  key, value = arg.split('=', 1)
242
  args[key] = value
243
-
244
  await self.execute_prompt(prompt_name, args)
245
  else:
246
  print(f"Unknown command: {command}")
247
  continue
248
-
249
  await self.process_query(query)
250
-
251
  except Exception as e:
252
  print(f"\nError: {str(e)}")
253
-
254
  async def cleanup(self):
255
  await self.exit_stack.aclose()
256
 
@@ -265,4 +265,4 @@ async def main():
265
 
266
 
267
  if __name__ == "__main__":
268
- asyncio.run(main())
 
17
  self.anthropic = Anthropic()
18
  # Tools list required for Anthropic API
19
  self.available_tools = []
20
+ # Prompts list for quick display
21
  self.available_prompts = []
22
  # Sessions dict maps tool/prompt names or resource URIs to MCP client sessions
23
  self.sessions = {}
 
33
  ClientSession(read, write)
34
  )
35
  await session.initialize()
36
+
37
+
38
  try:
39
  # List available tools
40
  response = await session.list_tools()
 
45
  "description": tool.description,
46
  "input_schema": tool.inputSchema
47
  })
48
+
49
  # List available prompts
50
  prompts_response = await session.list_prompts()
51
  if prompts_response and prompts_response.prompts:
 
62
  for resource in resources_response.resources:
63
  resource_uri = str(resource.uri)
64
  self.sessions[resource_uri] = session
65
+
66
  except Exception as e:
67
  print(f"Error {e}")
68
+
69
  except Exception as e:
70
  print(f"Error connecting to {server_name}: {e}")
71
 
 
79
  except Exception as e:
80
  print(f"Error loading server config: {e}")
81
  raise
82
+
83
  async def process_query(self, query):
84
  messages = [{'role':'user', 'content':query}]
85
+
86
  while True:
87
  response = self.anthropic.messages.create(
88
  max_tokens = 2024,
89
+ model = 'claude-3-7-sonnet-20250219',
90
  tools = self.available_tools,
91
  messages = messages
92
  )
93
+
94
  assistant_content = []
95
  has_tool_use = False
96
+
97
  for content in response.content:
98
  if content.type == 'text':
99
  print(content.text)
 
102
  has_tool_use = True
103
  assistant_content.append(content)
104
  messages.append({'role':'assistant', 'content':assistant_content})
105
+
106
  # Get session and call tool
107
  session = self.sessions.get(content.name)
108
  if not session:
109
  print(f"Tool '{content.name}' not found.")
110
  break
111
+
112
  result = await session.call_tool(content.name, arguments=content.input)
113
  messages.append({
114
+ "role": "user",
115
  "content": [
116
  {
117
  "type": "tool_result",
 
120
  }
121
  ]
122
  })
123
+
124
  # Exit loop if no tool was used
125
  if not has_tool_use:
126
  break
127
 
128
  async def get_resource(self, resource_uri):
129
  session = self.sessions.get(resource_uri)
130
+
131
  # Fallback for papers URIs - try any papers resource session
132
  if not session and resource_uri.startswith("papers://"):
133
  for uri, sess in self.sessions.items():
134
  if uri.startswith("papers://"):
135
  session = sess
136
  break
137
+
138
  if not session:
139
  print(f"Resource '{resource_uri}' not found.")
140
  return
141
+
142
  try:
143
  result = await session.read_resource(uri=resource_uri)
144
  if result and result.contents:
 
149
  print("No content available.")
150
  except Exception as e:
151
  print(f"Error: {e}")
152
+
153
  async def list_prompts(self):
154
  """List all available prompts."""
155
  if not self.available_prompts:
156
  print("No prompts available.")
157
  return
158
+
159
  print("\nAvailable prompts:")
160
  for prompt in self.available_prompts:
161
  print(f"- {prompt['name']}: {prompt['description']}")
 
164
  for arg in prompt['arguments']:
165
  arg_name = arg.name if hasattr(arg, 'name') else arg.get('name', '')
166
  print(f" - {arg_name}")
167
+
168
  async def execute_prompt(self, prompt_name, args):
169
  """Execute a prompt with the given arguments."""
170
  session = self.sessions.get(prompt_name)
171
  if not session:
172
  print(f"Prompt '{prompt_name}' not found.")
173
  return
174
+
175
  try:
176
  result = await session.get_prompt(prompt_name, arguments=args)
177
  if result and result.messages:
178
  prompt_content = result.messages[0].content
179
+
180
  # Extract text from content (handles different formats)
181
  if isinstance(prompt_content, str):
182
  text = prompt_content
 
184
  text = prompt_content.text
185
  else:
186
  # Handle list of content items
187
+ text = " ".join(item.text if hasattr(item, 'text') else str(item)
188
  for item in prompt_content)
189
+
190
  print(f"\nExecuting prompt '{prompt_name}'...")
191
  await self.process_query(text)
192
  except Exception as e:
193
  print(f"Error: {e}")
194
+
195
  async def chat_loop(self):
196
  print("\nMCP Chatbot Started!")
197
  print("Type your queries or 'quit' to exit.")
 
199
  print("Use @<topic> to search papers in that topic")
200
  print("Use /prompts to list available prompts")
201
  print("Use /prompt <name> <arg1=value1> to execute a prompt")
202
+
203
  while True:
204
  try:
205
  query = input("\nQuery: ").strip()
206
  if not query:
207
  continue
208
+
209
  if query.lower() == 'quit':
210
  break
211
+
212
  # Check for @resource syntax first
213
  if query.startswith('@'):
214
+ # Remove @ sign
215
  topic = query[1:]
216
  if topic == "folders":
217
  resource_uri = "papers://folders"
 
219
  resource_uri = f"papers://{topic}"
220
  await self.get_resource(resource_uri)
221
  continue
222
+
223
  # Check for /command syntax
224
  if query.startswith('/'):
225
  parts = query.split()
226
  command = parts[0].lower()
227
+
228
  if command == '/prompts':
229
  await self.list_prompts()
230
  elif command == '/prompt':
231
  if len(parts) < 2:
232
  print("Usage: /prompt <name> <arg1=value1> <arg2=value2>")
233
  continue
234
+
235
  prompt_name = parts[1]
236
  args = {}
237
+
238
  # Parse arguments
239
  for arg in parts[2:]:
240
  if '=' in arg:
241
  key, value = arg.split('=', 1)
242
  args[key] = value
243
+
244
  await self.execute_prompt(prompt_name, args)
245
  else:
246
  print(f"Unknown command: {command}")
247
  continue
248
+
249
  await self.process_query(query)
250
+
251
  except Exception as e:
252
  print(f"\nError: {str(e)}")
253
+
254
  async def cleanup(self):
255
  await self.exit_stack.aclose()
256
 
 
265
 
266
 
267
  if __name__ == "__main__":
268
+ asyncio.run(main())
mcp_diagram.txt CHANGED
@@ -58,4 +58,4 @@
58
  | - Resources | | - Elicitation |
59
  | - Prompts | | - Logging |
60
  +--------------------+ +----------------------+
61
- ```
 
58
  | - Resources | | - Elicitation |
59
  | - Prompts | | - Logging |
60
  +--------------------+ +----------------------+
61
+ ```
mcp_summary.md CHANGED
@@ -63,4 +63,4 @@ Each primitive type has associated methods for discovery (`*/list`), retrieval (
63
 
64
  #### Notifications
65
 
66
- The protocol supports real-time notifications to enable dynamic updates between servers and clients, sent as JSON-RPC 2.0 notification messages without expecting a response.
 
63
 
64
  #### Notifications
65
 
66
+ The protocol supports real-time notifications to enable dynamic updates between servers and clients, sent as JSON-RPC 2.0 notification messages without expecting a response.
papers/algebra/papers_info.json CHANGED
@@ -45,4 +45,4 @@
45
  "pdf_url": "http://arxiv.org/pdf/math/0506093v1",
46
  "published": "2005-06-06"
47
  }
48
- }
 
45
  "pdf_url": "http://arxiv.org/pdf/math/0506093v1",
46
  "published": "2005-06-06"
47
  }
48
+ }
papers/artificial_intelligence/papers_info.json CHANGED
@@ -47,4 +47,4 @@
47
  "pdf_url": "http://arxiv.org/pdf/1304.3846v1",
48
  "published": "2013-04-13"
49
  }
50
- }
 
47
  "pdf_url": "http://arxiv.org/pdf/1304.3846v1",
48
  "published": "2013-04-13"
49
  }
50
+ }
papers/chemistry/papers_info.json CHANGED
@@ -68,4 +68,4 @@
68
  "pdf_url": "http://arxiv.org/pdf/2109.12552v1",
69
  "published": "2021-09-26"
70
  }
71
- }
 
68
  "pdf_url": "http://arxiv.org/pdf/2109.12552v1",
69
  "published": "2021-09-26"
70
  }
71
+ }
papers/computers/papers_info.json CHANGED
@@ -47,4 +47,4 @@
47
  "pdf_url": "http://arxiv.org/pdf/2403.03925v1",
48
  "published": "2024-03-06"
49
  }
50
- }
 
47
  "pdf_url": "http://arxiv.org/pdf/2403.03925v1",
48
  "published": "2024-03-06"
49
  }
50
+ }
papers/deepseek/papers_info.json CHANGED
@@ -24,4 +24,4 @@
24
  "pdf_url": "http://arxiv.org/pdf/2503.00624v1",
25
  "published": "2025-03-01"
26
  }
27
- }
 
24
  "pdf_url": "http://arxiv.org/pdf/2503.00624v1",
25
  "published": "2025-03-01"
26
  }
27
+ }
papers/gpt-5/papers_info.json CHANGED
@@ -22,4 +22,4 @@
22
  "pdf_url": "http://arxiv.org/pdf/2508.19259v1",
23
  "published": "2025-08-16"
24
  }
25
- }
 
22
  "pdf_url": "http://arxiv.org/pdf/2508.19259v1",
23
  "published": "2025-08-16"
24
  }
25
+ }
papers/intelligence/papers_info.json CHANGED
@@ -52,4 +52,4 @@
52
  "pdf_url": "http://arxiv.org/pdf/2409.14496v1",
53
  "published": "2024-09-22"
54
  }
55
- }
 
52
  "pdf_url": "http://arxiv.org/pdf/2409.14496v1",
53
  "published": "2024-09-22"
54
  }
55
+ }
papers/large_language_model/papers_info.json CHANGED
@@ -50,4 +50,4 @@
50
  "pdf_url": "http://arxiv.org/pdf/2404.09579v1",
51
  "published": "2024-04-15"
52
  }
53
- }
 
50
  "pdf_url": "http://arxiv.org/pdf/2404.09579v1",
51
  "published": "2024-04-15"
52
  }
53
+ }
papers/large_language_models/papers_info.json CHANGED
@@ -50,4 +50,4 @@
50
  "pdf_url": "http://arxiv.org/pdf/2404.09579v1",
51
  "published": "2024-04-15"
52
  }
53
- }
 
50
  "pdf_url": "http://arxiv.org/pdf/2404.09579v1",
51
  "published": "2024-04-15"
52
  }
53
+ }
papers/llm_evaluation/papers_info.json CHANGED
@@ -30,4 +30,4 @@
30
  "pdf_url": "http://arxiv.org/pdf/2410.07069v1",
31
  "published": "2024-10-09"
32
  }
33
- }
 
30
  "pdf_url": "http://arxiv.org/pdf/2410.07069v1",
31
  "published": "2024-10-09"
32
  }
33
+ }
papers/physics/papers_info.json CHANGED
@@ -50,4 +50,4 @@
50
  "pdf_url": "http://arxiv.org/pdf/1405.5530v1",
51
  "published": "2014-05-22"
52
  }
53
- }
 
50
  "pdf_url": "http://arxiv.org/pdf/1405.5530v1",
51
  "published": "2014-05-22"
52
  }
53
+ }
papers/transformer_attention_nlp/papers_info.json CHANGED
@@ -36,4 +36,4 @@
36
  "pdf_url": "http://arxiv.org/pdf/2202.07856v2",
37
  "published": "2022-02-16"
38
  }
39
- }
 
36
  "pdf_url": "http://arxiv.org/pdf/2202.07856v2",
37
  "published": "2022-02-16"
38
  }
39
+ }
papers/transformer_neural_networks/papers_info.json CHANGED
@@ -33,4 +33,4 @@
33
  "pdf_url": "http://arxiv.org/pdf/2112.12345v1",
34
  "published": "2021-12-23"
35
  }
36
- }
 
33
  "pdf_url": "http://arxiv.org/pdf/2112.12345v1",
34
  "published": "2021-12-23"
35
  }
36
+ }
papers/transformers/papers_info.json CHANGED
@@ -27,4 +27,4 @@
27
  "pdf_url": "http://arxiv.org/pdf/1605.08683v1",
28
  "published": "2016-05-27"
29
  }
30
- }
 
27
  "pdf_url": "http://arxiv.org/pdf/1605.08683v1",
28
  "published": "2016-05-27"
29
  }
30
+ }
research_server.py CHANGED
@@ -15,16 +15,16 @@ mcp = FastMCP("research")
15
  def search_papers(topic: str, max_results: int = 5) -> List[str]:
16
  """
17
  Search for papers on arXiv based on a topic and store their information.
18
-
19
  Args:
20
  topic: The topic to search for
21
  max_results: Maximum number of results to retrieve (default: 5)
22
-
23
  Returns:
24
  List of paper IDs found in the search
25
  """
26
-
27
- # Use arxiv to find the papers
28
  client = arxiv.Client()
29
 
30
  # Search for the most relevant articles matching the queried topic
@@ -35,11 +35,11 @@ def search_papers(topic: str, max_results: int = 5) -> List[str]:
35
  )
36
 
37
  papers = client.results(search)
38
-
39
  # Create directory for this topic
40
  path = os.path.join(PAPER_DIR, topic.lower().replace(" ", "_"))
41
  os.makedirs(path, exist_ok=True)
42
-
43
  file_path = os.path.join(path, "papers_info.json")
44
 
45
  # Try to load existing papers info
@@ -49,7 +49,7 @@ def search_papers(topic: str, max_results: int = 5) -> List[str]:
49
  except (FileNotFoundError, json.JSONDecodeError):
50
  papers_info = {}
51
 
52
- # Process each paper and add to papers_info
53
  paper_ids = []
54
  for paper in papers:
55
  paper_ids.append(paper.get_short_id())
@@ -61,27 +61,27 @@ def search_papers(topic: str, max_results: int = 5) -> List[str]:
61
  'published': str(paper.published.date())
62
  }
63
  papers_info[paper.get_short_id()] = paper_info
64
-
65
  # Save updated papers_info to json file
66
  with open(file_path, "w") as json_file:
67
  json.dump(papers_info, json_file, indent=2)
68
-
69
  print(f"Results are saved in: {file_path}")
70
-
71
  return paper_ids
72
 
73
  @mcp.tool()
74
  def extract_info(paper_id: str) -> str:
75
  """
76
  Search for information about a specific paper across all topic directories.
77
-
78
  Args:
79
  paper_id: The ID of the paper to look for
80
-
81
  Returns:
82
  JSON string with paper information if found, error message if not found
83
  """
84
-
85
  for item in os.listdir(PAPER_DIR):
86
  item_path = os.path.join(PAPER_DIR, item)
87
  if os.path.isdir(item_path):
@@ -95,7 +95,7 @@ def extract_info(paper_id: str) -> str:
95
  except (FileNotFoundError, json.JSONDecodeError) as e:
96
  print(f"Error reading {file_path}: {str(e)}")
97
  continue
98
-
99
  return f"There's no saved information related to paper {paper_id}."
100
 
101
 
 
15
  def search_papers(topic: str, max_results: int = 5) -> List[str]:
16
  """
17
  Search for papers on arXiv based on a topic and store their information.
18
+
19
  Args:
20
  topic: The topic to search for
21
  max_results: Maximum number of results to retrieve (default: 5)
22
+
23
  Returns:
24
  List of paper IDs found in the search
25
  """
26
+
27
+ # Use arxiv to find the papers
28
  client = arxiv.Client()
29
 
30
  # Search for the most relevant articles matching the queried topic
 
35
  )
36
 
37
  papers = client.results(search)
38
+
39
  # Create directory for this topic
40
  path = os.path.join(PAPER_DIR, topic.lower().replace(" ", "_"))
41
  os.makedirs(path, exist_ok=True)
42
+
43
  file_path = os.path.join(path, "papers_info.json")
44
 
45
  # Try to load existing papers info
 
49
  except (FileNotFoundError, json.JSONDecodeError):
50
  papers_info = {}
51
 
52
+ # Process each paper and add to papers_info
53
  paper_ids = []
54
  for paper in papers:
55
  paper_ids.append(paper.get_short_id())
 
61
  'published': str(paper.published.date())
62
  }
63
  papers_info[paper.get_short_id()] = paper_info
64
+
65
  # Save updated papers_info to json file
66
  with open(file_path, "w") as json_file:
67
  json.dump(papers_info, json_file, indent=2)
68
+
69
  print(f"Results are saved in: {file_path}")
70
+
71
  return paper_ids
72
 
73
  @mcp.tool()
74
  def extract_info(paper_id: str) -> str:
75
  """
76
  Search for information about a specific paper across all topic directories.
77
+
78
  Args:
79
  paper_id: The ID of the paper to look for
80
+
81
  Returns:
82
  JSON string with paper information if found, error message if not found
83
  """
84
+
85
  for item in os.listdir(PAPER_DIR):
86
  item_path = os.path.join(PAPER_DIR, item)
87
  if os.path.isdir(item_path):
 
95
  except (FileNotFoundError, json.JSONDecodeError) as e:
96
  print(f"Error reading {file_path}: {str(e)}")
97
  continue
98
+
99
  return f"There's no saved information related to paper {paper_id}."
100
 
101
 
research_server_L7.py CHANGED
@@ -38,16 +38,16 @@ mcp = FastMCP("research")
38
  def search_papers(topic: str, max_results: int = 5) -> List[str]:
39
  """
40
  Search for papers on arXiv based on a topic and store their information.
41
-
42
  Args:
43
  topic: The topic to search for
44
  max_results: Maximum number of results to retrieve (default: 5)
45
-
46
  Returns:
47
  List of paper IDs found in the search
48
  """
49
-
50
- # Use arxiv to find the papers
51
  client = arxiv.Client()
52
 
53
  # Search for the most relevant articles matching the queried topic
@@ -58,11 +58,11 @@ def search_papers(topic: str, max_results: int = 5) -> List[str]:
58
  )
59
 
60
  papers = client.results(search)
61
-
62
  # Create directory for this topic
63
  path = os.path.join(PAPER_DIR, topic.lower().replace(" ", "_"))
64
  os.makedirs(path, exist_ok=True)
65
-
66
  file_path = os.path.join(path, "papers_info.json")
67
 
68
  # Try to load existing papers info
@@ -72,7 +72,7 @@ def search_papers(topic: str, max_results: int = 5) -> List[str]:
72
  except (FileNotFoundError, json.JSONDecodeError):
73
  papers_info = {}
74
 
75
- # Process each paper and add to papers_info
76
  paper_ids = []
77
  for paper in papers:
78
  paper_ids.append(paper.get_short_id())
@@ -84,27 +84,27 @@ def search_papers(topic: str, max_results: int = 5) -> List[str]:
84
  'published': str(paper.published.date())
85
  }
86
  papers_info[paper.get_short_id()] = paper_info
87
-
88
  # Save updated papers_info to json file
89
  with open(file_path, "w") as json_file:
90
  json.dump(papers_info, json_file, indent=2)
91
-
92
  print(f"Results are saved in: {file_path}")
93
-
94
  return paper_ids
95
 
96
  @mcp.tool()
97
  def extract_info(paper_id: str) -> str:
98
  """
99
  Search for information about a specific paper across all topic directories.
100
-
101
  Args:
102
  paper_id: The ID of the paper to look for
103
-
104
  Returns:
105
  JSON string with paper information if found, error message if not found
106
  """
107
-
108
  for item in os.listdir(PAPER_DIR):
109
  item_path = os.path.join(PAPER_DIR, item)
110
  if os.path.isdir(item_path):
@@ -118,7 +118,7 @@ def extract_info(paper_id: str) -> str:
118
  except (FileNotFoundError, json.JSONDecodeError) as e:
119
  print(f"Error reading {file_path}: {str(e)}")
120
  continue
121
-
122
  return f"There's no saved information related to paper {paper_id}."
123
 
124
 
@@ -127,11 +127,11 @@ def extract_info(paper_id: str) -> str:
127
  def get_available_folders() -> str:
128
  """
129
  List all available topic folders in the papers directory.
130
-
131
  This resource provides a simple list of all available topic folders.
132
  """
133
  folders = []
134
-
135
  # Get all topic directories
136
  if os.path.exists(PAPER_DIR):
137
  for topic_dir in os.listdir(PAPER_DIR):
@@ -141,7 +141,7 @@ def get_available_folders() -> str:
141
  papers_file = os.path.join(topic_path, "papers_info.json")
142
  if os.path.exists(papers_file):
143
  folders.append(topic_dir)
144
-
145
  # Create a simple markdown list
146
  content = "# Available Topics\n\n"
147
  if folders:
@@ -150,31 +150,31 @@ def get_available_folders() -> str:
150
  content += f"\nUse @{folder} to access papers in that topic.\n"
151
  else:
152
  content += "No topics found.\n"
153
-
154
  return content
155
 
156
  @mcp.resource("papers://{topic}")
157
  def get_topic_papers(topic: str) -> str:
158
  """
159
  Get detailed information about papers on a specific topic.
160
-
161
  Args:
162
  topic: The research topic to retrieve papers for
163
  """
164
  topic_dir = topic.lower().replace(" ", "_")
165
  papers_file = os.path.join(PAPER_DIR, topic_dir, "papers_info.json")
166
-
167
  if not os.path.exists(papers_file):
168
  return f"# No papers found for topic: {topic}\n\nTry searching for papers on this topic first."
169
-
170
  try:
171
  with open(papers_file, 'r') as f:
172
  papers_data = json.load(f)
173
-
174
  # Create markdown content with paper details
175
  content = f"# Papers on {topic.replace('_', ' ').title()}\n\n"
176
  content += f"Total papers: {len(papers_data)}\n\n"
177
-
178
  for paper_id, paper_info in papers_data.items():
179
  content += f"## {paper_info['title']}\n"
180
  content += f"- **Paper ID**: {paper_id}\n"
@@ -183,7 +183,7 @@ def get_topic_papers(topic: str) -> str:
183
  content += f"- **PDF URL**: [{paper_info['pdf_url']}]({paper_info['pdf_url']})\n\n"
184
  content += f"### Summary\n{paper_info['summary'][:500]}...\n\n"
185
  content += "---\n\n"
186
-
187
  return content
188
  except json.JSONDecodeError:
189
  return f"# Error reading papers data for {topic}\n\nThe papers data file is corrupted."
@@ -191,7 +191,7 @@ def get_topic_papers(topic: str) -> str:
191
  @mcp.prompt()
192
  def generate_search_prompt(topic: str, num_papers: int = 5) -> str:
193
  """Generate a prompt for Claude to find and discuss academic papers on a specific topic."""
194
- return f"""Search for {num_papers} academic papers about '{topic}' using the search_papers tool.
195
 
196
  Follow these instructions:
197
  1. First, search for papers using search_papers(topic='{topic}', max_results={num_papers})
@@ -216,4 +216,4 @@ Please present both detailed information about each paper and a high-level synth
216
 
217
  if __name__ == "__main__":
218
  # Initialize and run the server
219
- mcp.run(transport='stdio')
 
38
  def search_papers(topic: str, max_results: int = 5) -> List[str]:
39
  """
40
  Search for papers on arXiv based on a topic and store their information.
41
+
42
  Args:
43
  topic: The topic to search for
44
  max_results: Maximum number of results to retrieve (default: 5)
45
+
46
  Returns:
47
  List of paper IDs found in the search
48
  """
49
+
50
+ # Use arxiv to find the papers
51
  client = arxiv.Client()
52
 
53
  # Search for the most relevant articles matching the queried topic
 
58
  )
59
 
60
  papers = client.results(search)
61
+
62
  # Create directory for this topic
63
  path = os.path.join(PAPER_DIR, topic.lower().replace(" ", "_"))
64
  os.makedirs(path, exist_ok=True)
65
+
66
  file_path = os.path.join(path, "papers_info.json")
67
 
68
  # Try to load existing papers info
 
72
  except (FileNotFoundError, json.JSONDecodeError):
73
  papers_info = {}
74
 
75
+ # Process each paper and add to papers_info
76
  paper_ids = []
77
  for paper in papers:
78
  paper_ids.append(paper.get_short_id())
 
84
  'published': str(paper.published.date())
85
  }
86
  papers_info[paper.get_short_id()] = paper_info
87
+
88
  # Save updated papers_info to json file
89
  with open(file_path, "w") as json_file:
90
  json.dump(papers_info, json_file, indent=2)
91
+
92
  print(f"Results are saved in: {file_path}")
93
+
94
  return paper_ids
95
 
96
  @mcp.tool()
97
  def extract_info(paper_id: str) -> str:
98
  """
99
  Search for information about a specific paper across all topic directories.
100
+
101
  Args:
102
  paper_id: The ID of the paper to look for
103
+
104
  Returns:
105
  JSON string with paper information if found, error message if not found
106
  """
107
+
108
  for item in os.listdir(PAPER_DIR):
109
  item_path = os.path.join(PAPER_DIR, item)
110
  if os.path.isdir(item_path):
 
118
  except (FileNotFoundError, json.JSONDecodeError) as e:
119
  print(f"Error reading {file_path}: {str(e)}")
120
  continue
121
+
122
  return f"There's no saved information related to paper {paper_id}."
123
 
124
 
 
127
  def get_available_folders() -> str:
128
  """
129
  List all available topic folders in the papers directory.
130
+
131
  This resource provides a simple list of all available topic folders.
132
  """
133
  folders = []
134
+
135
  # Get all topic directories
136
  if os.path.exists(PAPER_DIR):
137
  for topic_dir in os.listdir(PAPER_DIR):
 
141
  papers_file = os.path.join(topic_path, "papers_info.json")
142
  if os.path.exists(papers_file):
143
  folders.append(topic_dir)
144
+
145
  # Create a simple markdown list
146
  content = "# Available Topics\n\n"
147
  if folders:
 
150
  content += f"\nUse @{folder} to access papers in that topic.\n"
151
  else:
152
  content += "No topics found.\n"
153
+
154
  return content
155
 
156
  @mcp.resource("papers://{topic}")
157
  def get_topic_papers(topic: str) -> str:
158
  """
159
  Get detailed information about papers on a specific topic.
160
+
161
  Args:
162
  topic: The research topic to retrieve papers for
163
  """
164
  topic_dir = topic.lower().replace(" ", "_")
165
  papers_file = os.path.join(PAPER_DIR, topic_dir, "papers_info.json")
166
+
167
  if not os.path.exists(papers_file):
168
  return f"# No papers found for topic: {topic}\n\nTry searching for papers on this topic first."
169
+
170
  try:
171
  with open(papers_file, 'r') as f:
172
  papers_data = json.load(f)
173
+
174
  # Create markdown content with paper details
175
  content = f"# Papers on {topic.replace('_', ' ').title()}\n\n"
176
  content += f"Total papers: {len(papers_data)}\n\n"
177
+
178
  for paper_id, paper_info in papers_data.items():
179
  content += f"## {paper_info['title']}\n"
180
  content += f"- **Paper ID**: {paper_id}\n"
 
183
  content += f"- **PDF URL**: [{paper_info['pdf_url']}]({paper_info['pdf_url']})\n\n"
184
  content += f"### Summary\n{paper_info['summary'][:500]}...\n\n"
185
  content += "---\n\n"
186
+
187
  return content
188
  except json.JSONDecodeError:
189
  return f"# Error reading papers data for {topic}\n\nThe papers data file is corrupted."
 
191
  @mcp.prompt()
192
  def generate_search_prompt(topic: str, num_papers: int = 5) -> str:
193
  """Generate a prompt for Claude to find and discuss academic papers on a specific topic."""
194
+ return f"""Search for {num_papers} academic papers about '{topic}' using the search_papers tool.
195
 
196
  Follow these instructions:
197
  1. First, search for papers using search_papers(topic='{topic}', max_results={num_papers})
 
216
 
217
  if __name__ == "__main__":
218
  # Initialize and run the server
219
+ mcp.run(transport='stdio')
research_server_L9.py CHANGED
@@ -18,16 +18,16 @@ mcp = FastMCP("research", port=8001)
18
  def search_papers(topic: str, max_results: int = 5) -> List[str]:
19
  """
20
  Search for papers on arXiv based on a topic and store their information.
21
-
22
  Args:
23
  topic: The topic to search for
24
  max_results: Maximum number of results to retrieve (default: 5)
25
-
26
  Returns:
27
  List of paper IDs found in the search
28
  """
29
-
30
- # Use arxiv to find the papers
31
  client = arxiv.Client()
32
 
33
  # Search for the most relevant articles matching the queried topic
@@ -38,11 +38,11 @@ def search_papers(topic: str, max_results: int = 5) -> List[str]:
38
  )
39
 
40
  papers = client.results(search)
41
-
42
  # Create directory for this topic
43
  path = os.path.join(PAPER_DIR, topic.lower().replace(" ", "_"))
44
  os.makedirs(path, exist_ok=True)
45
-
46
  file_path = os.path.join(path, "papers_info.json")
47
 
48
  # Try to load existing papers info
@@ -52,7 +52,7 @@ def search_papers(topic: str, max_results: int = 5) -> List[str]:
52
  except (FileNotFoundError, json.JSONDecodeError):
53
  papers_info = {}
54
 
55
- # Process each paper and add to papers_info
56
  paper_ids = []
57
  for paper in papers:
58
  paper_ids.append(paper.get_short_id())
@@ -64,27 +64,27 @@ def search_papers(topic: str, max_results: int = 5) -> List[str]:
64
  'published': str(paper.published.date())
65
  }
66
  papers_info[paper.get_short_id()] = paper_info
67
-
68
  # Save updated papers_info to json file
69
  with open(file_path, "w") as json_file:
70
  json.dump(papers_info, json_file, indent=2)
71
-
72
  print(f"Results are saved in: {file_path}")
73
-
74
  return paper_ids
75
 
76
  @mcp.tool()
77
  def extract_info(paper_id: str) -> str:
78
  """
79
  Search for information about a specific paper across all topic directories.
80
-
81
  Args:
82
  paper_id: The ID of the paper to look for
83
-
84
  Returns:
85
  JSON string with paper information if found, error message if not found
86
  """
87
-
88
  for item in os.listdir(PAPER_DIR):
89
  item_path = os.path.join(PAPER_DIR, item)
90
  if os.path.isdir(item_path):
@@ -98,7 +98,7 @@ def extract_info(paper_id: str) -> str:
98
  except (FileNotFoundError, json.JSONDecodeError) as e:
99
  print(f"Error reading {file_path}: {str(e)}")
100
  continue
101
-
102
  return f"There's no saved information related to paper {paper_id}."
103
 
104
 
@@ -107,11 +107,11 @@ def extract_info(paper_id: str) -> str:
107
  def get_available_folders() -> str:
108
  """
109
  List all available topic folders in the papers directory.
110
-
111
  This resource provides a simple list of all available topic folders.
112
  """
113
  folders = []
114
-
115
  # Get all topic directories
116
  if os.path.exists(PAPER_DIR):
117
  for topic_dir in os.listdir(PAPER_DIR):
@@ -120,7 +120,7 @@ def get_available_folders() -> str:
120
  papers_file = os.path.join(topic_path, "papers_info.json")
121
  if os.path.exists(papers_file):
122
  folders.append(topic_dir)
123
-
124
  # Create a simple markdown list
125
  content = "# Available Topics\n\n"
126
  if folders:
@@ -129,31 +129,31 @@ def get_available_folders() -> str:
129
  content += f"\nUse @{folder} to access papers in that topic.\n"
130
  else:
131
  content += "No topics found.\n"
132
-
133
  return content
134
 
135
  @mcp.resource("papers://{topic}")
136
  def get_topic_papers(topic: str) -> str:
137
  """
138
  Get detailed information about papers on a specific topic.
139
-
140
  Args:
141
  topic: The research topic to retrieve papers for
142
  """
143
  topic_dir = topic.lower().replace(" ", "_")
144
  papers_file = os.path.join(PAPER_DIR, topic_dir, "papers_info.json")
145
-
146
  if not os.path.exists(papers_file):
147
  return f"# No papers found for topic: {topic}\n\nTry searching for papers on this topic first."
148
-
149
  try:
150
  with open(papers_file, 'r') as f:
151
  papers_data = json.load(f)
152
-
153
  # Create markdown content with paper details
154
  content = f"# Papers on {topic.replace('_', ' ').title()}\n\n"
155
  content += f"Total papers: {len(papers_data)}\n\n"
156
-
157
  for paper_id, paper_info in papers_data.items():
158
  content += f"## {paper_info['title']}\n"
159
  content += f"- **Paper ID**: {paper_id}\n"
@@ -162,7 +162,7 @@ def get_topic_papers(topic: str) -> str:
162
  content += f"- **PDF URL**: [{paper_info['pdf_url']}]({paper_info['pdf_url']})\n\n"
163
  content += f"### Summary\n{paper_info['summary'][:500]}...\n\n"
164
  content += "---\n\n"
165
-
166
  return content
167
  except json.JSONDecodeError:
168
  return f"# Error reading papers data for {topic}\n\nThe papers data file is corrupted."
@@ -170,7 +170,7 @@ def get_topic_papers(topic: str) -> str:
170
  @mcp.prompt()
171
  def generate_search_prompt(topic: str, num_papers: int = 5) -> str:
172
  """Generate a prompt for Claude to find and discuss academic papers on a specific topic."""
173
- return f"""Search for {num_papers} academic papers about '{topic}' using the search_papers tool.
174
 
175
  Follow these instructions:
176
  1. First, search for papers using search_papers(topic='{topic}', max_results={num_papers})
@@ -182,18 +182,24 @@ def generate_search_prompt(topic: str, num_papers: int = 5) -> str:
182
  - Main contributions or innovations
183
  - Methodologies used
184
  - Relevance to the topic '{topic}'
185
-
186
  3. Provide a comprehensive summary that includes:
187
  - Overview of the current state of research in '{topic}'
188
  - Common themes and trends across the papers
189
  - Key research gaps or areas for future investigation
190
  - Most impactful or influential papers in this area
191
-
192
  4. Organize your findings in a clear, structured format with headings and bullet points for easy readability.
193
-
194
  Please present both detailed information about each paper and a high-level synthesis of the research landscape in {topic}."""
195
 
196
  if __name__ == "__main__":
197
  import os
198
- port = int(os.environ.get("PORT", "8000")) # Render sets PORT for you
199
- mcp.run(transport="sse", host="0.0.0.0", port=port)
 
 
 
 
 
 
 
18
  def search_papers(topic: str, max_results: int = 5) -> List[str]:
19
  """
20
  Search for papers on arXiv based on a topic and store their information.
21
+
22
  Args:
23
  topic: The topic to search for
24
  max_results: Maximum number of results to retrieve (default: 5)
25
+
26
  Returns:
27
  List of paper IDs found in the search
28
  """
29
+
30
+ # Use arxiv to find the papers
31
  client = arxiv.Client()
32
 
33
  # Search for the most relevant articles matching the queried topic
 
38
  )
39
 
40
  papers = client.results(search)
41
+
42
  # Create directory for this topic
43
  path = os.path.join(PAPER_DIR, topic.lower().replace(" ", "_"))
44
  os.makedirs(path, exist_ok=True)
45
+
46
  file_path = os.path.join(path, "papers_info.json")
47
 
48
  # Try to load existing papers info
 
52
  except (FileNotFoundError, json.JSONDecodeError):
53
  papers_info = {}
54
 
55
+ # Process each paper and add to papers_info
56
  paper_ids = []
57
  for paper in papers:
58
  paper_ids.append(paper.get_short_id())
 
64
  'published': str(paper.published.date())
65
  }
66
  papers_info[paper.get_short_id()] = paper_info
67
+
68
  # Save updated papers_info to json file
69
  with open(file_path, "w") as json_file:
70
  json.dump(papers_info, json_file, indent=2)
71
+
72
  print(f"Results are saved in: {file_path}")
73
+
74
  return paper_ids
75
 
76
  @mcp.tool()
77
  def extract_info(paper_id: str) -> str:
78
  """
79
  Search for information about a specific paper across all topic directories.
80
+
81
  Args:
82
  paper_id: The ID of the paper to look for
83
+
84
  Returns:
85
  JSON string with paper information if found, error message if not found
86
  """
87
+
88
  for item in os.listdir(PAPER_DIR):
89
  item_path = os.path.join(PAPER_DIR, item)
90
  if os.path.isdir(item_path):
 
98
  except (FileNotFoundError, json.JSONDecodeError) as e:
99
  print(f"Error reading {file_path}: {str(e)}")
100
  continue
101
+
102
  return f"There's no saved information related to paper {paper_id}."
103
 
104
 
 
107
  def get_available_folders() -> str:
108
  """
109
  List all available topic folders in the papers directory.
110
+
111
  This resource provides a simple list of all available topic folders.
112
  """
113
  folders = []
114
+
115
  # Get all topic directories
116
  if os.path.exists(PAPER_DIR):
117
  for topic_dir in os.listdir(PAPER_DIR):
 
120
  papers_file = os.path.join(topic_path, "papers_info.json")
121
  if os.path.exists(papers_file):
122
  folders.append(topic_dir)
123
+
124
  # Create a simple markdown list
125
  content = "# Available Topics\n\n"
126
  if folders:
 
129
  content += f"\nUse @{folder} to access papers in that topic.\n"
130
  else:
131
  content += "No topics found.\n"
132
+
133
  return content
134
 
135
  @mcp.resource("papers://{topic}")
136
  def get_topic_papers(topic: str) -> str:
137
  """
138
  Get detailed information about papers on a specific topic.
139
+
140
  Args:
141
  topic: The research topic to retrieve papers for
142
  """
143
  topic_dir = topic.lower().replace(" ", "_")
144
  papers_file = os.path.join(PAPER_DIR, topic_dir, "papers_info.json")
145
+
146
  if not os.path.exists(papers_file):
147
  return f"# No papers found for topic: {topic}\n\nTry searching for papers on this topic first."
148
+
149
  try:
150
  with open(papers_file, 'r') as f:
151
  papers_data = json.load(f)
152
+
153
  # Create markdown content with paper details
154
  content = f"# Papers on {topic.replace('_', ' ').title()}\n\n"
155
  content += f"Total papers: {len(papers_data)}\n\n"
156
+
157
  for paper_id, paper_info in papers_data.items():
158
  content += f"## {paper_info['title']}\n"
159
  content += f"- **Paper ID**: {paper_id}\n"
 
162
  content += f"- **PDF URL**: [{paper_info['pdf_url']}]({paper_info['pdf_url']})\n\n"
163
  content += f"### Summary\n{paper_info['summary'][:500]}...\n\n"
164
  content += "---\n\n"
165
+
166
  return content
167
  except json.JSONDecodeError:
168
  return f"# Error reading papers data for {topic}\n\nThe papers data file is corrupted."
 
170
  @mcp.prompt()
171
  def generate_search_prompt(topic: str, num_papers: int = 5) -> str:
172
  """Generate a prompt for Claude to find and discuss academic papers on a specific topic."""
173
+ return f"""Search for {num_papers} academic papers about '{topic}' using the search_papers tool.
174
 
175
  Follow these instructions:
176
  1. First, search for papers using search_papers(topic='{topic}', max_results={num_papers})
 
182
  - Main contributions or innovations
183
  - Methodologies used
184
  - Relevance to the topic '{topic}'
185
+
186
  3. Provide a comprehensive summary that includes:
187
  - Overview of the current state of research in '{topic}'
188
  - Common themes and trends across the papers
189
  - Key research gaps or areas for future investigation
190
  - Most impactful or influential papers in this area
191
+
192
  4. Organize your findings in a clear, structured format with headings and bullet points for easy readability.
193
+
194
  Please present both detailed information about each paper and a high-level synthesis of the research landscape in {topic}."""
195
 
196
  if __name__ == "__main__":
197
  import os
198
+
199
+ # Render donne PORT ; on le recopie dans FASTMCP_PORT
200
+ port = os.environ.get("PORT", "8000")
201
+ os.environ.setdefault("FASTMCP_HOST", "0.0.0.0")
202
+ os.environ["FASTMCP_PORT"] = str(port)
203
+
204
+ # Lancement SSE (FastMCP lira host/port via les variables ci-dessus)
205
+ mcp.run(transport="sse")
server_config.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "mcpServers": {
3
-
4
  "filesystem": {
5
  "command": "npx",
6
  "args": [
@@ -19,4 +19,3 @@
19
  }
20
  }
21
  }
22
-
 
1
  {
2
  "mcpServers": {
3
+
4
  "filesystem": {
5
  "command": "npx",
6
  "args": [
 
19
  }
20
  }
21
  }
 
server_config_L7.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "mcpServers": {
3
-
4
  "filesystem": {
5
  "command": "npx",
6
  "args": [
@@ -19,4 +19,3 @@
19
  }
20
  }
21
  }
22
-
 
1
  {
2
  "mcpServers": {
3
+
4
  "filesystem": {
5
  "command": "npx",
6
  "args": [
 
19
  }
20
  }
21
  }