Skip to main content
Glama

get_module_pages

Retrieve all pages (lessons) within a specific module of a Hotmart members area using the module ID and subdomain.

Instructions

Get Pages

Retorna as páginas (aulas) de um módulo.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
module_idYesID do módulo
subdomainYesSubdomínio da área de membros
selectNoSeleção de campos customizados na resposta

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The `get_module_pages` async handler function. Calls GET /club/api/v1/modules/{module_id}/pages via get_client(), passing subdomain and optional select params, returning JSON string.
    async def get_module_pages(
        module_id: str,
        subdomain: str,
        select: Optional[str] = None,
    ) -> str:
        """Get Pages
        
        Retorna as páginas (aulas) de um módulo.
        
        Args:
            module_id: ID do módulo
            subdomain: Subdomínio da área de membros
            select: Seleção de campos customizados na resposta"""
        endpoint = f"/club/api/v1/modules/{module_id}/pages"
        params = {}
        if subdomain is not None:
            params["subdomain"] = subdomain
        if select is not None:
            params["select"] = select
        result = await get_client().get(endpoint, params=params)
        return json.dumps(result, indent=2)
  • Automatic registration in `_discover_and_register_tools()`: iterates all tool modules, finds async functions, and registers them as MCP tools via `mcp.tool()(obj)`.
    def _discover_and_register_tools() -> int:
        """Import all modules under hotmart_mcp.tools and register async functions."""
        registered = 0
    
        for module_info in pkgutil.iter_modules(tools_pkg.__path__, prefix=f"{tools_pkg.__name__}."):
            if module_info.name.endswith("__init__"):
                continue
    
            module = importlib.import_module(module_info.name)
    
            for name, obj in inspect.getmembers(module, iscoroutinefunction):
                if name.startswith("_"):
                    continue
                mcp.tool()(obj)
                registered += 1
    
        return registered
  • The `get_client()` helper that provides the shared HotmartClient singleton used by get_module_pages.
    """Shared lazy singleton for the Hotmart API client."""
    
    from __future__ import annotations
    
    from hotmart_mcp.client import HotmartClient
    
    _client: HotmartClient | None = None
    
    
    def get_client() -> HotmartClient:
        global _client
        if _client is None:
            _client = HotmartClient()
        return _client
  • The `get()` method on `HotmartClient` that get_module_pages calls to make the actual HTTP GET request.
    async def get(
        self,
        path: str,
        params: dict[str, Any] | None = None,
        select: list[str] | None = None,
    ) -> dict[str, Any]:
        return await self._request("GET", path, params=params, select=select)
    
    async def post(
        self,
        path: str,
        json: dict[str, Any] | None = None,
        params: dict[str, Any] | None = None,
    ) -> dict[str, Any]:
        return await self._request("POST", path, params=params, json=json)
    
    async def put(
        self,
        path: str,
        json: dict[str, Any] | None = None,
        params: dict[str, Any] | None = None,
    ) -> dict[str, Any]:
        return await self._request("PUT", path, params=params, json=json)
    
    async def patch(
        self,
        path: str,
        json: dict[str, Any] | None = None,
        params: dict[str, Any] | None = None,
    ) -> dict[str, Any]:
        return await self._request("PATCH", path, params=params, json=json)
    
    async def delete(
        self,
        path: str,
        params: dict[str, Any] | None = None,
    ) -> dict[str, Any]:
        return await self._request("DELETE", path, params=params)
    
    async def get_all_pages(
        self,
        path: str,
        params: dict[str, Any] | None = None,
        select: list[str] | None = None,
        items_key: str = "items",
    ) -> list[dict[str, Any]]:
        params = dict(params) if params else {}
        all_items: list[dict[str, Any]] = []
    
        while True:
            data = await self.get(path, params=params, select=select)
            items = data.get(items_key, [])
            all_items.extend(items)
    
            next_token = (data.get("page_info") or {}).get("next_page_token")
            if not next_token:
                break
    
            params["page_token"] = next_token
    
        return all_items
  • Re-exports all club tools (including get_module_pages) via `from .club import *`.
    from .club import *  # noqa: F401,F403
    from .coupons import *  # noqa: F401,F403
    from .negotiation import *  # noqa: F401,F403
    from .products import *  # noqa: F401,F403
    from .sales import *  # noqa: F401,F403
    from .subscriptions import *  # noqa: F401,F403
    from .tickets import *  # noqa: F401,F403
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, and the description only states 'returns pages' without mentioning read-only nature, side effects, or permissions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is very concise with two sentences, front-loading the purpose, though in Portuguese.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, description is adequate for basic purpose, but lacks usage context for sibling differentiation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% so parameters are documented in schema; description adds no extra meaning beyond 'get pages of a module'.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Returns the pages (lessons) of a module' with a specific verb and resource, distinguishing it from siblings like get_modules.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool vs alternatives or any prerequisites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/thaleslaray/hotmart-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server