Skip to main content
Glama
TheOneTrueNiz

Grokipedia MCP Server

get_page_section

Read-onlyIdempotent

Extract specific sections from Grokipedia articles by header name to focus on particular aspects like History or Applications. Use get_page_sections first to discover available headers.

Instructions

Extract a specific section from a Grokipedia article by header name.

Use for: focusing on particular aspects of a topic (e.g., 'History', 'Applications'). Returns: section header and content. Tips: Use get_page_sections first to discover available section headers.

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 `get_page_section` handler function which extracts a specific section from a Grokipedia article based on a provided header.
    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 a Grokipedia article by header name.
    
        Use for: focusing on particular aspects of a topic (e.g., 'History', 'Applications').
        Returns: section header and content.
        Tips: Use get_page_sections first to discover available section headers.
        """
        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
  • MCP tool registration for the get_page_section function.
    @mcp.tool(
        annotations=ToolAnnotations(
            readOnlyHint=True,
            destructiveHint=False,
            idempotentHint=True
        )
    )
Behavior4/5

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

Annotations declare readOnly/idempotent/non-destructive properties. Description adds valuable behavioral context: return format ('section header and content') and operational workflow (discovery prerequisite). No contradictions with annotations; 'Extract' aligns with readOnlyHint=true.

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

Conciseness5/5

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

Extremely efficient structure using labeled clauses (Use for:, Returns:, Tips:). Every sentence earns its place—no filler. Front-loaded with core purpose, followed by usage context and workflow tip. Optimal length for quick agent comprehension.

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

Completeness4/5

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

No output schema exists, but description compensates by stating return format ('section header and content'). Workflow guidance (use get_page_sections first) provides necessary operational context. Lacks error handling documentation (e.g., section not found), but adequately complete given schema richness.

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

Parameters4/5

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

Schema coverage is 100% with complete property descriptions. Description enhances semantics by providing concrete example values for section_header ('History', 'Applications') that clarify expected input format beyond the schema's generic 'Exact header text' description.

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?

Description states specific action ('Extract') + resource ('section from a Grokipedia article') + mechanism ('by header name'). It clearly distinguishes from sibling 'get_page_sections' by targeting a specific section rather than listing all sections.

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

Usage Guidelines5/5

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

Explicitly states when to use ('focusing on particular aspects of a topic') and provides concrete examples ('History', 'Applications'). Critically, it names the sibling alternative 'get_page_sections' with specific instruction to use it first, establishing clear workflow precedence.

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

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