Skip to main content
Glama
lin2000wl

Serena MCP Server

by lin2000wl

replace_symbol_body

Update symbol definitions in your codebase by specifying a name path and providing new body content, enabling direct code modifications within the Serena MCP Server environment.

Instructions

Replaces the body of the symbol with the given name_path.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
name_pathYesFor finding the symbol to replace, same logic as in the `find_symbol` tool.
relative_pathYesThe relative path to the file containing the symbol.
bodyYesThe new symbol body. Important: Begin directly with the symbol definition and provide no leading indentation for the first line (but do indent the rest of the body according to the context).

Implementation Reference

  • The handler function for replacing the body of a symbol identified by name_path in a specific file. It locates the symbol using the language server and delegates to replace_body_at_location for the edit.
    def replace_body(self, name_path: str, relative_file_path: str, body: str, *, use_same_indentation: bool = True) -> None:
        """
        Replace the body of the symbol with the given name_path in the given file.
    
        :param name_path: the name path of the symbol to replace.
        :param relative_file_path: the relative path of the file in which the symbol is defined.
        :param body: the new body
        :param use_same_indentation: whether to use the same indentation as the original body. This means that
            the user doesn't have to provide the correct indentation, but can just write the body.
        """
        symbol_candidates = self.find_by_name(name_path, within_relative_path=relative_file_path)
        if len(symbol_candidates) == 0:
            raise ValueError(f"No symbol with name {name_path} found in file {relative_file_path}")
        if len(symbol_candidates) > 1:
            raise ValueError(
                f"Found multiple {len(symbol_candidates)} symbols with name {name_path} in file {relative_file_path}. "
                "Will not replace the body of any of them, but you can use `replace_body_at_location`, the replace lines tool or other editing "
                "tools to perform your edits. Their locations are: \n "
                + json.dumps([s.location.to_dict() for s in symbol_candidates], indent=2)
            )
        symbol = symbol_candidates[0]
        return self.replace_body_at_location(symbol.location, body, use_same_indentation=use_same_indentation)
  • Helper function that performs the actual text deletion and insertion to replace the symbol body using LSP operations.
    def replace_body_at_location(self, location: SymbolLocation, body: str, *, use_same_indentation: bool = True) -> None:
        """
        Replace the body of the symbol at the given location with the given body
    
        :param location: the location of the symbol to replace.
        :param body: the new body
        :param use_same_indentation: whether to use the same indentation as the original body. This means that
            the user doesn't have to provide the correct indentation, but can just write the body.
        """
        with self._edited_symbol_location(location) as symbol:
            assert location.relative_path is not None
            start_pos = symbol.body_start_position
            end_pos = symbol.body_end_position
            if start_pos is None or end_pos is None:
                raise ValueError(f"Symbol at {location} does not have a defined body range.")
            start_line, start_col = start_pos["line"], start_pos["character"]
    
            if use_same_indentation:
                indent = " " * start_col
                body_lines = body.splitlines()
                body = body_lines[0] + "\n" + "\n".join(indent + line for line in body_lines[1:])
    
            # make sure the replacement adds no additional newlines (before or after) - all newlines
            # and whitespace before/after should remain the same, so we strip it entirely
            body = body.strip()
    
            self._lang_server.delete_text_between_positions(location.relative_path, start_pos, end_pos)
            self._lang_server.insert_text_at_position(location.relative_path, start_line, start_col, body)
  • Dataclass defining the SymbolLocation used as input for precise symbol identification in replace_body_at_location.
    class SymbolLocation:
        """
        Represents the (start) location of a symbol identifier, which, within Serena, uniquely identifies the symbol.
        """
    
        relative_path: str | None
        """
        the relative path of the file containing the symbol; if None, the symbol is defined outside of the project's scope
        """
        line: int | None
        """
        the line number in which the symbol identifier is defined (if the symbol is a function, class, etc.);
        may be None for some types of symbols (e.g. SymbolKind.File)
        """
        column: int | None
        """
        the column number in which the symbol identifier is defined (if the symbol is a function, class, etc.);
        may be None for some types of symbols (e.g. SymbolKind.File)
        """
    
        def __post_init__(self) -> None:
            if self.relative_path is not None:
                self.relative_path = self.relative_path.replace("/", os.path.sep)
    
        def to_dict(self) -> dict[str, Any]:
            return asdict(self)
    
        def has_position_in_file(self) -> bool:
            return self.relative_path is not None and self.line is not None and self.column is not None
Behavior2/5

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

No annotations are provided, so the description must fully disclose behavioral traits. It states the tool 'replaces' the body, implying a mutation operation, but doesn't cover critical aspects like whether this is destructive (e.g., overwrites existing content), requires specific permissions, or has side effects. The mention of 'name_path' logic hints at dependencies but lacks detail on error handling or response format, leaving significant gaps in transparency.

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

Conciseness5/5

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

The description is a single, direct sentence that efficiently conveys the core action without unnecessary words. It front-loads the key information ('replaces the body of the symbol') and avoids redundancy, making it highly concise and well-structured for quick understanding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of a mutation tool with no annotations and no output schema, the description is incomplete. It lacks details on behavioral traits (e.g., destructiveness, error cases), usage context, and what the tool returns. While the schema covers parameters well, the overall context for safe and effective use is insufficient, especially for a tool that modifies symbols.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the input schema already documents all parameters thoroughly. The description adds minimal value by referencing 'name_path' logic from 'find_symbol', which provides some contextual meaning beyond the schema. However, it doesn't elaborate on parameter interactions or usage examples, staying at the baseline level where the schema does most of the work.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('replaces') and target ('body of the symbol'), making the purpose understandable. It specifies the 'name_path' parameter as the identifier, which adds specificity. However, it doesn't explicitly differentiate from sibling tools like 'replace_lines' or 'insert_after_symbol', which could involve similar symbol modifications, so it falls short of a perfect score.

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

Usage Guidelines2/5

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

The description provides no guidance on when to use this tool versus alternatives, such as 'replace_lines' or 'insert_before_symbol', which might handle similar tasks. It mentions 'name_path' logic from 'find_symbol', implying a prerequisite but not explicitly stating when this tool is preferred. Without clear usage context or exclusions, it offers minimal practical guidance.

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

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/lin2000wl/Serena-cursor-mcp'

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