Making Your Own MCP Server in Midio

We’ve recently added a new package (mcp-server) to the Midio package registry, which lets you easily create your own MCP servers with little effort. What’s especially cool is that the entire package is built in pure Midio, which means you can peek under the hood and learn exactly how things work.

While there are still a few rough edges to smooth out, it’s already surprisingly easy to set up and customize your own MCP server. Let’s walk through how it works and how you can create your own MCP server.

In the end, we'll connect it to Cursor to see it in action.

Using the MCP Package

The MCP protocol supports several different transport variants, but Midio currently supports only the most widely adopted one: Server-Sent Events (SSE).

This approach requires defining two endpoints to establish a two-way communication channel with the client.

  1. The first establishes a long-lived SSE stream from the server to the client.

The first endpoint, which establishes a long lived SSE stream, and tells the client where to post requests.

  1. The second one is for all subsequent requests from the client.

Next up, we'll discuss the lifecycle of our MCP server.

The Initialization Phase

When a client connects to our MCP server, it will first connect to our GET endpoint to set up the long-lived stream. We do this on the server side by responding with the Start SSE Response, which establishes our response as a stream. We then use the Send POST Endpoint Response from the mcp-server package to tell the client where to send any subsequent POST requests. We embed a unique ID as a query parameter in the URL, which ensures each client session is isolated and supports concurrent usage.

The Message Loop

Once the connection is established and the client has the POST endpoint, we enter the message loop:

  • Clients send requests to the provided POST endpoint.

  • The server listens and responds via the SSE stream.

  • Additionally, the server regularly pings the client to see if it is still there.

Midio has a powerful primitive called Merge on Key that makes this kind of setup quite simple. This node allows a process to merge with another process by using a shared key—in this case, the clientId. It essentially routes the client’s POST request back to the correct SSE stream process.

Pinging the client

Lastly, instead of just ending the process when we time out, like in the example above, we want to try pinging the client to see if it is still there. We can do this like so:

If we time out waiting for a request from the client, and we haven't already tried to ping it, we send a ping message using the Send Ping Message function. This prompts the client to send us a response, which is handled like any other request. If we receive a response, we reset the didPing variable. If we don't receive a response, the next time the If function is called after a timeout, we will not ping again, log the event and terminate the process.

Example: A Todo List MCP Server

Let’s create a minimal MCP server for managing a todo list from Cursor. Cursor only supports using MCP tools, so we’ll implement everything as tools inside Midio.

Defining the Tools

The Handle MCP Request function expects a list of tools, which can be any Midio function. We'll create three functions that handle our basic requirements:

  • Get Todos

  • Add Todo

  • Complete Todo

Each function uses a shared Ephemeral Store to persist todos across requests. To ensure client data remains isolated, we use Midio’s partial function application feature to pre-apply the clientId to each function. This keeps todos for each client separated.

Once defined, we bundle the three functions together and pass them into the tools input of Handle MCP Request.

The Get Todo List Tools function returns our functions as a list.

We hook it up to our Handle MCP Request function like so:

At this point, your todo MCP server is ready to go.

Connecting with Cursor

Lets connect to our server from Cursor.

Copy the URL of the main endpoint, and add an entry to your Cursor MCP settings (File → Preferences → Cursor Settings → MCP → press the "Add new global MCP server" button).

Add the following to your config (using your own url).

{
    "mcpServers": {
        "midio-mcp": {
            "url": "https://<your-project>.midio.dev:<your-port>/mcp-todo",
            "env": {
            }
        }
    }
}

Cursor should automatically try connecting to your server. If not, make sure it is enabled and try clicking the refresh icon.


Final Thoughts

It’s still early days for this feature, and as you can see, it does require a little bit of setup, but we think it's pretty cool that everything can be implemented directly in Midio.

There are still some MCP features that we haven't added support for, like logging, completion, progress, change notifications and a few more, but we plan on expanding the feature set over time, and based on demand.

Last updated

Was this helpful?