From 7ecfb1fefd0d82917dc18e2aef71085f965861e5 Mon Sep 17 00:00:00 2001 From: Fanyang Meng Date: Thu, 13 Feb 2025 00:21:56 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Implemented=20dynamic=20module?= =?UTF-8?q?=20discovery=20and=20import?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ghost_mcp/tools.py | 143 ++++++++++++++++------------------------- 1 file changed, 54 insertions(+), 89 deletions(-) diff --git a/src/ghost_mcp/tools.py b/src/ghost_mcp/tools.py index e648c4b..51d718a 100644 --- a/src/ghost_mcp/tools.py +++ b/src/ghost_mcp/tools.py @@ -1,91 +1,56 @@ -"""Ghost MCP tools package.""" +"""Ghost MCP tools package. -# Re-export all tools from their respective modules -from .tools.posts import ( - search_posts_by_title, - list_posts, - read_post, - create_post, - update_post, - delete_post, - batchly_update_post -) -from .tools.users import ( - list_users, - read_user, - update_user, - delete_user -) -from .tools.members import ( - list_members, - read_member, - create_member, - update_member -) -from .tools.tiers import ( - list_tiers, - read_tier, - create_tier, - update_tier -) -from .tools.offers import ( - list_offers, - read_offer, - create_offer, - update_offer -) -from .tools.newsletters import ( - list_newsletters, - read_newsletter, - create_newsletter, - update_newsletter -) -from .tools.roles import list_roles -from .tools.invites import create_invite -from .tools.webhooks import create_webhook, update_webhook, delete_webhook -from .tools.tags import ( - browse_tags, - read_tag, - create_tag, - update_tag, - delete_tag -) +This module dynamically imports all tools from the tools package directory. +It automatically discovers and imports all non-private functions and variables +from Python files in the tools directory, making them available at the package level. -__all__ = [ - 'search_posts_by_title', - 'list_posts', - 'read_post', - 'create_post', - 'update_post', - 'delete_post', - 'batchly_update_post', - 'list_users', - 'read_user', - 'update_user', - 'delete_user', - 'list_members', - 'read_member', - 'create_member', - 'list_tiers', - 'read_tier', - 'create_tier', - 'update_tier', - 'list_offers', - 'read_offer', - 'create_offer', - 'update_offer', - 'list_newsletters', - 'read_newsletter', - 'create_newsletter', - 'update_newsletter', - 'list_roles', - 'create_invite', - 'create_webhook', - 'update_webhook', - 'delete_webhook', - 'browse_tags', - 'read_tag', - 'create_tag', - 'update_tag', - 'delete_tag' -] +When adding new tools: +1. Create new Python files in the tools directory +2. Define your tools as functions in these files +3. No need to modify this file - tools will be imported automatically +""" + +from importlib import import_module +from pathlib import Path +from typing import Dict, Any + +def _import_submodules() -> Dict[str, Any]: + """Dynamically import all modules from the tools package. + + Returns: + Dict mapping module names to imported module objects + + Raises: + FileNotFoundError: If the tools directory doesn't exist + """ + current_dir = Path(__file__).parent + tools_dir = current_dir / 'tools' + + if not tools_dir.exists(): + raise FileNotFoundError(f"Tools directory not found at: {tools_dir}") + + modules: Dict[str, Any] = {} + for py_file in tools_dir.glob('*.py'): + if py_file.name.startswith('__'): + continue + + module_name = py_file.stem + full_module_name = f"ghost_mcp.tools.{module_name}" + + # Import the module + module = import_module(f".tools.{module_name}", package="ghost_mcp") + modules[module_name] = module + + # Get all non-private attributes + for attr_name in dir(module): + if not attr_name.startswith('_'): + # Add to the current module's namespace + globals()[attr_name] = getattr(module, attr_name) + + return modules + +# Run the dynamic imports +_import_submodules() + +# Create sorted __all__ from the imported attributes for consistent ordering +__all__ = sorted(name for name in globals() if not name.startswith('_'))