diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,10 @@
 # Revision history for haskell-lsp-types
 
+## 0.14.0.0 -- 2019-06-13
+
+* Add support for custom request and notification methods
+  (@cocreature)
+
 ## 0.11.0.0 -- 2019-04-28
 
 * Fix `window/progress/cancel` notification being a from server
diff --git a/haskell-lsp-types.cabal b/haskell-lsp-types.cabal
--- a/haskell-lsp-types.cabal
+++ b/haskell-lsp-types.cabal
@@ -1,5 +1,5 @@
 name:                haskell-lsp-types
-version:             0.13.0.0
+version:             0.14.0.0
 synopsis:            Haskell library for the Microsoft Language Server Protocol, data types
 
 description:         An implementation of the types to allow language implementors to
@@ -46,7 +46,7 @@
   ghc-options:         -Wall
   -- ghc-options:         -Werror
   build-depends:       base >=4.9 && <4.13
-                     , aeson >=1.0.0.0
+                     , aeson >=1.2.2.0
                      , bytestring
                      , data-default
                      , deepseq
diff --git a/src/Language/Haskell/LSP/Types/DataTypesJSON.hs b/src/Language/Haskell/LSP/Types/DataTypesJSON.hs
--- a/src/Language/Haskell/LSP/Types/DataTypesJSON.hs
+++ b/src/Language/Haskell/LSP/Types/DataTypesJSON.hs
@@ -841,6 +841,14 @@
 
 type TelemetryNotification = NotificationMessage ServerMethod A.Value
 
+type CustomClientNotification = NotificationMessage ClientMethod A.Value
+type CustomServerNotification = NotificationMessage ServerMethod A.Value
+
+type CustomClientRequest = RequestMessage ClientMethod A.Value A.Value
+type CustomServerRequest = RequestMessage ServerMethod A.Value A.Value
+
+type CustomResponse = ResponseMessage A.Value
+
 -- ---------------------------------------------------------------------
 {-
 New in 3.0
diff --git a/src/Language/Haskell/LSP/Types/Message.hs b/src/Language/Haskell/LSP/Types/Message.hs
--- a/src/Language/Haskell/LSP/Types/Message.hs
+++ b/src/Language/Haskell/LSP/Types/Message.hs
@@ -8,9 +8,7 @@
 import           Data.Aeson.Types
 import           Data.Hashable
 -- For <= 8.2.2
-import           Data.Monoid                                ((<>))
 import           Data.Text                                  (Text)
-import qualified Data.Text                                  as T
 import           Language.Haskell.LSP.Types.Constants
 
 
@@ -115,9 +113,8 @@
  | TextDocumentOnTypeFormatting
  | TextDocumentRename
  | TextDocumentFoldingRange
- -- Messages of the form $/message
- -- Implementation Dependent, can be ignored
- | Misc Text
+ -- A custom message type. It is not enforced that this starts with $/.
+ | CustomClientMethod Text
    deriving (Eq,Ord,Read,Show)
 
 instance A.FromJSON ClientMethod where
@@ -163,9 +160,7 @@
   parseJSON (A.String "textDocument/rename")              = return TextDocumentRename
   parseJSON (A.String "textDocument/foldingRange")        = return TextDocumentFoldingRange
   parseJSON (A.String "window/progress/cancel")           = return WindowProgressCancel
-  parseJSON (A.String x)                                  = if T.isPrefixOf "$/" x
-                                                               then return $ Misc (T.drop 2 x)
-                                                            else mempty
+  parseJSON (A.String x)                                  = return (CustomClientMethod x)
   parseJSON _                                             = mempty
 
 instance A.ToJSON ClientMethod where
@@ -211,7 +206,7 @@
   toJSON TextDocumentDocumentLink        = A.String "textDocument/documentLink"
   toJSON DocumentLinkResolve             = A.String "documentLink/resolve"
   toJSON WindowProgressCancel            = A.String "window/progress/cancel"
-  toJSON (Misc xs)                       = A.String $ "$/" <> xs
+  toJSON (CustomClientMethod xs)         = A.String xs
 
 data ServerMethod =
   -- Window
@@ -233,6 +228,7 @@
   | TextDocumentPublishDiagnostics
   -- Cancelling
   | CancelRequestServer
+  | CustomServerMethod Text
    deriving (Eq,Ord,Read,Show)
 
 instance A.FromJSON ServerMethod where
@@ -255,6 +251,7 @@
   parseJSON (A.String "textDocument/publishDiagnostics") = return TextDocumentPublishDiagnostics
   -- Cancelling
   parseJSON (A.String "$/cancelRequest")                 = return CancelRequestServer
+  parseJSON (A.String m)                                 = return (CustomServerMethod m)
   parseJSON _                                            = mempty
 
 instance A.ToJSON ServerMethod where
@@ -277,6 +274,7 @@
   toJSON TextDocumentPublishDiagnostics = A.String "textDocument/publishDiagnostics"
   -- Cancelling
   toJSON CancelRequestServer = A.String "$/cancelRequest"
+  toJSON (CustomServerMethod m) = A.String m
 
 data RequestMessage m req resp =
   RequestMessage
diff --git a/src/Language/Haskell/LSP/Types/Uri.hs b/src/Language/Haskell/LSP/Types/Uri.hs
--- a/src/Language/Haskell/LSP/Types/Uri.hs
+++ b/src/Language/Haskell/LSP/Types/Uri.hs
@@ -66,11 +66,24 @@
   }
 
 platformAdjustToUriPath :: SystemOS -> FilePath -> String
-platformAdjustToUriPath systemOS srcPath =
-  if systemOS /= windowsOS || null srcPath then srcPath
-    else let
-      drive:rest = FPW.splitDirectories srcPath
-      leaveCharUnescaped = (/= ':')
-      removePathSeparator = filter (not . FPW.isPathSeparator)
-      escapedDrive = removePathSeparator $ escapeURIString leaveCharUnescaped drive
-      in '/' : FPP.joinPath (escapedDrive : rest)
+platformAdjustToUriPath systemOS srcPath
+  | systemOS == windowsOS = '/' : escapedPath
+  | otherwise = escapedPath
+  where
+    (splitDirectories, splitDrive)
+      | systemOS == windowsOS = (FPW.splitDirectories, FPW.splitDrive)
+      | otherwise = (FPP.splitDirectories, FPP.splitDrive)
+    escapedPath =
+        case splitDrive srcPath of
+            (drv, rest) ->
+                convertDrive drv `FPP.joinDrive`
+                FPP.joinPath (map (escapeURIString unescaped) $ splitDirectories rest)
+    -- splitDirectories does not remove the path separator after the drive so
+    -- we do a final replacement of \ to /
+    convertDrive drv
+      | systemOS == windowsOS && FPW.hasTrailingPathSeparator drv =
+        FPP.addTrailingPathSeparator (init drv)
+      | otherwise = drv
+    unescaped c
+      | systemOS == windowsOS = isUnreserved c || c `elem` [':', '\\', '/']
+      | otherwise = isUnreserved c || c == '/'
