enhance: Add optional mcp server to API server

Also switch CLI MCP server to fastify to reuse frontend code.
Also fix DELETE /mcp which was wrong
This commit is contained in:
Gabriel Horner
2025-09-17 15:02:27 -04:00
parent a4a1b16852
commit a16c89b986
8 changed files with 522 additions and 146 deletions

View File

@@ -13,6 +13,7 @@
"@logseq/nbb-logseq": "github:logseq/nbb-logseq#feat-db-v28",
"@modelcontextprotocol/sdk": "^1.17.5",
"better-sqlite3": "~11.10.0",
"fastify": "5.3.2",
"fs-extra": "^11.3.0",
"jszip": "3.8.0",
"mldoc": "^1.5.9",

View File

@@ -1,165 +1,77 @@
(ns logseq.cli.commands.mcp-server
"Command to run a MCP server"
(:require ["@modelcontextprotocol/sdk/server/mcp.js" :refer [McpServer]]
["@modelcontextprotocol/sdk/server/stdio.js" :refer [StdioServerTransport]]
["@modelcontextprotocol/sdk/server/streamableHttp.js" :refer [StreamableHTTPServerTransport]]
["@modelcontextprotocol/sdk/types.js" :refer [isInitializeRequest]]
["express$default" :as express]
(:require ["@modelcontextprotocol/sdk/server/stdio.js" :refer [StdioServerTransport]]
["fastify$default" :as Fastify]
["fs" :as fs]
["zod/v3" :as z]
[logseq.cli.common.mcp.server :as cli-common-mcp-server]
[logseq.cli.common.mcp.tools :as cli-common-mcp-tools]
[logseq.cli.util :as cli-util]
[logseq.db.common.sqlite-cli :as sqlite-cli]
[nbb.core :as nbb]
[promesa.core :as p]))
(defn- mcp-error-response [msg]
#js {:content
#js [#js {:type "text"
:text msg}]})
(defn- mcp-success-response [data]
(clj->js {:content
[{:type "text"
:text (js/JSON.stringify (clj->js data))}]}))
(defn- unexpected-api-error [error]
#js {:content
#js [#js {:type "text"
:text (str "Unexpected API error: " (.-message error))}]})
(defn- api-tool
"Calls API method w/ args and returns a MCP response"
[api-server-token api-method method-args]
(-> (p/let [resp (cli-util/api-fetch api-server-token api-method method-args)]
(if (= 200 (.-status resp))
(p/let [body (.json resp)]
(mcp-success-response body))
(cli-util/api-handle-error-response resp mcp-error-response)))
(p/catch unexpected-api-error)))
(defn- api-get-page
[{{:keys [api-server-token]} :opts} args]
(api-tool api-server-token "logseq.cli.getPageData" [(aget args "pageName")]))
(defn- api-list-pages
[{{:keys [api-server-token]} :opts} _args]
(api-tool api-server-token "logseq.cli.listPages" []))
(defn- api-list-tags
[{{:keys [api-server-token]} :opts} _args]
(api-tool api-server-token "logseq.cli.listTags" []))
(defn- api-list-properties
[{{:keys [api-server-token]} :opts} _args]
(api-tool api-server-token "logseq.cli.listProperties" []))
(def ^:private api-tools
"MCP Tools when running with API server"
{:listPages
{:fn api-list-pages
:config #js {:title "List Pages"}}
:getPage
{:fn api-get-page
:config #js {:title "Get Page"
:description "Get a page's content including its blocks"
:inputSchema #js {:pageName (z/string)}}}
:listTags
{:fn api-list-tags
:config #js {:title "List Tags"}}
:listProperties
{:fn api-list-properties
:config #js {:title "List Properties"}}})
(defn- local-get-page [conn args]
(if-let [blocks (cli-common-mcp-tools/get-page-blocks @conn (aget args "pageName"))]
(mcp-success-response blocks)
(mcp-error-response (str "Error: Page " (pr-str (aget args "pageName")) " not found"))))
(cli-common-mcp-server/mcp-success-response blocks)
(cli-common-mcp-server/mcp-error-response (str "Error: Page " (pr-str (aget args "pageName")) " not found"))))
(defn- local-list-pages [conn _args]
(mcp-success-response (cli-common-mcp-tools/list-pages @conn)))
(cli-common-mcp-server/mcp-success-response (cli-common-mcp-tools/list-pages @conn)))
(defn- local-list-properties [conn _args]
(mcp-success-response (cli-common-mcp-tools/list-properties @conn)))
(cli-common-mcp-server/mcp-success-response (cli-common-mcp-tools/list-properties @conn)))
(defn- local-list-tags [conn _args]
(mcp-success-response (cli-common-mcp-tools/list-tags @conn)))
(cli-common-mcp-server/mcp-success-response (cli-common-mcp-tools/list-tags @conn)))
(def ^:private local-tools
"MCP Tools when running with a local graph"
(merge-with
merge
api-tools
cli-common-mcp-server/api-tools
{:getPage {:fn local-get-page}
:listPages {:fn local-list-pages}
:listProperties {:fn local-list-properties}
:listTags {:fn local-list-tags}}))
(def ^:private transports
"Stores transports by session ID"
(atom {}))
(defn- handle-post-session-request [mcp-server {:keys [port]} req res]
(let [session-id (aget (.-headers req) "mcp-session-id")]
(js/console.log "POST /mcp request" session-id)
(cond
(and session-id (@transports session-id))
(.handleRequest (@transports session-id) req res (.-body req))
(and (not session-id)
(isInitializeRequest (.-body req)))
(let [transport (StreamableHTTPServerTransport.
#js {:sessionIdGenerator (comp str random-uuid)
:enableDnsRebindingProtection true
:allowedHosts #js [(str "localhost:" port)]})]
(set! (.-onclose transport)
(fn []
(js/console.log "Transport closed")
(when (.-sessionId transport)
(swap! transports dissoc (.-sessionId transport)))))
(.connect mcp-server transport)
(.handleRequest transport req res (.-body req))
(js/console.log "Initialize sessionId" (.-sessionId transport))
(if (.-sessionId transport)
(swap! transports assoc (.-sessionId transport) transport)
(js/console.error "No sessionId to initialize!")))
:else
(do
(.status res 400)
(.json res #js {:jsonrpc "2.0"
:error #js {:code -32000
:message "Bad Request: No valid session ID provided"}
:id nil})))))
(defn- handle-session-request
"Reusable handler for GET and DELETE"
[req res]
(let [session-id (aget (.-headers req) "mcp-session-id")]
(js/console.log (.-method req) "/mcp" session-id)
(if-let [transport (and session-id (@transports session-id))]
(.handleRequest transport req res)
(-> res (.status 400) (.send res "Invalid or missing session ID")))))
(defn- create-http-server [mcp-server opts]
(let [app (express)]
(.use app (.json express))
(.post app "/mcp" #(handle-post-session-request mcp-server opts %1 %2))
(.get app "/mcp" handle-session-request)
(.delete app "/mcp" handle-session-request)
(defn- create-http-server
[mcp-server opts]
(let [app (Fastify. #js {:requestTimeout (* 1000 30)})]
(.post app "/mcp" #(cli-common-mcp-server/handle-post-request mcp-server opts %1 %2))
(.get app "/mcp" cli-common-mcp-server/handle-get-request)
(.delete app "/mcp" cli-common-mcp-server/handle-delete-request)
app))
(defn- start-http-server [mcp-server {:keys [port] :as opts}]
(defn- start-http-server [mcp-server {:keys [port host] :as opts}]
(let [app (create-http-server mcp-server opts)]
(.listen app port
(.listen app (clj->js (select-keys opts [:port :host]))
(fn [error]
(if error
(do (js/console.error "Failed to start server:" error)
(js/process.exit 1))
(js/console.log
(str "MCP Streamable HTTP Server started on port " port)))))))
(str "MCP Streamable HTTP Server started on " host ":" port)))))))
(defn start [{{:keys [debug-tool graph stdio] :as opts} :opts :as m}]
(defn- call-api
"Calls API from CLI for use w/ cli-common-mcp-server/api-tool"
[api-server-token api-method method-args]
(p/let [resp (cli-util/api-fetch api-server-token api-method method-args)]
(if (= 200 (.-status resp))
(.json resp)
(p/let [body (.text resp)]
#js {:error (str "Server status " (.-status resp)
"\nAPI Response: " (pr-str body))}))))
(defn- create-mcp-server [{{:keys [api-server-token]} :opts} graph]
(if graph
(let [mcp-server (cli-common-mcp-server/create-mcp-server)
conn (apply sqlite-cli/open-db! (cli-util/->open-db-args graph))]
(doseq [[k v] local-tools]
(.registerTool mcp-server (name k) (:config v) (partial (:fn v) conn)))
mcp-server)
(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))))
(cli-util/error "Graph" (pr-str graph) "does not exist"))
(if debug-tool
@@ -169,18 +81,13 @@
(p/let [resp ((:fn tool-m) conn (clj->js (dissoc opts :debug-tool)))]
(js/console.log (clj->js resp))))
(cli-util/error "Tool" (pr-str debug-tool) "not found"))
(if-let [tool-m (get api-tools debug-tool)]
(p/let [resp ((:fn tool-m) m (clj->js (dissoc opts :debug-tool)))]
(if-let [tool-m (get cli-common-mcp-server/api-tools debug-tool)]
(p/let [resp (cli-common-mcp-server/call-api-tool (:fn tool-m)
(partial call-api api-server-token)
(clj->js (dissoc opts :debug-tool)))]
(js/console.log resp))
(cli-util/error "Tool" (pr-str debug-tool) "not found")))
(let [mcp-server (McpServer. #js {:name "Logseq MCP Server"
:version "0.1.0"})]
(if graph
(let [conn (apply sqlite-cli/open-db! (cli-util/->open-db-args graph))]
(doseq [[k v] local-tools]
(.registerTool mcp-server (name k) (:config v) (partial (:fn v) conn))))
(doseq [[k v] api-tools]
(.registerTool mcp-server (name k) (:config v) (partial (:fn v) m))))
(let [mcp-server (create-mcp-server m graph)]
(if stdio
(nbb/await (.connect mcp-server (StdioServerTransport.)))
(start-http-server mcp-server (select-keys opts [:port]))))))
(start-http-server mcp-server (select-keys opts [:port :host]))))))

View File

@@ -0,0 +1,144 @@
(ns logseq.cli.common.mcp.server
"MCP server related fns shared between CLI and frontend"
(:require ["@modelcontextprotocol/sdk/server/mcp.js" :refer [McpServer]]
["@modelcontextprotocol/sdk/server/streamableHttp.js" :refer [StreamableHTTPServerTransport]]
["@modelcontextprotocol/sdk/types.js" :refer [isInitializeRequest]]
["zod/v3" :as z] ;; zod 4 doesn't work w/ mcp - https://github.com/modelcontextprotocol/typescript-sdk/issues/925
[promesa.core :as p]))
;; Server util fns
;; ===============
(def ^:private transports
"Stores transports by session ID"
(atom {}))
;; See https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http
;; for how to respond to different MCP requests
(defn handle-post-request [mcp-server {:keys [port host]} req res]
(let [session-id (aget (.-headers req) "mcp-session-id")]
(js/console.log "POST /mcp request" session-id (.-body req))
(cond
(and session-id (@transports session-id))
(let [^js transport (@transports session-id)]
(.handleRequest transport (.-raw req) (.-raw res) (.-body req)))
(and (not session-id)
(isInitializeRequest (.-body req)))
(let [transport (StreamableHTTPServerTransport.
#js {:sessionIdGenerator (comp str random-uuid)
:enableDnsRebindingProtection true
:allowedHosts #js [(str host ":" port)]})]
(set! (.-onclose transport)
(fn []
(js/console.log "Transport closed" (.-sessionId transport))
(swap! transports dissoc (.-sessionId transport))))
(.connect mcp-server transport)
(.handleRequest transport (.-raw req) (.-raw res) (.-body req))
(js/console.log "Initialize sessionId" (.-sessionId transport))
(if (.-sessionId transport)
(swap! transports assoc (.-sessionId transport) transport)
(js/console.error "No sessionId to initialize!"))
res)
:else
(do
(.code res 400)
(.send res #js {:jsonrpc "2.0"
:error #js {:code -32000
:message "Bad Request: No valid session ID provided"}
:id nil})))))
(defn handle-get-request
[req res]
(let [session-id (aget (.-headers req) "mcp-session-id")]
(js/console.log "GET /mcp" session-id)
(if-let [transport (and session-id (@transports session-id))]
(.handleRequest ^js transport (.-raw req) (.-raw res))
(-> res (.status 400) (.send res "Invalid or missing session ID")))))
(defn handle-delete-request
[req res]
(let [session-id (aget (.-headers req) "mcp-session-id")]
(js/console.log "DELETE /mcp" session-id)
(if-let [transport (and session-id (@transports session-id))]
(do
(.close transport)
(-> res (.code 200) (.send #js {:ok true})))
(-> res (.status 400) (.send res "Invalid or missing session ID")))))
(defn mcp-error-response [msg]
#js {:content
#js [#js {:type "text"
:text msg}]})
(defn mcp-success-response [data]
(clj->js {:content
[{:type "text"
:text (js/JSON.stringify (clj->js data))}]}))
;; API tool fns
;; ============
(defn- unexpected-api-error [error]
#js {:content
#js [#js {:type "text"
:text (str "Unexpected API error: " (.-message error))}]})
(defn- api-tool
"Calls API method w/ args and returns a MCP response"
[api-fn api-method method-args]
(-> (p/let [body (api-fn api-method method-args)]
(if-let [error (aget body "error")]
(mcp-error-response (str "API Error: " error))
(mcp-success-response body)))
(p/catch unexpected-api-error)))
(defn- api-get-page
[call-api-fn args]
(call-api-fn "logseq.cli.getPageData" [(aget args "pageName")]))
(defn- api-list-pages
[call-api-fn _args]
(call-api-fn "logseq.cli.listPages" []))
(defn- api-list-tags
[call-api-fn _args]
(call-api-fn "logseq.cli.listTags" []))
(defn- api-list-properties
[call-api-fn _args]
(call-api-fn "logseq.cli.listProperties" []))
(def api-tools
"MCP Tools when calling API server"
{:listPages
{:fn api-list-pages
:config #js {:title "List Pages"}}
:getPage
{:fn api-get-page
:config #js {:title "Get Page"
:description "Get a page's content including its blocks"
:inputSchema #js {:pageName (z/string)}}}
:listTags
{:fn api-list-tags
:config #js {:title "List Tags"}}
:listProperties
{:fn api-list-properties
:config #js {:title "List Properties"}}})
(defn call-api-tool [tool-fn api-fn args]
(tool-fn (partial api-tool api-fn) args))
;; Server fns
;; ==========
(defn create-mcp-server []
(McpServer. #js {:name "Logseq MCP Server"
:version "0.1.0"}))
(defn create-mcp-api-server [api-fn]
(let [mcp-server (create-mcp-server)]
(doseq [[k v] api-tools]
(.registerTool mcp-server
(name k)
(:config v)
(partial call-api-tool (:fn v) api-fn)))
mcp-server))

View File

@@ -42,7 +42,7 @@
(:logseq.property.class/properties e)
(update :logseq.property.class/properties #(mapv :db/ident %))
(:logseq.property.view/type e)
(update :logseq.property.view/type :db/ident)
(assoc :logseq.property.view/type (:db/ident (:logseq.property.view/type e)))
(:logseq.property/description e)
(update :logseq.property/description db-property/property-value-content))))))

View File

@@ -61,6 +61,8 @@
:default 3000
:coerce :long
:desc "Port for streamable HTTP server"}
:host {:default "localhost"
:desc "Host for streamable HHP server"}
:debug-tool {:alias :t
:coerce :keyword
:desc "Debug mcp tool with direct invocation"}})

307
deps/cli/yarn.lock vendored
View File

@@ -2,6 +2,47 @@
# yarn lockfile v1
"@fastify/ajv-compiler@^4.0.0":
version "4.0.2"
resolved "https://registry.yarnpkg.com/@fastify/ajv-compiler/-/ajv-compiler-4.0.2.tgz#da05938cf852901bfb953738764f553b5449b80b"
integrity sha512-Rkiu/8wIjpsf46Rr+Fitd3HRP+VsxUFDDeag0hs9L0ksfnwx2g7SPQQTFL0E8Qv+rfXzQOxBJnjUB9ITUDjfWQ==
dependencies:
ajv "^8.12.0"
ajv-formats "^3.0.1"
fast-uri "^3.0.0"
"@fastify/error@^4.0.0":
version "4.2.0"
resolved "https://registry.yarnpkg.com/@fastify/error/-/error-4.2.0.tgz#d40f46ba75f541fdcc4dc276b7308bbc8e8e6d7a"
integrity sha512-RSo3sVDXfHskiBZKBPRgnQTtIqpi/7zhJOEmAxCiBcM7d0uwdGdxLlsCaLzGs8v8NnxIRlfG0N51p5yFaOentQ==
"@fastify/fast-json-stringify-compiler@^5.0.0":
version "5.0.3"
resolved "https://registry.yarnpkg.com/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-5.0.3.tgz#fae495bf30dbbd029139839ec5c2ea111bde7d3f"
integrity sha512-uik7yYHkLr6fxd8hJSZ8c+xF4WafPK+XzneQDPU+D10r5X19GW8lJcom2YijX2+qtFF1ENJlHXKFM9ouXNJYgQ==
dependencies:
fast-json-stringify "^6.0.0"
"@fastify/forwarded@^3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@fastify/forwarded/-/forwarded-3.0.0.tgz#0fc96cdbbb5a38ad453d2d5533a34f09b4949b37"
integrity sha512-kJExsp4JCms7ipzg7SJ3y8DwmePaELHxKYtg+tZow+k0znUTf3cb+npgyqm8+ATZOdmfgfydIebPDWM172wfyA==
"@fastify/merge-json-schemas@^0.2.0":
version "0.2.1"
resolved "https://registry.yarnpkg.com/@fastify/merge-json-schemas/-/merge-json-schemas-0.2.1.tgz#3aa30d2f0c81a8ac5995b6d94ed4eaa2c3055824"
integrity sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==
dependencies:
dequal "^2.0.3"
"@fastify/proxy-addr@^5.0.0":
version "5.0.0"
resolved "https://registry.yarnpkg.com/@fastify/proxy-addr/-/proxy-addr-5.0.0.tgz#e9d1c7a49b8380d9f92a879fdc623ac47ee27de3"
integrity sha512-37qVVA1qZ5sgH7KpHkkC4z9SK6StIsIcOmpjvMPXNb3vx2GQxhZocogVYbr2PbbeLCQxYIPDok307xEvRZOzGA==
dependencies:
"@fastify/forwarded" "^3.0.0"
ipaddr.js "^2.1.0"
"@logseq/nbb-logseq@github:logseq/nbb-logseq#feat-db-v28":
version "1.2.173-feat-db-v28"
resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/c0410ff81a8b0d510705581cccd39788d862dc91"
@@ -26,6 +67,11 @@
zod "^3.23.8"
zod-to-json-schema "^3.24.1"
abstract-logging@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839"
integrity sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==
accepts@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-2.0.0.tgz#bbcf4ba5075467f3f2131eab3cffc73c2f5d7895"
@@ -34,6 +80,13 @@ accepts@^2.0.0:
mime-types "^3.0.0"
negotiator "^1.0.0"
ajv-formats@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-3.0.1.tgz#3d5dc762bca17679c3c2ea7e90ad6b7532309578"
integrity sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==
dependencies:
ajv "^8.0.0"
ajv@^6.12.6:
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
@@ -44,6 +97,16 @@ ajv@^6.12.6:
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
ajv@^8.0.0, ajv@^8.12.0:
version "8.17.1"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6"
integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==
dependencies:
fast-deep-equal "^3.1.3"
fast-uri "^3.0.1"
json-schema-traverse "^1.0.0"
require-from-string "^2.0.2"
ansi-regex@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
@@ -54,6 +117,19 @@ ansi-regex@^3.0.0:
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1"
integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==
atomic-sleep@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b"
integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==
avvio@^9.0.0:
version "9.1.0"
resolved "https://registry.yarnpkg.com/avvio/-/avvio-9.1.0.tgz#0ff80ed211682441d8aa39ff21a4b9d022109c44"
integrity sha512-fYASnYi600CsH/j9EQov7lECAniYiBFiiAtBNuZYLA2leLe9qOvZzqYHFjtIj6gD2VMoMLP14834LFWvr4IfDw==
dependencies:
"@fastify/error" "^4.0.0"
fastq "^1.17.1"
base64-js@^1.3.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
@@ -173,6 +249,11 @@ cookie@^0.7.1:
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7"
integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==
cookie@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-1.0.2.tgz#27360701532116bd3f1f9416929d176afe1e4610"
integrity sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==
core-util-is@~1.0.0:
version "1.0.3"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
@@ -235,6 +316,11 @@ depd@2.0.0, depd@^2.0.0:
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
dequal@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be"
integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==
detect-libc@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.4.tgz#f04715b8ba815e53b4d8109655b6508a6865a7e8"
@@ -361,7 +447,12 @@ express@^5.0.1:
type-is "^2.0.1"
vary "^1.1.2"
fast-deep-equal@^3.1.1:
fast-decode-uri-component@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz#46f8b6c22b30ff7a81357d4f59abfae938202543"
integrity sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
@@ -371,6 +462,63 @@ fast-json-stable-stringify@^2.0.0:
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
fast-json-stringify@^6.0.0:
version "6.0.1"
resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-6.0.1.tgz#82f1cb45fa96d0ca24b601f1738066976d6e2430"
integrity sha512-s7SJE83QKBZwg54dIbD5rCtzOBVD43V1ReWXXYqBgwCwHLYAAT0RQc/FmrQglXqWPpz6omtryJQOau5jI4Nrvg==
dependencies:
"@fastify/merge-json-schemas" "^0.2.0"
ajv "^8.12.0"
ajv-formats "^3.0.1"
fast-uri "^3.0.0"
json-schema-ref-resolver "^2.0.0"
rfdc "^1.2.0"
fast-querystring@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/fast-querystring/-/fast-querystring-1.1.2.tgz#a6d24937b4fc6f791b4ee31dcb6f53aeafb89f53"
integrity sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==
dependencies:
fast-decode-uri-component "^1.0.1"
fast-redact@^3.1.1:
version "3.5.0"
resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.5.0.tgz#e9ea02f7e57d0cd8438180083e93077e496285e4"
integrity sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==
fast-uri@^3.0.0, fast-uri@^3.0.1:
version "3.1.0"
resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa"
integrity sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==
fastify@5.3.2:
version "5.3.2"
resolved "https://registry.yarnpkg.com/fastify/-/fastify-5.3.2.tgz#88c895a30c0f67166979077ac8649fe8b205a1b3"
integrity sha512-AIPqBgtqBAwkOkrnwesEE+dOyU30dQ4kh7udxeGVR05CRGwubZx+p2H8P0C4cRnQT0+EPK4VGea2DTL2RtWttg==
dependencies:
"@fastify/ajv-compiler" "^4.0.0"
"@fastify/error" "^4.0.0"
"@fastify/fast-json-stringify-compiler" "^5.0.0"
"@fastify/proxy-addr" "^5.0.0"
abstract-logging "^2.0.1"
avvio "^9.0.0"
fast-json-stringify "^6.0.0"
find-my-way "^9.0.0"
light-my-request "^6.0.0"
pino "^9.0.0"
process-warning "^5.0.0"
rfdc "^1.3.1"
secure-json-parse "^4.0.0"
semver "^7.6.0"
toad-cache "^3.7.0"
fastq@^1.17.1:
version "1.19.1"
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5"
integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==
dependencies:
reusify "^1.0.4"
file-uri-to-path@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
@@ -388,6 +536,15 @@ finalhandler@^2.1.0:
parseurl "^1.3.3"
statuses "^2.0.1"
find-my-way@^9.0.0:
version "9.3.0"
resolved "https://registry.yarnpkg.com/find-my-way/-/find-my-way-9.3.0.tgz#9f57786b5d772cc45142bf39dd5349f9cc883f91"
integrity sha512-eRoFWQw+Yv2tuYlK2pjFS2jGXSxSppAs3hSQjfxVKxM5amECzIgYYc1FEI8ZmhSh/Ig+FrKEz43NLRKJjYCZVg==
dependencies:
fast-deep-equal "^3.1.3"
fast-querystring "^1.0.0"
safe-regex2 "^5.0.0"
find-up@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
@@ -547,6 +704,11 @@ ipaddr.js@1.9.1:
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
ipaddr.js@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8"
integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==
is-fullwidth-code-point@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
@@ -579,11 +741,23 @@ isexe@^2.0.0:
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
json-schema-ref-resolver@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/json-schema-ref-resolver/-/json-schema-ref-resolver-2.0.1.tgz#c92f16b452df069daac53e1984159e0f9af0598d"
integrity sha512-HG0SIB9X4J8bwbxCbnd5FfPEbcXAJYTi1pBJeP/QPON+w8ovSME8iRG+ElHNxZNX2Qh6eYn1GdzJFS4cDFfx0Q==
dependencies:
dequal "^2.0.3"
json-schema-traverse@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
json-schema-traverse@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
jsonfile@^6.0.1:
version "6.1.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
@@ -617,6 +791,15 @@ lie@~3.3.0:
dependencies:
immediate "~3.0.5"
light-my-request@^6.0.0:
version "6.6.0"
resolved "https://registry.yarnpkg.com/light-my-request/-/light-my-request-6.6.0.tgz#c9448772323f65f33720fb5979c7841f14060add"
integrity sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==
dependencies:
cookie "^1.0.1"
process-warning "^4.0.0"
set-cookie-parser "^2.6.0"
locate-path@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
@@ -744,6 +927,11 @@ object-inspect@^1.13.3:
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213"
integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==
on-exit-leak-free@^2.1.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8"
integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==
on-finished@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
@@ -831,6 +1019,35 @@ path-to-regexp@^8.0.0:
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.3.0.tgz#aa818a6981f99321003a08987d3cec9c3474cd1f"
integrity sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==
pino-abstract-transport@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz#de241578406ac7b8a33ce0d77ae6e8a0b3b68a60"
integrity sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==
dependencies:
split2 "^4.0.0"
pino-std-serializers@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz#7c625038b13718dbbd84ab446bd673dc52259e3b"
integrity sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==
pino@^9.0.0:
version "9.9.5"
resolved "https://registry.yarnpkg.com/pino/-/pino-9.9.5.tgz#f06a5a0b4c715e34606290070dbb938c27eddd8b"
integrity sha512-d1s98p8/4TfYhsJ09r/Azt30aYELRi6NNnZtEbqFw6BoGsdPVf5lKNK3kUwH8BmJJfpTLNuicjUQjaMbd93dVg==
dependencies:
atomic-sleep "^1.0.0"
fast-redact "^3.1.1"
on-exit-leak-free "^2.1.0"
pino-abstract-transport "^2.0.0"
pino-std-serializers "^7.0.0"
process-warning "^5.0.0"
quick-format-unescaped "^4.0.3"
real-require "^0.2.0"
safe-stable-stringify "^2.3.1"
sonic-boom "^4.0.1"
thread-stream "^3.0.0"
pkce-challenge@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/pkce-challenge/-/pkce-challenge-5.0.0.tgz#c3a405cb49e272094a38e890a2b51da0228c4d97"
@@ -859,6 +1076,16 @@ process-nextick-args@~2.0.0:
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
process-warning@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-4.0.1.tgz#5c1db66007c67c756e4e09eb170cdece15da32fb"
integrity sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==
process-warning@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-5.0.0.tgz#566e0bf79d1dff30a72d8bbbe9e8ecefe8d378d7"
integrity sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==
proxy-addr@^2.0.7:
version "2.0.7"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
@@ -887,6 +1114,11 @@ qs@^6.14.0:
dependencies:
side-channel "^1.1.0"
quick-format-unescaped@^4.0.3:
version "4.0.4"
resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7"
integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==
range-parser@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
@@ -934,16 +1166,41 @@ readable-stream@~2.3.6:
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
real-require@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78"
integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==
require-directory@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
require-from-string@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
require-main-filename@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
integrity sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==
ret@~0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/ret/-/ret-0.5.0.tgz#30a4d38a7e704bd96dc5ffcbe7ce2a9274c41c95"
integrity sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==
reusify@^1.0.4:
version "1.1.0"
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f"
integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==
rfdc@^1.2.0, rfdc@^1.3.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca"
integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==
router@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/router/-/router-2.2.0.tgz#019be620b711c87641167cc79b99090f00b146ef"
@@ -965,17 +1222,34 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
safe-regex2@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/safe-regex2/-/safe-regex2-5.0.0.tgz#762e4a4c328603427281d2b99662f2d04e4ae811"
integrity sha512-YwJwe5a51WlK7KbOJREPdjNrpViQBI3p4T50lfwPuDhZnE3XGVTlGvi+aolc5+RvxDD6bnUmjVsU9n1eboLUYw==
dependencies:
ret "~0.5.0"
safe-stable-stringify@^2.3.1:
version "2.5.0"
resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd"
integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==
"safer-buffer@>= 2.1.2 < 3.0.0":
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
secure-json-parse@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-4.0.0.tgz#2ee1b7581be38ab348bab5a3e49280ba80a89c85"
integrity sha512-dxtLJO6sc35jWidmLxo7ij+Eg48PM/kleBsxpC8QJE0qJICe+KawkDQmvCMZUr9u7WKVHgMW6vy3fQ7zMiFZMA==
semver@^5.5.0:
version "5.7.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
semver@^7.3.5:
semver@^7.3.5, semver@^7.6.0:
version "7.7.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58"
integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==
@@ -1012,6 +1286,11 @@ set-blocking@^2.0.0:
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==
set-cookie-parser@^2.6.0:
version "2.7.1"
resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz#3016f150072202dfbe90fadee053573cc89d2943"
integrity sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==
set-immediate-shim@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61"
@@ -1105,6 +1384,18 @@ simple-get@^4.0.0:
once "^1.3.1"
simple-concat "^1.0.0"
sonic-boom@^4.0.1:
version "4.2.0"
resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-4.2.0.tgz#e59a525f831210fa4ef1896428338641ac1c124d"
integrity sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==
dependencies:
atomic-sleep "^1.0.0"
split2@^4.0.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4"
integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==
statuses@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
@@ -1191,6 +1482,18 @@ tar-stream@^2.1.4:
inherits "^2.0.3"
readable-stream "^3.1.1"
thread-stream@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-3.1.0.tgz#4b2ef252a7c215064507d4ef70c05a5e2d34c4f1"
integrity sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==
dependencies:
real-require "^0.2.0"
toad-cache@^3.7.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/toad-cache/-/toad-cache-3.7.0.tgz#b9b63304ea7c45ec34d91f1d2fa513517025c441"
integrity sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==
toidentifier@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"

View File

@@ -24,6 +24,7 @@
"dependencies": {
"@fastify/cors": "11.0.1",
"@logseq/rsapi": "0.0.92",
"@modelcontextprotocol/sdk": "^1.17.5",
"@sentry/electron": "2.5.1",
"abort-controller": "3.0.0",
"chokidar": "^3.5.1",
@@ -44,20 +45,21 @@
"posthog-js": "1.10.2",
"semver": "7.5.2",
"socks-proxy-agent": "8.0.2",
"update-electron-app": "2.0.1"
"update-electron-app": "2.0.1",
"zod": "^4.1.5"
},
"devDependencies": {
"@electron-forge/cli": "^7.8.3",
"@electron-forge/maker-deb": "^7.8.3",
"@electron-forge/maker-dmg": "^7.8.3",
"@electron-forge/maker-wix": "^7.8.3",
"@electron-forge/maker-rpm": "^7.8.3",
"@electron-forge/maker-squirrel": "^7.8.3",
"@electron-forge/maker-wix": "^7.8.3",
"@electron-forge/maker-zip": "^7.8.3",
"@electron/rebuild": "4.0.1",
"electron": "37.2.6",
"electron-builder": "26.0.12",
"electron-forge-maker-appimage": "https://github.com/logseq/electron-forge-maker-appimage.git",
"electron-devtools-installer": "4.0.0"
"electron-devtools-installer": "4.0.0",
"electron-forge-maker-appimage": "https://github.com/logseq/electron-forge-maker-appimage.git"
}
}

View File

@@ -11,6 +11,7 @@
[electron.logger :as logger]
[electron.utils :as utils]
[electron.window :as window]
[logseq.cli.common.mcp.server :as cli-common-mcp-server]
[promesa.core :as p]))
(defonce ^:private *win (atom nil))
@@ -29,7 +30,8 @@
:host (get-host)
:port (get-port)
:tokens (cfgs/get-item :server/tokens)
:autostart (cfgs/get-item :server/autostart)}))
:autostart (cfgs/get-item :server/autostart)
:mcp-enabled? true}))
(defn- set-status!
([status] (set-status! status nil))
@@ -130,6 +132,19 @@
(p/catch (fn [^js e]
(set-status! :running e))))))
(defn- initialize-mcp-routes [^js server]
(let [api-fn (fn api-fn [meth args]
(if-let [meth' (resolve-real-api-method meth)]
(invoke-logseq-api! meth' args)
#js {:error (str "No method found for " (pr-str meth))}))
mcp-server (cli-common-mcp-server/create-mcp-api-server api-fn)]
(logger/debug "[server] MCP routes initialized")
(.post server "/mcp"
#(cli-common-mcp-server/handle-post-request mcp-server {:port (get-port)
:host (get-host)} %1 %2))
(.get server "/mcp" cli-common-mcp-server/handle-get-request)
(.delete server "/mcp" cli-common-mcp-server/handle-get-request)))
(defn start!
[]
(-> (p/let [_ (close!)
@@ -151,7 +166,9 @@
(string/replace-first "${HOST}" HOST)
(string/replace-first "${PORT}" PORT))]
(doto rep (.type "text/html")
(.send html))))))
(.send html))))))
_ (when (:mcp-enabled? @*state)
(initialize-mcp-routes s))
;; listen port
_ (.listen s (bean/->js (select-keys @*state [:host :port])))]
(reset! *server s)