diff --git a/.clj-kondo/config.edn b/.clj-kondo/config.edn index 91a1afebd0..340aa8b3e5 100644 --- a/.clj-kondo/config.edn +++ b/.clj-kondo/config.edn @@ -168,6 +168,7 @@ logseq.cli.common.export.common cli-export-common logseq.cli.common.export.text cli-export-text logseq.cli.common.file common-file + logseq.cli.common.mcp.server cli-common-mcp-server logseq.cli.common.mcp.tools cli-common-mcp-tools logseq.cli.text-util cli-text-util logseq.common.config common-config diff --git a/deps/cli/.clj-kondo/config.edn b/deps/cli/.clj-kondo/config.edn index 53e23db7ff..52d461f1b7 100644 --- a/deps/cli/.clj-kondo/config.edn +++ b/deps/cli/.clj-kondo/config.edn @@ -12,6 +12,7 @@ clojure.string string datascript.core d logseq.cli.commands.graph cli-graph + logseq.cli.common.mcp.server cli-common-mcp-server logseq.cli.common.mcp.tools cli-common-mcp-tools logseq.cli.common.graph cli-common-graph logseq.cli.common.export.text cli-export-text diff --git a/deps/cli/README.md b/deps/cli/README.md index 096adc7347..2170b69458 100644 --- a/deps/cli/README.md +++ b/deps/cli/README.md @@ -125,6 +125,13 @@ Exported 16 properties, 16 classes and 36 pages # Append text to current page $ logseq append add this text -a my-token Success! + +# Start mcp-server against a local desktop graph +$ logseq mcp-server -g yep +MCP Streamable HTTP Server started on 127.0.0.1:12315 +# Start mcp-server against a local graph file +$ logseq mcp-server -g ~/Downloads/logseq_db_yep_1751032977.sqlite +MCP Streamable HTTP Server started on 127.0.0.1:12315 ``` ## API diff --git a/deps/cli/src/logseq/cli/commands/export.cljs b/deps/cli/src/logseq/cli/commands/export.cljs index dd4659a7ec..589230fb44 100644 --- a/deps/cli/src/logseq/cli/commands/export.cljs +++ b/deps/cli/src/logseq/cli/commands/export.cljs @@ -74,7 +74,7 @@ (println "Exported" (count exported-files) "pages to" file-name))))) (defn export [{{:keys [graph] :as opts} :opts}] - (if (fs/existsSync (cli-util/get-graph-dir graph)) + (if (fs/existsSync (cli-util/get-graph-path graph)) (let [conn (apply sqlite-cli/open-db! (cli-util/->open-db-args graph))] (export-repo-as-markdown! (str common-config/db-version-prefix graph) @conn opts)) (cli-util/error "Graph" (pr-str graph) "does not exist"))) \ No newline at end of file diff --git a/deps/cli/src/logseq/cli/commands/export_edn.cljs b/deps/cli/src/logseq/cli/commands/export_edn.cljs index 447f2f28df..94864e3e14 100644 --- a/deps/cli/src/logseq/cli/commands/export_edn.cljs +++ b/deps/cli/src/logseq/cli/commands/export_edn.cljs @@ -8,7 +8,7 @@ [logseq.cli.util :as cli-util])) (defn export [{{:keys [graph] :as options} :opts}] - (if (fs/existsSync (cli-util/get-graph-dir graph)) + (if (fs/existsSync (cli-util/get-graph-path graph)) (let [conn (apply sqlite-cli/open-db! (cli-util/->open-db-args graph)) export-map (sqlite-export/build-export @conn (cond-> {:export-type (:export-type options)} diff --git a/deps/cli/src/logseq/cli/commands/graph.cljs b/deps/cli/src/logseq/cli/commands/graph.cljs index e940f67639..c604e1196a 100644 --- a/deps/cli/src/logseq/cli/commands/graph.cljs +++ b/deps/cli/src/logseq/cli/commands/graph.cljs @@ -19,7 +19,7 @@ (defn show-graph [{{:keys [graphs]} :opts}] (doseq [graph graphs] - (let [graph-dir (cli-util/get-graph-dir graph)] + (let [graph-dir (cli-util/get-graph-path graph)] (if (fs/existsSync graph-dir) (let [conn (apply sqlite-cli/open-db! (cli-util/->open-db-args graph)) kv-value #(:kv/value (d/entity @conn %))] diff --git a/deps/cli/src/logseq/cli/commands/mcp_server.cljs b/deps/cli/src/logseq/cli/commands/mcp_server.cljs index bdbb8feffc..8b95c488c2 100644 --- a/deps/cli/src/logseq/cli/commands/mcp_server.cljs +++ b/deps/cli/src/logseq/cli/commands/mcp_server.cljs @@ -86,7 +86,7 @@ (cli-common-mcp-server/create-mcp-api-server (partial call-api api-server-token)))) (defn start [{{:keys [debug-tool graph stdio api-server-token] :as opts} :opts :as m}] - (when (and graph (not (fs/existsSync (cli-util/get-graph-dir graph)))) + (when (and graph (not (fs/existsSync (cli-util/get-graph-path graph)))) (cli-util/error "Graph" (pr-str graph) "does not exist")) (if debug-tool (if graph diff --git a/deps/cli/src/logseq/cli/commands/query.cljs b/deps/cli/src/logseq/cli/commands/query.cljs index 35f40c8d66..8d5c256585 100644 --- a/deps/cli/src/logseq/cli/commands/query.cljs +++ b/deps/cli/src/logseq/cli/commands/query.cljs @@ -74,7 +74,7 @@ [{{:keys [graph args graphs properties-readable title-query]} :opts}] (let [graphs' (into [graph] graphs)] (doseq [graph' graphs'] - (if (fs/existsSync (cli-util/get-graph-dir graph')) + (if (fs/existsSync (cli-util/get-graph-path graph')) (let [conn (apply sqlite-cli/open-db! (cli-util/->open-db-args graph)) query* (when (string? (first args)) (common-util/safe-read-string {:log-error? false} (first args))) results (cond diff --git a/deps/cli/src/logseq/cli/commands/search.cljs b/deps/cli/src/logseq/cli/commands/search.cljs index 24798f0409..2371bd2e2d 100644 --- a/deps/cli/src/logseq/cli/commands/search.cljs +++ b/deps/cli/src/logseq/cli/commands/search.cljs @@ -51,7 +51,7 @@ (p/catch cli-util/command-catch-handler))) (defn- local-search [search-term {{:keys [graph raw limit]} :opts}] - (if (fs/existsSync (cli-util/get-graph-dir graph)) + (if (fs/existsSync (cli-util/get-graph-path graph)) (let [conn (apply sqlite-cli/open-db! (cli-util/->open-db-args graph)) nodes (->> (d/datoms @conn :aevt :block/title) (filter (fn [datom] diff --git a/deps/cli/src/logseq/cli/spec.cljs b/deps/cli/src/logseq/cli/spec.cljs index 44e77402ce..fdb5717e96 100644 --- a/deps/cli/src/logseq/cli/spec.cljs +++ b/deps/cli/src/logseq/cli/spec.cljs @@ -58,11 +58,11 @@ :stdio {:alias :s :desc "Run the MCP server via stdio transport"} :port {:alias :p - :default 3000 + :default 12315 :coerce :long :desc "Port for streamable HTTP server"} - :host {:default "localhost" - :desc "Host for streamable HHP server"} + :host {:default "127.0.0.1" + :desc "Host for streamable HTTP server"} :debug-tool {:alias :t :coerce :keyword :desc "Debug mcp tool with direct invocation"}}) \ No newline at end of file diff --git a/deps/cli/src/logseq/cli/util.cljs b/deps/cli/src/logseq/cli/util.cljs index 572d8e4ba1..6f0a88ed82 100644 --- a/deps/cli/src/logseq/cli/util.cljs +++ b/deps/cli/src/logseq/cli/util.cljs @@ -1,20 +1,28 @@ (ns ^:node-only logseq.cli.util "CLI only util fns" (:require ["path" :as node-path] + ["fs" :as fs] [clojure.string :as string] [logseq.cli.common.graph :as cli-common-graph] [logseq.db.common.sqlite :as common-sqlite] [nbb.error] [promesa.core :as p])) -(defn get-graph-dir - [graph] - (node-path/join (cli-common-graph/get-db-graphs-dir) (common-sqlite/sanitize-db-name graph))) - (defn ->open-db-args "Creates args for sqlite-cli/open-db! given a graph. Similar to sqlite-cli/->open-db-args" [graph] - [(cli-common-graph/get-db-graphs-dir) (common-sqlite/sanitize-db-name graph)]) + (cond + (and (fs/existsSync graph) (.isFile (fs/statSync graph))) + [graph] + (string/includes? graph "/") + ((juxt node-path/dirname node-path/basename) graph) + :else + [(cli-common-graph/get-db-graphs-dir) (common-sqlite/sanitize-db-name graph)])) + +(defn get-graph-path + "If graph is a file, return its path. Otherwise returns the graph's dir" + [graph] + (apply node-path/join (->open-db-args graph))) (defn api-fetch [token method args] (js/fetch "http://127.0.0.1:12315/api"