Skip to main content
Glama
component_library.py32.2 kB
""" Grasshopper Component Library Searchable database of Grasshopper components with documentation """ import json from typing import Optional from dataclasses import dataclass, asdict from pathlib import Path # ============================================================================= # PREFERRED COMPONENT MAP # When a component name has multiple versions (old vs new), specify which to use # Format: "ComponentName": ("Category", "SubCategory") or None to use default # ============================================================================= PREFERRED_COMPONENTS = { # Curve components - prefer Curve/Primitive over Params/Geometry "Rectangle": ("Curve", "Primitive"), "Circle": ("Curve", "Primitive"), "Line": ("Curve", "Primitive"), "Arc": ("Curve", "Primitive"), "Polygon": ("Curve", "Primitive"), "Polyline": ("Curve", "Primitive"), # Transform components - prefer Transform/Euclidean over Vector/Vector "Rotate": ("Transform", "Euclidean"), "Move": ("Transform", "Euclidean"), "Scale": ("Transform", "Euclidean"), "Mirror": ("Transform", "Euclidean"), "Orient": ("Transform", "Euclidean"), # Surface components "Extrude": ("Surface", "Freeform"), "Loft": ("Surface", "Freeform"), "Pipe": ("Surface", "Freeform"), "Sweep1": ("Surface", "Freeform"), "Sweep2": ("Surface", "Freeform"), # Box components - prefer Surface/Primitive "Box": ("Surface", "Primitive"), "Center Box": ("Surface", "Primitive"), "Box 2Pt": ("Surface", "Primitive"), # Vector components "Unit X": ("Vector", "Vector"), "Unit Y": ("Vector", "Vector"), "Unit Z": ("Vector", "Vector"), "Vector 2Pt": ("Vector", "Vector"), "Amplitude": ("Vector", "Vector"), # Point components "Construct Point": ("Vector", "Point"), "Deconstruct Point": ("Vector", "Point"), "Distance": ("Vector", "Point"), # Sets components "Series": ("Sets", "Sequence"), "Range": ("Sets", "Sequence"), "Random": ("Sets", "Sequence"), "Repeat": ("Sets", "Sequence"), # List components "List Item": ("Sets", "List"), "List Length": ("Sets", "List"), "Reverse List": ("Sets", "List"), "Shift List": ("Sets", "List"), "Cross Reference": ("Sets", "List"), # Math components "Addition": ("Maths", "Operators"), "Subtraction": ("Maths", "Operators"), "Multiplication": ("Maths", "Operators"), "Division": ("Maths", "Operators"), "Radians": ("Maths", "Trig"), "Degrees": ("Maths", "Trig"), # Domain components "Construct Domain": ("Maths", "Domain"), "Remap Numbers": ("Maths", "Domain"), # Curve Division/Analysis "Divide Curve": ("Curve", "Division"), "Evaluate Curve": ("Curve", "Analysis"), "Curve Length": ("Curve", "Analysis"), } def get_find_component_code() -> str: """ Returns Python code that can be executed in Rhino/Grasshopper to find the correct component by name, category, and subcategory. This code should be prepended to any script that creates GH components. """ return ''' # ============================================================================= # Component Finder Helper - Ensures correct component version is used # ============================================================================= PREFERRED_COMPONENTS = { "Rectangle": ("Curve", "Primitive"), "Circle": ("Curve", "Primitive"), "Line": ("Curve", "Primitive"), "Arc": ("Curve", "Primitive"), "Polygon": ("Curve", "Primitive"), "Polyline": ("Curve", "Primitive"), "Rotate": ("Transform", "Euclidean"), "Move": ("Transform", "Euclidean"), "Scale": ("Transform", "Euclidean"), "Mirror": ("Transform", "Euclidean"), "Orient": ("Transform", "Euclidean"), "Extrude": ("Surface", "Freeform"), "Loft": ("Surface", "Freeform"), "Pipe": ("Surface", "Freeform"), "Sweep1": ("Surface", "Freeform"), "Sweep2": ("Surface", "Freeform"), "Box": ("Surface", "Primitive"), "Center Box": ("Surface", "Primitive"), "Box 2Pt": ("Surface", "Primitive"), "Unit X": ("Vector", "Vector"), "Unit Y": ("Vector", "Vector"), "Unit Z": ("Vector", "Vector"), "Vector 2Pt": ("Vector", "Vector"), "Amplitude": ("Vector", "Vector"), "Construct Point": ("Vector", "Point"), "Deconstruct Point": ("Vector", "Point"), "Distance": ("Vector", "Point"), "Series": ("Sets", "Sequence"), "Range": ("Sets", "Sequence"), "Random": ("Sets", "Sequence"), "Repeat": ("Sets", "Sequence"), "List Item": ("Sets", "List"), "List Length": ("Sets", "List"), "Reverse List": ("Sets", "List"), "Shift List": ("Sets", "List"), "Cross Reference": ("Sets", "List"), "Addition": ("Maths", "Operators"), "Subtraction": ("Maths", "Operators"), "Multiplication": ("Maths", "Operators"), "Division": ("Maths", "Operators"), "Radians": ("Maths", "Trig"), "Degrees": ("Maths", "Trig"), "Construct Domain": ("Maths", "Domain"), "Remap Numbers": ("Maths", "Domain"), "Divide Curve": ("Curve", "Division"), "Evaluate Curve": ("Curve", "Analysis"), "Curve Length": ("Curve", "Analysis"), } def find_component(server, name, category=None, subcategory=None): """ Find a Grasshopper component by name with preference for specific category/subcategory. Args: server: Grasshopper.Instances.ComponentServer name: Component name (e.g., "Rectangle", "Rotate") category: Optional category override (e.g., "Curve", "Transform") subcategory: Optional subcategory override (e.g., "Primitive", "Euclidean") Returns: Component proxy or None """ # Use preference map if no explicit category given if category is None and name in PREFERRED_COMPONENTS: category, subcategory = PREFERRED_COMPONENTS[name] # Search for exact match first if category is not None: for proxy in server.ObjectProxies: if proxy.Desc.Name == name and proxy.Desc.Category == category: if subcategory is None or proxy.Desc.SubCategory == subcategory: return proxy # Fallback to default search return server.FindObjectByName(name, True, True) def create_component(server, doc, name, x, y, category=None, subcategory=None): """ Create a component and add it to the document at specified position. Args: server: Grasshopper.Instances.ComponentServer doc: Grasshopper document name: Component name x, y: Canvas position category: Optional category override subcategory: Optional subcategory override Returns: Created component instance or None """ import System.Drawing as SD proxy = find_component(server, name, category, subcategory) if proxy is None: print(f"Component not found: {name}") return None comp = proxy.CreateInstance() comp.CreateAttributes() comp.Attributes.Pivot = SD.PointF(x, y) doc.AddObject(comp, False) return comp ''' @dataclass class ComponentInfo: """Information about a Grasshopper component""" name: str guid: str category: str subcategory: str description: str inputs: list[dict] outputs: list[dict] keywords: list[str] # Core Grasshopper components database # This is a subset - the full database would be much larger COMPONENT_DATABASE: list[dict] = [ # Params - Geometry { "name": "Point", "guid": "3581f42a-9592-4549-bd6b-1c0fc39d067b", "category": "Params", "subcategory": "Geometry", "description": "Contains a collection of 3D points", "inputs": [], "outputs": [{"name": "Point", "type": "Point3d", "description": "Point data"}], "keywords": ["pt", "vertex", "location"] }, { "name": "Curve", "guid": "59e0b89a-e487-49f8-bab8-b5bab16be14c", "category": "Params", "subcategory": "Geometry", "description": "Contains a collection of curves", "inputs": [], "outputs": [{"name": "Curve", "type": "Curve", "description": "Curve data"}], "keywords": ["line", "polyline", "arc", "spline"] }, { "name": "Surface", "guid": "b7e9f4aa-8c7f-4d91-b0c8-8e3a63c77d17", "category": "Params", "subcategory": "Geometry", "description": "Contains a collection of surfaces", "inputs": [], "outputs": [{"name": "Surface", "type": "Surface", "description": "Surface data"}], "keywords": ["srf", "nurbs", "face"] }, { "name": "Brep", "guid": "2a8b1c3d-4e5f-6789-abcd-ef0123456789", "category": "Params", "subcategory": "Geometry", "description": "Contains a collection of Breps (boundary representations)", "inputs": [], "outputs": [{"name": "Brep", "type": "Brep", "description": "Brep geometry"}], "keywords": ["solid", "polysurface", "boundary"] }, { "name": "Mesh", "guid": "8d3e4f5a-6b7c-8d9e-0f1a-2b3c4d5e6f7a", "category": "Params", "subcategory": "Geometry", "description": "Contains a collection of meshes", "inputs": [], "outputs": [{"name": "Mesh", "type": "Mesh", "description": "Mesh geometry"}], "keywords": ["polygon", "triangulate", "vertices", "faces"] }, # Params - Primitive { "name": "Number Slider", "guid": "57da07bd-ecab-415d-9d86-af36d7073abc", "category": "Params", "subcategory": "Input", "description": "Numeric slider for input values", "inputs": [], "outputs": [{"name": "Number", "type": "double", "description": "Slider value"}], "keywords": ["slider", "value", "input", "parameter"] }, { "name": "Panel", "guid": "59e0b89a-e487-49f8-bab8-b5bab16be14c", "category": "Params", "subcategory": "Input", "description": "Text panel for displaying or inputting data", "inputs": [{"name": "Input", "type": "any", "description": "Data to display"}], "outputs": [{"name": "Output", "type": "string", "description": "Panel content"}], "keywords": ["text", "display", "output", "debug"] }, { "name": "Boolean Toggle", "guid": "2e78987b-9dfb-42a2-8b76-3923ac8bd91a", "category": "Params", "subcategory": "Input", "description": "Boolean true/false toggle", "inputs": [], "outputs": [{"name": "Boolean", "type": "bool", "description": "True or False"}], "keywords": ["true", "false", "switch", "toggle", "on", "off"] }, # Maths - Operators { "name": "Addition", "guid": "a0d62394-a118-422d-abb3-6af115c75b25", "category": "Maths", "subcategory": "Operators", "description": "Mathematical addition", "inputs": [ {"name": "A", "type": "double", "description": "First operand"}, {"name": "B", "type": "double", "description": "Second operand"} ], "outputs": [{"name": "Result", "type": "double", "description": "A + B"}], "keywords": ["add", "plus", "sum", "+"] }, { "name": "Subtraction", "guid": "b1e73405-b229-533e-ccc4-7bf226d86b36", "category": "Maths", "subcategory": "Operators", "description": "Mathematical subtraction", "inputs": [ {"name": "A", "type": "double", "description": "First operand"}, {"name": "B", "type": "double", "description": "Second operand"} ], "outputs": [{"name": "Result", "type": "double", "description": "A - B"}], "keywords": ["subtract", "minus", "difference", "-"] }, { "name": "Multiplication", "guid": "c2f84516-c33a-644f-ddd5-8cf337e97c47", "category": "Maths", "subcategory": "Operators", "description": "Mathematical multiplication", "inputs": [ {"name": "A", "type": "double", "description": "First operand"}, {"name": "B", "type": "double", "description": "Second operand"} ], "outputs": [{"name": "Result", "type": "double", "description": "A * B"}], "keywords": ["multiply", "times", "product", "*"] }, { "name": "Division", "guid": "d3095627-d44b-755g-eee6-9d0448f08d58", "category": "Maths", "subcategory": "Operators", "description": "Mathematical division", "inputs": [ {"name": "A", "type": "double", "description": "Dividend"}, {"name": "B", "type": "double", "description": "Divisor"} ], "outputs": [{"name": "Result", "type": "double", "description": "A / B"}], "keywords": ["divide", "quotient", "/"] }, # Maths - Domain { "name": "Construct Domain", "guid": "e4106738-e55c-866h-fff7-ae1559019e69", "category": "Maths", "subcategory": "Domain", "description": "Create a numeric domain from two numbers", "inputs": [ {"name": "A", "type": "double", "description": "Domain start"}, {"name": "B", "type": "double", "description": "Domain end"} ], "outputs": [{"name": "Domain", "type": "Domain", "description": "Numeric domain"}], "keywords": ["range", "interval", "bounds"] }, { "name": "Remap Numbers", "guid": "f5217849-f66d-977i-000a-bf266a12af7a", "category": "Maths", "subcategory": "Domain", "description": "Remap numbers from one domain to another", "inputs": [ {"name": "Value", "type": "double", "description": "Value to remap"}, {"name": "Source", "type": "Domain", "description": "Source domain"}, {"name": "Target", "type": "Domain", "description": "Target domain"} ], "outputs": [{"name": "Mapped", "type": "double", "description": "Remapped value"}], "keywords": ["map", "scale", "normalize", "lerp"] }, # Vector - Point { "name": "Construct Point", "guid": "06328950-077e-088j-111b-c0377b23b08b", "category": "Vector", "subcategory": "Point", "description": "Create a point from X, Y, Z coordinates", "inputs": [ {"name": "X", "type": "double", "description": "X coordinate"}, {"name": "Y", "type": "double", "description": "Y coordinate"}, {"name": "Z", "type": "double", "description": "Z coordinate"} ], "outputs": [{"name": "Point", "type": "Point3d", "description": "Resulting point"}], "keywords": ["pt", "xyz", "coordinate", "vertex"] }, { "name": "Deconstruct Point", "guid": "17439061-188f-199k-222c-d1488c34c19c", "category": "Vector", "subcategory": "Point", "description": "Extract X, Y, Z coordinates from a point", "inputs": [{"name": "Point", "type": "Point3d", "description": "Point to deconstruct"}], "outputs": [ {"name": "X", "type": "double", "description": "X coordinate"}, {"name": "Y", "type": "double", "description": "Y coordinate"}, {"name": "Z", "type": "double", "description": "Z coordinate"} ], "keywords": ["pt", "xyz", "extract", "components"] }, { "name": "Distance", "guid": "2854a172-299g-2aal-333d-e2599d45d2ad", "category": "Vector", "subcategory": "Point", "description": "Calculate distance between two points", "inputs": [ {"name": "A", "type": "Point3d", "description": "First point"}, {"name": "B", "type": "Point3d", "description": "Second point"} ], "outputs": [{"name": "Distance", "type": "double", "description": "Distance between points"}], "keywords": ["length", "magnitude", "spacing"] }, # Curve - Primitive { "name": "Line", "guid": "3965b283-3aah-3bbm-444e-f36aae56e3be", "category": "Curve", "subcategory": "Primitive", "description": "Create a line between two points", "inputs": [ {"name": "A", "type": "Point3d", "description": "Start point"}, {"name": "B", "type": "Point3d", "description": "End point"} ], "outputs": [{"name": "Line", "type": "Line", "description": "Resulting line"}], "keywords": ["segment", "straight", "edge"] }, { "name": "Circle", "guid": "4a76c394-4bbi-4ccn-555f-047bbf67f4cf", "category": "Curve", "subcategory": "Primitive", "description": "Create a circle from plane and radius", "inputs": [ {"name": "Plane", "type": "Plane", "description": "Circle plane"}, {"name": "Radius", "type": "double", "description": "Circle radius"} ], "outputs": [{"name": "Circle", "type": "Circle", "description": "Resulting circle"}], "keywords": ["round", "arc", "ellipse"] }, { "name": "Arc", "guid": "5b87d4a5-5ccj-5ddo-666g-158cc078g5dg", "category": "Curve", "subcategory": "Primitive", "description": "Create an arc from three points", "inputs": [ {"name": "A", "type": "Point3d", "description": "Start point"}, {"name": "B", "type": "Point3d", "description": "Interior point"}, {"name": "C", "type": "Point3d", "description": "End point"} ], "outputs": [{"name": "Arc", "type": "Arc", "description": "Resulting arc"}], "keywords": ["curve", "segment", "circular"] }, { "name": "Polyline", "guid": "6c98e5b6-6ddk-6eep-777h-269dd189h6eh", "category": "Curve", "subcategory": "Primitive", "description": "Create a polyline from points", "inputs": [ {"name": "Vertices", "type": "Point3d[]", "description": "Polyline vertices"}, {"name": "Closed", "type": "bool", "description": "Close polyline"} ], "outputs": [{"name": "Polyline", "type": "Polyline", "description": "Resulting polyline"}], "keywords": ["pline", "polygon", "segments"] }, { "name": "Interpolate", "guid": "7da9f6c7-7eel-7ffq-888i-37aee29ai7fi", "category": "Curve", "subcategory": "Spline", "description": "Create an interpolated curve through points", "inputs": [ {"name": "Vertices", "type": "Point3d[]", "description": "Interpolation points"}, {"name": "Degree", "type": "int", "description": "Curve degree"}, {"name": "Periodic", "type": "bool", "description": "Periodic curve"} ], "outputs": [{"name": "Curve", "type": "Curve", "description": "Interpolated curve"}], "keywords": ["spline", "nurbs", "smooth", "fit"] }, # Curve - Analysis { "name": "Evaluate Curve", "guid": "8eba07d8-8ffm-800r-999j-48bff3abj8gj", "category": "Curve", "subcategory": "Analysis", "description": "Evaluate a curve at a parameter", "inputs": [ {"name": "Curve", "type": "Curve", "description": "Curve to evaluate"}, {"name": "Parameter", "type": "double", "description": "Parameter on curve"} ], "outputs": [ {"name": "Point", "type": "Point3d", "description": "Point on curve"}, {"name": "Tangent", "type": "Vector3d", "description": "Tangent at point"} ], "keywords": ["sample", "point on curve", "tangent"] }, { "name": "Curve Length", "guid": "9fcb18e9-900n-911s-aaak-59c004bck9hk", "category": "Curve", "subcategory": "Analysis", "description": "Measure the length of a curve", "inputs": [{"name": "Curve", "type": "Curve", "description": "Curve to measure"}], "outputs": [{"name": "Length", "type": "double", "description": "Curve length"}], "keywords": ["measure", "distance", "arc length"] }, { "name": "Divide Curve", "guid": "a0dc29fa-a11o-a22t-bbbl-6ad115cdlail", "category": "Curve", "subcategory": "Division", "description": "Divide a curve into segments", "inputs": [ {"name": "Curve", "type": "Curve", "description": "Curve to divide"}, {"name": "Count", "type": "int", "description": "Number of segments"} ], "outputs": [ {"name": "Points", "type": "Point3d[]", "description": "Division points"}, {"name": "Tangents", "type": "Vector3d[]", "description": "Tangents at points"}, {"name": "Parameters", "type": "double[]", "description": "Parameters at points"} ], "keywords": ["split", "segment", "subdivide"] }, # Surface - Primitive { "name": "Extrude", "guid": "b1ed3a0b-b22p-b33u-cccm-7be226dembjm", "category": "Surface", "subcategory": "Freeform", "description": "Extrude a curve along a vector", "inputs": [ {"name": "Curve", "type": "Curve", "description": "Curve to extrude"}, {"name": "Direction", "type": "Vector3d", "description": "Extrusion direction"} ], "outputs": [{"name": "Surface", "type": "Surface", "description": "Extruded surface"}], "keywords": ["sweep", "linear", "extend"] }, { "name": "Loft", "guid": "c2fe4b1c-c33q-c44v-dddn-8cf337fencko", "category": "Surface", "subcategory": "Freeform", "description": "Create a lofted surface through curves", "inputs": [ {"name": "Curves", "type": "Curve[]", "description": "Section curves"}, {"name": "Options", "type": "int", "description": "Loft options"} ], "outputs": [{"name": "Surface", "type": "Brep", "description": "Lofted surface"}], "keywords": ["skin", "blend", "ruled"] }, { "name": "Sweep1", "guid": "d30f5c2d-d44r-d55w-eeeo-9d0448gfodlp", "category": "Surface", "subcategory": "Freeform", "description": "Sweep a section curve along a rail", "inputs": [ {"name": "Rail", "type": "Curve", "description": "Rail curve"}, {"name": "Section", "type": "Curve", "description": "Section curve"} ], "outputs": [{"name": "Surface", "type": "Brep", "description": "Swept surface"}], "keywords": ["extrude along", "pipe", "rail"] }, # Transform { "name": "Move", "guid": "e4106d3e-e55s-e66x-fffp-ae1559hgpemq", "category": "Transform", "subcategory": "Euclidean", "description": "Move geometry along a vector", "inputs": [ {"name": "Geometry", "type": "Geometry", "description": "Geometry to move"}, {"name": "Motion", "type": "Vector3d", "description": "Translation vector"} ], "outputs": [{"name": "Geometry", "type": "Geometry", "description": "Moved geometry"}], "keywords": ["translate", "shift", "offset"] }, { "name": "Rotate", "guid": "f5217e4f-f66t-f77y-000q-bf266aihqfnr", "category": "Transform", "subcategory": "Euclidean", "description": "Rotate geometry around an axis", "inputs": [ {"name": "Geometry", "type": "Geometry", "description": "Geometry to rotate"}, {"name": "Angle", "type": "double", "description": "Rotation angle (radians)"}, {"name": "Plane", "type": "Plane", "description": "Rotation plane"} ], "outputs": [{"name": "Geometry", "type": "Geometry", "description": "Rotated geometry"}], "keywords": ["spin", "turn", "revolve"] }, { "name": "Scale", "guid": "06328f50-077u-088z-111r-c0377bjirhos", "category": "Transform", "subcategory": "Euclidean", "description": "Scale geometry uniformly", "inputs": [ {"name": "Geometry", "type": "Geometry", "description": "Geometry to scale"}, {"name": "Center", "type": "Point3d", "description": "Scale center"}, {"name": "Factor", "type": "double", "description": "Scale factor"} ], "outputs": [{"name": "Geometry", "type": "Geometry", "description": "Scaled geometry"}], "keywords": ["resize", "enlarge", "shrink"] }, { "name": "Mirror", "guid": "17439061-188v-199a1-222s-d1488ckjsipt", "category": "Transform", "subcategory": "Euclidean", "description": "Mirror geometry across a plane", "inputs": [ {"name": "Geometry", "type": "Geometry", "description": "Geometry to mirror"}, {"name": "Plane", "type": "Plane", "description": "Mirror plane"} ], "outputs": [{"name": "Geometry", "type": "Geometry", "description": "Mirrored geometry"}], "keywords": ["reflect", "flip", "symmetry"] }, # Sets - List { "name": "List Item", "guid": "28540172-299w-2ab1-333t-e2599dlktjqu", "category": "Sets", "subcategory": "List", "description": "Get item at index from a list", "inputs": [ {"name": "List", "type": "any[]", "description": "List to index"}, {"name": "Index", "type": "int", "description": "Item index"}, {"name": "Wrap", "type": "bool", "description": "Wrap index"} ], "outputs": [{"name": "Item", "type": "any", "description": "Item at index"}], "keywords": ["index", "get", "element", "access"] }, { "name": "List Length", "guid": "3965b283-3aax-3bc1-444u-f36aaemlukrv", "category": "Sets", "subcategory": "List", "description": "Get the number of items in a list", "inputs": [{"name": "List", "type": "any[]", "description": "List to measure"}], "outputs": [{"name": "Length", "type": "int", "description": "Number of items"}], "keywords": ["count", "size", "number"] }, { "name": "Reverse List", "guid": "4a76c394-4bby-4cd1-555v-047bbfnmvlsw", "category": "Sets", "subcategory": "List", "description": "Reverse the order of a list", "inputs": [{"name": "List", "type": "any[]", "description": "List to reverse"}], "outputs": [{"name": "List", "type": "any[]", "description": "Reversed list"}], "keywords": ["flip", "invert", "backwards"] }, # Sets - Tree { "name": "Flatten", "guid": "5b87d4a5-5ccz-5de1-666w-158cconwmtx", "category": "Sets", "subcategory": "Tree", "description": "Flatten a data tree to a single list", "inputs": [{"name": "Tree", "type": "DataTree", "description": "Tree to flatten"}], "outputs": [{"name": "List", "type": "any[]", "description": "Flattened list"}], "keywords": ["collapse", "merge", "simplify"] }, { "name": "Graft", "guid": "6c98e5b6-6dda1-6ef1-777x-269ddpoxnuy", "category": "Sets", "subcategory": "Tree", "description": "Graft each item into its own branch", "inputs": [{"name": "Tree", "type": "DataTree", "description": "Tree to graft"}], "outputs": [{"name": "Tree", "type": "DataTree", "description": "Grafted tree"}], "keywords": ["branch", "separate", "individual"] }, # Script components { "name": "GhPython Script", "guid": "410755b1-224a-4c1e-a407-bf32fb45ea7e", "category": "Maths", "subcategory": "Script", "description": "Python scripting component for custom logic", "inputs": [{"name": "x", "type": "any", "description": "Script input"}], "outputs": [{"name": "a", "type": "any", "description": "Script output"}], "keywords": ["python", "code", "script", "custom", "ghpython"] }, { "name": "C# Script", "guid": "a9d51e9f-60c1-4c9f-8e34-c5f6a5f5e5e1", "category": "Maths", "subcategory": "Script", "description": "C# scripting component for custom logic", "inputs": [{"name": "x", "type": "any", "description": "Script input"}], "outputs": [{"name": "A", "type": "any", "description": "Script output"}], "keywords": ["csharp", "code", "script", "custom", "dotnet"] }, # Display { "name": "Custom Preview", "guid": "7da9f6c7-7eeb1-7fg1-888y-37aeeqpyovz", "category": "Display", "subcategory": "Preview", "description": "Preview geometry with custom color", "inputs": [ {"name": "Geometry", "type": "Geometry", "description": "Geometry to preview"}, {"name": "Material", "type": "Material", "description": "Display material"} ], "outputs": [], "keywords": ["color", "render", "visualize"] }, { "name": "Colour Swatch", "guid": "8eba07d8-8ffc1-8gh1-999z-48bffrqzpwa", "category": "Display", "subcategory": "Colour", "description": "Color picker/swatch", "inputs": [], "outputs": [{"name": "Colour", "type": "Color", "description": "Selected color"}], "keywords": ["color", "rgb", "picker"] }, ] class ComponentLibrary: """Searchable component library""" def __init__(self): self.components = [ComponentInfo(**c) for c in COMPONENT_DATABASE] def search(self, query: str, limit: int = 20) -> list[dict]: """Search components by name, description, or keywords""" query_lower = query.lower() results = [] for comp in self.components: score = 0 # Exact name match if query_lower == comp.name.lower(): score = 100 # Name contains query elif query_lower in comp.name.lower(): score = 50 # Description contains query elif query_lower in comp.description.lower(): score = 30 # Keyword match elif any(query_lower in kw.lower() for kw in comp.keywords): score = 40 # Category/subcategory match elif query_lower in comp.category.lower() or query_lower in comp.subcategory.lower(): score = 20 if score > 0: results.append((score, asdict(comp))) # Sort by score descending results.sort(key=lambda x: x[0], reverse=True) return [r[1] for r in results[:limit]] def get_by_category(self, category: str) -> list[dict]: """Get all components in a category""" return [ asdict(c) for c in self.components if c.category.lower() == category.lower() ] def get_by_subcategory(self, category: str, subcategory: str) -> list[dict]: """Get components in a specific subcategory""" return [ asdict(c) for c in self.components if c.category.lower() == category.lower() and c.subcategory.lower() == subcategory.lower() ] def get_categories(self) -> dict: """Get all categories and their subcategories""" categories = {} for comp in self.components: if comp.category not in categories: categories[comp.category] = set() categories[comp.category].add(comp.subcategory) return {k: sorted(list(v)) for k, v in sorted(categories.items())} def get_by_guid(self, guid: str) -> Optional[dict]: """Get component by GUID""" for comp in self.components: if comp.guid == guid: return asdict(comp) return None def list_all(self) -> list[dict]: """List all components""" return [asdict(c) for c in self.components] # Singleton instance _library: Optional[ComponentLibrary] = None def get_library() -> ComponentLibrary: """Get or create the component library""" global _library if _library is None: _library = ComponentLibrary() return _library

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/dongwoosuk/grasshopper-mcp'

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