codepp 0.0.437__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- code_puppy/__init__.py +10 -0
- code_puppy/__main__.py +10 -0
- code_puppy/agents/__init__.py +31 -0
- code_puppy/agents/agent_c_reviewer.py +155 -0
- code_puppy/agents/agent_code_puppy.py +117 -0
- code_puppy/agents/agent_code_reviewer.py +90 -0
- code_puppy/agents/agent_cpp_reviewer.py +132 -0
- code_puppy/agents/agent_creator_agent.py +638 -0
- code_puppy/agents/agent_golang_reviewer.py +151 -0
- code_puppy/agents/agent_helios.py +124 -0
- code_puppy/agents/agent_javascript_reviewer.py +160 -0
- code_puppy/agents/agent_manager.py +742 -0
- code_puppy/agents/agent_pack_leader.py +385 -0
- code_puppy/agents/agent_planning.py +165 -0
- code_puppy/agents/agent_python_programmer.py +169 -0
- code_puppy/agents/agent_python_reviewer.py +90 -0
- code_puppy/agents/agent_qa_expert.py +163 -0
- code_puppy/agents/agent_qa_kitten.py +208 -0
- code_puppy/agents/agent_scheduler.py +121 -0
- code_puppy/agents/agent_security_auditor.py +181 -0
- code_puppy/agents/agent_terminal_qa.py +323 -0
- code_puppy/agents/agent_typescript_reviewer.py +166 -0
- code_puppy/agents/base_agent.py +2156 -0
- code_puppy/agents/event_stream_handler.py +348 -0
- code_puppy/agents/json_agent.py +202 -0
- code_puppy/agents/pack/__init__.py +34 -0
- code_puppy/agents/pack/bloodhound.py +304 -0
- code_puppy/agents/pack/husky.py +327 -0
- code_puppy/agents/pack/retriever.py +393 -0
- code_puppy/agents/pack/shepherd.py +348 -0
- code_puppy/agents/pack/terrier.py +287 -0
- code_puppy/agents/pack/watchdog.py +367 -0
- code_puppy/agents/prompt_reviewer.py +145 -0
- code_puppy/agents/subagent_stream_handler.py +276 -0
- code_puppy/api/__init__.py +13 -0
- code_puppy/api/app.py +169 -0
- code_puppy/api/main.py +21 -0
- code_puppy/api/pty_manager.py +453 -0
- code_puppy/api/routers/__init__.py +12 -0
- code_puppy/api/routers/agents.py +36 -0
- code_puppy/api/routers/commands.py +217 -0
- code_puppy/api/routers/config.py +75 -0
- code_puppy/api/routers/sessions.py +234 -0
- code_puppy/api/templates/terminal.html +361 -0
- code_puppy/api/websocket.py +154 -0
- code_puppy/callbacks.py +692 -0
- code_puppy/chatgpt_codex_client.py +338 -0
- code_puppy/claude_cache_client.py +672 -0
- code_puppy/cli_runner.py +1073 -0
- code_puppy/command_line/__init__.py +1 -0
- code_puppy/command_line/add_model_menu.py +1092 -0
- code_puppy/command_line/agent_menu.py +662 -0
- code_puppy/command_line/attachments.py +395 -0
- code_puppy/command_line/autosave_menu.py +704 -0
- code_puppy/command_line/clipboard.py +527 -0
- code_puppy/command_line/colors_menu.py +532 -0
- code_puppy/command_line/command_handler.py +293 -0
- code_puppy/command_line/command_registry.py +150 -0
- code_puppy/command_line/config_commands.py +719 -0
- code_puppy/command_line/core_commands.py +867 -0
- code_puppy/command_line/diff_menu.py +865 -0
- code_puppy/command_line/file_path_completion.py +73 -0
- code_puppy/command_line/load_context_completion.py +52 -0
- code_puppy/command_line/mcp/__init__.py +10 -0
- code_puppy/command_line/mcp/base.py +32 -0
- code_puppy/command_line/mcp/catalog_server_installer.py +175 -0
- code_puppy/command_line/mcp/custom_server_form.py +688 -0
- code_puppy/command_line/mcp/custom_server_installer.py +195 -0
- code_puppy/command_line/mcp/edit_command.py +148 -0
- code_puppy/command_line/mcp/handler.py +138 -0
- code_puppy/command_line/mcp/help_command.py +147 -0
- code_puppy/command_line/mcp/install_command.py +214 -0
- code_puppy/command_line/mcp/install_menu.py +705 -0
- code_puppy/command_line/mcp/list_command.py +94 -0
- code_puppy/command_line/mcp/logs_command.py +235 -0
- code_puppy/command_line/mcp/remove_command.py +82 -0
- code_puppy/command_line/mcp/restart_command.py +100 -0
- code_puppy/command_line/mcp/search_command.py +123 -0
- code_puppy/command_line/mcp/start_all_command.py +135 -0
- code_puppy/command_line/mcp/start_command.py +117 -0
- code_puppy/command_line/mcp/status_command.py +184 -0
- code_puppy/command_line/mcp/stop_all_command.py +112 -0
- code_puppy/command_line/mcp/stop_command.py +80 -0
- code_puppy/command_line/mcp/test_command.py +107 -0
- code_puppy/command_line/mcp/utils.py +129 -0
- code_puppy/command_line/mcp/wizard_utils.py +334 -0
- code_puppy/command_line/mcp_completion.py +174 -0
- code_puppy/command_line/model_picker_completion.py +197 -0
- code_puppy/command_line/model_settings_menu.py +932 -0
- code_puppy/command_line/motd.py +96 -0
- code_puppy/command_line/onboarding_slides.py +179 -0
- code_puppy/command_line/onboarding_wizard.py +342 -0
- code_puppy/command_line/pin_command_completion.py +329 -0
- code_puppy/command_line/prompt_toolkit_completion.py +846 -0
- code_puppy/command_line/session_commands.py +302 -0
- code_puppy/command_line/shell_passthrough.py +145 -0
- code_puppy/command_line/skills_completion.py +160 -0
- code_puppy/command_line/uc_menu.py +893 -0
- code_puppy/command_line/utils.py +93 -0
- code_puppy/command_line/wiggum_state.py +78 -0
- code_puppy/config.py +1770 -0
- code_puppy/error_logging.py +134 -0
- code_puppy/gemini_code_assist.py +385 -0
- code_puppy/gemini_model.py +754 -0
- code_puppy/hook_engine/README.md +105 -0
- code_puppy/hook_engine/__init__.py +21 -0
- code_puppy/hook_engine/aliases.py +155 -0
- code_puppy/hook_engine/engine.py +221 -0
- code_puppy/hook_engine/executor.py +296 -0
- code_puppy/hook_engine/matcher.py +156 -0
- code_puppy/hook_engine/models.py +240 -0
- code_puppy/hook_engine/registry.py +106 -0
- code_puppy/hook_engine/validator.py +144 -0
- code_puppy/http_utils.py +361 -0
- code_puppy/keymap.py +128 -0
- code_puppy/main.py +10 -0
- code_puppy/mcp_/__init__.py +66 -0
- code_puppy/mcp_/async_lifecycle.py +286 -0
- code_puppy/mcp_/blocking_startup.py +469 -0
- code_puppy/mcp_/captured_stdio_server.py +275 -0
- code_puppy/mcp_/circuit_breaker.py +290 -0
- code_puppy/mcp_/config_wizard.py +507 -0
- code_puppy/mcp_/dashboard.py +308 -0
- code_puppy/mcp_/error_isolation.py +407 -0
- code_puppy/mcp_/examples/retry_example.py +226 -0
- code_puppy/mcp_/health_monitor.py +589 -0
- code_puppy/mcp_/managed_server.py +428 -0
- code_puppy/mcp_/manager.py +807 -0
- code_puppy/mcp_/mcp_logs.py +224 -0
- code_puppy/mcp_/registry.py +451 -0
- code_puppy/mcp_/retry_manager.py +337 -0
- code_puppy/mcp_/server_registry_catalog.py +1126 -0
- code_puppy/mcp_/status_tracker.py +355 -0
- code_puppy/mcp_/system_tools.py +209 -0
- code_puppy/mcp_prompts/__init__.py +1 -0
- code_puppy/mcp_prompts/hook_creator.py +103 -0
- code_puppy/messaging/__init__.py +255 -0
- code_puppy/messaging/bus.py +613 -0
- code_puppy/messaging/commands.py +167 -0
- code_puppy/messaging/markdown_patches.py +57 -0
- code_puppy/messaging/message_queue.py +361 -0
- code_puppy/messaging/messages.py +569 -0
- code_puppy/messaging/queue_console.py +271 -0
- code_puppy/messaging/renderers.py +311 -0
- code_puppy/messaging/rich_renderer.py +1158 -0
- code_puppy/messaging/spinner/__init__.py +83 -0
- code_puppy/messaging/spinner/console_spinner.py +240 -0
- code_puppy/messaging/spinner/spinner_base.py +95 -0
- code_puppy/messaging/subagent_console.py +460 -0
- code_puppy/model_factory.py +848 -0
- code_puppy/model_switching.py +63 -0
- code_puppy/model_utils.py +168 -0
- code_puppy/models.json +174 -0
- code_puppy/models_dev_api.json +1 -0
- code_puppy/models_dev_parser.py +592 -0
- code_puppy/plugins/__init__.py +186 -0
- code_puppy/plugins/agent_skills/__init__.py +22 -0
- code_puppy/plugins/agent_skills/config.py +175 -0
- code_puppy/plugins/agent_skills/discovery.py +136 -0
- code_puppy/plugins/agent_skills/downloader.py +392 -0
- code_puppy/plugins/agent_skills/installer.py +22 -0
- code_puppy/plugins/agent_skills/metadata.py +219 -0
- code_puppy/plugins/agent_skills/prompt_builder.py +60 -0
- code_puppy/plugins/agent_skills/register_callbacks.py +241 -0
- code_puppy/plugins/agent_skills/remote_catalog.py +322 -0
- code_puppy/plugins/agent_skills/skill_catalog.py +257 -0
- code_puppy/plugins/agent_skills/skills_install_menu.py +664 -0
- code_puppy/plugins/agent_skills/skills_menu.py +781 -0
- code_puppy/plugins/antigravity_oauth/__init__.py +10 -0
- code_puppy/plugins/antigravity_oauth/accounts.py +406 -0
- code_puppy/plugins/antigravity_oauth/antigravity_model.py +706 -0
- code_puppy/plugins/antigravity_oauth/config.py +42 -0
- code_puppy/plugins/antigravity_oauth/constants.py +133 -0
- code_puppy/plugins/antigravity_oauth/oauth.py +478 -0
- code_puppy/plugins/antigravity_oauth/register_callbacks.py +518 -0
- code_puppy/plugins/antigravity_oauth/storage.py +288 -0
- code_puppy/plugins/antigravity_oauth/test_plugin.py +319 -0
- code_puppy/plugins/antigravity_oauth/token.py +167 -0
- code_puppy/plugins/antigravity_oauth/transport.py +863 -0
- code_puppy/plugins/antigravity_oauth/utils.py +168 -0
- code_puppy/plugins/chatgpt_oauth/__init__.py +8 -0
- code_puppy/plugins/chatgpt_oauth/config.py +52 -0
- code_puppy/plugins/chatgpt_oauth/oauth_flow.py +329 -0
- code_puppy/plugins/chatgpt_oauth/register_callbacks.py +176 -0
- code_puppy/plugins/chatgpt_oauth/test_plugin.py +301 -0
- code_puppy/plugins/chatgpt_oauth/utils.py +523 -0
- code_puppy/plugins/claude_code_hooks/__init__.py +1 -0
- code_puppy/plugins/claude_code_hooks/config.py +137 -0
- code_puppy/plugins/claude_code_hooks/register_callbacks.py +175 -0
- code_puppy/plugins/claude_code_oauth/README.md +167 -0
- code_puppy/plugins/claude_code_oauth/SETUP.md +93 -0
- code_puppy/plugins/claude_code_oauth/__init__.py +25 -0
- code_puppy/plugins/claude_code_oauth/config.py +52 -0
- code_puppy/plugins/claude_code_oauth/register_callbacks.py +453 -0
- code_puppy/plugins/claude_code_oauth/test_plugin.py +283 -0
- code_puppy/plugins/claude_code_oauth/token_refresh_heartbeat.py +241 -0
- code_puppy/plugins/claude_code_oauth/utils.py +640 -0
- code_puppy/plugins/customizable_commands/__init__.py +0 -0
- code_puppy/plugins/customizable_commands/register_callbacks.py +152 -0
- code_puppy/plugins/example_custom_command/README.md +280 -0
- code_puppy/plugins/example_custom_command/register_callbacks.py +51 -0
- code_puppy/plugins/file_permission_handler/__init__.py +4 -0
- code_puppy/plugins/file_permission_handler/register_callbacks.py +470 -0
- code_puppy/plugins/frontend_emitter/__init__.py +25 -0
- code_puppy/plugins/frontend_emitter/emitter.py +121 -0
- code_puppy/plugins/frontend_emitter/register_callbacks.py +261 -0
- code_puppy/plugins/hook_creator/__init__.py +1 -0
- code_puppy/plugins/hook_creator/register_callbacks.py +33 -0
- code_puppy/plugins/hook_manager/__init__.py +1 -0
- code_puppy/plugins/hook_manager/config.py +290 -0
- code_puppy/plugins/hook_manager/hooks_menu.py +564 -0
- code_puppy/plugins/hook_manager/register_callbacks.py +227 -0
- code_puppy/plugins/oauth_puppy_html.py +228 -0
- code_puppy/plugins/scheduler/__init__.py +1 -0
- code_puppy/plugins/scheduler/register_callbacks.py +88 -0
- code_puppy/plugins/scheduler/scheduler_menu.py +522 -0
- code_puppy/plugins/scheduler/scheduler_wizard.py +341 -0
- code_puppy/plugins/shell_safety/__init__.py +6 -0
- code_puppy/plugins/shell_safety/agent_shell_safety.py +69 -0
- code_puppy/plugins/shell_safety/command_cache.py +156 -0
- code_puppy/plugins/shell_safety/register_callbacks.py +202 -0
- code_puppy/plugins/synthetic_status/__init__.py +1 -0
- code_puppy/plugins/synthetic_status/register_callbacks.py +132 -0
- code_puppy/plugins/synthetic_status/status_api.py +147 -0
- code_puppy/plugins/universal_constructor/__init__.py +13 -0
- code_puppy/plugins/universal_constructor/models.py +138 -0
- code_puppy/plugins/universal_constructor/register_callbacks.py +47 -0
- code_puppy/plugins/universal_constructor/registry.py +302 -0
- code_puppy/plugins/universal_constructor/sandbox.py +584 -0
- code_puppy/prompts/antigravity_system_prompt.md +1 -0
- code_puppy/pydantic_patches.py +356 -0
- code_puppy/reopenable_async_client.py +232 -0
- code_puppy/round_robin_model.py +150 -0
- code_puppy/scheduler/__init__.py +41 -0
- code_puppy/scheduler/__main__.py +9 -0
- code_puppy/scheduler/cli.py +118 -0
- code_puppy/scheduler/config.py +126 -0
- code_puppy/scheduler/daemon.py +280 -0
- code_puppy/scheduler/executor.py +155 -0
- code_puppy/scheduler/platform.py +19 -0
- code_puppy/scheduler/platform_unix.py +22 -0
- code_puppy/scheduler/platform_win.py +32 -0
- code_puppy/session_storage.py +338 -0
- code_puppy/status_display.py +257 -0
- code_puppy/summarization_agent.py +176 -0
- code_puppy/terminal_utils.py +418 -0
- code_puppy/tools/__init__.py +501 -0
- code_puppy/tools/agent_tools.py +603 -0
- code_puppy/tools/ask_user_question/__init__.py +26 -0
- code_puppy/tools/ask_user_question/constants.py +73 -0
- code_puppy/tools/ask_user_question/demo_tui.py +55 -0
- code_puppy/tools/ask_user_question/handler.py +232 -0
- code_puppy/tools/ask_user_question/models.py +304 -0
- code_puppy/tools/ask_user_question/registration.py +26 -0
- code_puppy/tools/ask_user_question/renderers.py +309 -0
- code_puppy/tools/ask_user_question/terminal_ui.py +329 -0
- code_puppy/tools/ask_user_question/theme.py +155 -0
- code_puppy/tools/ask_user_question/tui_loop.py +423 -0
- code_puppy/tools/browser/__init__.py +37 -0
- code_puppy/tools/browser/browser_control.py +289 -0
- code_puppy/tools/browser/browser_interactions.py +545 -0
- code_puppy/tools/browser/browser_locators.py +640 -0
- code_puppy/tools/browser/browser_manager.py +378 -0
- code_puppy/tools/browser/browser_navigation.py +251 -0
- code_puppy/tools/browser/browser_screenshot.py +179 -0
- code_puppy/tools/browser/browser_scripts.py +462 -0
- code_puppy/tools/browser/browser_workflows.py +221 -0
- code_puppy/tools/browser/chromium_terminal_manager.py +259 -0
- code_puppy/tools/browser/terminal_command_tools.py +534 -0
- code_puppy/tools/browser/terminal_screenshot_tools.py +552 -0
- code_puppy/tools/browser/terminal_tools.py +525 -0
- code_puppy/tools/command_runner.py +1346 -0
- code_puppy/tools/common.py +1409 -0
- code_puppy/tools/display.py +84 -0
- code_puppy/tools/file_modifications.py +886 -0
- code_puppy/tools/file_operations.py +802 -0
- code_puppy/tools/scheduler_tools.py +412 -0
- code_puppy/tools/skills_tools.py +244 -0
- code_puppy/tools/subagent_context.py +158 -0
- code_puppy/tools/tools_content.py +51 -0
- code_puppy/tools/universal_constructor.py +889 -0
- code_puppy/uvx_detection.py +242 -0
- code_puppy/version_checker.py +82 -0
- codepp-0.0.437.dist-info/METADATA +766 -0
- codepp-0.0.437.dist-info/RECORD +288 -0
- codepp-0.0.437.dist-info/WHEEL +4 -0
- codepp-0.0.437.dist-info/entry_points.txt +3 -0
- codepp-0.0.437.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,1126 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MCP Server Registry Catalog - Pre-configured MCP servers.
|
|
3
|
+
A curated collection of MCP servers that can be easily searched and installed.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from typing import Dict, List, Optional, Union
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class MCPServerRequirements:
|
|
12
|
+
"""Comprehensive requirements for an MCP server installation."""
|
|
13
|
+
|
|
14
|
+
environment_vars: List[str] = field(
|
|
15
|
+
default_factory=list
|
|
16
|
+
) # ["GITHUB_TOKEN", "API_KEY"]
|
|
17
|
+
command_line_args: List[Dict[str, Union[str, bool]]] = field(
|
|
18
|
+
default_factory=list
|
|
19
|
+
) # [{"name": "port", "prompt": "Port number", "default": "3000", "required": False}]
|
|
20
|
+
required_tools: List[str] = field(
|
|
21
|
+
default_factory=list
|
|
22
|
+
) # ["node", "python", "npm", "npx"]
|
|
23
|
+
package_dependencies: List[str] = field(
|
|
24
|
+
default_factory=list
|
|
25
|
+
) # ["jupyter", "@modelcontextprotocol/server-discord"]
|
|
26
|
+
system_requirements: List[str] = field(
|
|
27
|
+
default_factory=list
|
|
28
|
+
) # ["Docker installed", "Git configured"]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class MCPServerTemplate:
|
|
33
|
+
"""Template for a pre-configured MCP server."""
|
|
34
|
+
|
|
35
|
+
id: str
|
|
36
|
+
name: str
|
|
37
|
+
display_name: str
|
|
38
|
+
description: str
|
|
39
|
+
category: str
|
|
40
|
+
tags: List[str]
|
|
41
|
+
type: str # "stdio", "http", "sse"
|
|
42
|
+
config: Dict
|
|
43
|
+
author: str = "Community"
|
|
44
|
+
verified: bool = False
|
|
45
|
+
popular: bool = False
|
|
46
|
+
requires: Union[List[str], MCPServerRequirements] = field(
|
|
47
|
+
default_factory=list
|
|
48
|
+
) # Backward compatible
|
|
49
|
+
example_usage: str = ""
|
|
50
|
+
|
|
51
|
+
def get_requirements(self) -> MCPServerRequirements:
|
|
52
|
+
"""Get requirements as MCPServerRequirements object."""
|
|
53
|
+
if isinstance(self.requires, list):
|
|
54
|
+
# Backward compatibility - treat as required_tools
|
|
55
|
+
return MCPServerRequirements(required_tools=self.requires)
|
|
56
|
+
return self.requires
|
|
57
|
+
|
|
58
|
+
def get_environment_vars(self) -> List[str]:
|
|
59
|
+
"""Get list of required environment variables."""
|
|
60
|
+
requirements = self.get_requirements()
|
|
61
|
+
env_vars = requirements.environment_vars.copy()
|
|
62
|
+
|
|
63
|
+
# Also check config for env vars (existing logic)
|
|
64
|
+
if "env" in self.config:
|
|
65
|
+
for _key, value in self.config["env"].items():
|
|
66
|
+
if isinstance(value, str) and value.startswith("$"):
|
|
67
|
+
var_name = value[1:]
|
|
68
|
+
if var_name not in env_vars:
|
|
69
|
+
env_vars.append(var_name)
|
|
70
|
+
|
|
71
|
+
return env_vars
|
|
72
|
+
|
|
73
|
+
def get_command_line_args(self) -> List[Dict]:
|
|
74
|
+
"""Get list of configurable command line arguments."""
|
|
75
|
+
return self.get_requirements().command_line_args
|
|
76
|
+
|
|
77
|
+
def get_required_tools(self) -> List[str]:
|
|
78
|
+
"""Get list of required system tools."""
|
|
79
|
+
return self.get_requirements().required_tools
|
|
80
|
+
|
|
81
|
+
def get_package_dependencies(self) -> List[str]:
|
|
82
|
+
"""Get list of package dependencies."""
|
|
83
|
+
return self.get_requirements().package_dependencies
|
|
84
|
+
|
|
85
|
+
def get_system_requirements(self) -> List[str]:
|
|
86
|
+
"""Get list of system requirements."""
|
|
87
|
+
return self.get_requirements().system_requirements
|
|
88
|
+
|
|
89
|
+
def to_server_config(self, custom_name: Optional[str] = None, **cmd_args) -> Dict:
|
|
90
|
+
"""Convert template to server configuration with optional overrides.
|
|
91
|
+
|
|
92
|
+
Replaces placeholders in the config with actual values.
|
|
93
|
+
Placeholders are in the format ${ARG_NAME} in args array.
|
|
94
|
+
"""
|
|
95
|
+
import copy
|
|
96
|
+
|
|
97
|
+
config = {
|
|
98
|
+
"name": custom_name or self.name,
|
|
99
|
+
"type": self.type,
|
|
100
|
+
**copy.deepcopy(self.config),
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
# Apply command line argument substitutions
|
|
104
|
+
if cmd_args and "args" in config:
|
|
105
|
+
new_args = []
|
|
106
|
+
for arg in config["args"]:
|
|
107
|
+
# Check if this arg contains a placeholder like ${db_path}
|
|
108
|
+
if isinstance(arg, str) and "${" in arg:
|
|
109
|
+
# Replace all placeholders in this arg
|
|
110
|
+
new_arg = arg
|
|
111
|
+
for key, value in cmd_args.items():
|
|
112
|
+
placeholder = f"${{{key}}}"
|
|
113
|
+
if placeholder in new_arg:
|
|
114
|
+
new_arg = new_arg.replace(placeholder, str(value))
|
|
115
|
+
new_args.append(new_arg)
|
|
116
|
+
else:
|
|
117
|
+
new_args.append(arg)
|
|
118
|
+
config["args"] = new_args
|
|
119
|
+
|
|
120
|
+
# Also handle environment variable placeholders
|
|
121
|
+
if "env" in config:
|
|
122
|
+
for env_key, env_value in config["env"].items():
|
|
123
|
+
if isinstance(env_value, str) and "${" in env_value:
|
|
124
|
+
# Replace all placeholders in env values
|
|
125
|
+
new_value = env_value
|
|
126
|
+
for key, value in cmd_args.items():
|
|
127
|
+
placeholder = f"${{{key}}}"
|
|
128
|
+
if placeholder in new_value:
|
|
129
|
+
new_value = new_value.replace(placeholder, str(value))
|
|
130
|
+
config["env"][env_key] = new_value
|
|
131
|
+
|
|
132
|
+
return config
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
# Pre-configured MCP Server Registry
|
|
136
|
+
MCP_SERVER_REGISTRY: List[MCPServerTemplate] = [
|
|
137
|
+
MCPServerTemplate(
|
|
138
|
+
id="serena",
|
|
139
|
+
name="serena",
|
|
140
|
+
display_name="Serena",
|
|
141
|
+
description="Code Generation MCP Tooling",
|
|
142
|
+
tags=["Agentic", "Code", "SDK", "AI"],
|
|
143
|
+
category="Code",
|
|
144
|
+
type="stdio",
|
|
145
|
+
config={
|
|
146
|
+
"command": "uvx",
|
|
147
|
+
"args": [
|
|
148
|
+
"--from",
|
|
149
|
+
"git+https://github.com/oraios/serena",
|
|
150
|
+
"serena",
|
|
151
|
+
"start-mcp-server",
|
|
152
|
+
],
|
|
153
|
+
},
|
|
154
|
+
verified=True,
|
|
155
|
+
popular=True,
|
|
156
|
+
example_usage="Agentic AI for writing programs",
|
|
157
|
+
requires=["uvx"],
|
|
158
|
+
),
|
|
159
|
+
# ========== File System & Storage ==========
|
|
160
|
+
MCPServerTemplate(
|
|
161
|
+
id="filesystem",
|
|
162
|
+
name="filesystem",
|
|
163
|
+
display_name="Filesystem Access",
|
|
164
|
+
description="Read and write files in specified directories",
|
|
165
|
+
category="Storage",
|
|
166
|
+
tags=["files", "io", "read", "write", "directory"],
|
|
167
|
+
type="stdio",
|
|
168
|
+
config={
|
|
169
|
+
"command": "npx",
|
|
170
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
|
|
171
|
+
"timeout": 30,
|
|
172
|
+
},
|
|
173
|
+
verified=True,
|
|
174
|
+
popular=True,
|
|
175
|
+
requires=["node", "npm"],
|
|
176
|
+
example_usage="Access and modify files in /tmp directory",
|
|
177
|
+
),
|
|
178
|
+
MCPServerTemplate(
|
|
179
|
+
id="filesystem-home",
|
|
180
|
+
name="filesystem-home",
|
|
181
|
+
display_name="Home Directory Access",
|
|
182
|
+
description="Read and write files in user's home directory",
|
|
183
|
+
category="Storage",
|
|
184
|
+
tags=["files", "home", "user", "personal"],
|
|
185
|
+
type="stdio",
|
|
186
|
+
config={
|
|
187
|
+
"command": "npx",
|
|
188
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "~"],
|
|
189
|
+
"timeout": 30,
|
|
190
|
+
},
|
|
191
|
+
verified=True,
|
|
192
|
+
requires=["node", "npm"],
|
|
193
|
+
),
|
|
194
|
+
# Enhanced server with comprehensive requirements
|
|
195
|
+
MCPServerTemplate(
|
|
196
|
+
id="gdrive",
|
|
197
|
+
name="gdrive",
|
|
198
|
+
display_name="Google Drive",
|
|
199
|
+
description="Access and manage Google Drive files with OAuth2 authentication",
|
|
200
|
+
category="Storage",
|
|
201
|
+
tags=["google", "drive", "cloud", "storage", "sync", "oauth"],
|
|
202
|
+
type="stdio",
|
|
203
|
+
config={
|
|
204
|
+
"command": "npx",
|
|
205
|
+
"args": ["-y", "@modelcontextprotocol/server-gdrive"],
|
|
206
|
+
"env": {
|
|
207
|
+
"GOOGLE_CLIENT_ID": "$GOOGLE_CLIENT_ID",
|
|
208
|
+
"GOOGLE_CLIENT_SECRET": "$GOOGLE_CLIENT_SECRET",
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
requires=MCPServerRequirements(
|
|
212
|
+
environment_vars=["GOOGLE_CLIENT_ID", "GOOGLE_CLIENT_SECRET"],
|
|
213
|
+
command_line_args=[
|
|
214
|
+
{
|
|
215
|
+
"name": "port",
|
|
216
|
+
"prompt": "OAuth redirect port",
|
|
217
|
+
"default": "3000",
|
|
218
|
+
"required": False,
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
"name": "scope",
|
|
222
|
+
"prompt": "Google Drive API scope",
|
|
223
|
+
"default": "https://www.googleapis.com/auth/drive.readonly",
|
|
224
|
+
"required": False,
|
|
225
|
+
},
|
|
226
|
+
],
|
|
227
|
+
required_tools=["node", "npx", "npm"],
|
|
228
|
+
package_dependencies=["@modelcontextprotocol/server-gdrive"],
|
|
229
|
+
system_requirements=["Internet connection for OAuth"],
|
|
230
|
+
),
|
|
231
|
+
verified=True,
|
|
232
|
+
popular=True,
|
|
233
|
+
example_usage="List files: 'Show me my Google Drive files'",
|
|
234
|
+
),
|
|
235
|
+
# Regular server (backward compatible)
|
|
236
|
+
MCPServerTemplate(
|
|
237
|
+
id="filesystem-simple",
|
|
238
|
+
name="filesystem-simple",
|
|
239
|
+
display_name="Simple Filesystem",
|
|
240
|
+
description="Basic filesystem access",
|
|
241
|
+
category="Storage",
|
|
242
|
+
tags=["files", "basic"],
|
|
243
|
+
type="stdio",
|
|
244
|
+
config={
|
|
245
|
+
"command": "npx",
|
|
246
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
|
|
247
|
+
"timeout": 30,
|
|
248
|
+
},
|
|
249
|
+
verified=True,
|
|
250
|
+
popular=True,
|
|
251
|
+
requires=MCPServerRequirements(
|
|
252
|
+
environment_vars=["GOOGLE_CLIENT_ID", "GOOGLE_CLIENT_SECRET"],
|
|
253
|
+
command_line_args=[
|
|
254
|
+
{
|
|
255
|
+
"name": "port",
|
|
256
|
+
"prompt": "OAuth redirect port",
|
|
257
|
+
"default": "3000",
|
|
258
|
+
"required": False,
|
|
259
|
+
}
|
|
260
|
+
],
|
|
261
|
+
required_tools=["node", "npm", "npx"],
|
|
262
|
+
package_dependencies=["@modelcontextprotocol/server-gdrive"],
|
|
263
|
+
),
|
|
264
|
+
),
|
|
265
|
+
# ========== Databases ==========
|
|
266
|
+
MCPServerTemplate(
|
|
267
|
+
id="postgres",
|
|
268
|
+
name="postgres",
|
|
269
|
+
display_name="PostgreSQL Database",
|
|
270
|
+
description="Connect to and query PostgreSQL databases",
|
|
271
|
+
category="Database",
|
|
272
|
+
tags=["database", "sql", "postgres", "postgresql", "query"],
|
|
273
|
+
type="stdio",
|
|
274
|
+
config={
|
|
275
|
+
"command": "npx",
|
|
276
|
+
"args": [
|
|
277
|
+
"-y",
|
|
278
|
+
"@modelcontextprotocol/server-postgres",
|
|
279
|
+
"${connection_string}",
|
|
280
|
+
],
|
|
281
|
+
"timeout": 30,
|
|
282
|
+
},
|
|
283
|
+
verified=True,
|
|
284
|
+
popular=True,
|
|
285
|
+
requires=MCPServerRequirements(
|
|
286
|
+
environment_vars=["DATABASE_URL"],
|
|
287
|
+
command_line_args=[
|
|
288
|
+
{
|
|
289
|
+
"name": "connection_string",
|
|
290
|
+
"prompt": "PostgreSQL connection string",
|
|
291
|
+
"default": "postgresql://localhost/mydb",
|
|
292
|
+
"required": True,
|
|
293
|
+
}
|
|
294
|
+
],
|
|
295
|
+
required_tools=["node", "npm", "npx"],
|
|
296
|
+
package_dependencies=["@modelcontextprotocol/server-postgres"],
|
|
297
|
+
system_requirements=["PostgreSQL server running"],
|
|
298
|
+
),
|
|
299
|
+
example_usage="postgresql://user:password@localhost:5432/dbname",
|
|
300
|
+
),
|
|
301
|
+
MCPServerTemplate(
|
|
302
|
+
id="sqlite",
|
|
303
|
+
name="sqlite",
|
|
304
|
+
display_name="SQLite Database",
|
|
305
|
+
description="Connect to and query SQLite databases",
|
|
306
|
+
category="Database",
|
|
307
|
+
tags=["database", "sql", "sqlite", "local", "embedded"],
|
|
308
|
+
type="stdio",
|
|
309
|
+
config={
|
|
310
|
+
"command": "npx",
|
|
311
|
+
"args": ["-y", "mcp-sqlite", "${db_path}"],
|
|
312
|
+
"timeout": 30,
|
|
313
|
+
},
|
|
314
|
+
verified=True,
|
|
315
|
+
popular=True,
|
|
316
|
+
requires=MCPServerRequirements(
|
|
317
|
+
command_line_args=[
|
|
318
|
+
{
|
|
319
|
+
"name": "db_path",
|
|
320
|
+
"prompt": "Path to SQLite database file",
|
|
321
|
+
"default": "./database.db",
|
|
322
|
+
"required": True,
|
|
323
|
+
}
|
|
324
|
+
],
|
|
325
|
+
required_tools=["node", "npm", "npx"],
|
|
326
|
+
package_dependencies=["@modelcontextprotocol/server-sqlite"],
|
|
327
|
+
),
|
|
328
|
+
),
|
|
329
|
+
MCPServerTemplate(
|
|
330
|
+
id="mysql",
|
|
331
|
+
name="mysql",
|
|
332
|
+
display_name="MySQL Database",
|
|
333
|
+
description="Connect to and query MySQL databases",
|
|
334
|
+
category="Database",
|
|
335
|
+
tags=["database", "sql", "mysql", "mariadb", "query"],
|
|
336
|
+
type="stdio",
|
|
337
|
+
config={
|
|
338
|
+
"command": "npx",
|
|
339
|
+
"args": [
|
|
340
|
+
"-y",
|
|
341
|
+
"@modelcontextprotocol/server-mysql",
|
|
342
|
+
"${connection_string}",
|
|
343
|
+
],
|
|
344
|
+
"timeout": 30,
|
|
345
|
+
},
|
|
346
|
+
verified=True,
|
|
347
|
+
requires=MCPServerRequirements(
|
|
348
|
+
environment_vars=["MYSQL_URL"],
|
|
349
|
+
command_line_args=[
|
|
350
|
+
{
|
|
351
|
+
"name": "connection_string",
|
|
352
|
+
"prompt": "MySQL connection string",
|
|
353
|
+
"default": "mysql://localhost/mydb",
|
|
354
|
+
"required": True,
|
|
355
|
+
}
|
|
356
|
+
],
|
|
357
|
+
required_tools=["node", "npm", "npx"],
|
|
358
|
+
package_dependencies=["@modelcontextprotocol/server-mysql"],
|
|
359
|
+
system_requirements=["MySQL server running"],
|
|
360
|
+
),
|
|
361
|
+
),
|
|
362
|
+
MCPServerTemplate(
|
|
363
|
+
id="mongodb",
|
|
364
|
+
name="mongodb",
|
|
365
|
+
display_name="MongoDB Database",
|
|
366
|
+
description="Connect to and query MongoDB databases",
|
|
367
|
+
category="Database",
|
|
368
|
+
tags=["database", "nosql", "mongodb", "document", "query"],
|
|
369
|
+
type="stdio",
|
|
370
|
+
config={
|
|
371
|
+
"command": "npx",
|
|
372
|
+
"args": [
|
|
373
|
+
"-y",
|
|
374
|
+
"@modelcontextprotocol/server-mongodb",
|
|
375
|
+
"${connection_string}",
|
|
376
|
+
],
|
|
377
|
+
"timeout": 30,
|
|
378
|
+
},
|
|
379
|
+
verified=True,
|
|
380
|
+
requires=MCPServerRequirements(
|
|
381
|
+
environment_vars=["MONGODB_URI"],
|
|
382
|
+
command_line_args=[
|
|
383
|
+
{
|
|
384
|
+
"name": "connection_string",
|
|
385
|
+
"prompt": "MongoDB connection string",
|
|
386
|
+
"default": "mongodb://localhost:27017/mydb",
|
|
387
|
+
"required": True,
|
|
388
|
+
}
|
|
389
|
+
],
|
|
390
|
+
required_tools=["node", "npm", "npx"],
|
|
391
|
+
package_dependencies=["@modelcontextprotocol/server-mongodb"],
|
|
392
|
+
system_requirements=["MongoDB server running"],
|
|
393
|
+
),
|
|
394
|
+
),
|
|
395
|
+
# ========== Development Tools ==========
|
|
396
|
+
MCPServerTemplate(
|
|
397
|
+
id="git",
|
|
398
|
+
name="git",
|
|
399
|
+
display_name="Git Repository",
|
|
400
|
+
description="Manage Git repositories and perform version control operations",
|
|
401
|
+
category="Development",
|
|
402
|
+
tags=["git", "version-control", "repository", "commit", "branch"],
|
|
403
|
+
type="stdio",
|
|
404
|
+
config={
|
|
405
|
+
"command": "npx",
|
|
406
|
+
"args": ["-y", "@modelcontextprotocol/server-git"],
|
|
407
|
+
"timeout": 30,
|
|
408
|
+
},
|
|
409
|
+
verified=True,
|
|
410
|
+
popular=True,
|
|
411
|
+
requires=MCPServerRequirements(
|
|
412
|
+
required_tools=["node", "npm", "npx", "git"],
|
|
413
|
+
package_dependencies=["@modelcontextprotocol/server-git"],
|
|
414
|
+
system_requirements=["Git repository initialized"],
|
|
415
|
+
),
|
|
416
|
+
),
|
|
417
|
+
MCPServerTemplate(
|
|
418
|
+
id="github",
|
|
419
|
+
name="github",
|
|
420
|
+
display_name="GitHub API",
|
|
421
|
+
description="Access GitHub repositories, issues, PRs, and more",
|
|
422
|
+
category="Development",
|
|
423
|
+
tags=["github", "api", "repository", "issues", "pull-requests"],
|
|
424
|
+
type="stdio",
|
|
425
|
+
config={
|
|
426
|
+
"command": "npx",
|
|
427
|
+
"args": ["-y", "@modelcontextprotocol/server-github"],
|
|
428
|
+
"env": {"GITHUB_TOKEN": "$GITHUB_TOKEN"},
|
|
429
|
+
"timeout": 30,
|
|
430
|
+
},
|
|
431
|
+
verified=True,
|
|
432
|
+
popular=True,
|
|
433
|
+
requires=MCPServerRequirements(
|
|
434
|
+
environment_vars=["GITHUB_TOKEN"],
|
|
435
|
+
required_tools=["node", "npm", "npx"],
|
|
436
|
+
package_dependencies=["@modelcontextprotocol/server-github"],
|
|
437
|
+
system_requirements=["GitHub account with personal access token"],
|
|
438
|
+
),
|
|
439
|
+
),
|
|
440
|
+
MCPServerTemplate(
|
|
441
|
+
id="gitlab",
|
|
442
|
+
name="gitlab",
|
|
443
|
+
display_name="GitLab API",
|
|
444
|
+
description="Access GitLab repositories, issues, and merge requests",
|
|
445
|
+
category="Development",
|
|
446
|
+
tags=["gitlab", "api", "repository", "issues", "merge-requests"],
|
|
447
|
+
type="stdio",
|
|
448
|
+
config={
|
|
449
|
+
"command": "npx",
|
|
450
|
+
"args": ["-y", "@modelcontextprotocol/server-gitlab"],
|
|
451
|
+
"env": {"GITLAB_TOKEN": "$GITLAB_TOKEN"},
|
|
452
|
+
"timeout": 30,
|
|
453
|
+
},
|
|
454
|
+
verified=True,
|
|
455
|
+
requires=MCPServerRequirements(
|
|
456
|
+
environment_vars=["GITLAB_TOKEN"],
|
|
457
|
+
required_tools=["node", "npm", "npx"],
|
|
458
|
+
package_dependencies=["@modelcontextprotocol/server-gitlab"],
|
|
459
|
+
system_requirements=["GitLab account with personal access token"],
|
|
460
|
+
),
|
|
461
|
+
),
|
|
462
|
+
# ========== Web & Browser ==========
|
|
463
|
+
MCPServerTemplate(
|
|
464
|
+
id="puppeteer",
|
|
465
|
+
name="puppeteer",
|
|
466
|
+
display_name="Puppeteer Browser",
|
|
467
|
+
description="Control headless Chrome for web scraping and automation",
|
|
468
|
+
category="Web",
|
|
469
|
+
tags=["browser", "web", "scraping", "automation", "chrome", "puppeteer"],
|
|
470
|
+
type="stdio",
|
|
471
|
+
config={
|
|
472
|
+
"command": "npx",
|
|
473
|
+
"args": ["-y", "@modelcontextprotocol/server-puppeteer"],
|
|
474
|
+
"timeout": 60,
|
|
475
|
+
},
|
|
476
|
+
verified=True,
|
|
477
|
+
popular=True,
|
|
478
|
+
requires=MCPServerRequirements(
|
|
479
|
+
command_line_args=[
|
|
480
|
+
{
|
|
481
|
+
"name": "headless",
|
|
482
|
+
"prompt": "Run in headless mode",
|
|
483
|
+
"default": "true",
|
|
484
|
+
"required": False,
|
|
485
|
+
}
|
|
486
|
+
],
|
|
487
|
+
required_tools=["node", "npm", "npx"],
|
|
488
|
+
package_dependencies=["@modelcontextprotocol/server-puppeteer"],
|
|
489
|
+
system_requirements=["Chrome/Chromium browser"],
|
|
490
|
+
),
|
|
491
|
+
),
|
|
492
|
+
MCPServerTemplate(
|
|
493
|
+
id="playwright",
|
|
494
|
+
name="playwright",
|
|
495
|
+
display_name="Playwright Browser",
|
|
496
|
+
description="Cross-browser automation for web testing and scraping",
|
|
497
|
+
category="Web",
|
|
498
|
+
tags=["browser", "web", "testing", "automation", "playwright"],
|
|
499
|
+
type="stdio",
|
|
500
|
+
config={
|
|
501
|
+
"command": "npx",
|
|
502
|
+
"args": ["-y", "@modelcontextprotocol/server-playwright"],
|
|
503
|
+
"timeout": 60,
|
|
504
|
+
},
|
|
505
|
+
verified=True,
|
|
506
|
+
requires=MCPServerRequirements(
|
|
507
|
+
command_line_args=[
|
|
508
|
+
{
|
|
509
|
+
"name": "browser",
|
|
510
|
+
"prompt": "Browser to use",
|
|
511
|
+
"default": "chromium",
|
|
512
|
+
"required": False,
|
|
513
|
+
}
|
|
514
|
+
],
|
|
515
|
+
required_tools=["node", "npm", "npx"],
|
|
516
|
+
package_dependencies=["@modelcontextprotocol/server-playwright"],
|
|
517
|
+
system_requirements=["Playwright browsers (will be installed)"],
|
|
518
|
+
),
|
|
519
|
+
),
|
|
520
|
+
MCPServerTemplate(
|
|
521
|
+
id="fetch",
|
|
522
|
+
name="fetch",
|
|
523
|
+
display_name="Web Fetch",
|
|
524
|
+
description="Fetch and process web pages and APIs",
|
|
525
|
+
category="Web",
|
|
526
|
+
tags=["web", "http", "api", "fetch", "request"],
|
|
527
|
+
type="stdio",
|
|
528
|
+
config={
|
|
529
|
+
"command": "npx",
|
|
530
|
+
"args": ["-y", "@modelcontextprotocol/server-fetch"],
|
|
531
|
+
"timeout": 30,
|
|
532
|
+
},
|
|
533
|
+
verified=True,
|
|
534
|
+
requires=MCPServerRequirements(
|
|
535
|
+
required_tools=["node", "npm", "npx"],
|
|
536
|
+
package_dependencies=["@modelcontextprotocol/server-fetch"],
|
|
537
|
+
),
|
|
538
|
+
),
|
|
539
|
+
# ========== Communication ==========
|
|
540
|
+
MCPServerTemplate(
|
|
541
|
+
id="slack",
|
|
542
|
+
name="slack",
|
|
543
|
+
display_name="Slack Integration",
|
|
544
|
+
description="Send messages and interact with Slack workspaces",
|
|
545
|
+
category="Communication",
|
|
546
|
+
tags=["slack", "chat", "messaging", "notification"],
|
|
547
|
+
type="stdio",
|
|
548
|
+
config={
|
|
549
|
+
"command": "npx",
|
|
550
|
+
"args": ["-y", "@modelcontextprotocol/server-slack"],
|
|
551
|
+
"env": {"SLACK_TOKEN": "$SLACK_TOKEN"},
|
|
552
|
+
"timeout": 30,
|
|
553
|
+
},
|
|
554
|
+
verified=True,
|
|
555
|
+
popular=True,
|
|
556
|
+
requires=MCPServerRequirements(
|
|
557
|
+
environment_vars=["SLACK_TOKEN"],
|
|
558
|
+
required_tools=["node", "npm", "npx"],
|
|
559
|
+
package_dependencies=["@modelcontextprotocol/server-slack"],
|
|
560
|
+
system_requirements=["Slack app with bot token"],
|
|
561
|
+
),
|
|
562
|
+
),
|
|
563
|
+
MCPServerTemplate(
|
|
564
|
+
id="discord",
|
|
565
|
+
name="discord",
|
|
566
|
+
display_name="Discord Bot",
|
|
567
|
+
description="Interact with Discord servers and channels",
|
|
568
|
+
category="Communication",
|
|
569
|
+
tags=["discord", "chat", "bot", "messaging"],
|
|
570
|
+
type="stdio",
|
|
571
|
+
config={
|
|
572
|
+
"command": "npx",
|
|
573
|
+
"args": ["-y", "@modelcontextprotocol/server-discord"],
|
|
574
|
+
"env": {"DISCORD_TOKEN": "$DISCORD_TOKEN"},
|
|
575
|
+
"timeout": 30,
|
|
576
|
+
},
|
|
577
|
+
verified=True,
|
|
578
|
+
requires=MCPServerRequirements(
|
|
579
|
+
environment_vars=["DISCORD_TOKEN"],
|
|
580
|
+
required_tools=["node", "npm", "npx"],
|
|
581
|
+
package_dependencies=["@modelcontextprotocol/server-discord"],
|
|
582
|
+
system_requirements=["Discord bot token"],
|
|
583
|
+
),
|
|
584
|
+
),
|
|
585
|
+
MCPServerTemplate(
|
|
586
|
+
id="email",
|
|
587
|
+
name="email",
|
|
588
|
+
display_name="Email (SMTP/IMAP)",
|
|
589
|
+
description="Send and receive emails",
|
|
590
|
+
category="Communication",
|
|
591
|
+
tags=["email", "smtp", "imap", "mail"],
|
|
592
|
+
type="stdio",
|
|
593
|
+
config={
|
|
594
|
+
"command": "npx",
|
|
595
|
+
"args": ["-y", "@modelcontextprotocol/server-email"],
|
|
596
|
+
"timeout": 30,
|
|
597
|
+
},
|
|
598
|
+
verified=True,
|
|
599
|
+
requires=MCPServerRequirements(
|
|
600
|
+
environment_vars=["EMAIL_HOST", "EMAIL_PORT", "EMAIL_USER", "EMAIL_PASS"],
|
|
601
|
+
required_tools=["node", "npm", "npx"],
|
|
602
|
+
package_dependencies=["@modelcontextprotocol/server-email"],
|
|
603
|
+
),
|
|
604
|
+
),
|
|
605
|
+
# ========== AI & Machine Learning ==========
|
|
606
|
+
MCPServerTemplate(
|
|
607
|
+
id="openai",
|
|
608
|
+
name="openai",
|
|
609
|
+
display_name="OpenAI API",
|
|
610
|
+
description="Access OpenAI models for text, image, and embedding generation",
|
|
611
|
+
category="AI",
|
|
612
|
+
tags=["ai", "openai", "gpt", "dalle", "embedding"],
|
|
613
|
+
type="stdio",
|
|
614
|
+
config={
|
|
615
|
+
"command": "npx",
|
|
616
|
+
"args": ["-y", "@modelcontextprotocol/server-openai"],
|
|
617
|
+
"env": {"OPENAI_API_KEY": "$OPENAI_API_KEY"},
|
|
618
|
+
"timeout": 60,
|
|
619
|
+
},
|
|
620
|
+
verified=True,
|
|
621
|
+
popular=True,
|
|
622
|
+
requires=MCPServerRequirements(
|
|
623
|
+
environment_vars=["OPENAI_API_KEY"],
|
|
624
|
+
required_tools=["node", "npm", "npx"],
|
|
625
|
+
package_dependencies=["@modelcontextprotocol/server-openai"],
|
|
626
|
+
),
|
|
627
|
+
),
|
|
628
|
+
MCPServerTemplate(
|
|
629
|
+
id="anthropic",
|
|
630
|
+
name="anthropic",
|
|
631
|
+
display_name="Anthropic Claude API",
|
|
632
|
+
description="Access Anthropic's Claude models",
|
|
633
|
+
category="AI",
|
|
634
|
+
tags=["ai", "anthropic", "claude", "llm"],
|
|
635
|
+
type="stdio",
|
|
636
|
+
config={
|
|
637
|
+
"command": "npx",
|
|
638
|
+
"args": ["-y", "@modelcontextprotocol/server-anthropic"],
|
|
639
|
+
"env": {"ANTHROPIC_API_KEY": "$ANTHROPIC_API_KEY"},
|
|
640
|
+
"timeout": 60,
|
|
641
|
+
},
|
|
642
|
+
verified=True,
|
|
643
|
+
requires=MCPServerRequirements(
|
|
644
|
+
environment_vars=["ANTHROPIC_API_KEY"],
|
|
645
|
+
required_tools=["node", "npm", "npx"],
|
|
646
|
+
package_dependencies=["@modelcontextprotocol/server-anthropic"],
|
|
647
|
+
),
|
|
648
|
+
),
|
|
649
|
+
# ========== Data Processing ==========
|
|
650
|
+
MCPServerTemplate(
|
|
651
|
+
id="pandas",
|
|
652
|
+
name="pandas",
|
|
653
|
+
display_name="Pandas Data Analysis",
|
|
654
|
+
description="Process and analyze data using Python pandas",
|
|
655
|
+
category="Data",
|
|
656
|
+
tags=["data", "pandas", "python", "analysis", "csv", "dataframe"],
|
|
657
|
+
type="stdio",
|
|
658
|
+
config={
|
|
659
|
+
"command": "python",
|
|
660
|
+
"args": ["-m", "mcp_server_pandas"],
|
|
661
|
+
"timeout": 30,
|
|
662
|
+
},
|
|
663
|
+
verified=True,
|
|
664
|
+
popular=True,
|
|
665
|
+
requires=MCPServerRequirements(
|
|
666
|
+
required_tools=["python", "pip"],
|
|
667
|
+
package_dependencies=["pandas", "mcp-server-pandas"],
|
|
668
|
+
),
|
|
669
|
+
),
|
|
670
|
+
MCPServerTemplate(
|
|
671
|
+
id="jupyter",
|
|
672
|
+
name="jupyter",
|
|
673
|
+
display_name="Jupyter Notebook",
|
|
674
|
+
description="Execute code in Jupyter notebooks",
|
|
675
|
+
category="Data",
|
|
676
|
+
tags=["jupyter", "notebook", "python", "data-science"],
|
|
677
|
+
type="stdio",
|
|
678
|
+
config={
|
|
679
|
+
"command": "python",
|
|
680
|
+
"args": ["-m", "mcp_server_jupyter"],
|
|
681
|
+
"timeout": 60,
|
|
682
|
+
},
|
|
683
|
+
verified=True,
|
|
684
|
+
requires=MCPServerRequirements(
|
|
685
|
+
required_tools=["python", "pip", "jupyter"],
|
|
686
|
+
package_dependencies=["jupyter", "mcp-server-jupyter"],
|
|
687
|
+
),
|
|
688
|
+
),
|
|
689
|
+
# ========== Cloud Services ==========
|
|
690
|
+
MCPServerTemplate(
|
|
691
|
+
id="aws-s3",
|
|
692
|
+
name="aws-s3",
|
|
693
|
+
display_name="AWS S3 Storage",
|
|
694
|
+
description="Manage AWS S3 buckets and objects",
|
|
695
|
+
category="Cloud",
|
|
696
|
+
tags=["aws", "s3", "storage", "cloud", "bucket"],
|
|
697
|
+
type="stdio",
|
|
698
|
+
config={
|
|
699
|
+
"command": "npx",
|
|
700
|
+
"args": ["-y", "@modelcontextprotocol/server-aws-s3"],
|
|
701
|
+
"env": {
|
|
702
|
+
"AWS_ACCESS_KEY_ID": "$AWS_ACCESS_KEY_ID",
|
|
703
|
+
"AWS_SECRET_ACCESS_KEY": "$AWS_SECRET_ACCESS_KEY",
|
|
704
|
+
},
|
|
705
|
+
"timeout": 30,
|
|
706
|
+
},
|
|
707
|
+
verified=True,
|
|
708
|
+
popular=True,
|
|
709
|
+
requires=MCPServerRequirements(
|
|
710
|
+
environment_vars=["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"],
|
|
711
|
+
command_line_args=[
|
|
712
|
+
{
|
|
713
|
+
"name": "region",
|
|
714
|
+
"prompt": "AWS region",
|
|
715
|
+
"default": "us-east-1",
|
|
716
|
+
"required": False,
|
|
717
|
+
}
|
|
718
|
+
],
|
|
719
|
+
required_tools=["node", "npm", "npx"],
|
|
720
|
+
package_dependencies=["@modelcontextprotocol/server-aws-s3"],
|
|
721
|
+
system_requirements=["AWS account with S3 access"],
|
|
722
|
+
),
|
|
723
|
+
),
|
|
724
|
+
MCPServerTemplate(
|
|
725
|
+
id="azure-storage",
|
|
726
|
+
name="azure-storage",
|
|
727
|
+
display_name="Azure Storage",
|
|
728
|
+
description="Manage Azure blob storage",
|
|
729
|
+
category="Cloud",
|
|
730
|
+
tags=["azure", "storage", "cloud", "blob"],
|
|
731
|
+
type="stdio",
|
|
732
|
+
config={
|
|
733
|
+
"command": "npx",
|
|
734
|
+
"args": ["-y", "@modelcontextprotocol/server-azure-storage"],
|
|
735
|
+
"env": {
|
|
736
|
+
"AZURE_STORAGE_CONNECTION_STRING": "$AZURE_STORAGE_CONNECTION_STRING"
|
|
737
|
+
},
|
|
738
|
+
"timeout": 30,
|
|
739
|
+
},
|
|
740
|
+
verified=True,
|
|
741
|
+
requires=MCPServerRequirements(
|
|
742
|
+
environment_vars=["AZURE_STORAGE_CONNECTION_STRING"],
|
|
743
|
+
required_tools=["node", "npm", "npx"],
|
|
744
|
+
package_dependencies=["@modelcontextprotocol/server-azure-storage"],
|
|
745
|
+
system_requirements=["Azure storage account"],
|
|
746
|
+
),
|
|
747
|
+
),
|
|
748
|
+
# ========== Security & Authentication ==========
|
|
749
|
+
MCPServerTemplate(
|
|
750
|
+
id="1password",
|
|
751
|
+
name="1password",
|
|
752
|
+
display_name="1Password Vault",
|
|
753
|
+
description="Access 1Password vaults securely",
|
|
754
|
+
category="Security",
|
|
755
|
+
tags=["security", "password", "vault", "1password", "secrets"],
|
|
756
|
+
type="stdio",
|
|
757
|
+
config={"command": "op", "args": ["mcp-server"], "timeout": 30},
|
|
758
|
+
verified=True,
|
|
759
|
+
requires=MCPServerRequirements(
|
|
760
|
+
required_tools=["op"],
|
|
761
|
+
system_requirements=["1Password CLI installed and authenticated"],
|
|
762
|
+
),
|
|
763
|
+
),
|
|
764
|
+
MCPServerTemplate(
|
|
765
|
+
id="vault",
|
|
766
|
+
name="vault",
|
|
767
|
+
display_name="HashiCorp Vault",
|
|
768
|
+
description="Manage secrets in HashiCorp Vault",
|
|
769
|
+
category="Security",
|
|
770
|
+
tags=["security", "vault", "secrets", "hashicorp"],
|
|
771
|
+
type="stdio",
|
|
772
|
+
config={
|
|
773
|
+
"command": "npx",
|
|
774
|
+
"args": ["-y", "@modelcontextprotocol/server-vault"],
|
|
775
|
+
"env": {"VAULT_TOKEN": "$VAULT_TOKEN"},
|
|
776
|
+
"timeout": 30,
|
|
777
|
+
},
|
|
778
|
+
verified=True,
|
|
779
|
+
requires=MCPServerRequirements(
|
|
780
|
+
environment_vars=["VAULT_TOKEN", "VAULT_ADDR"],
|
|
781
|
+
required_tools=["node", "npm", "npx"],
|
|
782
|
+
package_dependencies=["@modelcontextprotocol/server-vault"],
|
|
783
|
+
system_requirements=["HashiCorp Vault server accessible"],
|
|
784
|
+
),
|
|
785
|
+
),
|
|
786
|
+
# ========== Documentation & Knowledge ==========
|
|
787
|
+
MCPServerTemplate(
|
|
788
|
+
id="context7",
|
|
789
|
+
name="context7",
|
|
790
|
+
display_name="Context7 Documentation Search",
|
|
791
|
+
description="Search and retrieve documentation from multiple sources with AI-powered context understanding",
|
|
792
|
+
category="Documentation",
|
|
793
|
+
tags=["documentation", "search", "context", "ai", "knowledge", "docs", "cloud"],
|
|
794
|
+
type="http",
|
|
795
|
+
config={
|
|
796
|
+
"url": "https://mcp.context7.com/mcp",
|
|
797
|
+
"headers": {"Authorization": "Bearer $CONTEXT7_API_KEY"},
|
|
798
|
+
},
|
|
799
|
+
verified=True,
|
|
800
|
+
popular=True,
|
|
801
|
+
requires=MCPServerRequirements(
|
|
802
|
+
environment_vars=["CONTEXT7_API_KEY"],
|
|
803
|
+
),
|
|
804
|
+
example_usage="Cloud-based service - no local setup required",
|
|
805
|
+
),
|
|
806
|
+
MCPServerTemplate(
|
|
807
|
+
id="sse-example",
|
|
808
|
+
name="sse-example",
|
|
809
|
+
display_name="SSE Example Server",
|
|
810
|
+
description="Example Server-Sent Events MCP server for testing SSE connections",
|
|
811
|
+
category="Development",
|
|
812
|
+
tags=["sse", "example", "testing", "events"],
|
|
813
|
+
type="sse",
|
|
814
|
+
config={
|
|
815
|
+
"url": "http://localhost:8080/sse",
|
|
816
|
+
"headers": {"Authorization": "Bearer $SSE_API_KEY"},
|
|
817
|
+
},
|
|
818
|
+
verified=False,
|
|
819
|
+
popular=False,
|
|
820
|
+
requires=MCPServerRequirements(
|
|
821
|
+
environment_vars=["SSE_API_KEY"],
|
|
822
|
+
),
|
|
823
|
+
example_usage="Example SSE server - for testing purposes",
|
|
824
|
+
),
|
|
825
|
+
MCPServerTemplate(
|
|
826
|
+
id="confluence",
|
|
827
|
+
name="confluence",
|
|
828
|
+
display_name="Confluence Wiki",
|
|
829
|
+
description="Access and manage Confluence pages",
|
|
830
|
+
category="Documentation",
|
|
831
|
+
tags=["wiki", "confluence", "documentation", "atlassian"],
|
|
832
|
+
type="stdio",
|
|
833
|
+
config={
|
|
834
|
+
"command": "npx",
|
|
835
|
+
"args": ["-y", "@modelcontextprotocol/server-confluence"],
|
|
836
|
+
"env": {"CONFLUENCE_TOKEN": "$CONFLUENCE_TOKEN"},
|
|
837
|
+
"timeout": 30,
|
|
838
|
+
},
|
|
839
|
+
verified=True,
|
|
840
|
+
requires=MCPServerRequirements(
|
|
841
|
+
environment_vars=["CONFLUENCE_TOKEN", "CONFLUENCE_BASE_URL"],
|
|
842
|
+
required_tools=["node", "npm", "npx"],
|
|
843
|
+
package_dependencies=["@modelcontextprotocol/server-confluence"],
|
|
844
|
+
system_requirements=["Confluence API access"],
|
|
845
|
+
),
|
|
846
|
+
),
|
|
847
|
+
MCPServerTemplate(
|
|
848
|
+
id="notion",
|
|
849
|
+
name="notion",
|
|
850
|
+
display_name="Notion Workspace",
|
|
851
|
+
description="Access and manage Notion pages and databases",
|
|
852
|
+
category="Documentation",
|
|
853
|
+
tags=["notion", "wiki", "documentation", "database"],
|
|
854
|
+
type="stdio",
|
|
855
|
+
config={
|
|
856
|
+
"command": "npx",
|
|
857
|
+
"args": ["-y", "@modelcontextprotocol/server-notion"],
|
|
858
|
+
"env": {"NOTION_TOKEN": "$NOTION_TOKEN"},
|
|
859
|
+
"timeout": 30,
|
|
860
|
+
},
|
|
861
|
+
verified=True,
|
|
862
|
+
popular=True,
|
|
863
|
+
requires=MCPServerRequirements(
|
|
864
|
+
environment_vars=["NOTION_TOKEN"],
|
|
865
|
+
required_tools=["node", "npm", "npx"],
|
|
866
|
+
package_dependencies=["@modelcontextprotocol/server-notion"],
|
|
867
|
+
system_requirements=["Notion integration API key"],
|
|
868
|
+
),
|
|
869
|
+
),
|
|
870
|
+
# ========== DevOps & Infrastructure ==========
|
|
871
|
+
MCPServerTemplate(
|
|
872
|
+
id="docker",
|
|
873
|
+
name="docker",
|
|
874
|
+
display_name="Docker Management",
|
|
875
|
+
description="Manage Docker containers and images",
|
|
876
|
+
category="DevOps",
|
|
877
|
+
tags=["docker", "container", "devops", "infrastructure"],
|
|
878
|
+
type="stdio",
|
|
879
|
+
config={
|
|
880
|
+
"command": "npx",
|
|
881
|
+
"args": ["-y", "@modelcontextprotocol/server-docker"],
|
|
882
|
+
"timeout": 30,
|
|
883
|
+
},
|
|
884
|
+
verified=True,
|
|
885
|
+
popular=True,
|
|
886
|
+
requires=MCPServerRequirements(
|
|
887
|
+
required_tools=["node", "npm", "npx", "docker"],
|
|
888
|
+
package_dependencies=["@modelcontextprotocol/server-docker"],
|
|
889
|
+
system_requirements=["Docker daemon running"],
|
|
890
|
+
),
|
|
891
|
+
),
|
|
892
|
+
MCPServerTemplate(
|
|
893
|
+
id="kubernetes",
|
|
894
|
+
name="kubernetes",
|
|
895
|
+
display_name="Kubernetes Cluster",
|
|
896
|
+
description="Manage Kubernetes resources",
|
|
897
|
+
category="DevOps",
|
|
898
|
+
tags=["kubernetes", "k8s", "container", "orchestration"],
|
|
899
|
+
type="stdio",
|
|
900
|
+
config={
|
|
901
|
+
"command": "npx",
|
|
902
|
+
"args": ["-y", "@modelcontextprotocol/server-kubernetes"],
|
|
903
|
+
"timeout": 30,
|
|
904
|
+
},
|
|
905
|
+
verified=True,
|
|
906
|
+
requires=MCPServerRequirements(
|
|
907
|
+
required_tools=["node", "npm", "npx", "kubectl"],
|
|
908
|
+
package_dependencies=["@modelcontextprotocol/server-kubernetes"],
|
|
909
|
+
system_requirements=["Kubernetes cluster access (kubeconfig)"],
|
|
910
|
+
),
|
|
911
|
+
),
|
|
912
|
+
MCPServerTemplate(
|
|
913
|
+
id="terraform",
|
|
914
|
+
name="terraform",
|
|
915
|
+
display_name="Terraform Infrastructure",
|
|
916
|
+
description="Manage infrastructure as code with Terraform",
|
|
917
|
+
category="DevOps",
|
|
918
|
+
tags=["terraform", "iac", "infrastructure", "devops"],
|
|
919
|
+
type="stdio",
|
|
920
|
+
config={
|
|
921
|
+
"command": "npx",
|
|
922
|
+
"args": ["-y", "@modelcontextprotocol/server-terraform"],
|
|
923
|
+
"timeout": 60,
|
|
924
|
+
},
|
|
925
|
+
verified=True,
|
|
926
|
+
requires=MCPServerRequirements(
|
|
927
|
+
required_tools=["node", "npm", "npx", "terraform"],
|
|
928
|
+
package_dependencies=["@modelcontextprotocol/server-terraform"],
|
|
929
|
+
system_requirements=["Terraform configuration files"],
|
|
930
|
+
),
|
|
931
|
+
),
|
|
932
|
+
# ========== Monitoring & Observability ==========
|
|
933
|
+
MCPServerTemplate(
|
|
934
|
+
id="prometheus",
|
|
935
|
+
name="prometheus",
|
|
936
|
+
display_name="Prometheus Metrics",
|
|
937
|
+
description="Query Prometheus metrics",
|
|
938
|
+
category="Monitoring",
|
|
939
|
+
tags=["monitoring", "metrics", "prometheus", "observability"],
|
|
940
|
+
type="stdio",
|
|
941
|
+
config={
|
|
942
|
+
"command": "npx",
|
|
943
|
+
"args": [
|
|
944
|
+
"-y",
|
|
945
|
+
"@modelcontextprotocol/server-prometheus",
|
|
946
|
+
"${prometheus_url}",
|
|
947
|
+
],
|
|
948
|
+
"timeout": 30,
|
|
949
|
+
},
|
|
950
|
+
verified=True,
|
|
951
|
+
requires=MCPServerRequirements(
|
|
952
|
+
command_line_args=[
|
|
953
|
+
{
|
|
954
|
+
"name": "prometheus_url",
|
|
955
|
+
"prompt": "Prometheus server URL",
|
|
956
|
+
"default": "http://localhost:9090",
|
|
957
|
+
"required": True,
|
|
958
|
+
}
|
|
959
|
+
],
|
|
960
|
+
required_tools=["node", "npm", "npx"],
|
|
961
|
+
package_dependencies=["@modelcontextprotocol/server-prometheus"],
|
|
962
|
+
system_requirements=["Prometheus server accessible"],
|
|
963
|
+
),
|
|
964
|
+
),
|
|
965
|
+
MCPServerTemplate(
|
|
966
|
+
id="grafana",
|
|
967
|
+
name="grafana",
|
|
968
|
+
display_name="Grafana Dashboards",
|
|
969
|
+
description="Access Grafana dashboards and alerts",
|
|
970
|
+
category="Monitoring",
|
|
971
|
+
tags=["monitoring", "dashboard", "grafana", "visualization"],
|
|
972
|
+
type="stdio",
|
|
973
|
+
config={
|
|
974
|
+
"command": "npx",
|
|
975
|
+
"args": ["-y", "@modelcontextprotocol/server-grafana"],
|
|
976
|
+
"env": {"GRAFANA_TOKEN": "$GRAFANA_TOKEN"},
|
|
977
|
+
"timeout": 30,
|
|
978
|
+
},
|
|
979
|
+
verified=True,
|
|
980
|
+
requires=MCPServerRequirements(
|
|
981
|
+
environment_vars=["GRAFANA_TOKEN", "GRAFANA_URL"],
|
|
982
|
+
required_tools=["node", "npm", "npx"],
|
|
983
|
+
package_dependencies=["@modelcontextprotocol/server-grafana"],
|
|
984
|
+
system_requirements=["Grafana server with API access"],
|
|
985
|
+
),
|
|
986
|
+
),
|
|
987
|
+
# ========== Package Management ==========
|
|
988
|
+
MCPServerTemplate(
|
|
989
|
+
id="npm",
|
|
990
|
+
name="npm",
|
|
991
|
+
display_name="NPM Package Manager",
|
|
992
|
+
description="Search and manage NPM packages",
|
|
993
|
+
category="Package Management",
|
|
994
|
+
tags=["npm", "node", "package", "javascript"],
|
|
995
|
+
type="stdio",
|
|
996
|
+
config={
|
|
997
|
+
"command": "npx",
|
|
998
|
+
"args": ["-y", "@modelcontextprotocol/server-npm"],
|
|
999
|
+
"timeout": 30,
|
|
1000
|
+
},
|
|
1001
|
+
verified=True,
|
|
1002
|
+
requires=MCPServerRequirements(
|
|
1003
|
+
required_tools=["node", "npm", "npx"],
|
|
1004
|
+
package_dependencies=["@modelcontextprotocol/server-npm"],
|
|
1005
|
+
),
|
|
1006
|
+
),
|
|
1007
|
+
MCPServerTemplate(
|
|
1008
|
+
id="pypi",
|
|
1009
|
+
name="pypi",
|
|
1010
|
+
display_name="PyPI Package Manager",
|
|
1011
|
+
description="Search and manage Python packages",
|
|
1012
|
+
category="Package Management",
|
|
1013
|
+
tags=["python", "pip", "pypi", "package"],
|
|
1014
|
+
type="stdio",
|
|
1015
|
+
config={"command": "python", "args": ["-m", "mcp_server_pypi"], "timeout": 30},
|
|
1016
|
+
verified=True,
|
|
1017
|
+
requires=MCPServerRequirements(
|
|
1018
|
+
required_tools=["python", "pip"], package_dependencies=["mcp-server-pypi"]
|
|
1019
|
+
),
|
|
1020
|
+
),
|
|
1021
|
+
]
|
|
1022
|
+
|
|
1023
|
+
|
|
1024
|
+
class MCPServerCatalog:
|
|
1025
|
+
"""Catalog for searching and managing pre-configured MCP servers."""
|
|
1026
|
+
|
|
1027
|
+
def __init__(self):
|
|
1028
|
+
# Start with built-in servers
|
|
1029
|
+
self.servers = list(MCP_SERVER_REGISTRY)
|
|
1030
|
+
|
|
1031
|
+
# Let plugins add their own catalog entries
|
|
1032
|
+
try:
|
|
1033
|
+
from code_puppy.callbacks import on_register_mcp_catalog_servers
|
|
1034
|
+
|
|
1035
|
+
plugin_results = on_register_mcp_catalog_servers()
|
|
1036
|
+
for result in plugin_results:
|
|
1037
|
+
if isinstance(result, list):
|
|
1038
|
+
self.servers.extend(result)
|
|
1039
|
+
except Exception:
|
|
1040
|
+
pass # Don't break catalog if plugins fail
|
|
1041
|
+
|
|
1042
|
+
self._build_index()
|
|
1043
|
+
|
|
1044
|
+
def _build_index(self):
|
|
1045
|
+
"""Build search index for fast lookups."""
|
|
1046
|
+
self.by_id = {s.id: s for s in self.servers}
|
|
1047
|
+
self.by_category = {}
|
|
1048
|
+
for server in self.servers:
|
|
1049
|
+
if server.category not in self.by_category:
|
|
1050
|
+
self.by_category[server.category] = []
|
|
1051
|
+
self.by_category[server.category].append(server)
|
|
1052
|
+
|
|
1053
|
+
def search(self, query: str) -> List[MCPServerTemplate]:
|
|
1054
|
+
"""
|
|
1055
|
+
Search for servers by name, description, or tags.
|
|
1056
|
+
|
|
1057
|
+
Args:
|
|
1058
|
+
query: Search query string
|
|
1059
|
+
|
|
1060
|
+
Returns:
|
|
1061
|
+
List of matching server templates
|
|
1062
|
+
"""
|
|
1063
|
+
query_lower = query.lower()
|
|
1064
|
+
results = []
|
|
1065
|
+
|
|
1066
|
+
for server in self.servers:
|
|
1067
|
+
# Check name
|
|
1068
|
+
if query_lower in server.name.lower():
|
|
1069
|
+
results.append(server)
|
|
1070
|
+
continue
|
|
1071
|
+
|
|
1072
|
+
# Check display name
|
|
1073
|
+
if query_lower in server.display_name.lower():
|
|
1074
|
+
results.append(server)
|
|
1075
|
+
continue
|
|
1076
|
+
|
|
1077
|
+
# Check description
|
|
1078
|
+
if query_lower in server.description.lower():
|
|
1079
|
+
results.append(server)
|
|
1080
|
+
continue
|
|
1081
|
+
|
|
1082
|
+
# Check tags
|
|
1083
|
+
for tag in server.tags:
|
|
1084
|
+
if query_lower in tag.lower():
|
|
1085
|
+
results.append(server)
|
|
1086
|
+
break
|
|
1087
|
+
|
|
1088
|
+
# Check category
|
|
1089
|
+
if query_lower in server.category.lower() and server not in results:
|
|
1090
|
+
results.append(server)
|
|
1091
|
+
|
|
1092
|
+
# Sort by relevance (name matches first, then popular)
|
|
1093
|
+
results.sort(
|
|
1094
|
+
key=lambda s: (
|
|
1095
|
+
not s.name.lower().startswith(query_lower),
|
|
1096
|
+
not s.popular,
|
|
1097
|
+
s.name,
|
|
1098
|
+
)
|
|
1099
|
+
)
|
|
1100
|
+
|
|
1101
|
+
return results
|
|
1102
|
+
|
|
1103
|
+
def get_by_id(self, server_id: str) -> Optional[MCPServerTemplate]:
|
|
1104
|
+
"""Get server template by ID."""
|
|
1105
|
+
return self.by_id.get(server_id)
|
|
1106
|
+
|
|
1107
|
+
def get_by_category(self, category: str) -> List[MCPServerTemplate]:
|
|
1108
|
+
"""Get all servers in a category."""
|
|
1109
|
+
return self.by_category.get(category, [])
|
|
1110
|
+
|
|
1111
|
+
def list_categories(self) -> List[str]:
|
|
1112
|
+
"""List all available categories."""
|
|
1113
|
+
return sorted(self.by_category.keys())
|
|
1114
|
+
|
|
1115
|
+
def get_popular(self, limit: int = 10) -> List[MCPServerTemplate]:
|
|
1116
|
+
"""Get popular servers."""
|
|
1117
|
+
popular = [s for s in self.servers if s.popular]
|
|
1118
|
+
return popular[:limit]
|
|
1119
|
+
|
|
1120
|
+
def get_verified(self) -> List[MCPServerTemplate]:
|
|
1121
|
+
"""Get all verified servers."""
|
|
1122
|
+
return [s for s in self.servers if s.verified]
|
|
1123
|
+
|
|
1124
|
+
|
|
1125
|
+
# Global catalog instance
|
|
1126
|
+
catalog = MCPServerCatalog()
|