Skip to main content
Glama
jinwei233

emacs-runtime-mcp

by jinwei233

emacs-runtime-mcp

A small MCP stdio server that evaluates one Emacs Lisp form in an already-running Emacs instance. It exposes exactly one tool, emacs_eval; agents discover built-in, package, and user-defined capabilities from the live runtime instead of loading a generated command catalog.

Security

This package provides arbitrary code execution with the permissions of your Emacs process and user account. Use it only with trusted local MCP clients.

It is not a sandbox, access-control boundary, transaction system, or safe network service. A connected client can read, modify, or delete user-accessible data and control Emacs. A request timeout only terminates emacsclient; Lisp already accepted by Emacs may continue running. Output limits do not prevent Emacs from constructing a large value in memory.

See SECURITY.md before enabling the server.

Related MCP server: win-cli-mcp-tmyy

Requirements

Component

Supported

Node.js

20 or newer

Emacs and emacsclient

28 or newer, preferably from the same installation

Transport

Local stdio MCP

Platform

macOS and Linux

The server never starts Emacs. Start a daemon yourself (emacs --daemon) or enable server-mode in the Emacs instance you want to control.

Install

From npm after a release:

npm install --global emacs-runtime-mcp

From a source checkout:

pnpm install
pnpm build
node dist/cli.js --help

MCP Client Configuration

For a global installation:

{
  "mcpServers": {
    "emacs": {
      "command": "emacs-runtime-mcp"
    }
  }
}

For a named daemon such as emacs --daemon=work:

{
  "mcpServers": {
    "emacs": {
      "command": "emacs-runtime-mcp",
      "args": ["--socket-name", "work"]
    }
  }
}

An explicit server file is also supported:

{
  "mcpServers": {
    "emacs": {
      "command": "emacs-runtime-mcp",
      "args": ["--server-file", "/absolute/path/to/server-file"]
    }
  }
}

--socket-name and --server-file are mutually exclusive. Every invocation passes --alternate-editor=false, so an unavailable server fails instead of starting another editor or daemon.

Options And Environment

CLI option

Environment variable

Default

--emacsclient PATH

EMACS_RUNTIME_MCP_EMACSCLIENT

emacsclient

--socket-name NAME

EMACS_RUNTIME_MCP_SOCKET_NAME

default server

--server-file PATH

EMACS_RUNTIME_MCP_SERVER_FILE

unset

--timeout-ms N

EMACS_RUNTIME_MCP_TIMEOUT_MS

10000

--max-output-chars N

EMACS_RUNTIME_MCP_MAX_OUTPUT_CHARS

65536

CLI values override the corresponding environment value. Supplying both kinds of server selector is a startup error.

Tool

emacs_eval accepts:

{
  "expression": "(list (emacs-version) (buffer-name))",
  "timeout_ms": 10000,
  "max_output_chars": 65536
}

expression must contain exactly one readable Emacs Lisp form. Node validates the request shape and numeric limits; the selected Emacs runtime performs Lisp reading and rejects trailing non-whitespace content before evaluation.

Supported limits:

  • expression: 1 to 262,144 Unicode code points

  • timeout_ms: 100 to 120,000

  • max_output_chars: 1 to 262,144

  • combined subprocess stdout/stderr: fixed 1 MiB hard ceiling

The tool returns the prin1-to-string representation, not an automatic JSON conversion of the Lisp value.

Success

{
  "ok": true,
  "value": "(\"GNU Emacs 31.1\" \"notes.org\")",
  "truncated": false,
  "original_chars": 31,
  "elapsed_ms": 4
}

original_chars is always present. max_output_chars limits only value. Counts use Emacs string characters after printing, not UTF-8 bytes or grapheme clusters.

Failure

{
  "ok": false,
  "error": {
    "code": "elisp_error",
    "message": "Symbol's value as variable is void: missing",
    "data": {
      "symbol": "void-variable"
    }
  },
  "elapsed_ms": 3
}

Stable codes are invalid_request, invalid_expression, emacs_unavailable, elisp_error, evaluation_timeout, output_too_large, bridge_protocol_error, and internal_error.

MCP results carry the same envelope in structuredContent and JSON text content. Failed envelopes set isError: true.

Agent Discovery Skill

skills/emacs-live/SKILL.md teaches agents to:

  1. inspect explicit live buffer, window, mode, and project context;

  2. discover symbols with Emacs introspection;

  3. review signatures, interactive prompts, source, and side effects;

  4. invoke one explicit operation;

  5. verify its postcondition.

The Skill contains reusable discovery patterns, not a command inventory.

Troubleshooting

  • emacs_unavailable: verify the daemon name or server file with emacsclient --alternate-editor=false --socket-name NAME --eval t.

  • invalid_expression: submit one form; wrap multiple intended operations in progn.

  • elisp_error: inspect error.data.symbol and the message, then inspect the candidate function and runtime context.

  • evaluation_timeout: assume runtime state is unknown. Run a read-only health probe and inspect relevant state before another mutation.

  • output_too_large: narrow the query. Increasing max_output_chars cannot exceed the fixed transport ceiling.

  • bridge_protocol_error: confirm emacsclient and Emacs are compatible and that no wrapper output is being modified.

All server diagnostics go to stderr. Stdout is reserved for MCP JSON-RPC.

Development

pnpm check
pnpm test:integration
pnpm build
pnpm pack

Integration tests create a random named emacs -Q daemon with temporary state and always target it explicitly; they never use the developer's default server.

Licensed under MIT.

Available Tools

1 tool
emacs_evalEvaluate Emacs LispC

Evaluate exactly one Emacs Lisp form in an already-running trusted local Emacs server.

ParametersJSON Schema
NameRequiredDescriptionDefault
expressionYesOne Emacs Lisp form to evaluate in the live Emacs runtime.
timeout_msNo
max_output_charsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

C2.9/5.0
Behavior2/5

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

With no annotations, the description carries the full behavioral burden. It gestures at safety with 'trusted local' but never warns that this executes arbitrary code with full server-side side effects, nor explains timeout or output-truncation behavior. For an eval tool this is a significant disclosure gap.

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

Conciseness4/5

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

A single, front-loaded sentence with no filler. It is efficient, though its brevity is part of why behavioral and parameter context is missing.

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?

An output schema exists so return values needn't be explained, but for an arbitrary-code-execution tool with zero annotations the description should disclose side effects, timeout semantics, and output limits. Those omissions leave an agent under-informed about the two undocumented parameters and the tool's blast radius.

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

Parameters2/5

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

Schema coverage is only 33%: 'expression' is documented in the schema, but 'timeout_ms' and 'max_output_chars' carry no description anywhere. The description adds nothing about these controls, so it fails to compensate for the coverage gap despite their relevance to a long-running or chatty evaluation.

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?

States a specific verb and resource: evaluate exactly one Emacs Lisp form against a running Emacs server. The 'exactly one form' constraint and the runtime target are clear. No siblings exist to differentiate from, so it doesn't need comparative wording.

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

Usage Guidelines3/5

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

The phrase 'already-running trusted local Emacs server' implies a precondition (a server must exist and be local/trusted), which is useful routing context. However, it never states when to reach for this tool versus other execution paths, nor any exclusions or failure conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 1 tool updatev0.1.0
    • First observedemacs_eval

TDQS

B3.2/5.0

Scored across 1 tool

Disambiguation5/5

There is only one tool, so there is no possibility of selecting the wrong one. Its purpose—evaluating a single Emacs Lisp form—is unambiguous.

Naming Consistency4/5

The single name 'emacs_eval' follows a clear namespace_verb convention in snake_case, which is readable and predictable. With only one tool there is no pattern to verify against, so it cannot be judged fully consistent.

Tool Count3/5

A single tool is thin for a server whose stated scope is an Emacs runtime. It earns its place, but the surface is minimal enough that agents will hit its limits quickly.

Completeness3/5

Evaluation of one form at a time is functional but leaves notable gaps: no batch evaluation, no file loading or buffer inspection, and no way to explore server state. The core operation exists, but the surrounding lifecycle is largely absent.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables live runtime inspection of any Python application, allowing MCP clients to query state, evaluate expressions, inspect objects, and read source code while the app runs.
    -
  • A
    license
    Not graded
    quality
    A
    maintenance
    It enables local MCP clients to interact with the live Positron R or Python session, supporting variable inspection, silent evaluation, and state-changing execution.
    2
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to expose and control local and self-hosted tools via MCP, with isolated workers, long-running task management, persisted state, and modular integrations for reverse engineering and development workflows.
    MIT