Skip to content

Commit 8542344

Browse files
new operations
1 parent 1941183 commit 8542344

File tree

2 files changed

+57
-4
lines changed

2 files changed

+57
-4
lines changed

lib/Echidna/MCP.hs

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,78 @@
11
module Echidna.MCP (runMCPServer) where
22

33
import Control.Monad.IO.Class (liftIO)
4+
import Data.Aeson (encode)
45
import Data.IORef (readIORef)
5-
import Data.Text (pack)
6+
import Data.List (find, isInfixOf)
7+
import Data.Maybe (fromMaybe)
8+
import Data.Set (toList)
9+
import Data.Text (pack, unpack)
10+
import Data.Text.Lazy (toStrict)
11+
import Data.Text.Lazy.Encoding (decodeUtf8)
612
import MCP.Server
713
import Network.Wai.Handler.Warp (Port)
814

915
import Echidna.Types.Config (Env(..))
1016
import Echidna.Types.Corpus (corpusSize)
17+
import Echidna.Types.Tx (Tx)
18+
import Echidna.Pretty (ppTx)
1119

1220
getCorpusSize :: Env -> ToolCallHandler IO
1321
getCorpusSize env _ _ = do
1422
corpus <- liftIO $ readIORef env.corpusRef
1523
pure $ Right $ ContentText $ pack $ show $ corpusSize corpus
1624

25+
inspectCorpusTransactions :: Env -> ToolCallHandler IO
26+
inspectCorpusTransactions env _ args = do
27+
corpus <- liftIO $ readIORef env.corpusRef
28+
let
29+
sequence' = read $ unpack $ fromMaybe "0" $ lookup "sequence" args
30+
page = read $ unpack $ fromMaybe "0" $ lookup "page" args
31+
txs = fromMaybe [] $ snd <$> find (\(i, _) -> i == sequence') (toList corpus)
32+
paginatedTxs = take 10 $ drop (page * 10) txs
33+
pure $ Right $ ContentText $ pack $ unlines $ map (ppTx mempty) paginatedTxs
34+
35+
findTransactionInCorpus :: Env -> ToolCallHandler IO
36+
findTransactionInCorpus env _ args = do
37+
corpus <- liftIO $ readIORef env.corpusRef
38+
let
39+
query = unpack $ fromMaybe "" $ lookup "query" args
40+
results =
41+
[ (seq', i `div` 10)
42+
| (seq', txs) <- toList corpus
43+
, (tx, i) <- zip txs [0..]
44+
, query `isInfixOf` ppTx mempty tx
45+
]
46+
pure $ Right $ ContentText $ pack $ show results
47+
1748
runMCPServer :: Env -> Port -> IO ()
1849
runMCPServer env port = do
1950
let
2051
info = McpServerInfo "Echidna" "2.2.7" "Echidna MCP server"
21-
tools =
52+
tools' =
2253
[ ToolDefinition "getCorpusSize" "Get the current corpus size" (InputSchemaDefinitionObject [] []) Nothing
54+
, ToolDefinition "inspectCorpusTransactions" "Inspect corpus transactions"
55+
(InputSchemaDefinitionObject
56+
[ ("sequence", InputSchemaDefinitionProperty "integer" "Sequence number")
57+
, ("page", InputSchemaDefinitionProperty "integer" "Page number (10 txs per page)")
58+
]
59+
["sequence", "page"])
60+
Nothing
61+
, ToolDefinition "findTransactionInCorpus" "Find transaction in corpus"
62+
(InputSchemaDefinitionObject
63+
[ ("query", InputSchemaDefinitionProperty "string" "String to search")
64+
]
65+
["query"])
66+
Nothing
2367
]
68+
toolHandler :: ToolCallHandler IO
69+
toolHandler "getCorpusSize" args = getCorpusSize env "getCorpusSize" args
70+
toolHandler "inspectCorpusTransactions" args = inspectCorpusTransactions env "inspectCorpusTransactions" args
71+
toolHandler "findTransactionInCorpus" args = findTransactionInCorpus env "findTransactionInCorpus" args
72+
toolHandler _ _ = pure $ Left $ InternalError "Unknown tool"
2473
handlers = McpServerHandlers
2574
{ prompts = Nothing
2675
, resources = Nothing
27-
, tools = Just (pure tools, getCorpusSize env)
76+
, tools = Just (pure tools', toolHandler)
2877
}
2978
runMcpServerHttpWithConfig (HttpConfig {httpPort = port, httpHost = "127.0.0.1", httpEndpoint = "/mcp", httpVerbose = False}) info handlers

lib/Echidna/Pretty.hs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import EVM.Types (Addr)
1010

1111
import Echidna.ABI (ppAbiValue)
1212
import Echidna.Types.Signature (SolCall)
13-
import Echidna.Types.Tx (TxCall(..))
13+
import Echidna.Types.Tx (Tx(..), TxCall(..))
1414

1515
-- | Pretty-print some 'AbiCall'.
1616
ppSolCall :: Map Addr Text -> SolCall -> String
@@ -24,3 +24,7 @@ ppTxCall _ (SolCreate _) = "<CREATE>"
2424
ppTxCall labels (SolCall x) = ppSolCall labels x
2525
ppTxCall _ NoCall = "*wait*"
2626
ppTxCall _ (SolCalldata x) = BSC8.unpack $ "0x" <> BS16.encode x
27+
28+
-- | Pretty-print some 'Tx'
29+
ppTx :: Map Addr Text -> Tx -> String
30+
ppTx labels tx = ppTxCall labels (tx.call)

0 commit comments

Comments
 (0)