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)
Behavior2/5

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

With no annotations provided, the description carries full burden but only minimally discloses behavior. It states the tool 'finds' a node and returns 'Node information or None', but omits critical details like error handling (e.g., invalid positions), performance characteristics, or what 'Node information' entails. For a tool with 4 parameters and no annotation coverage, this is insufficient.

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

Conciseness4/5

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

The description is appropriately sized and front-loaded with the core purpose. The Args/Returns sections are structured efficiently, though the formatting with indentation could be slightly cleaner. Every sentence adds value without redundancy.

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 the tool's moderate complexity (4 parameters, no output schema, no annotations), the description is partially complete. It covers parameters well and states the return value, but lacks details on error cases, output format, or behavioral nuances. For a tool that interacts with ASTs, more context on what 'Node information' includes would be beneficial.

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?

The description adds significant value beyond the input schema, which has 0% description coverage. It explains all 4 parameters (project, path, row, column) with clear semantics, including that row/column are 0-based. This fully compensates for the schema's lack of descriptions, making parameters well-understood.

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 clearly states the specific action ('Find the AST node') and resource ('at a specific position'), distinguishing it from siblings like get_ast (which retrieves the entire AST) or get_symbols (which focuses on symbols). The verb+resource combination is precise and unambiguous.

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

Usage Guidelines3/5

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

The description implies usage when needing to locate a node by position in an AST, but provides no explicit guidance on when to use this versus alternatives like get_ast (for full AST) or find_similar_code (for semantic matching). It lacks any 'when-not' or prerequisite information, leaving usage context inferred rather than stated.

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

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

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