Spaces:
Runtime error
Runtime error
VotreNomUtilisateurboscherj commited on
Commit ·
064fc28
1
Parent(s): 54e3dbf
chore(pre-commit): apply autofixes
Browse files- .pre-commit-config.yaml +14 -0
- .secrets.baseline +127 -0
- .vscode/launch.json +1 -1
- mcp_architecture_diagram.txt +1 -1
- mcp_chatbot.py +4 -4
- mcp_chatbot_L7.py +40 -40
- mcp_chatbot_v2.py +6 -6
- mcp_chatbot_v3.py +39 -39
- mcp_diagram.txt +1 -1
- mcp_summary.md +1 -1
- papers/algebra/papers_info.json +1 -1
- papers/artificial_intelligence/papers_info.json +1 -1
- papers/chemistry/papers_info.json +1 -1
- papers/computers/papers_info.json +1 -1
- papers/deepseek/papers_info.json +1 -1
- papers/gpt-5/papers_info.json +1 -1
- papers/intelligence/papers_info.json +1 -1
- papers/large_language_model/papers_info.json +1 -1
- papers/large_language_models/papers_info.json +1 -1
- papers/llm_evaluation/papers_info.json +1 -1
- papers/physics/papers_info.json +1 -1
- papers/transformer_attention_nlp/papers_info.json +1 -1
- papers/transformer_neural_networks/papers_info.json +1 -1
- papers/transformers/papers_info.json +1 -1
- research_server.py +14 -14
- research_server_L7.py +26 -26
- research_server_L9.py +36 -30
- server_config.json +1 -2
- server_config_L7.json +1 -2
.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 |
-
|
| 199 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
}
|
|
|