find_symbol
Locate specific symbols (classes, methods, etc.) in a codebase using a name path pattern. Specify depth to include descendants, restrict searches to files/directories, and optionally include source code or filter by symbol types.
Instructions
Retrieves information on all symbols/code entities (classes, methods, etc.) based on the given name_path,
which represents a pattern for the symbol's path within the symbol tree of a single file.
The returned symbol location can be used for edits or further queries.
Specify depth > 0 to retrieve children (e.g., methods of a class).
The matching behavior is determined by the structure of name_path, which can
either be a simple name (e.g. "method") or a name path like "class/method" (relative name path)
or "/class/method" (absolute name path). Note that the name path is not a path in the file system
but rather a path in the symbol tree within a single file. Thus, file or directory names should never
be included in the name_path. For restricting the search to a single file or directory,
the within_relative_path parameter should be used instead. The retrieved symbols' name_path attribute
will always be composed of symbol names, never file or directory names.
Key aspects of the name path matching behavior:
Trailing slashes in
name_pathplay no role and are ignored.The name of the retrieved symbols will match (either exactly or as a substring) the last segment of
name_path, while other segments will restrict the search to symbols that have a desired sequence of ancestors.If there is no starting or intermediate slash in
name_path, there is no restriction on the ancestor symbols. For example, passingmethodwill match against symbols with name paths likemethod,class/method,class/nested_class/method, etc.If
name_pathcontains a/but doesn't start with a/, the matching is restricted to symbols with the same ancestors as the last segment ofname_path. For example, passingclass/methodwill match againstclass/methodas well asnested_class/class/methodbut notmethod.If
name_pathstarts with a/, it will be treated as an absolute name path pattern, meaning that the first segment of it must match the first segment of the symbol's name path. For example, passing/classwill match only against top-level symbols likeclassbut not againstnested_class/class. Passing/class/methodwill match againstclass/methodbut notnested_class/class/methodormethod. Returns a list of symbols (with locations) matching the name.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| depth | No | Depth to retrieve descendants (e.g., 1 for class methods/attributes). | |
| exclude_kinds | No | Optional. List of LSP symbol kind integers to exclude. Takes precedence over `include_kinds`. If not provided, no kinds are excluded. | |
| include_body | No | If True, include the symbol's source code. Use judiciously. | |
| include_kinds | No | Optional. List of LSP symbol kind integers to include. (e.g., 5 for Class, 12 for Function). Valid kinds: 1=file, 2=module, 3=namespace, 4=package, 5=class, 6=method, 7=property, 8=field, 9=constructor, 10=enum, 11=interface, 12=function, 13=variable, 14=constant, 15=string, 16=number, 17=boolean, 18=array, 19=object, 20=key, 21=null, 22=enum member, 23=struct, 24=event, 25=operator, 26=type parameter. If not provided, all kinds are included. | |
| max_answer_chars | No | Max characters for the JSON result. If exceeded, no content is returned. | |
| name_path | Yes | The name path pattern to search for, see above for details. | |
| relative_path | No | Optional. Restrict search to this file or directory. If None, searches entire codebase. If a directory is passed, the search will be restricted to the files in that directory. If a file is passed, the search will be restricted to that file. If you have some knowledge about the codebase, you should use this parameter, as it will significantly speed up the search as well as reduce the number of results. | |
| substring_matching | No | If True, use substring matching for the last segment of `name`. |
Implementation Reference
- src/serena/tools/symbol_tools.py:79-149 (handler)The FindSymbolTool class with its apply method implements the execution logic for the MCP tool 'find_symbol'. It searches for symbols matching the name_path_pattern using the language server backend and returns JSON-formatted results.class FindSymbolTool(Tool, ToolMarkerSymbolicRead): """ Performs a global (or local) search using the language server backend. """ # noinspection PyDefaultArgument def apply( self, name_path_pattern: str, depth: int = 0, relative_path: str = "", include_body: bool = False, include_kinds: list[int] = [], # noqa: B006 exclude_kinds: list[int] = [], # noqa: B006 substring_matching: bool = False, max_answer_chars: int = -1, ) -> str: """ Retrieves information on all symbols/code entities (classes, methods, etc.) based on the given name path pattern. The returned symbol information can be used for edits or further queries. Specify `depth > 0` to also retrieve children/descendants (e.g., methods of a class). A name path is a path in the symbol tree *within a source file*. For example, the method `my_method` defined in class `MyClass` would have the name path `MyClass/my_method`. If a symbol is overloaded (e.g., in Java), a 0-based index is appended (e.g. "MyClass/my_method[0]") to uniquely identify it. To search for a symbol, you provide a name path pattern that is used to match against name paths. It can be * a simple name (e.g. "method"), which will match any symbol with that name * a relative path like "class/method", which will match any symbol with that name path suffix * an absolute name path "/class/method" (absolute name path), which requires an exact match of the full name path within the source file. Append an index `[i]` to match a specific overload only, e.g. "MyClass/my_method[1]". :param name_path_pattern: the name path matching pattern (see above) :param depth: depth up to which descendants shall be retrieved (e.g. use 1 to also retrieve immediate children; for the case where the symbol is a class, this will return its methods). Default 0. :param relative_path: Optional. Restrict search to this file or directory. If None, searches entire codebase. If a directory is passed, the search will be restricted to the files in that directory. If a file is passed, the search will be restricted to that file. If you have some knowledge about the codebase, you should use this parameter, as it will significantly speed up the search as well as reduce the number of results. :param include_body: If True, include the symbol's source code. Use judiciously. :param include_kinds: Optional. List of LSP symbol kind integers to include. (e.g., 5 for Class, 12 for Function). Valid kinds: 1=file, 2=module, 3=namespace, 4=package, 5=class, 6=method, 7=property, 8=field, 9=constructor, 10=enum, 11=interface, 12=function, 13=variable, 14=constant, 15=string, 16=number, 17=boolean, 18=array, 19=object, 20=key, 21=null, 22=enum member, 23=struct, 24=event, 25=operator, 26=type parameter. If not provided, all kinds are included. :param exclude_kinds: Optional. List of LSP symbol kind integers to exclude. Takes precedence over `include_kinds`. If not provided, no kinds are excluded. :param substring_matching: If True, use substring matching for the last element of the pattern, such that "Foo/get" would match "Foo/getValue" and "Foo/getData". :param max_answer_chars: Max characters for the JSON result. If exceeded, no content is returned. -1 means the default value from the config will be used. :return: a list of symbols (with locations) matching the name. """ parsed_include_kinds: Sequence[SymbolKind] | None = [SymbolKind(k) for k in include_kinds] if include_kinds else None parsed_exclude_kinds: Sequence[SymbolKind] | None = [SymbolKind(k) for k in exclude_kinds] if exclude_kinds else None symbol_retriever = self.create_language_server_symbol_retriever() symbols = symbol_retriever.find_by_name( name_path_pattern, include_kinds=parsed_include_kinds, exclude_kinds=parsed_exclude_kinds, substring_matching=substring_matching, within_relative_path=relative_path, ) symbol_dicts = [_sanitize_symbol_dict(s.to_dict(kind=True, location=True, depth=depth, include_body=include_body)) for s in symbols] result = self._to_json(symbol_dicts) return self._limit_length(result, max_answer_chars)
- src/serena/mcp.py:233-241 (registration)Registers all active Serena tools, including 'find_symbol', into the FastMCP server's tool manager by name derived from tool.get_name().def _set_mcp_tools(self, mcp: FastMCP, openai_tool_compatible: bool = False) -> None: """Update the tools in the MCP server""" if mcp is not None: mcp._tool_manager._tools = {} for tool in self._iter_tools(): mcp_tool = self.make_mcp_tool(tool, openai_tool_compatible=openai_tool_compatible) mcp._tool_manager._tools[tool.get_name()] = mcp_tool log.info(f"Starting MCP server with {len(mcp._tool_manager._tools)} tools: {list(mcp._tool_manager._tools.keys())}")
- src/serena/tools/tools_base.py:358-370 (registration)ToolRegistry scans all Tool subclasses (including FindSymbolTool) and registers them with snake_case names like 'find_symbol', making them available for instantiation and MCP exposure.@singleton class ToolRegistry: def __init__(self) -> None: self._tool_dict: dict[str, RegisteredTool] = {} for cls in iter_subclasses(Tool): if not cls.__module__.startswith("serena.tools"): continue is_optional = issubclass(cls, ToolMarkerOptional) name = cls.get_name_from_cls() if name in self._tool_dict: raise ValueError(f"Duplicate tool name found: {name}. Tool classes must have unique names.") self._tool_dict[name] = RegisteredTool(tool_class=cls, is_optional=is_optional, tool_name=name)
- Helper function used by FindSymbolTool to clean up symbol dictionaries before returning as JSON.def _sanitize_symbol_dict(symbol_dict: dict[str, Any]) -> dict[str, Any]: """ Sanitize a symbol dictionary inplace by removing unnecessary information. """ # We replace the location entry, which repeats line information already included in body_location # and has unnecessary information on column, by just the relative path. symbol_dict = copy(symbol_dict) s_relative_path = symbol_dict.get("location", {}).get("relative_path") if s_relative_path is not None: symbol_dict["relative_path"] = s_relative_path symbol_dict.pop("location", None) # also remove name, name_path should be enough symbol_dict.pop("name") return symbol_dict
- The apply method signature and docstring define the input schema (parameters with types and descriptions) and output format (JSON string of symbol list) for the 'find_symbol' tool, used to generate MCP/JSON schema.def apply( self, name_path_pattern: str, depth: int = 0, relative_path: str = "", include_body: bool = False, include_kinds: list[int] = [], # noqa: B006 exclude_kinds: list[int] = [], # noqa: B006 substring_matching: bool = False, max_answer_chars: int = -1, ) -> str: """ Retrieves information on all symbols/code entities (classes, methods, etc.) based on the given name path pattern. The returned symbol information can be used for edits or further queries. Specify `depth > 0` to also retrieve children/descendants (e.g., methods of a class). A name path is a path in the symbol tree *within a source file*. For example, the method `my_method` defined in class `MyClass` would have the name path `MyClass/my_method`. If a symbol is overloaded (e.g., in Java), a 0-based index is appended (e.g. "MyClass/my_method[0]") to uniquely identify it. To search for a symbol, you provide a name path pattern that is used to match against name paths. It can be * a simple name (e.g. "method"), which will match any symbol with that name * a relative path like "class/method", which will match any symbol with that name path suffix * an absolute name path "/class/method" (absolute name path), which requires an exact match of the full name path within the source file. Append an index `[i]` to match a specific overload only, e.g. "MyClass/my_method[1]". :param name_path_pattern: the name path matching pattern (see above) :param depth: depth up to which descendants shall be retrieved (e.g. use 1 to also retrieve immediate children; for the case where the symbol is a class, this will return its methods). Default 0. :param relative_path: Optional. Restrict search to this file or directory. If None, searches entire codebase. If a directory is passed, the search will be restricted to the files in that directory. If a file is passed, the search will be restricted to that file. If you have some knowledge about the codebase, you should use this parameter, as it will significantly speed up the search as well as reduce the number of results. :param include_body: If True, include the symbol's source code. Use judiciously. :param include_kinds: Optional. List of LSP symbol kind integers to include. (e.g., 5 for Class, 12 for Function). Valid kinds: 1=file, 2=module, 3=namespace, 4=package, 5=class, 6=method, 7=property, 8=field, 9=constructor, 10=enum, 11=interface, 12=function, 13=variable, 14=constant, 15=string, 16=number, 17=boolean, 18=array, 19=object, 20=key, 21=null, 22=enum member, 23=struct, 24=event, 25=operator, 26=type parameter. If not provided, all kinds are included. :param exclude_kinds: Optional. List of LSP symbol kind integers to exclude. Takes precedence over `include_kinds`. If not provided, no kinds are excluded. :param substring_matching: If True, use substring matching for the last element of the pattern, such that "Foo/get" would match "Foo/getValue" and "Foo/getData". :param max_answer_chars: Max characters for the JSON result. If exceeded, no content is returned. -1 means the default value from the config will be used. :return: a list of symbols (with locations) matching the name.