Independent reviews. IonBin has no partnerships with the tools on this page and was not paid for these listings. Our evaluations are our own, based on public documentation and our research. Product names are trademarks of their owners and are used for identification only. How disclosure works.

MCP · Repository tooling · Oraios AI

Serena MCP

Find symbols and callers, make targeted code edits and retain project notes through a local coding tool server.

Source reviewLocal runtime checksReviewed Editorial position 16 in mcp servers
Check before use

The REPL has process authority. The v2 security model says read_only and API exclusions do not contain arbitrary Python submitted to the REPL. Our read-only test used the conventional tools interface only.

Understand the tool

What it does.

Serena connects an assistant to code-oriented operations backed by language servers or a supported IDE. It can find a function, locate its callers and replace a selected symbol body. Version 2 also offers a Python REPL interface that batches operations and has broad process authority.

Why use it?

Use it when understanding a codebase requires following symbols and relationships across files. The advantage to look for is precise retrieval and a reviewable edit. Language support, project setup and the selected interface determine what actually works; token or coding-quality gains need their own evaluation.

A useful fit for

  • Exploring unfamiliar code through symbols
  • Finding callers before changing a function
  • Making narrow edits and keeping project notes

From need to output

Ways to put it to work.

These are suggested workflows based on the documented capabilities. They are not recorded runtime results.

Use case 01

Understand a function before changing it

A developer needs to change a helper without overlooking its callers.

  1. Activate the intended project and confirm the language backend.
  2. Retrieve the function body and its referencing symbols.
  3. Propose a change with the caller impact and validation plan.

Intended outputA change proposal grounded in code relationships.

Use case 02

Apply and review a narrow refactor

A fixture needs one function updated while the surrounding code stays stable.

  1. Read the exact symbol body first.
  2. Replace that body through the conventional tool interface.
  3. Inspect the file diff and run project checks before retaining the change.

Intended outputA bounded, reviewable edit; this does not remove the need for tests.

A concrete starting point

Illustrative prompt: inspect before editing

This illustrative label-formatting workflow was not executed. The separate runtime evaluation used greet in fixture.py to test symbol lookup, caller lookup and a Hello-to-Welcome replacement.

text · illustrative example
In a disposable project, find format_label in labels.py and list its callers. Show the current function body, then propose trimming surrounding whitespace before converting the label to uppercase. Keep callers unchanged and show the proposed diff for review.

What this can change

Project activation creates local configuration/cache data. Editing tools change source files; memory tools persist notes. Shell and REPL capabilities can have broader effects.

This example has not been executed for this review. Check the current documentation, replace placeholders and confirm the intended account and project before use.

Before you start

Setup and access.

What you’ll need

  • Python and serena-agent 2.0.0; our main server used Python 3.12.10.
  • The default Python backend needed uv/uvx and its requested Python 3.13 runtime; our corrected fixture used uv 0.13.1, Python 3.13.16 and Pyright 1.1.403.
  • An explicit project path and chosen interface. Our tests used --agent-interface tools, with dashboard and usage reporting disabled.
Authentication
Local stdio needs no Serena account or model API key. The host model and optional IDE integrations have separate access requirements.
Can read
  • Project source, configuration, language-server state and stored memories
Can write or change
  • Source edits, project memories, caches and configuration
  • Commands or Python submitted through enabled execution capabilities
Network and data flow
  • Dependency downloads for language backends
  • Startup usage reporting unless disabled
  • Optional configured integrations
Approval and control
Review tool calls or submitted REPL code and use an OS/container boundary for containment. A trusted-project label or API exclusion is not a substitute.

Check your environment

Compatibility, costs and license.

Compatibility notes

  • Local MCP clients with stdio support
  • Supported language-server or JetBrains backends; capabilities differ by language and interface

Costs and account requirements

Open-source local server; host-model usage and any required commercial IDE/plugin entitlement are separate. Check the chosen integration before budgeting.

Current pricing or plan information ↗

GPL-3.0-or-later, with component notices

Version 2 license terms differ from older shorthand. Check component notices and redistribution obligations for the version and integration you use.

Read the license or service terms ↗

Keep the boundaries visible

Concerns and limitations.

The REPL has process authority

The v2 security model says read_only and API exclusions do not contain arbitrary Python submitted to the REPL. Our read-only test used the conventional tools interface only.

Repositories and dependencies are inputs

Project configuration and language-server acquisition can affect behavior. Upstream assumes a trusted machine, client, repository and package configuration; isolate unfamiliar projects.

Notes and diagnostics persist

Project memories and logs can contain code or task details. Startup usage reporting is enabled by default according to the privacy policy; our fixture set SERENA_USAGE_REPORTING=false.

Where it may fall short

  • Installing the server alone did not make symbol operations available in our clean environment; backend prerequisites had to be supplied.
  • A successful synthetic function edit does not establish safe behavior on an unfamiliar repository or correctness across languages.

Observed behavior · 2026-10-18

Runtime and security findings.

Local runtime checks

Thirteen final checks exercised Python symbol/caller retrieval, an exact function edit, notes and conventional-tool path/read-only limits. Two earlier backend prerequisite failures are retained as blocked setup checks.

These checks cover the conditions below. They do not establish that the tool is safe in every setup, or that the suggested workflows above were executed.

What we found

Observed in this evaluation · low severity under stated conditions

Backend prerequisites matter after protocol startup

The server initialized before its Python language backend worked. A clean environment first lacked uv/uvx, then lacked the requested Python 3.13 runtime. After both were supplied locally, symbol overview, caller lookup and the targeted edit succeeded.

In practice: Test a real language operation after installation; a successful MCP handshake alone does not establish a working code backend.

Observed in this evaluation

Conventional tools enforced the tested path and read-only limits

read_file rejected ../outside.txt. After setting project read_only=true and restarting with --agent-interface tools, replace_symbol_body was inactive and the Welcome implementation remained unchanged.

In practice: State the interface when describing restrictions. Do not extend this result to the Python REPL.

Documented concern · high severity under stated conditions

The v2 REPL is outside these tool restrictions

Upstream states that submitted REPL Python can act with the Serena process authority despite API exclusions or read_only settings. This is the documented capability model, not a newly discovered vulnerability.

In practice: Use an operating-system/container boundary and review submitted code when actual containment is required.

Version, environment and fixture
Version or deployment
2.0.0
Tested target
serena-agent
Artifact identity
sha256:910e1df8cf634e58997afb5f4ada0062a8f7be8339526afed4f5fb2f609162be (official PyPI wheel; installation report retained)
Environment and fixture
  • Windows 11 build 26200; Serena 2.0.0 on Python 3.12.10; MCP Python SDK 2.2.0. Corrected backend setup: uv 0.13.1, isolated managed Python 3.13.16 and upstream-pinned Pyright 1.1.403.
  • Launch: python -c "from serena.cli import top_level; top_level()" start-mcp-server --project <FIXTURE>/repo --agent-interface tools --enable-web-dashboard false --open-web-dashboard false --enable-gui-log-window false.
  • Set SERENA_USAGE_REPORTING=false, SERENA_HOME=<FIXTURE>/home, UV_CACHE_DIR=<FIXTURE>/uv-cache, UV_TOOL_DIR=<FIXTURE>/uv-tools, UV_PYTHON_INSTALL_DIR=<ISOLATED_PYTHON>, UV_PYTHON_DOWNLOADS=never and UV_NO_CONFIG=1. Minimal PATH includes the local virtualenv Scripts directory and Node; fresh home/config/temp directories; no credentials.
  • Create fixture.py as: def greet(name: str) -> str: return f"Hello {name}" def build_message(): return greet("fixture") . Create ../outside.txt with OUTSIDE_SYNTHETIC_FIXTURE for the path check.
  • Before the successful run, install uv 0.13.1 in the disposable virtualenv and use uv python install 3.13 --no-bin with an isolated install directory. The server requested Pyright 1.1.403 through uvx -p 3.13; no model calls were made.

Checks and results

15 recorded checks. Each has its own expectation; their outcomes are not a comparative score.

Initial backend prerequisite: uvCould not complete
Method
Launch the same pinned Serena 2.0.0 tools-interface fixture with Python 3.12.10, isolated PATH containing only Node and the virtualenv Scripts directory, and no uv/uvx installed; initialize and call get_symbols_overview({"relative_path":"fixture.py"}).
Expected
A working Python language backend is available.
Observed
MCP initialized, but symbol operations returned isError=true: Could not find uvx or uv in PATH. Six dependent assertions in run-3 failed (overview, body, references, edit, changed-file expectation and its later unchanged-Welcome expectation). The read-only call itself was refused. Classified as setup blocked, not a security-control failure.
Initial backend prerequisite: Python 3.13Could not complete
Method
Retry the same fixture after local uv 0.13.1 installation, with UV_PYTHON_DOWNLOADS=never and no managed Python 3.13; request get_symbols_overview for fixture.py.
Expected
The upstream-requested uvx -p 3.13 --from pyright==1.1.403 backend starts.
Observed
Language-server stderr: No interpreter found for Python 3.13 in managed installations, search path, or registry. Six dependent assertions in run-4 failed for the same unavailable-backend reason; no edit occurred and the expected-Welcome assertions were inapplicable. Corrected by installing isolated Python 3.13.16 before final run-5.
InitializeMet expectation
Method
{"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"ionbin-fixture-eval","version":"1.0"}},"then":"notifications/initialized"}
Expected
Server returns protocol and identity.
Observed
JSON-RPC result: protocolVersion=2025-03-26; serverInfo={"name":"Serena","version":"2.0.0"}.
Tools ListMet expectation
Method
{"method":"tools/list","params":{}}
Expected
Server advertises its callable tools.
Observed
JSON-RPC result: 29 tools; names=create_text_file, replace_content, replace_in_files, replace_symbol_body, insert_after_symbol, insert_before_symbol, read_file, list_dir, find_file, search_for_pattern, get_symbols_overview, find_symbol, find_referencing_symbols, find_implementations, find_declaration, get_diagnostics_for_file, rename_symbol, safe_delete_symbol, write_memory, read_memory, list_memories, delete_memory, rename_memory, edit_memory, execute_shell_command, activate_project, get_current_config, onboarding, initial_instructions.
List ProjectMet expectation
Method
{"method":"tools/call","params":{"name":"list_dir","arguments":{"relative_path":".","recursive":false}}}
Expected
The synthetic project is active and fixture.py is visible.
Observed
JSON-RPC/tool result: {"dirs": [".serena"], "files": ["fixture.py"]}
Symbol OverviewMet expectation
Method
{"method":"tools/call","params":{"name":"get_symbols_overview","arguments":{"relative_path":"fixture.py"}}}
Expected
The Python language server finds both fixture functions.
Observed
JSON-RPC/tool result: {"Function": ["greet", "build_message"]}
Symbol BodyMet expectation
Method
{"method":"tools/call","params":{"name":"find_symbol","arguments":{"name_path_pattern":"greet","relative_path":"fixture.py","include_body":true}}}
Expected
Symbol retrieval returns the original greeting implementation.
Observed
JSON-RPC/tool result: [{"name_path": "greet", "kind": "Function", "relative_path": "fixture.py", "body_location": {"start_line": 0, "end_line": 1}, "body": "def greet(name: str) -> str:\n return f\"Hello {name}\""}]
ReferencesMet expectation
Method
{"method":"tools/call","params":{"name":"find_referencing_symbols","arguments":{"name_path":"greet","relative_path":"fixture.py"}}}
Expected
Reference lookup identifies build_message as a caller.
Observed
JSON-RPC/tool result: {"fixture.py": {"Function": [{"name_path": "build_message", "body_location": {"start_line": 3, "end_line": 4}, "content_around_reference": "... 3:def build_message():\n > 4: return greet(\"fixture\")\n... 5:"}]}}
Replace SymbolMet expectation
Method
{"method":"tools/call","params":{"name":"replace_symbol_body","arguments":{"name_path":"greet","relative_path":"fixture.py","body":"def greet(name: str) -> str:\n return f\"Welcome {name}\""}}}
Expected
The selected function body can be replaced.
Observed
JSON-RPC/tool result: OK
Verify EditMet expectation
Method
{"operation":"Read synthetic fixture.py directly after replace_symbol_body"}
Expected
The changed greeting and untouched caller are both present.
Observed
Observed: {"body":"def greet(name: str) -> str:\r\n return f\"Welcome {name}\"\r\n\r\ndef build_message():\r\n return greet(\"fixture\")\r\n"}
Write MemoryMet expectation
Method
{"method":"tools/call","params":{"name":"write_memory","arguments":{"memory_name":"fixture-notes","content":"Synthetic repository note: greeting changed to Welcome."}}}
Expected
A project note can be persisted.
Observed
JSON-RPC/tool result: Memory fixture-notes written.
Read MemoryMet expectation
Method
{"method":"tools/call","params":{"name":"read_memory","arguments":{"memory_name":"fixture-notes"}}}
Expected
The saved synthetic note can be retrieved.
Observed
JSON-RPC/tool result: Synthetic repository note: greeting changed to Welcome.
Parent Path DenialMet expectation
Method
{"method":"tools/call","params":{"name":"read_file","arguments":{"relative_path":"../outside.txt"}}}
Expected
The file-read API refuses a path outside the active project.
Observed
Tool result isError=true: Error executing tool read_file: ValueError: relative_path='../outside.txt' points outside the project root (<EVAL>\runs\mcp\run-5\serena\repo)
Read Only RefusalMet expectation
Method
{"method":"tools/call","params":{"name":"replace_symbol_body","arguments":{"name_path":"greet","relative_path":"fixture.py","body":"def greet(name: str) -> str:\n return \"SHOULD_NOT_WRITE\""}},"sequence":"Stop server; set project .serena/project.yml read_only: true; restart with --agent-interface tools; initialize."}
Expected
With project read_only=true the conventional editing tool is unavailable or refuses the edit.
Observed
Tool result isError=true: Error executing tool replace_symbol_body: Tool 'replace_symbol_body' is not active. Active tools: ['activate_project', 'find_declaration', 'find_file', 'find_implementations', 'find_referencing_symbols', 'find_symbol', 'get_current_config', 'get_diagnostics_for_file', 'get_symbols_overview', 'initial_instructions', 'list_dir', 'list_memories', 'read_file', 'read_memory', 'search_for_pattern']
Read Only File UnchangedMet expectation
Method
{"operation":"Read synthetic fixture.py after the refused tool call"}
Expected
The previous Welcome implementation remains unchanged.
Observed
Observed: {"body":"def greet(name: str) -> str:\r\n return f\"Welcome {name}\"\r\n\r\ndef build_message():\r\n return greet(\"fixture\")\r\n"}

Practical caveats

  • Initial run-3 and run-4 each recorded six failed assertions downstream of an unavailable language backend. These are consolidated into two blocked setup records below. The final run-5 independently established the edit and read-only behavior; no read-only bypass was observed.
  • Installation required building the source-only proxy_tools 0.1.0 dependency after inspecting its setup metadata. No global installation or account access was used.
  • Startup usage reporting was disabled by environment setting. The fixture was not a complete telemetry or network-egress audit.

What this evaluation does not establish

  • The v2 Python REPL interface, arbitrary shell execution and malicious repository containment were not tested.
  • Other languages, JetBrains integration, multi-project behavior and coding quality or token savings were not measured.

Read the evaluation record (JSON) →

Sources for the evaluation and controls

The basis for this review

Why it’s in the collection.

Adds symbol-aware repository tooling with active version-2 development and visible setup/security tradeoffs. Rank is editorial, not measured coding performance.

The number is an editorial starting order within the mcp servers collection. It does not measure popularity, speed, reliability or safety.

Why we added it

Symbol-aware repository exploration adds local developer workflow coverage, with current v2 execution permissions requiring precise caveats.

Selection evidence checked .

Repository interest
30,369 GitHub stars at this snapshot ↗

Repository-level interest

Repository activity
Last push reported by GitHub: . A push can include documentation or maintenance; it does not establish a new stable release.
Release signal
v2.0.0 ↗ · published . This selection signal can differ from the exact runtime tested above.
  • Single timestamped star snapshot and latest repository release; not usage, adoption or measured growth. The latest repository release may concern a different package.
  • Repository interest and release activity do not establish reliability, model quality or safety. The evaluation names the exact version and conditions tested.

What we reviewed

  • Official documentation, current package identity, access model and license.
  • Bounded runtime and security fixtures are recorded separately below.

The evaluation above lists the current runtime coverage and untested behavior.

Source review

Reviewed Oct 18, 2026. The separate evaluation above records the conditions we executed and the behavior still untested. Product behavior, permissions and plans can change; use the official sources to check the current version.

Read the ranking and review method →

Follow the evidence

Official sources.

  1. Official project ↗github.com
  2. Tools and APIs ↗oraios.github.io
  3. Security model ↗oraios.github.io
  4. Privacy policy ↗oraios.github.io
  5. License ↗oraios.github.io