diff --git a/servant-matrix-param.cabal b/servant-matrix-param.cabal
--- a/servant-matrix-param.cabal
+++ b/servant-matrix-param.cabal
@@ -1,5 +1,5 @@
 name:           servant-matrix-param
-version:        0.3
+version:        0.3.1
 synopsis:       Matrix parameter combinator for servant
 description:    Matrix parameter combinator for servant
 category:       Web
@@ -24,6 +24,11 @@
   manual: True
   default: False
 
+flag with-servant-client
+  description: support for servant-server
+  manual: True
+  default: False
+
 library
   default-language: Haskell2010
   ghc-options: -Wall
@@ -34,11 +39,13 @@
     , servant >= 0.7 && < 0.10
   exposed-modules:
       Servant.MatrixParam
+
   if flag(with-servant-aeson-specs)
     build-depends:
         servant-aeson-specs > 0.2 && < 0.6
     exposed-modules:
         Servant.MatrixParam.AesonSpecs
+
   if flag(with-servant-server)
     build-depends:
       servant-server >= 0.7 && < 0.10,
@@ -51,6 +58,14 @@
       Servant.MatrixParam.Server.Internal
       Servant.MatrixParam.Server.Internal.ArgList
 
+  if flag(with-servant-client)
+    build-depends:
+      servant-client,
+      text
+    exposed-modules:
+      Servant.MatrixParam.Client
+      Servant.MatrixParam.Client.Internal
+
 test-suite spec
   default-language: Haskell2010
   ghc-options: -Wall
@@ -65,17 +80,21 @@
     , servant-aeson-specs
     , servant-matrix-param
     , servant-server
+    , servant-client
     , wai
+    , warp
     , containers
     , text
     , wai-extra
     , http-types
+    , http-client
     , bytestring
     , transformers
     , aeson
   other-modules:
       Servant.MatrixParam.AesonSpecsSpec
       Servant.MatrixParam.ServerSpec
+      Servant.MatrixParam.ClientSpec
       Servant.MatrixParamSpec
 
 test-suite doctest
diff --git a/src/Servant/MatrixParam.hs b/src/Servant/MatrixParam.hs
--- a/src/Servant/MatrixParam.hs
+++ b/src/Servant/MatrixParam.hs
@@ -6,6 +6,7 @@
 module Servant.MatrixParam (
   WithMatrixParams,
   MatrixParam,
+  MatrixFlag,
 ) where
 
 import           Data.Typeable (Typeable)
@@ -24,4 +25,20 @@
 -- >>>
 -- >>> type MyApi = "books" :> MatrixParam "author" String :> Get '[JSON] [String]
 data MatrixParam (key :: Symbol) a
+    deriving (Typeable)
+
+-- | Lookup a potentially value-less matrix string parameter
+-- with boolean semantics. If the param @sym@ is there without any value,
+-- or if it's there with value "true" or "1", it's interpreted as 'True'.
+-- Otherwise, it's interpreted as 'False'.
+--
+--
+-- @/book;published@
+--
+-- would be represented as:
+--
+-- >>> import Servant
+-- >>>
+-- >>> type MyApi = "book" :> MatrixFlag "published" :> Get '[JSON] [String]
+data MatrixFlag (key :: Symbol)
     deriving (Typeable)
diff --git a/src/Servant/MatrixParam/Client.hs b/src/Servant/MatrixParam/Client.hs
new file mode 100644
--- /dev/null
+++ b/src/Servant/MatrixParam/Client.hs
@@ -0,0 +1,3 @@
+module Servant.MatrixParam.Client () where
+
+import Servant.MatrixParam.Client.Internal ()
diff --git a/src/Servant/MatrixParam/Client/Internal.hs b/src/Servant/MatrixParam/Client/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Servant/MatrixParam/Client/Internal.hs
@@ -0,0 +1,67 @@
+{-# LANGUAGE DataKinds            #-}
+{-# LANGUAGE FlexibleInstances    #-}
+{-# LANGUAGE ScopedTypeVariables  #-}
+{-# LANGUAGE TypeFamilies         #-}
+{-# LANGUAGE TypeOperators        #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Servant.MatrixParam.Client.Internal where
+
+import           Data.Proxy
+import qualified Data.Text           as T
+import           GHC.TypeLits
+import           Servant.API
+import           Servant.Client
+import           Servant.Common.Req
+import           Servant.MatrixParam
+
+instance
+  ( HasClient (WMP path mat :> api)
+  , KnownSymbol path
+  )
+  => HasClient (WithMatrixParams path mat :> api) where
+
+  type Client (WithMatrixParams path mat :> api)
+    = Client (WMP path mat :> api)
+
+  clientWithRoute Proxy req =
+    clientWithRoute (Proxy :: Proxy (WMP path mat :> api))
+                    req { reqPath = reqPath req ++ "/" ++ path }
+    where
+     path = symbolVal (Proxy :: Proxy path)
+
+-- This is just a dummy used to keep track of whether we have already processed
+-- the leading path. If we are in a WMP instance, we have already dealt with
+-- the leading path, and can just proceed recursively over the matrix params.
+-- If not, we deal with the leading path, and call the WMP instance. WMP itself
+-- should not be exported.
+data WMP (p :: Symbol) (x :: [*])
+
+instance
+  ( HasClient (WMP path rest :> api)
+  , ToHttpApiData v
+  , KnownSymbol k
+  ) => HasClient (WMP path (MatrixParam k v ': rest) :> api) where
+
+  type Client (WMP path (MatrixParam k v ': rest) :> api)
+    = Maybe v -> Client (WMP path rest :> api)
+
+  clientWithRoute Proxy req x = case x of
+    Nothing -> clientWithRoute nextProxy req
+    Just v  -> clientWithRoute nextProxy
+      req { reqPath = reqPath req ++ ";" ++ key ++ "=" ++ T.unpack (toQueryParam v) }
+    where
+      nextProxy :: Proxy (WMP path rest :> api)
+      nextProxy = Proxy
+
+      key :: String
+      key = symbolVal (Proxy :: Proxy k)
+
+instance
+  ( HasClient api
+  ) => HasClient (WMP path '[] :> api) where
+
+  type Client (WMP path '[] :> api) = Client api
+
+  clientWithRoute Proxy req =
+    clientWithRoute (Proxy :: Proxy api) req
diff --git a/src/Servant/MatrixParam/Server/Internal.hs b/src/Servant/MatrixParam/Server/Internal.hs
--- a/src/Servant/MatrixParam/Server/Internal.hs
+++ b/src/Servant/MatrixParam/Server/Internal.hs
@@ -7,7 +7,6 @@
   parsePathSegment,
 ) where
 
-import           Data.List (foldl')
 import           Data.Map.Strict
 import           Data.Maybe
 import           Data.Text
@@ -16,11 +15,11 @@
 data MatrixSegment
   = MatrixSegment {
     segmentPath :: Text,
-    segmentParams :: Maybe (Map Text Text)
+    segmentParams :: Maybe (Map Text (Maybe Text))
   }
   deriving (Show, Eq)
 
-getSegmentParams :: MatrixSegment -> Map Text Text
+getSegmentParams :: MatrixSegment -> Map Text (Maybe Text)
 getSegmentParams = fromMaybe mempty . segmentParams
 
 parsePathSegment :: Text -> Maybe MatrixSegment
@@ -30,16 +29,10 @@
   [path, ""] -> return $ MatrixSegment path mempty
   (path : pairs) ->
     Just $ MatrixSegment path $
-      fmap collectPairs $ mapM parsePair pairs
+      fmap fromList $ mapM parsePair pairs
 
 parsePair :: Text -> Maybe (Text, Maybe Text)
 parsePair pair = case splitOn "=" pair of
   [key, value] -> Just (key, Just value)
   [flag] -> Just (flag, Nothing)
   _ -> Nothing
-
-collectPairs :: forall a b . Ord a => [(a, Maybe b)] -> Map a b
-collectPairs =
-  Data.List.foldl'
-    (\ acc (k, mv) -> maybe acc (\ v -> insert k v acc) mv)
-    mempty
diff --git a/src/Servant/MatrixParam/Server/Internal/ArgList.hs b/src/Servant/MatrixParam/Server/Internal/ArgList.hs
--- a/src/Servant/MatrixParam/Server/Internal/ArgList.hs
+++ b/src/Servant/MatrixParam/Server/Internal/ArgList.hs
@@ -2,27 +2,32 @@
 {-# LANGUAGE FlexibleInstances     #-}
 {-# LANGUAGE GADTs                 #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings     #-}
 {-# LANGUAGE ScopedTypeVariables   #-}
 {-# LANGUAGE TypeFamilies          #-}
 {-# LANGUAGE TypeOperators         #-}
 {-# LANGUAGE UndecidableInstances  #-}
 module Servant.MatrixParam.Server.Internal.ArgList where
 
+import           Control.Monad       (join)
+import           Data.Char
 import qualified Data.Map            as Map
 import           Data.Proxy
 import qualified Data.Text           as T
 import           GHC.TypeLits        (KnownSymbol, symbolVal)
 import           Servant.MatrixParam
-import           Web.HttpApiData     (parseQueryParamMaybe, FromHttpApiData)
+import           Web.HttpApiData     (FromHttpApiData, parseQueryParamMaybe)
 
 -- An HList that stores the arguments to a function
 data ArgList a where
   NoArgs :: ArgList '[]
   (:.:)  :: Maybe a -> ArgList as -> ArgList (MatrixParam key a ': as)
+  (:?:)  :: Bool -> ArgList as -> ArgList (MatrixFlag key ': as)
 
 type family Unapped (params :: [*]) end where
   Unapped '[] r = r
   Unapped (MatrixParam key a ': rest) r = Maybe a -> Unapped rest r
+  Unapped (MatrixFlag key ': rest) r = Bool -> Unapped rest r
 
 class (Apped (Unapped argList fn) argList ~ fn) => App fn (argList :: [*]) where
   type Apped fn argList
@@ -31,7 +36,7 @@
 
 class ParseArgs argList where
   -- Gets the arguments from a map
-  parseArgs :: Map.Map T.Text T.Text -> ArgList argList
+  parseArgs :: Map.Map T.Text (Maybe T.Text) -> ArgList argList
 
 instance (App r rest
         , Apped (Unapped rest (Maybe a -> r)) rest ~ (Maybe a -> r)
@@ -39,11 +44,27 @@
   type Apped (Maybe a -> r) (MatrixParam key a ': rest) = Apped r rest
   apply fn (a :.: rest) = apply (fn a) rest
 
+instance (App r rest
+        , Apped (Unapped rest (Bool -> r)) rest ~ (Bool -> r)
+        ) => App (Bool -> r) (MatrixFlag key ': rest) where
+  type Apped (Bool -> r) (MatrixFlag key ': rest) = Apped r rest
+  apply fn (a :?: rest) = apply (fn a) rest
+
 instance (FromHttpApiData a, KnownSymbol key, ParseArgs rest) => ParseArgs (MatrixParam key a ': rest) where
   parseArgs m = val :.: (parseArgs m :: ArgList rest)
     where
       key = T.pack $ symbolVal (Proxy :: Proxy key)
-      val = Map.lookup key m >>= parseQueryParamMaybe
+      val = join $ Map.lookup key m >>= fmap parseQueryParamMaybe
+
+instance (KnownSymbol key, ParseArgs rest) => ParseArgs (MatrixFlag key ': rest) where
+  parseArgs m = val :?: (parseArgs m :: ArgList rest)
+    where
+      key = T.pack $ symbolVal (Proxy :: Proxy key)
+      val = case Map.lookup key m of
+        Nothing -> False
+        Just Nothing -> True
+                          -- Mimicking prior behaviour
+        Just (Just x) -> T.map toLower x == "true" || x == "1"
 
 instance App r '[] where
   type Apped r '[] = r
diff --git a/test/Servant/MatrixParam/ClientSpec.hs b/test/Servant/MatrixParam/ClientSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Servant/MatrixParam/ClientSpec.hs
@@ -0,0 +1,129 @@
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeOperators       #-}
+module Servant.MatrixParam.ClientSpec (spec) where
+
+import Control.Exception
+import Control.Monad
+import Data.ByteString     (ByteString)
+import Data.IORef
+import Data.Proxy
+import Network.HTTP.Client (Manager, Request, defaultManagerSettings,
+                            managerModifyRequest, managerResponseTimeout,
+                            newManager, path)
+import Servant
+import Servant.Client
+import System.IO.Unsafe
+import Test.Hspec
+
+#if MIN_VERSION_http_client(0,5,0)
+import Network.HTTP.Client (responseTimeoutMicro)
+#endif
+#if MIN_VERSION_servant_client(0,9,0)
+import Network.Wai.Handler.Warp (testWithApplication)
+import Data.Maybe          (fromMaybe)
+#else
+import Control.Monad.Trans.Except (runExceptT)
+#endif
+
+
+import Servant.MatrixParam
+import Servant.MatrixParam.Client ()
+import Servant.MatrixParam.Server ()
+
+spec :: Spec
+spec = do
+
+  describe "Servant.API.MatrixParam" $ do
+
+    it "generates correct paths when arguments are not Nothing" $ do
+      cliA (Just "alice") `hasRequestPath` "/a;name=alice"
+      cliB (Just 3) (Just 2) `hasRequestPath` "/b;foo=3;bar=2"
+
+    it "generates correct paths when arguments are Nothing" $ do
+      cliA Nothing `hasRequestPath` "/a"
+      cliB Nothing Nothing `hasRequestPath` "/b"
+
+#if MIN_VERSION_servant_client(0,9,0)
+    it "generates paths that servant-server understands" $ do
+      testWithApplication (return $ serve api server) $ \port -> do
+        let res = (,) <$> cliA (Just "There is a there there")
+                      <*> cliB (Just 1) (Just 2)
+            url = BaseUrl Http "localhost" port ""
+        mgr' <- newManager defaultManagerSettings
+        runClientM res (ClientEnv mgr' url)
+          `shouldReturn` Right ("There is a there there", "3")
+#endif
+------------------------------------------------------------------------------
+-- API
+------------------------------------------------------------------------------
+
+type Api =
+       WithMatrixParams "a" '[MatrixParam "name" String] :> Get '[JSON] String
+  :<|> WithMatrixParams "b" '[MatrixParam "foo" Int, MatrixParam "bar" Int]
+         :> Get '[JSON] String
+
+api :: Proxy Api
+api = Proxy
+
+
+#if MIN_VERSION_servant_client(0,9,0)
+server :: Server Api
+server = e1 :<|> e2
+  where
+    e1 name = return $ fromMaybe "" name
+    e2 foo bar = return . show $ fromMaybe 0 foo + fromMaybe 0 bar
+#endif
+
+------------------------------------------------------------------------------
+-- Utils
+------------------------------------------------------------------------------
+
+#if MIN_VERSION_servant_client(0,9,0)
+hasRequestPath :: ClientM any -> ByteString -> IO ()
+#else
+hasRequestPath :: (Manager -> BaseUrl -> ClientM any) -> ByteString -> IO ()
+#endif
+hasRequestPath c expectedPath = do
+  let anyBurl = BaseUrl Http "localhost" 6660 ""
+#if MIN_VERSION_servant_client(0,9,0)
+  _ <- void (runClientM c $ ClientEnv mgr anyBurl)
+    `catch` \(_ :: SomeException) -> return ()
+#else
+  _ <- void (runExceptT $ c mgr anyBurl)
+    `catch` \(_ :: SomeException) -> return ()
+#endif
+  Just r <- readIORef lastRequest
+  path r `shouldBe` expectedPath
+
+
+lastRequest :: IORef (Maybe Network.HTTP.Client.Request)
+lastRequest = unsafePerformIO $ newIORef Nothing
+{-# NOINLINE lastRequest #-}
+
+
+mgr :: Manager
+mgr = unsafePerformIO . newManager $ defaultManagerSettings
+  { managerModifyRequest = \req -> writeIORef lastRequest (Just req) >> return req
+#if MIN_VERSION_http_client(0,5,0)
+  , managerResponseTimeout = responseTimeoutMicro 1
+#else
+  , managerResponseTimeout = Just 1
+#endif
+  }
+{-# NOINLINE mgr #-}
+
+
+
+
+#if MIN_VERSION_servant_client(0,9,0)
+cliA :: Maybe String -> ClientM String
+cliB :: Maybe Int -> Maybe Int -> ClientM String
+#else
+cliA :: Maybe String -> Manager -> BaseUrl -> ClientM String
+cliB :: Maybe Int -> Maybe Int -> Manager -> BaseUrl -> ClientM String
+#endif
+cliA :<|> cliB = client api
diff --git a/test/Servant/MatrixParam/ServerSpec.hs b/test/Servant/MatrixParam/ServerSpec.hs
--- a/test/Servant/MatrixParam/ServerSpec.hs
+++ b/test/Servant/MatrixParam/ServerSpec.hs
@@ -24,12 +24,14 @@
        WithMatrixParams "a" '[MatrixParam "name" String] :> Get '[PlainText] String
   :<|> WithMatrixParams "b" '[MatrixParam "foo" Int, MatrixParam "bar" Int]
          :> Get '[PlainText] String
+  :<|> WithMatrixParams "c" '[MatrixParam "foo" Int, MatrixFlag "baz", MatrixParam "bar" Int]
+         :> Get '[PlainText] String
 
 api :: Proxy Api
 api = Proxy
 
 server :: Server Api
-server = a :<|> b
+server = a :<|> b :<|> c
   where
     a :: Maybe String -> Handler String
     a p = return $ show p
@@ -37,6 +39,10 @@
     b :: Maybe Int -> Maybe Int -> Handler String
     b foo bar = return $ show (foo, bar)
 
+    c :: Maybe Int -> Bool -> Maybe Int -> Handler String
+    c foo baz bar | baz = return $ show (foo, bar)
+                  | otherwise = return ""
+
 testWithPath :: [Text] -> ByteString -> IO ()
 testWithPath segments expected = do
   (flip runSession) (serve api server) $ do
@@ -53,6 +59,19 @@
     it "allows to retrieve simple matrix parameters" $ do
       testWithPath ["a;name=bob"] "Just \"bob\""
 
+    it "retrieves matrix flags" $ do
+      testWithPath ["c;baz"] "(Nothing,Nothing)"
+      testWithPath ["c;foo=1;baz"] "(Just 1,Nothing)"
+      testWithPath ["c;bar=1;baz"] "(Nothing,Just 1)"
+      testWithPath ["c;bar=1;baz;foo=2"] "(Just 2,Just 1)"
+      testWithPath ["c;foo=1"] ""
+
+    it "treats 'true' as a flag that's present" $ do
+      testWithPath ["c;baz=true"] "(Nothing,Nothing)"
+
+    it "treats '1' as a flag that's present" $ do
+      testWithPath ["c;baz=1"] "(Nothing,Nothing)"
+
     it "allows to omit matrix parameters" $ do
       testWithPath ["a"] "Nothing"
 
@@ -62,10 +81,11 @@
     it "allows to overwrite matrix params" $ do
       testWithPath ["a;name=alice;name=bob"] "Just \"bob\""
 
+
   describe "parsePathSegment" $ do
     it "parses a path segment with a matrix param" $ do
       parsePathSegment "foo;bar=baz" `shouldBe`
-        Just (MatrixSegment "foo" (Just (fromList [("bar", "baz")])))
+        Just (MatrixSegment "foo" (Just (fromList [("bar", Just "baz")])))
 
     it "parses a bare segment" $ do
       parsePathSegment "foo" `shouldBe`
@@ -73,11 +93,12 @@
 
     it "parses a segment with multiple matrix params" $ do
       parsePathSegment "foo;bar=baz;huhu=baba" `shouldBe`
-        Just (MatrixSegment "foo" (Just (fromList [("bar", "baz"), ("huhu", "baba")])))
+        Just (MatrixSegment "foo" (Just (fromList [("bar", Just "baz"),
+                                                   ("huhu", Just "baba")])))
 
     it "parses a segment with multiple values for the same matrix param" $ do
       parsePathSegment "foo;bar=baz;bar=huhu" `shouldBe`
-        Just (MatrixSegment "foo" (Just (fromList [("bar", "huhu")])))
+        Just (MatrixSegment "foo" (Just (fromList [("bar", Just "huhu")])))
 
     it "parses a segment with semicolon but without params" $ do
       parsePathSegment "foo;" `shouldBe`
@@ -89,4 +110,4 @@
 
     it "can parse the empty string as value" $ do
       parsePathSegment "foo;bar=" `shouldBe`
-        Just (MatrixSegment "foo" (Just (fromList [("bar", "")])))
+        Just (MatrixSegment "foo" (Just (fromList [("bar", Just "")])))
