DEV Community

Cover image for Creating an MCP Server for the Pulsar Editor
Dustin Runnells
Dustin Runnells

Posted on

Creating an MCP Server for the Pulsar Editor

Over the last few months there has been a lot of talk about MCP (Model Context Protocol) for adding tooling to LLMs (Large Language Models). Prior to MCP, I have written applications to interact with LLMs beyond chat simply by asking the LLM to respond in a specific format and parsing the results. This worked great! BUT, having a standard way to call tools without needing to write your own parsing code every time with MCP feels like the right way to go.

As I continue my projects, I have observed that there are lots of new applications integrating LLMs in every way imaginable. One of the most interesting LLM integrations to me is the concept of having an LLM assist in code writing - right in your editor! My editor of choice for my coding projects is Pulsar (formally Atom). Since the early days of ChatGPT until now, I've mostly just copy/pasted whatever I needed an AI to help me with into my editor. But the "vibe coding" trend and the time lost to copy/paste has made me a little jealous of folks that use editors that have a direct integration with AI/LLM coding assistants. This coupled with a recent experience modifying a Pulsar package that I use frequently and experimenting with using MCP as a client in AnythingLLM has given me the confidence to start a new Pulsar package to run an MCP server inside Pulsar to give an LLM control over common editing functions. Ultimately, I'd like to chat with the LLM about the code I'm working on and let it make adjustments/additions.

This week I took the first step with my own Pulsar package for this.

At the time of this writing, this is little more than a proof of concept as a combination of the starter Pulsar package-generator package, the Atom package creation tutorial and the example from the official MCP Typescript SDK with some editor tool functions registered. Hopefully it will become more soon, since I am looking forward to actually using it to build stuff!

I did run into some hurdles along the way, which I'll mention below. Here are the steps that I've taken so far to get here:

  1. Created a new Pulsar package with https://web.pulsar-edit.dev/packages/package-generator

  2. Removed the unneeded default UI elements from the view

  3. Added a status tile to indicate when the MCP server is listening

  4. Pasted in the Streamable HTTP MCP server code from the official MCP typescript quickstart page: https://github.com/modelcontextprotocol/typescript-sdk

  5. Added the dependencies for the MCP SDK and strict typing validation to my package.json:

      "dependencies": {
        "@modelcontextprotocol/sdk": "^1.13.0",
        "zod": "^3.25.67"
      },
    
  6. Hit some roadblocks! Pulsar seems to be bundled with an older version of Node JS, that does not like the "node:" protocol in import and require! This seems to be everywhere in the MCP Typescript SDK. I grepped for the "node:" instances and made my edits to the dependencies and their dependencies to remove the text "node:" from the lines and require/import the old way.

  7. More roadblocks! The older Node JS also doesn't like Object.hasOwn() in one of the dependencies (marge-descriptors). Replaced that with Object.prototype.hasOwnProperty.call().

  8. Still more roadblocks! Something seems incompatible with the old Node JS and crypto.randomUUID(). I'm not interested figuring out why, so I found a simple javascript UUID function on Stack Overflow and call that one instead.

  9. Woohoo! My Pulsar package now runs without errors! To make the ppm (Pulsar Package Manager) capable of doing these edits for me instead of asking users to manually find and do the edits in the dependencies, I ran patch-package on each of the dependencies that I modified:

    npx patch-package @modelcontextprotocol/sdk
    npx patch-package express
    npx patch-package router
    npx patch-package body-parser
    npx patch-package merge-descriptors
    

    And updated my Pulsar package's package.json to do the patching:

      "devDependencies": {
        "patch-package": "^8.0.0"
      },
      "scripts": {
        "postinstall": "patch-package"
      }
    
  10. With server being my instance of McpServer() I can now register some tools from the Pulsar API to it. Here is an example for moving the cursor around:

        server.registerTool("move-cursor", {
            title: "Move Cursor",
            description: "Move cursor to location in editor.",
            inputSchema: { row: z.number(), column: z.number() }
          },
          async ({ row, column }) => {
            const editor = atom.workspace.getActiveTextEditor();
            editor.setCursorBufferPosition([row-1, column-1]);
            return {
              content: [{ type: "text", text: String("Moved cursor to row " + row + ", column " + column) }]
            };
        });
    
  11. Now I'll launch another instance of Pulsar and start the MCP Listener with the menu item that I created (see source). I also observed that the "MCP:On" status tile I added is shown in a status tile in the lower left of Pulsar.

  12. To see if the MCP server is actually working inside my Pulsar package, we can use the official MCP Inspector from the command line:

    npx @modelcontextprotocol/inspector
    

    The inspector connects to an MCP server and runs a little http server that you can point a browser to to allow you to send MCP commands and see the responses. This lets you confirm things are working as you expect before pointing your LLM to your MCP Server. Executing the command above gae me a URL to visit in my browser:

    http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=<Random_Token>

  13. Next I executed some of the new tools in the MCP inspector with some parameters.

    Image description

    All went smoothly and I can see my Pulsar editor react to the MCP tool!

  14. Ok, now to finally point AnythingLLM (my current favorite desktop LLM client) to the MCP server and tell the LLM to do something in the Pulsar editor! AnythingLLM keeps it's mcpServers config in this file on Mac:

    ~/Library/Application\ Support/anythingllm-desktop/storage/plugins/anythingllm_mcp_servers.json

    The configuration for this MCP server should look like:

    {
            "mcpServers": {
                    "pulsar-edit-mcp-server": {
                            "url": "http://localhost:3000/mcp",
                            "disabled": false,
                            "alwaysAllow": [],
                            "type": "streamable"
                    }
            }
    }
    
  15. Now I'll try it out and ask the LLM to add some text to the editor:

    Image description

  16. It's working!

  17. Next I'll add some more editor functions and recruit some contributors (perhaps YOU!?).

  18. Thanks for reading!

Top comments (0)