Content
#+TITLE: MCP.el - Model Context Protocol for Emacs
[[https://melpa.org/#/mcp][file:https://melpa.org/packages/mcp-badge.svg]]
[[https://www.gnu.org/licenses/gpl-3.0][https://img.shields.io/badge/License-GPLv3-blue.svg]]
This is an Emacs client for interfacing with [[https://modelcontextprotocol.io/introduction][MCP]], supporting connections to MCP servers.
* Features
- Structured communication with MCP servers
- Support for filesystem and generic MCP servers
- Extensible tool and prompt system
- Asynchronous and synchronous operations
- Resource management capabilities
- Intuitive interface for managing server lifecycle (start/stop/restart)
- Integration with popular Emacs packages (e.g., gptel, llm)
* Installation
Need Emacs 30 or higher version
#+begin_src elisp
(use-package mcp
:ensure t
:after gptel
:custom (mcp-hub-servers
`(("filesystem" . (:command "npx" :args ("-y" "@modelcontextprotocol/server-filesystem" "/home/lizqwer/MyProject/")))
("fetch" . (:command "uvx" :args ("mcp-server-fetch")))
("qdrant" . (:url "http://localhost:8000/sse"))
("graphlit" . (
:command "npx"
:args ("-y" "graphlit-mcp-server")
:env (
:GRAPHLIT_ORGANIZATION_ID "your-organization-id"
:GRAPHLIT_ENVIRONMENT_ID "your-environment-id"
:GRAPHLIT_JWT_SECRET "your-jwt-secret")))))
:config (require 'mcp-hub)
:hook (after-init . mcp-hub-start-all-server))
#+end_src
* Usage
** Mcp hub
*** Configuring MCP Servers
#+begin_src elisp
(setq mcp-hub-servers
'(("filesystem" . (:command "npx" :args ("-y" "@modelcontextprotocol/server-filesystem" "/home/lizqwer/MyProject/")))
("fetch" . (:command "uvx" :args ("mcp-server-fetch")))
("qdrant" . (:url "http://localhost:8000/sse"))
("graphlit" . (
:command "npx"
:args ("-y" "graphlit-mcp-server")
:env (
:GRAPHLIT_ORGANIZATION_ID "your-organization-id"
:GRAPHLIT_ENVIRONMENT_ID "your-environment-id"
:GRAPHLIT_JWT_SECRET "your-jwt-secret")))))
#+end_src
You can use =mcp-hub-start-all-server= to start all MCP servers, such as launching all MCP servers after starting Emacs.
#+begin_src elisp
(add-hook 'after-init-hook
#'mcp-hub-start-all-server)
#+end_src
*** Managing MCP Servers
Use =mcp-hub= to launch the server management interface, which will automatically start all configured MCP servers.
#+html: <img src="https://github.com/user-attachments/assets/31877c0b-d71a-491d-9830-2afed8d6218a" alt="mcp-hub"/>
*** Keymap
| key | function | description |
|-----+----------------------------+-----------------------------------------|
| l | mcp-hub-view-log | View server logs |
| s | mcp-hub-start-server | Start server under cursor |
| k | mcp-hub-close-server | Stop server under cursor |
| r | mcp-hub-restart-server | Restart server under cursor |
| S | mcp-hub-start-all-server | Start all configured servers |
| R | mcp-hub-restart-all-server | Restart all configured servers |
| K | mcp-hub-close-all-server | Stop all running servers |
*** use with [[https://github.com/karthink/gptel][gptel]]
- For =gptel= integration, See the [[https://github.com/karthink/gptel?tab=readme-ov-file#model-context-protocol-mcp-integration][gptel mcp]] for details.
- [[https://github.com/lizqwerscott/gptel-mcp.el][gptel-mcp.el]] is interface integration for gptel.el and mcp.el
** Example [[https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem][filesystem]] server.
*** Establish the connection first.
#+begin_src elisp
(mcp-connect-server "filesystem" :command "npx" :args '("-y" "@modelcontextprotocol/server-filesystem" "~/Downloads/")
:initial-callback
#'(lambda (connection)
(message "%s connection" (jsonrpc-name connection)))
:tools-callback
#'(lambda (connection tools)
(message "%s tools: %s" (jsonrpc-name connection) tools))
:prompts-callback
#'(lambda (connection prompts)
(message "%s prompts: %s" (jsonrpc-name connection) prompts))
:resources-callback
#'(lambda (connection resources)
(message "%s resources: %s" (jsonrpc-name connection) resources)))
#+end_src
*** Define the use of tools.
The current text is being tested using the [[https://github.com/karthink/gptel/issues/514][gptel tool]] branch.Use =mcp-make-text-tool= to create standard tool call data ([[https://github.com/ahyatt/llm/discussions/124][Discussions]]).It is recommended to create tools within the tools-callback or wait for the mcp connect server to complete.
#+begin_src elisp
(mcp-make-text-tool "filesystem" "write_file")
#+end_src
This will generate a data structure where the function is an auto-generated synchronous or asynchronous lambda function for accessing the MCP server.
#+begin_src elisp
(list :function #'(lambda (&rest args)
;; Synchronous or asynchronous access to the MCP server's Lambda function.
)
:name "write_file"
:async nil
:description "Create a new file or completely overwrite an existing file with new content. Use with caution as it will overwrite existing files without warning. Handles text content with proper encoding. Only works within allowed directories."
:args ((:type "string" :name "path" :description "path")
(:type "string" :name "content" :description "content"))
:category "files")
#+end_src
*** Disconnect from the server.
#+begin_src elisp
(mcp-stop-server "filesystem")
#+end_src
*** Manual function call
**** Synchronize
#+begin_src elisp
(let ((connection (gethash "filesystem" mcp-server-connections)))
(mcp-call-tool connection "write_file" '(:path "filename or file path" :content "the file content")))
#+end_src
**** Asynchronous
#+begin_src elisp
(let ((connection (gethash "filesystem" mcp-server-connections)))
(mcp-async-call-tool connection
"write_file"
'(:path "filename or file path" :content "the file content")
#'(lambda (res)
;; handle res
(mcp--parse-tool-call-result res))
#'(lambda (code message)
;; handle error
(format "call %s tool error with %s: %s"
tool-name
code
message))))
#+end_src
*** Manual get prompt
Since the [[https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem][filesystem]] lacks prompts, the [[https://github.com/modelcontextprotocol/servers/tree/main/src/everything][everything]] server is used for demonstration.
**** Synchronize
#+begin_src elisp
(let ((connection (gethash "everything" mcp-server-connections)))
(mcp-get-prompt connection "complex_prompt" '(:temperature "1.0")))
#+end_src
**** Asynchronous
#+begin_src elisp
(let ((connection (gethash "everything" mcp-server-connections)))
(mcp-async-get-prompt connection
"complex_prompt"
'(:temperature "1.0")
#'(lambda (res)
(message "prompt: %s" res))
#'(lambda (code message)
(message "error call: %s, %s" code message))))
#+end_src
*** Manual get resources
Since the [[https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem][filesystem]] lacks resources, the [[https://github.com/modelcontextprotocol/servers/tree/main/src/everything][everything]] server is used for demonstration.
**** Synchronize
#+begin_src elisp
(let ((connection (gethash "everything" mcp-server-connections)))
(mcp-read-resource connection "test://static/resource/1"))
#+end_src
**** Asynchronous
#+begin_src elisp
(let ((connection (gethash "everything" mcp-server-connections)))
(mcp-async-read-resource connection "test://static/resource/1"
#'(lambda (resource)
(message "res: %s" resource))))
#+end_src
*** Get resource templates
Since the [[https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem][filesystem]] lacks resources, the [[https://github.com/modelcontextprotocol/servers/tree/main/src/everything][everything]] server is used for demonstration.
#+begin_src elisp
(let ((connection (gethash "everything" mcp-server-connections)))
(mcp-async-list-resource-templates connection
#'(lambda (connection templates)
(message "%s" templates))))
#+end_src
* Roadmap
- [X] HTTP SSE based MCP server connections
- [ ] mcp marketplace (browser and auto install mcp server)
- [ ] Simplified integration with other Emacs AI clients
- [ ] Expanded documentation
- [ ] Full MCP protocol client implementation
* License
This project is licensed under the GNU General Public License v3.0 - see the [[file:LICENSE][LICENSE]] file for details.
You Might Also Like
Ollama
Ollama enables easy access to large language models on various platforms.

n8n
n8n is a secure workflow automation platform for technical teams with 400+...
OpenWebUI
Open WebUI is an extensible web interface for customizable applications.

Dify
Dify is a platform for AI workflows, enabling file uploads and self-hosting.

Zed
Zed is a high-performance multiplayer code editor from the creators of Atom.
MarkItDown MCP
markitdown-mcp is a lightweight MCP server for converting various URIs to Markdown.