packages feed

tricorder-mcp 0.2.0.0 → 1.0.0.1

raw patch · 4 files changed

+140/−114 lines, 4 filesdep ~atelier-coredep ~tricorder-typesPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: atelier-core, tricorder-types

API changes (from Hackage documentation)

- Tricorder.MCP.Tools: [force] :: RestartOptions -> Maybe Bool
+ Tricorder.MCP.Tools: [ignorePendingQueries] :: RestartOptions -> Maybe Bool

Files

CHANGELOG.md view
@@ -7,6 +7,21 @@  ## [Unreleased] +## [1.0.0.1] - 2026-10-30++### Fixed++- `start_daemon`, `stop_daemon` and `restart_daemon` now invoke `tricorder daemon {start,stop,restart}` instead of the removed top-level `start`, `stop` and `restart` subcommands. Non-breaking. (Thanks @michael-xavier-well)++## [1.0.0.0] - 2026-10-29++### Changed++- Uses the new flags for Tricorder's `status`, `daemon stop` and+  `daemon restart` commands.+- Support new `IfBuildIsPending` option.+- Rename `start` and `restart` tools' `force` option to `ignorePendingQueries`.+ ## [0.2.0.0] - 2026-10-23  ### Changed
src/Tricorder/MCP/Tools.hs view
@@ -24,10 +24,10 @@ import System.Exit (ExitCode (..)) import System.Posix (getWorkingDirectory) import System.Process.Typed (proc, readProcess, setWorkingDir)-import Tricorder.API.Force (Force)+import Tricorder.API.IfBuildIsPending (IfBuildIsPending)+import Tricorder.API.IfThereArePendingQueries (IfThereArePendingQueries) import Tricorder.API.OutputFormat (OutputFormat (..)) import Tricorder.API.TestFilter (TestFilter)-import Tricorder.API.WaitMode (WaitMode) import Tricorder.SourceLookup.SourceQuery (parseSourceQuery) import Prelude hiding (force) @@ -39,13 +39,13 @@ import Tricorder.API.FieldMask qualified as FieldMask import Tricorder.API.FieldMask.Args qualified as FieldMask.Args import Tricorder.API.FieldMask.Schema qualified as FieldMask.Schema-import Tricorder.API.Force qualified as Force+import Tricorder.API.IfBuildIsPending qualified as IfBuildIsPending import Tricorder.API.IfDaemonIsStopped qualified as IfDaemonIsStopped+import Tricorder.API.IfThereArePendingQueries qualified as IfThereArePendingQueries import Tricorder.API.OutputFormat qualified as OutputFormat import Tricorder.API.Test qualified as Test import Tricorder.API.Test.SuiteView.Schema qualified as Test.SuiteView.Schema import Tricorder.API.TestFilter qualified as TestFilter-import Tricorder.API.WaitMode qualified as WaitMode   data Tool@@ -64,13 +64,13 @@   data StopOptions = StopOptions-    { force :: Maybe Bool+    { ignorePendingQueries :: Maybe Bool     , projectRoot :: Maybe Text     }   data RestartOptions = RestartOptions-    { force :: Maybe Bool+    { ignorePendingQueries :: Maybe Bool     , projectRoot :: Maybe Text     } @@ -130,7 +130,7 @@             { optDescription = Just "Stop the tricorder daemon."             , optTitle = Just "Stop daemon"             , optFieldDescriptions =-                [ forceDesc+                [ ignorePendingQueriesDesc                 , projectRootDesc                 ]             }@@ -141,7 +141,7 @@             { optDescription = Just "Restart the tricorder daemon."             , optTitle = Just "Restart daemon"             , optFieldDescriptions =-                [ forceDesc+                [ ignorePendingQueriesDesc                 , projectRootDesc                 ]             }@@ -245,7 +245,7 @@         ( "wait"         , "Block and wait until the current build cycle finishes to provide the most up-to-date result."         )-    forceDesc = ("force", "Ignore pending queries instead of waiting for them to finish.")+    ignorePendingQueriesDesc = ("ignorePendingQueries", "Do not wait for pending queries to finish.")   -- | The @tricorder@ invocation for a tool call: the project directory to run@@ -253,100 +253,97 @@ -- and renders it via 'CLI.commandToArgs' so the flags stay in sync with -- "Tricorder.CLI.Arguments" instead of being duplicated here. toolCommand :: Tool -> (Maybe Text, Either Text [String])-toolCommand = \case-    StartDaemon (StartOptions {projectRoot}) ->-        ( projectRoot-        , Right $ Daemon.Command.toArgs Daemon.Command.Start-        )-    StopDaemon (StopOptions {force, projectRoot}) ->-        ( projectRoot-        , Right-            $ Daemon.Command.toArgs-            $ Daemon.Command.Stop-            $ toForce force-        )-    RestartDaemon (RestartOptions {force, projectRoot}) ->-        ( projectRoot-        , Right-            $ Daemon.Command.toArgs-            $ Daemon.Command.Restart-            $ toForce force-        )-    Status (StatusOptions {wait, verbose, expand, projectRoot}) ->-        ( projectRoot-        , Right-            $ Command.toArgs-            $ Command.Status-                Command.StatusOptions-                    { wait = toWaitMode wait-                    , format = JsonOutput-                    , verbosity = toVerbosity verbose-                    , expand-                    , ifDaemonIsStopped = IfDaemonIsStopped.StartDaemon-                    }-        )-    TestSuites opts ->-        ( opts.projectRoot-        , do-            fields <- traverse FieldMask.Args.parse opts.fields-            Right-                $ Command.toArgs-                $ Command.Test-                $ Test.Suites-                $ Test.SuitesOptions-                    { testFilter = fromMaybe TestFilter.All opts.testFilter-                    , wait = toWaitMode opts.wait-                    , suiteNames = fromMaybe [] opts.suiteNames-                    , format = OutputFormat.JsonOutput-                    , ifDaemonIsStopped = IfDaemonIsStopped.StartDaemon-                    , fields-                    }-        )-    Source (SourceOptions {modules, projectRoot}) ->-        ( projectRoot-        , Right-            $ Command.toArgs-            $ Command.Source-                Command.SourceOptions-                    { queries = parseSourceQuery <$> modules-                    , maxDepth = Nothing-                    , maxModules = Nothing-                    }-        )-    EvalComments (EvalCommentsOptions {wait, projectRoot}) ->-        ( projectRoot-        , Right-            $ Command.toArgs-            $ Command.EvalComments-                Command.EvalCommentsOptions-                    { wait = toWaitMode wait-                    , format = JsonOutput-                    , ifDaemonIsStopped = IfDaemonIsStopped.StartDaemon-                    }-        )-    LogPath (LogPathOptions {projectRoot}) ->-        ( projectRoot-        , Right-            $ Command.toArgs-            $ Command.Log Command.ShowLogPath-        )-    LogContents (LogContentsOptions {projectRoot}) ->-        ( projectRoot-        , Right-            $ Command.toArgs-            $ Command.Log Command.ShowLog-        )+toolCommand =+    second (fmap Command.toArgs) . \case+        StartDaemon (StartOptions {projectRoot}) ->+            ( projectRoot+            , Right+                $ Command.Daemon Daemon.Command.Start+            )+        StopDaemon (StopOptions {ignorePendingQueries, projectRoot}) ->+            ( projectRoot+            , Right+                $ Command.Daemon+                $ Daemon.Command.Stop+                $ toIfThereArePendingQueries ignorePendingQueries+            )+        RestartDaemon (RestartOptions {ignorePendingQueries, projectRoot}) ->+            ( projectRoot+            , Right+                $ Command.Daemon+                $ Daemon.Command.Restart+                $ toIfThereArePendingQueries ignorePendingQueries+            )+        Status (StatusOptions {wait, verbose, expand, projectRoot}) ->+            ( projectRoot+            , Right+                $ Command.Status+                    Command.StatusOptions+                        { wait = toIfBuildIsPending wait+                        , format = JsonOutput+                        , verbosity = toVerbosity verbose+                        , expand+                        , ifDaemonIsStopped = IfDaemonIsStopped.StartDaemon+                        }+            )+        TestSuites opts ->+            ( opts.projectRoot+            , do+                fields <- traverse FieldMask.Args.parse opts.fields+                Right+                    $ Command.Test+                    $ Test.Suites+                    $ Test.SuitesOptions+                        { testFilter = fromMaybe TestFilter.All opts.testFilter+                        , ifBuildIsPending = toIfBuildIsPending opts.wait+                        , suiteNames = fromMaybe [] opts.suiteNames+                        , format = OutputFormat.JsonOutput+                        , ifDaemonIsStopped = IfDaemonIsStopped.StartDaemon+                        , fields+                        }+            )+        Source (SourceOptions {modules, projectRoot}) ->+            ( projectRoot+            , Right+                $ Command.Source+                    Command.SourceOptions+                        { queries = parseSourceQuery <$> modules+                        , maxDepth = Nothing+                        , maxModules = Nothing+                        }+            )+        EvalComments (EvalCommentsOptions {wait, projectRoot}) ->+            ( projectRoot+            , Right+                $ Command.EvalComments+                    Command.EvalCommentsOptions+                        { wait = toIfBuildIsPending wait+                        , format = JsonOutput+                        , ifDaemonIsStopped = IfDaemonIsStopped.StartDaemon+                        }+            )+        LogPath (LogPathOptions {projectRoot}) ->+            ( projectRoot+            , Right+                $ Command.Log Command.ShowLogPath+            )+        LogContents (LogContentsOptions {projectRoot}) ->+            ( projectRoot+            , Right+                $ Command.Log Command.ShowLog+            )  -toForce :: Maybe Bool -> Force-toForce = maybe Force.NoForce (\enabled -> if enabled then Force.Force else Force.NoForce)+toIfThereArePendingQueries :: Maybe Bool -> IfThereArePendingQueries+toIfThereArePendingQueries ignorePendingQueries+    | ignorePendingQueries == Just True = IfThereArePendingQueries.DontWait+    | otherwise = IfThereArePendingQueries.Wait  -toWaitMode :: Maybe Bool -> WaitMode-toWaitMode =-    maybe-        WaitMode.ShowCurrent-        (\enabled -> if enabled then WaitMode.WaitForBuild else WaitMode.ShowCurrent)+toIfBuildIsPending :: Maybe Bool -> IfBuildIsPending+toIfBuildIsPending =+    maybe IfBuildIsPending.UseCurrent+        $ bool IfBuildIsPending.UseCurrent IfBuildIsPending.WaitForBuild   toVerbosity :: Maybe Bool -> Command.Verbosity
test/Unit/Tricorder/MCP/ToolsSpec.hs view
@@ -27,23 +27,37 @@             "toolCommand"             [ testCase "starts with just the directory"                 $ toolCommand (StartDaemon StartOptions {projectRoot = Nothing})-                    @?= (Nothing, Right ["start"])-            , testCase "omits --force when unset"-                $ toolCommand (StopDaemon (StopOptions {force = Nothing, projectRoot = Nothing}))-                    @?= (Nothing, Right ["stop"])-            , testCase "omits --force when explicitly false"-                $ toolCommand (RestartDaemon (RestartOptions {force = Just False, projectRoot = Nothing}))-                    @?= (Nothing, Right ["restart"])-            , testCase "includes --force when true"+                    @?= (Nothing, Right ["daemon", "start"])+            , testCase "omits --ignore-pending-queries when unset"                 $ toolCommand                     ( StopDaemon                         ( StopOptions-                            { force = Just True+                            { ignorePendingQueries = Nothing                             , projectRoot = Nothing                             }                         )                     )-                    @?= (Nothing, Right ["stop", "--force"])+                    @?= (Nothing, Right ["daemon", "stop"])+            , testCase "omits --ignore-pending-queries when explicitly false"+                $ toolCommand+                    ( RestartDaemon+                        ( RestartOptions+                            { ignorePendingQueries = Just False+                            , projectRoot = Nothing+                            }+                        )+                    )+                    @?= (Nothing, Right ["daemon", "restart"])+            , testCase "includes --ignore-pending-queries when true"+                $ toolCommand+                    ( StopDaemon+                        ( StopOptions+                            { ignorePendingQueries = Just True+                            , projectRoot = Nothing+                            }+                        )+                    )+                    @?= (Nothing, Right ["daemon", "stop", "--ignore-pending-queries"])             , testCase "combines status flags in order, with --expand carrying its argument"                 $ toolCommand                     ( Status@@ -54,7 +68,7 @@                             , projectRoot = Nothing                             }                     )-                    @?= (Nothing, Right ["status", "--wait", "--json", "--expand", "3"])+                    @?= (Nothing, Right ["status", "--json", "--expand", "3"])             , testCase "turns modules into positional arguments"                 $ toolCommand                     ( Source
tricorder-mcp.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           tricorder-mcp-version:        0.2.0.0+version:        1.0.0.1 synopsis:       MCP server for Tricorder description:    Model Context Protocol server for Tricorder. category:       AI,@@ -61,7 +61,7 @@       TypeFamilies   ghc-options: -Weverything -Wno-unsafe -Wno-missing-safe-haskell-mode -Wno-monomorphism-restriction -Wno-missing-kind-signatures -Wno-missing-local-signatures -Wno-missing-import-lists -Wno-implicit-prelude -Wno-unticked-promoted-constructors -Wno-unused-packages -Wno-all-missed-specialisations -Wno-missed-specialisations -fplugin=Effectful.Plugin -threaded   build-depends:-      atelier-core ==0.8.*+      atelier-core ==1.0.*     , atelier-prelude ==0.4.*     , base >=4.18 && <4.23     , bytestring >=0.11 && <0.13@@ -72,7 +72,7 @@     , optparse-applicative ==0.19.*     , process ==1.6.*     , template-haskell >=2.20 && <2.25-    , tricorder-types ==0.6.*+    , tricorder-types ==1.0.*     , typed-process ==0.2.*     , unix ==2.8.*   mixins:@@ -150,7 +150,7 @@   build-tool-depends:       tasty-discover:tasty-discover   build-depends:-      atelier-core ==0.8.*+      atelier-core ==1.0.*     , atelier-prelude ==0.4.*     , base >=4.18 && <4.23     , effectful-core ==2.7.*