Skip to main content
Glama
florinel-chis

Magento 2 GraphQL Documentation MCP Server

get_document

Retrieve the full content of any Magento 2 GraphQL documentation page by providing its file path relative to the docs root.

Instructions

Retrieve complete documentation page by file path

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
file_pathYesFile path relative to docs root, e.g., 'schema/products/queries/products.md'

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The get_document MCP tool handler. Decorated with @mcp.tool, it accepts a file_path argument and queries the SQLite database to retrieve and format a full documentation page. It returns the document title, path, category, type, keywords, description, and full markdown content.
    @mcp.tool(
        name="get_document",
        description="Retrieve complete documentation page by file path"
    )
    def get_document(
        file_path: Annotated[str, Field(description="File path relative to docs root, e.g., 'schema/products/queries/products.md'")]
    ) -> str:
        """Get full document content"""
        db = Database(DB_PATH)
    
        try:
            # Query by file_path
            doc = dict(db.query(
                "SELECT * FROM documents WHERE file_path = ?",
                [file_path]
            ).__next__())
        except StopIteration:
            return f"Document not found: {file_path}\n\nTip: Use search_documentation to find the correct file path."
    
        # Parse keywords
        keywords = json.loads(doc.get('keywords_json', '[]'))
        keywords_str = ', '.join(keywords) if keywords else 'None'
    
        # Format document
        lines = [
            f"# {doc['title']}",
            "",
            f"**Path:** {doc['file_path']}",
            f"**Category:** {doc['category']}/{doc.get('subcategory', 'N/A')}",
            f"**Type:** {doc.get('content_type', 'N/A')}",
            f"**Keywords:** {keywords_str}",
            "",
        ]
    
        if doc.get('description'):
            lines.append(f"**Description:** {doc['description']}")
            lines.append("")
    
        lines.append("---")
        lines.append("")
        lines.append(doc['content_md'])
    
        return "\n".join(lines)
  • Registration of the get_document tool using FastMCP's @mcp.tool() decorator with the name 'get_document'.
    @mcp.tool(
        name="get_document",
        description="Retrieve complete documentation page by file path"
    )
  • Input schema/signature for get_document: takes a single 'file_path' string parameter annotated with Pydantic Field description, returns a string.
    def get_document(
        file_path: Annotated[str, Field(description="File path relative to docs root, e.g., 'schema/products/queries/products.md'")]
    ) -> str:
  • DB_PATH is a configuration constant that provides the database path used by get_document to connect to the SQLite database.
        return str(db_path)
    
    def get_docs_path() -> str:
        """
        Determines the GraphQL documentation directory path.
    
        Priority order:
        1. MAGENTO_GRAPHQL_DOCS_PATH environment variable
        2. ./data/ directory (symlink or actual directory in project root)
        3. ../commerce-webapi/src/pages/graphql/ (sibling directory)
    
        Validates that the path exists and contains documentation files.
        Raises FileNotFoundError with helpful message if not found.
        """
        # Priority 1: Environment variable
        env_path = os.environ.get("MAGENTO_GRAPHQL_DOCS_PATH")
        if env_path:
            path = Path(env_path).resolve()
            if not path.exists():
                print(f"ERROR: MAGENTO_GRAPHQL_DOCS_PATH set to '{env_path}' but directory does not exist", file=sys.stderr)
                raise FileNotFoundError(
                    f"Documentation directory not found: {env_path}\n"
                    f"The MAGENTO_GRAPHQL_DOCS_PATH environment variable points to a non-existent directory.\n"
                    f"Please verify the path or unset the variable to use auto-detection."
                )
            return str(path)
    
        # Priority 2: ./data/ directory (relative to project root)
        package_dir = Path(__file__).parent.parent
        data_path = package_dir / "data"
        if data_path.exists():
            # Check if it's a symlink or directory with content
            if data_path.is_symlink() or (data_path.is_dir() and list(data_path.glob("*.md"))):
                return str(data_path.resolve())
    
        # Priority 3: Sibling commerce-webapi directory
        sibling_path = package_dir.parent / "commerce-webapi" / "src" / "pages" / "graphql"
        if sibling_path.exists():
            return str(sibling_path)
    
        # No valid path found - provide helpful error message
        error_msg = (
            "Documentation directory not found!\n\n"
            "The Magento GraphQL documentation files are required but could not be located.\n\n"
            "Please choose one of these setup methods:\n\n"
            "1. Set environment variable:\n"
            f"   export MAGENTO_GRAPHQL_DOCS_PATH='/path/to/commerce-webapi/src/pages/graphql'\n\n"
            "2. Create symlink in project (recommended for development):\n"
            f"   cd {package_dir}\n"
            f"   ln -s /path/to/commerce-webapi/src/pages/graphql data\n\n"
            "3. Clone commerce-webapi as sibling directory:\n"
            f"   cd {package_dir.parent}\n"
            "   git clone https://github.com/AdobeDocs/commerce-webapi.git\n\n"
            "For detailed setup instructions, see SETUP.md"
        )
        print(f"ERROR: {error_msg}", file=sys.stderr)
        raise FileNotFoundError(error_msg)
    
    # Configuration values
    DB_PATH = get_db_path()
  • The Document data model used to store and retrieve documentation pages. The get_document handler queries the 'documents' table in the SQLite database, which stores rows matching this schema (title, file_path, category, subcategory, content_type, keywords_json, description, content_md, etc.).
    class Document(BaseModel):
        """Represents a documentation page"""
        id: str  # SHA256 hash of file_path
        file_path: str  # Relative to docs root
        title: str
        description: Optional[str] = None
        keywords: List[str] = Field(default_factory=list)
        category: str  # e.g., "schema", "develop", "usage"
        subcategory: Optional[str] = None  # e.g., "products", "cart"
        content_type: str  # "guide", "reference", "tutorial", "schema"
        searchable_text: str  # Combined: title + description + content
        headers: List[str] = Field(default_factory=list)  # All markdown headers
        last_modified: datetime
        content_md: str  # Full markdown content
    
    
    class CodeBlock(BaseModel):
        """Represents a code example"""
        document_id: str
        language: str  # graphql, json, javascript, bash
        code: str
        context: Optional[str] = None  # Surrounding text for context
        line_number: int
    
    
    class GraphQLElement(BaseModel):
        """Represents a GraphQL schema element"""
        document_id: str
        element_type: str  # query, mutation, type, interface, union
        name: str
        fields: List[str] = Field(default_factory=list)
        parameters: List[str] = Field(default_factory=list)
        return_type: Optional[str] = None
        description: Optional[str] = None
        searchable_text: str
    
    
    class MarkdownDocParser:
        """Parse markdown documentation files"""
    
        def __init__(self, docs_root: Path):
            self.docs_root = Path(docs_root)
            if not self.docs_root.exists():
                raise FileNotFoundError(f"Documentation directory not found: {docs_root}")
    
        def walk_directory(self) -> List[Path]:
            """Find all .md files recursively"""
            md_files = list(self.docs_root.rglob("**/*.md"))
            logger.info(f"Found {len(md_files)} markdown files")
            return md_files
    
        def parse_file(self, file_path: Path) -> Document:
            """Parse single markdown file"""
            # Read file content
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
    
            # Parse frontmatter
            post = frontmatter.loads(content)
            metadata = post.metadata
            markdown_content = post.content
    
            # Get file stats
            stat = file_path.stat()
            last_modified = datetime.fromtimestamp(stat.st_mtime, tz=timezone.utc)
Behavior2/5

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

No annotations are provided, so the description must carry the full burden of behavioral disclosure. It states the operation ('Retrieve') but does not clarify that it is read-only, what happens if the path is invalid, or any side effects. The description is too minimal to adequately inform an agent of behavioral traits.

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?

The description is a single sentence that is front-loaded with the verb and resource. It contains no unnecessary words or information, making it highly concise and well-structured.

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?

Given that the tool has only one parameter, a clear schema description, and an output schema (which obviates the need to describe return values), the description is adequate but minimal. It does not mention error handling, format of the returned page, or any prerequisites. For a straightforward tool, it meets the minimum viable bar but lacks completeness for unexpected scenarios.

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 description coverage is 100% (the single parameter has a detailed description). The tool's description adds the phrase 'by file path,' which is already implied by the parameter name and schema. Since the schema already explains the parameter meaning, the description provides no additional semantic value, resulting in a baseline score.

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 uses a specific verb ('Retrieve') and resource ('complete documentation page') along with the input ('by file path'). It clearly distinguishes from sibling tools like 'search_documentation' (which searches) and 'get_element_details' (which retrieves a specific element, not a full page).

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?

The description provides no explicit guidance on when to use this tool versus alternatives, nor does it mention when not to use it. It implies usage when the file path is known, but lacks context about when to prefer search over direct retrieval.

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/florinel-chis/magento-graphql-docs-mcp'

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