Skip to main content
Glama
server.py9.88 kB
"""Shopify Liquid Documentation MCP Server.""" import logging from typing import List, Optional from fastmcp import FastMCP from .ingest import ( index_documentation, search_documentation, get_by_category, get_document, ) logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # Initialize FastMCP server mcp = FastMCP("Shopify Liquid Docs") @mcp.tool() def search_liquid_docs(queries: List[str]) -> str: """Search Shopify Liquid documentation using full-text search. Args: queries: List of search terms (maximum 3) Returns: Formatted search results with snippets """ if not queries: return "Error: Please provide at least one search query" # Limit to 3 queries queries = queries[:3] logger.info(f"Searching for: {queries}") results = search_documentation(queries, limit=10) if not results: return f"No results found for: {', '.join(queries)}" # Format results output = [f"Found {len(results)} results for: {', '.join(queries)}\n"] for i, doc in enumerate(results, 1): output.append(f"{i}. **{doc['title']}** ({doc['category']})") output.append(f" Path: {doc['path']}") if doc.get("snippet"): output.append(f" {doc['snippet']}") output.append("") return "\n".join(output) @mcp.tool() def get_liquid_tag(tag_name: str) -> str: """Get documentation for a specific Shopify Liquid tag. Args: tag_name: Name of the tag (e.g., 'if', 'for', 'assign') Returns: Complete tag documentation """ doc = get_document("tags", tag_name) if not doc: return ( f"Tag '{tag_name}' not found. Use list_liquid_tags() to see available tags." ) return doc["content"] @mcp.tool() def get_liquid_filter(filter_name: str) -> str: """Get documentation for a specific Shopify Liquid filter. Args: filter_name: Name of the filter (e.g., 'upcase', 'date', 'money') Returns: Complete filter documentation """ doc = get_document("filters", filter_name) if not doc: return f"Filter '{filter_name}' not found. Use list_liquid_filters() to see available filters." return doc["content"] @mcp.tool() def get_liquid_object(object_name: str) -> str: """Get documentation for a specific Shopify Liquid object. Args: object_name: Name of the object (e.g., 'product', 'cart', 'shop') Returns: Complete object documentation """ doc = get_document("objects", object_name) if not doc: return f"Object '{object_name}' not found. Use list_liquid_objects() to see available objects." return doc["content"] @mcp.tool() def list_liquid_tags() -> str: """List all available Shopify Liquid tags. Returns: List of all tag names with titles """ docs = get_by_category("tags") if not docs: return "No tags found in database" output = [f"Available Liquid Tags ({len(docs)} total):\n"] # Group by common categories control_flow = [] iteration = [] variables = [] theme = [] other = [] for doc in docs: name = doc["name"] title = doc["title"] item = f"- **{name}**: {title}" if name in ["if", "unless", "case", "conditional-else"]: control_flow.append(item) elif name in [ "for", "break", "continue", "cycle", "tablerow", "iteration-else", "paginate", ]: iteration.append(item) elif name in ["assign", "capture", "increment", "decrement", "echo"]: variables.append(item) elif name in [ "layout", "section", "sections", "render", "include", "content_for", ]: theme.append(item) else: other.append(item) if control_flow: output.append("**Control Flow:**") output.extend(control_flow) output.append("") if iteration: output.append("**Iteration:**") output.extend(iteration) output.append("") if variables: output.append("**Variables:**") output.extend(variables) output.append("") if theme: output.append("**Theme:**") output.extend(theme) output.append("") if other: output.append("**Other:**") output.extend(other) return "\n".join(output) @mcp.tool() def list_liquid_filters() -> str: """List all available Shopify Liquid filters. Returns: List of all filter names with titles organized by category """ docs = get_by_category("filters") if not docs: return "No filters found in database" output = [f"Available Liquid Filters ({len(docs)} total):\n"] # Group by category string_filters = [] array_filters = [] math_filters = [] money_filters = [] other_filters = [] string_keywords = [ "case", "capitalize", "escape", "strip", "truncate", "replace", "remove", "append", "prepend", "split", "lstrip", "rstrip", ] array_keywords = [ "concat", "compact", "first", "last", "join", "map", "reverse", "size", "sort", "uniq", "where", ] math_keywords = [ "abs", "at_least", "at_most", "ceil", "floor", "minus", "plus", "times", "divided_by", "modulo", "round", ] money_keywords = ["money"] for doc in docs: name = doc["name"] title = doc["title"] item = f"- **{name}**: {title}" if any(kw in name for kw in string_keywords): string_filters.append(item) elif any(kw in name for kw in array_keywords): array_filters.append(item) elif any(kw in name for kw in math_keywords): math_filters.append(item) elif any(kw in name for kw in money_keywords): money_filters.append(item) else: other_filters.append(item) if string_filters: output.append("**String Filters:**") output.extend(string_filters[:15]) # Show first 15 if len(string_filters) > 15: output.append(f" ... and {len(string_filters) - 15} more") output.append("") if array_filters: output.append("**Array Filters:**") output.extend(array_filters) output.append("") if math_filters: output.append("**Math Filters:**") output.extend(math_filters) output.append("") if money_filters: output.append("**Money Filters:**") output.extend(money_filters) output.append("") if other_filters: output.append("**Other Filters:**") output.extend(other_filters[:15]) if len(other_filters) > 15: output.append(f" ... and {len(other_filters) - 15} more") return "\n".join(output) @mcp.tool() def list_liquid_objects() -> str: """List all available Shopify Liquid objects. Returns: List of all object names with titles organized by category """ docs = get_by_category("objects") if not docs: return "No objects found in database" output = [f"Available Liquid Objects ({len(docs)} total):\n"] # Group by category core = [] product_related = [] cart_related = [] customer_related = [] content = [] other_objects = [] for doc in docs: name = doc["name"] title = doc["title"] item = f"- **{name}**: {title}" if name in ["shop", "settings", "theme", "request", "routes"]: core.append(item) elif "product" in name or "variant" in name or "collection" in name: product_related.append(item) elif "cart" in name or "checkout" in name or "line_item" in name: cart_related.append(item) elif "customer" in name or "company" in name: customer_related.append(item) elif name in ["page", "blog", "article", "articles", "comment"]: content.append(item) else: other_objects.append(item) if core: output.append("**Core Objects:**") output.extend(core) output.append("") if product_related: output.append("**Product Related:**") output.extend(product_related) output.append("") if cart_related: output.append("**Cart & Checkout:**") output.extend(cart_related) output.append("") if customer_related: output.append("**Customer Related:**") output.extend(customer_related) output.append("") if content: output.append("**Content:**") output.extend(content) output.append("") if other_objects: output.append("**Other Objects:**") output.extend(other_objects[:15]) if len(other_objects) > 15: output.append(f" ... and {len(other_objects) - 15} more") return "\n".join(output) def main(): """Main entry point for the MCP server.""" # Index documentation on startup if not already indexed logger.info("Initializing Shopify Liquid Documentation MCP Server...") try: count = index_documentation(force=False) logger.info(f"Documentation indexed: {count} documents") except Exception as e: logger.error(f"Error indexing documentation: {e}") logger.info("Server will start but search may not work properly") # Run the MCP server mcp.run() if __name__ == "__main__": main()

Implementation Reference

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/shopify-liquid-mcp'

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