This is an Emacs client for interfacing with MCP, supporting connections to MCP servers.
- Install Emacs 30 or higher version
- Add the following code to your configuration file ~/.emacs:
(add-to-list 'load-path "<path-to-mcp.el>") (require 'mcp)
Example filesystem server.
(mcp-connect-server "filesystem" "npx" '("-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)))
The current text is being tested using the gptel tool branch.Use mcp-make-text-tool
to create standard tool call data (Discussions).It is recommended to create tools within the tools-callback or wait for the mcp connect server to complete.
(mcp-make-text-gptel-tool "filesystem" "write_file")
This will generate a data structure where the function is an auto-generated synchronous or asynchronous lambda function for accessing the MCP server.
(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")
(mcp-stop-server "filesystem")
(let ((connection (gethash "filesystem" mcp-server-connections)))
(mcp-call-tool "write_file" '(:path "filename or file path" :content "the file content")))
(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))))
Since the filesystem lacks prompts, the everything server is used for demonstration.
(let ((connection (gethash "everything" mcp-server-connections)))
(mcp-get-prompt connection "complex_prompt" '(:temperature "1.0")))
(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))))
Since the filesystem lacks resources, the everything server is used for demonstration.
(let ((connection (gethash "everything" mcp-server-connections)))
(mcp-read-resource connection "test://static/resource/1"))
(let ((connection (gethash "everything" mcp-server-connections)))
(mcp-async-read-resource connection "test://static/resource/1"
#'(lambda (resource)
(message "res: %s" resource))))
Since the filesystem lacks resources, the everything server is used for demonstration.
(let ((connection (gethash "everything" mcp-server-connections)))
(mcp-async-list-resource-templates connection
#'(lambda (connection templates)
(message "%s" templates))))