(ns cli.mcp (:require [cli.view :as view] [cheshire.core :as json])) ;; Tool definitions (def available-tools [{:name "list_snippets" :description "List all available code snippets" :inputSchema {:type "object" :properties {} :required []}}]) ;; Tool implementations (defn list-snippets-impl [] (try (let [snippets (view/fetch-snippets)] {:success true :snippets (map #(select-keys % [:id :title :slug :tags]) snippets)}) (catch Exception e {:success false :error (.getMessage e)}))) ;; Handle tools/list request (defn handle-tools-list [id] {:jsonrpc "2.0" :id id :result {:tools available-tools}}) ;; Handle tools/call request (defn handle-tools-call [id tool-name tool-input] {:jsonrpc "2.0" :id id :result (case tool-name "list_snippets" (list-snippets-impl) {:error (str "Unknown tool: " tool-name)})}) ;; Handle initialize request (defn handle-initialize [id] {:jsonrpc "2.0" :id id :result {:protocolVersion "2024-11-05" :capabilities {:tools {:listChanged true} :resources {:listChanged true} :prompts {:listChanged true}} :serverInfo {:name "snippets-server" :version "1.0.0"}}}) ;; Main request dispatcher (defn handle-request [request] (let [method (:method request) id (:id request) params (:params request)] (case method "initialize" (handle-initialize id) "tools/list" (handle-tools-list id) "tools/call" (handle-tools-call id (:name params) (:arguments params)) {:jsonrpc "2.0" :id id :error {:code -32601 :message (str "Method not found: " method)}}))) (defn -main [& args] ;; Read JSON-RPC requests from stdin and process them (loop [] (let [line (try (read-line) (catch Exception _))] (when line (try (let [request (json/parse-string line true) response (handle-request request)] (println (json/encode response))) (catch Exception e (println (json/encode {:jsonrpc "2.0" :error {:code -32700 :message "Parse error"}})))) (recur)))))