Skip to main content
Glama
wrale

mcp-server-tree-sitter

by wrale

get_node_at_position

Locates the Abstract Syntax Tree (AST) node at a specific position in a code file, given project name, file path, and row-column coordinates. Returns node details or None if not found.

Instructions

Find the AST node at a specific position.

    Args:
        project: Project name
        path: File path relative to project root
        row: Line number (0-based)
        column: Column number (0-based)

    Returns:
        Node information or None if not found
    

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
columnYes
pathYes
projectYes
rowYes

Implementation Reference

  • Primary MCP tool handler for get_node_at_position. Registers the tool via @mcp_server.tool() decorator and implements the full logic: retrieves project, detects language, parses file to AST, finds node at position, and serializes to dict.
    @mcp_server.tool()
    def get_node_at_position(project: str, path: str, row: int, column: int) -> Optional[Dict[str, Any]]:
        """Find the AST node at a specific position.
    
        Args:
            project: Project name
            path: File path relative to project root
            row: Line number (0-based)
            column: Column number (0-based)
    
        Returns:
            Node information or None if not found
        """
        from ..models.ast import node_to_dict
        from ..tools.ast_operations import find_node_at_position
    
        project_obj = project_registry.get_project(project)
        file_path = project_obj.get_file_path(path)
    
        language = language_registry.language_for_file(path)
        if not language:
            raise ValueError(f"Could not detect language for {path}")
    
        from ..tools.ast_operations import parse_file as parse_file_helper
    
        tree, source_bytes = parse_file_helper(file_path, language, language_registry, tree_cache)
    
        node = find_node_at_position(tree.root_node, row, column)
        if node:
            return node_to_dict(node, source_bytes, max_depth=2)
    
        return None
  • Core helper implementing cursor-based tree traversal to locate the most specific AST node at the given position (row, column). Used by the tool handler.
    def find_node_at_position(root_node: Any, row: int, column: int) -> Optional[Any]:
        """
        Find the most specific node at a given position using cursor-based traversal.
    
        Args:
            root_node: Root node to search from
            row: Row (line) number, 0-based
            column: Column number, 0-based
    
        Returns:
            The most specific node at the position, or None if not found
        """
        safe_node = ensure_node(root_node)
        point = (row, column)
    
        # Check if point is within root_node
        if not (safe_node.start_point <= point <= safe_node.end_point):
            return None
    
        # Find the smallest node that contains the point
        cursor = walk_tree(safe_node)
        current_best = cursor.node
    
        # Special handling for function definitions and identifiers
        def check_for_specific_nodes(node: Any) -> Optional[Any]:
            # For function definitions, check if position is over the function name
            if node.type == "function_definition":
                for child in node.children:
                    if child.type in ["identifier", "name"]:
                        if (
                            child.start_point[0] <= row <= child.end_point[0]
                            and child.start_point[1] <= column <= child.end_point[1]
                        ):
                            return child
            return None
    
        # First check if we have a specific node like a function name
        specific_node = check_for_specific_nodes(safe_node)
        if specific_node:
            return specific_node
    
        while cursor.goto_first_child():
            # If current node contains the point, it's better than the parent
            if cursor.node is not None and cursor.node.start_point <= point <= cursor.node.end_point:
                current_best = cursor.node
    
                # Check for specific nodes like identifiers
                specific_node = check_for_specific_nodes(cursor.node)
                if specific_node:
                    return specific_node
    
                continue  # Continue to first child
    
            # If first child doesn't contain point, try siblings
            cursor.goto_parent()
            current_best = cursor.node  # Reset current best to parent
    
            # Try siblings
            found_in_sibling = False
            while cursor.goto_next_sibling():
                if cursor.node is not None and cursor.node.start_point <= point <= cursor.node.end_point:
                    current_best = cursor.node
    
                    # Check for specific nodes
                    specific_node = check_for_specific_nodes(cursor.node)
                    if specific_node:
                        return specific_node
    
                    found_in_sibling = True
                    break
    
            # If a sibling contains the point, continue to its children
            if found_in_sibling:
                continue
            else:
                # No child or sibling contains the point, we're done
                break
    
        return current_best
  • Helper function to serialize the found AST node to a dictionary format with configurable depth and text inclusion. Called by the tool handler with max_depth=2.
    def node_to_dict(
        node: Any,
        source_bytes: Optional[bytes] = None,
        include_children: bool = True,
        include_text: bool = True,
        max_depth: int = 5,
    ) -> Dict[str, Any]:
        """
        Convert a tree-sitter node to a dictionary representation.
    
        This function now uses a cursor-based traversal approach for efficiency and
        reliability, especially with large ASTs that could cause stack overflow with
        recursive processing.
    
        Args:
            node: Tree-sitter Node object
            source_bytes: Source code bytes
            include_children: Whether to include children nodes
            include_text: Whether to include node text
            max_depth: Maximum depth to traverse
    
        Returns:
            Dictionary representation of the node
        """
        # Use the cursor-based implementation for improved reliability
        return node_to_dict_cursor(node, source_bytes, include_children, include_text, max_depth)

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/wrale/mcp-server-tree-sitter'

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