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