Enable MCP

Creating an MCP interface for your application

If you run a service with api App, you probably already have a lens HTTP =&> Maybe App parsing http requests into your local API. Similarly, if your service has a command-line interface, it also has a command line parser CLI =&> Maybe App. MCP works in a similar way, where the common interface to translate from is JSONRPC. Therefore, to make your service MCP-ready, you need to provide the following:

  • A lens JSONRPC =&> Maybe App that will parse JSONRPC requests
  • The list of services that App includes as an MCPSpec

Let’s take a concrete example. App is an API composed of three simple endpoints add_todo, mark_done, get_todos with those signatures:

  • add_todo : String :- ID
  • mark_done : ID :- ()
  • get_todos : () :- List Todo

The overall API for this application is add_todo + mark_done + get_todos.

Because each individual endpoint can be serialised/deserialised to/from JSON, we already have a lens JSON =&> Maybe App. But to correctly implement the discovery process of MCP we also need to convert each add_todo into an MCPSpec in that case a plausible MCPSpec for each would be:

add_todo_spec : MCPSpec
add_todo_spec = MkMCPSpec
  { name = "add_todo"
  , title = Nothing
  , description = "add a new todo item to the database"
  , inputSchema = JSAtom JSString
  , annotations = JObject []
  , execution = Just Forbidden
  , outputSchema = Just (JSAtom JSString)

mark_done_spec : MCPSpec
  { name = "mark_done"
  , title = Nothing
  , description = "mark an existing todo item as done"
  , inputSchema = JSAtom JSString
  , annotations = JObject []
  , execution = Just Forbidden
  , outputSchema = Nothing

get_todos_spec : MCPSpec
  { name = "get_todos"
  , title = Nothing
  , description = "obtain the list of todo items"
  , inputSchema = JSAtom JSNull
  , annotations = JObject []
  , execution = Just Forbidden
  , outputSchema = Just
      (JSArray
        (JSObject
          [ P "description" True (JSAtom JSString)
          , P "done" True (JSAtom JSBoolean)
          ]
        )
      )

allSpecs : List MCPSpec
allSpecs = [add_todo_spec, mark_done_spec, get_todos_spec]

using allSpecs you can instanciate a new server with an MCP interface that will run the MCP discovery process for you and convert all messages to the JSONRPC matching your definition.

Behind the scenes that process will add the two “init” and “close” messages to the API you are serving so that a client can reach it.