Skip to main content
Glama

get_page_section

Extract specific sections from Grokipedia articles by header name to retrieve targeted information without reading entire pages.

Instructions

Extract a specific section from an article by header name.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
slugYesUnique slug identifier of page to extract section from
section_headerYesExact header text of the section to extract (case-insensitive)
max_lengthNoMaximum length of section content to return (default: 5000)

Implementation Reference

  • The @mcp.tool decorator registers the 'get_page_section' tool with appropriate annotations indicating it is read-only, non-destructive, and idempotent.
    @mcp.tool(
        annotations=ToolAnnotations(
            readOnlyHint=True,
            destructiveHint=False,
            idempotentHint=True
        )
    )
  • The core handler function that implements the 'get_page_section' tool logic: fetches page content, parses markdown headers to extract the specified section, truncates if necessary, and returns both text and structured content.
    async def get_page_section(
        slug: Annotated[str, Field(description="Unique slug identifier of page to extract section from")],
        section_header: Annotated[str, Field(description="Exact header text of the section to extract (case-insensitive)")],
        max_length: Annotated[int, Field(description="Maximum length of section content to return (default: 5000)", ge=100)] = 5000,
        ctx: Context[ServerSession, AppContext] | None = None,
    ) -> CallToolResult:
        """Extract a specific section from an article by header name."""
        if ctx is None:
            raise ValueError("Context is required")
    
        await ctx.debug(f"Fetching section '{section_header}' from: '{slug}'")
    
        try:
            client = ctx.request_context.lifespan_context.client
            result = await client.get_page(slug=slug, include_content=True)
    
            if not result.found or result.page is None:
                await ctx.warning(f"Page not found: '{slug}'")
                raise ValueError(f"Page not found: {slug}")
    
            page = result.page
            content = page.content or ""
            
            header_pattern = rf'^#+\s*{re.escape(section_header)}\s*$'
            lines = content.split('\n')
            
            section_start = None
            section_end = None
            section_level = None
            
            for i, line in enumerate(lines):
                if section_start is None:
                    if re.match(header_pattern, line, re.IGNORECASE):
                        section_start = i
                        section_level = len(line) - len(line.lstrip('#'))
                elif section_start is not None:
                    if line.startswith('#'):
                        current_level = len(line) - len(line.lstrip('#'))
                        if section_level is not None and current_level <= section_level:
                            section_end = i
                            break
            
            if section_start is None:
                await ctx.warning(f"Section '{section_header}' not found in '{slug}'")
                raise ValueError(f"Section '{section_header}' not found")
            
            if section_end is None:
                section_end = len(lines)
            
            section_content = '\n'.join(lines[section_start:section_end]).strip()
            section_len = len(section_content)
            is_truncated = section_len > max_length
            
            if is_truncated:
                section_content = section_content[:max_length]
                await ctx.warning(
                    f"Section content truncated from {section_len} to {max_length} chars"
                )
            
            await ctx.info(f"Extracted section '{section_header}' from '{page.title}'")
            
            text_output = f"# {page.title}\n## {section_header}\n\n{section_content}"
            if is_truncated:
                text_output += f"\n\n... (truncated at {max_length} of {section_len} chars)"
            
            structured = {
                "slug": page.slug,
                "title": page.title,
                "section_header": section_header,
                "section_content": section_content,
                "content_length": len(section_content),
            }
    
            if is_truncated:
                structured["_truncated"] = True
                structured["_original_length"] = section_len
    
            return CallToolResult(
                content=[TextContent(type="text", text=text_output)],
                structuredContent=structured,
            )
    
        except GrokipediaNotFoundError as e:
            await ctx.error(f"Page not found: {e}")
            raise ValueError(f"Page not found: {slug}") from e
        except GrokipediaBadRequestError as e:
            await ctx.error(f"Bad request: {e}")
            raise ValueError(f"Invalid page slug: {e}") from e
        except GrokipediaNetworkError as e:
            await ctx.error(f"Network error: {e}")
            raise RuntimeError(f"Failed to connect to Grokipedia API: {e}") from e
        except GrokipediaAPIError as e:
            await ctx.error(f"API error: {e}")
            raise RuntimeError(f"Grokipedia API error: {e}") from e
  • Input schema defined via Annotated types with Field descriptions for parameters: slug (str), section_header (str), max_length (int, default 5000, >=100), and ctx. Output is CallToolResult.
        slug: Annotated[str, Field(description="Unique slug identifier of page to extract section from")],
        section_header: Annotated[str, Field(description="Exact header text of the section to extract (case-insensitive)")],
        max_length: Annotated[int, Field(description="Maximum length of section content to return (default: 5000)", ge=100)] = 5000,
        ctx: Context[ServerSession, AppContext] | None = None,
    ) -> CallToolResult:

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/skymoore/grokipedia-mcp'

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