In-depth architectural comparison of the Nvim MCP and Salesforce Metadata MCP MCP servers. Compare execution transports, security boundaries, tool capabilities, quality scores, and ready-to-paste client installation snippets for Claude, Cursor, Windsurf, and VS Code.
At a Glance & Executive Verdict
Nvim MCP
Developer Tools · Local stdio
Quality: 63/100 (Good) | Auth: No auth required
Salesforce Metadata MCP
Developer Tools · Local stdio
Quality: 63/100 (Good) | Auth: No auth required
Verdict Summary: Choose Nvim MCP if you need specialized Developer Tools tools running via a local process. Choose Salesforce Metadata MCP if your workspace requires Developer Tools integration with local subprocess execution. Both servers can be configured concurrently in your client's mcpServers manifest.
Which MCP Server Should You Choose?
Choose Nvim MCP when:
You need dedicated capabilities in the Developer Tools domain.
You prefer local stdio subprocess transport architecture.
Your security boundary fits: No auth required (Free / Open Source).
Connect to a running Neovim instance over its Unix socket or TCP address.
Call this before any other tool if the agent is not yet connected.
Connection is persistent for the session; you only need to call it once
unless you want to switch instances.
Called with no arguments: auto-connects when exactly one instance
is running; returns a list of instances when multiple are found.
Optional selection (provide at most one):
- index: pick from the listed instances (1-based).
- socket_path: connect directly to a known Unix socket or host:port.
- terminal_pid: find the Neovim instance whose process tree contains
this PID (useful when Neovim runs inside a specific terminal).
Returns {connected, cwd, file} on success, or {error} with details
on failure (e.g. no instances found, connection timeout, bad index).
send_command
Run one or more Vim ex commands in Neovim. This is a mutation tool —
commands can modify buffers, files on disk, windows, and editor state.
command: a single command string or a list of strings, without the
leading ':'. E.g. "w", "e src/main.py", "42", "wincmd v",
"lua vim.print(...)", or ["wincmd p", "e file.py", "wincmd p"].
Use this for editor operations that don't have a dedicated tool
(e.g. saving, opening files, splitting windows, setting options).
Use `send_keys` instead when you need normal-mode motions or
operator sequences. Use `find_and_replace_buf` or `write_full_buf`
for buffer text edits — they are safer and provide undo.
Returns {output} with the command's captured output, or {error}
if the command failed. When given a list, returns a list of results
in the same order; execution stops on the first error.
Ready-to-Paste Client Configurations
Paste either (or both) of these JSON server blocks into your client config file (e.g. claude_desktop_config.json or ~/.cursor/mcp.json).
Nvim MCP is categorized under Developer Tools and uses a local stdio subprocess. In contrast, Salesforce Metadata MCP belongs to Developer Tools using local stdio subprocess. Select Nvim MCP when you need capabilities focused on developer tools and Salesforce Metadata MCP when you require tools for developer tools.
Send raw keystrokes to Neovim as if typed by the user. This is a
mutation tool — keystrokes can modify buffers, change mode, and
trigger editor actions.
keys: a string of Vim keystrokes. Esc is prepended automatically, so
input always begins in normal mode. Multi-mode sequences must be sent
in a single call (e.g. "17GVG", not "17GV" then "G"). Use Vim
notation for special keys (e.g. "<CR>", "<C-w>v", "<Tab>").
Use this for normal-mode motions, visual selections, or operator
sequences. Use `send_command` for ex commands, and
`find_and_replace_buf` or `write_full_buf` for text edits — they
are safer and provide structured results.
Returns {sent} confirming the keys that were dispatched. Keystrokes
are fire-and-forget; errors from the resulting Vim actions are not
captured in the return value.
send_to_terminal
Type text into a terminal buffer's running program (usually a shell)
by writing to its job channel. This is a mutation tool — the text
reaches the program's stdin as if typed, but is not executed unless
submit is true.
text: the text to send, raw. In most shells an embedded newline acts
like pressing Enter, so multi-line text may execute line by line.
When submit is false, trailing newlines are stripped so nothing
runs by accident.
terminal: which terminal to target — a buffer number or buffer name,
as listed under `terminals` in `get_state` / `get_state_brief`.
Names match exactly first, then by unique substring. Omit it when
exactly one terminal exists; with several open, omitting it
returns an error listing them.
submit: false (default) leaves the text at the prompt for the user
to review and press Enter. true appends a carriage return so the
program executes it immediately. NEVER pass submit=true unless
the user has explicitly asked for the command to be run — "put",
"paste", "type", or "prepare" a command always means
submit=false. Suggesting a command yourself is not permission to
run it. When in doubt, use submit=false and let the user press
Enter.
Use this whenever text needs to go into a terminal. It works
regardless of focus, mode, or visibility and never moves the user's
cursor — unlike `send_keys`, which requires focusing the terminal
and juggling modes. Terminal buffers cannot be edited with the
buffer tools.
Returns {sent, terminal, buf, submitted} on success — sent is the
byte count actually written. On failure returns {error}, including
a `terminals` list when the target was missing or ambiguous.
get_all_diagnostics
Get LSP diagnostics from all open buffers in Neovim. Read-only.
Use this for a project-wide overview of errors and warnings. Use
`get_buf_diagnostics` instead when you only need diagnostics for a
specific file — it is more focused and returns less data.
Returns a list of {file, line, col, severity, message, source}.
severity is one of "error", "warning", "info", "hint". Returns an
empty list when there are no diagnostics. Results depend on which
LSP servers are attached and which buffers are loaded in Neovim.
get_buf_diagnostics
Get LSP diagnostics for a single Neovim buffer. Read-only.
file: path relative to Neovim's cwd (as shown in `get_state` buffers).
The buffer must already be open in Neovim; returns an error otherwise.
Use this when you need diagnostics for one specific file. Use
`get_all_diagnostics` instead for a project-wide overview.
Returns a list of {file, line, col, severity, message, source}.
severity is one of "error", "warning", "info", "hint". Returns an
empty list when the buffer has no diagnostics.
find_and_replace_buf
Find and replace text in a Neovim buffer. The edit happens in-memory
and is fully undoable — nothing is written to disk until the user saves.
file: path relative to Neovim's cwd (as shown in `get_state` buffers).
old_string: the exact text to find. Must match exactly once in the
buffer; returns an error if not found or if it matches multiple
locations. Include surrounding lines to disambiguate.
new_string: the replacement text.
Creates the buffer if it doesn't already exist. Use this for targeted
edits. Use `write_full_buf` instead when replacing the entire buffer
content. Use `read_full_buf` or `read_buf_range` first if you need
to see the current content before editing.
Returns {start_line, lines_removed, lines_added, total_lines} on
success, or {error} with a message on failure.
write_full_buf
Replace the entire content of a Neovim buffer. The edit happens
in-memory and is fully undoable — nothing is written to disk until
the user saves.
file: path relative to Neovim's cwd (as shown in `get_state` buffers).
content: the full new text for the buffer.
Creates the buffer if it doesn't already exist. Use this when you
need to rewrite the whole file. Use `find_and_replace_buf` instead
for targeted edits that preserve surrounding content.
Returns {total_lines} with the new line count.
read_full_buf
Read the full content of a Neovim buffer. Read-only; reads from
Neovim's in-memory buffer, which may differ from the file on disk
if there are unsaved changes.
file: path relative to Neovim's cwd (as shown in `get_state` buffers).
The buffer must already be open in Neovim; returns an error otherwise.
Use this when you need to see the entire file. Use `read_buf_range`
instead when you only need a specific section — it returns less data.
Returns {lines, total_lines}. lines is a list of strings, each
prefixed with its 1-based line number (e.g. "1: first line").
read_buf_range
Read a specific line range from a Neovim buffer. Read-only; reads
from Neovim's in-memory buffer, which may differ from the file on
disk if there are unsaved changes.
file: path relative to Neovim's cwd (as shown in `get_state` buffers).
The buffer must already be open in Neovim; returns an error otherwise.
start_line: first line to read (1-indexed, inclusive).
end_line: last line to read (1-indexed, inclusive). Out-of-range
values are clamped to the buffer bounds. If start_line > end_line
they are swapped automatically.
Use this when you only need a section of a file. Use `read_full_buf`
instead when you need the entire buffer.
Returns {lines, total_lines}. lines is a list of strings, each
prefixed with its 1-based line number (e.g. "10: some code").
get_state
Full snapshot of the current Neovim session. Read-only — does not
modify any editor state.
Use `get_state_brief` for quick orientation at the start of a turn.
Use this when you need the complete picture: all window details,
folds, marks, diagnostics summaries, highlights, virtual text, and
indent settings.
Returns: mode (normal/insert/visual/etc.), cwd, buffers (relative
paths of all listed buffers), modified_buffers, current_tab, tab_count,
and terminals — a list of open terminal buffers as {buf, name,
visible}, present only when at least one exists (targets for
`send_to_terminal`).
windows — list of visible windows (current tab only). The active
window is always first, the alternate window (previous) is second.
Each window entry contains:
file (path relative to cwd), filetype, total_lines, modified,
buftype ("file" for normal buffers, "terminal", etc.),
line, col, indent: {expandtab, shiftwidth, tabstop}.
Optional per-window fields (present when applicable):
- role: "active" or "alternate".
- context: numbered lines surrounding the cursor.
- selection: {start_line, start_col, end_line, end_col} in visual modes.
- folds: list of [start, end] closed fold ranges.
- diagnostics_summary: {error, warning, info, hint} counts.
- marks: list of {mark, line, col} for lowercase (a-z) buffer marks.
- mcp_highlights: list of {start_line, end_line, color} for active highlights.
- mcp_virtual_text: list of {line, position, lines, color} for active virtual text.
get_state_brief
Lightweight snapshot of the Neovim session for quick orientation.
Read-only — does not modify any editor state.
Use this at the start of each turn to see what the user is working
on. Use `get_state` instead when you need the full picture: all
windows, folds, marks, diagnostics summaries, highlights, virtual
text, and indent settings.
Returns: mode (normal/insert/visual/etc.), cwd, buffers (relative
paths of all listed buffers), modified_buffers, and active_window:
{file, filetype, total_lines, modified, buftype, line, col, context}.
context is a short list of numbered lines around the cursor.
If an alternate window exists, also returns alternate_window with
the same fields. When terminal buffers exist, returns terminals — a
list of {buf, name, visible} (targets for `send_to_terminal`).
+6 more tools listed on main page
Salesforce Metadata MCP Tools (20)
sf_create_custom_object
Creates a new Salesforce Custom Object using the Metadata API. The object name must end with '__c'. Use this when a user asks to create a new object, entity, or table in Salesforce.
sf_create_custom_field
Creates a new custom field on an existing Salesforce object. The field API name must end with '__c'. Supports all field types: Text, Number, Picklist, Lookup, etc.
sf_add_picklist_values
Adds new picklist values to an existing Picklist or MultiselectPicklist field without removing existing values. Use when a user wants to add new options to a dropdown.
sf_create_approval_process
Creates or updates a Salesforce Approval Process via the Metadata API. Define who can submit, approval steps with approvers, entry criteria, and what happens on approval or rejection.
sf_create_validation_rule
Creates or updates a Salesforce Validation Rule on any object via the Metadata API. The errorConditionFormula returns TRUE when data is INVALID. Use for data quality enforcement.
sf_create_workflow_field_update
Creates a Workflow Field Update action that can be referenced by Approval Processes, Workflow Rules, or Flows. Sets a field to a literal value, formula result, or null.
sf_create_formula_field
Creates a formula field on any Salesforce object. Supports all return types (Text, Number, Currency, Date, DateTime, Checkbox, Percent) and the full Salesforce formula language: IF/AND/OR/NOT, BLANKVALUE, TEXT, VALUE, DATE, DATEVALUE, TODAY, NOW, date functions (MONTH/YEAR/DAY), math (FLOOR/CEILING/MOD), string functions (LEN/LEFT/RIGHT/MID/TRIM/UPPER/LOWER/CONTAINS/BEGINS), record type and picklist functions (ISPICKVAL, ISNULL, ISBLANK), cross-object field references (e.g. Account.Owner.Name), and VLOOKUP. Complex multi-line formulas are fully supported.
sf_deploy_metadata
Deploys a set of metadata components directly to the org using the Metadata API SOAP deploy operation. Builds a package.xml and deployment zip in memory. Supports validate-only (checkOnly:true) for pre-deployment validation without making changes. Specify runTests to execute test classes during deployment (required for production). Polls until complete or timeout.
sf_check_deploy_status
Checks the status of an in-progress or recently completed metadata deployment by async job ID. Returns the status (Pending, InProgress, Succeeded, Failed, Canceled), component successes, failures, and test results. Use with the deploy ID returned from sf_deploy_metadata.
sf_retrieve_metadata
Retrieves metadata components from the org and returns their actual file contents. Use this to read existing configuration before making changes, to back up metadata, or to check what is really deployed rather than what you think is deployed. Waits for the async retrieve to finish and unpacks the resulting zip, returning each file's path and source. Large files are truncated. Accepts 'components' (array), or 'metadataType'+'componentName' as a single-item shortcut, or a raw 'packageXml' document — provide exactly one form.
sf_delete_metadata
Permanently deletes one or more metadata components of a given type via the Metadata API's deleteMetadata call — works for CustomObject, CustomField, Flow, GenAiFunction, GenAiPlugin, GenAiPlannerBundle, Bot, ApexClass, and most other metadata types. There was previously no way to remove anything created by this MCP server (sf_deploy_metadata only supports adding/updating components, not destructiveChanges) — diagnostic or abandoned metadata had nowhere to go. Deletes each fullName independently: check the response's deleted/errors lists rather than assuming all all-or-nothing. Some types have dependency order requirements (e.g. delete a Bot's GenAiFunction/GenAiPlugin/GenAiPlannerBundle before the Bot itself, delete CustomField before its parent CustomObject) — Salesforce will reject a delete that still has dependents, naming them in the error.
sf_query_records
Executes a SOQL query against the org and returns matching records. Provide the full SOQL string in the query param. Use for reading data, checking existing records before creating, or verifying changes.
Supports aggregate queries — GROUP BY with COUNT(), SUM(), AVG(), MAX(), MIN(), e.g.:
'SELECT StageName, COUNT(Id), SUM(Amount) FROM Opportunity GROUP BY StageName'
Aggregate results come back as regular records with the aggregate expressions as field keys (e.g. "expr0").
Row cap: 'limit' defaults to 200 and is a ceiling, not a hint. If the SOQL carries its own LIMIT the smaller of the two applies, so a LIMIT in the query can tighten the cap but never raise it. When rows are cut off the response sets truncated: true and reports appliedLimit and limitSource, so a capped result is never mistaken for a complete one.
MCP server providing AI assistants with full control of Neovim instances via msgpack-RPC. Read/edit buffers, run commands, send keys, query LSP diagnostics, and annotate code with highlights. No plugin required.
The only Salesforce MCP with Agentforce, OmniStudio & DevOps Center tools — 228 total.