Skip to content

Commit 17bfece

Browse files
store digests in vector db
1 parent 4bc5f5e commit 17bfece

File tree

5 files changed

+244
-233
lines changed

5 files changed

+244
-233
lines changed

examples/sqlite-vec/main.go

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -172,25 +172,31 @@ func (vs *VectorServer) registerTools(server *mcp.Server) {
172172
Properties: map[string]*jsonschema.Schema{},
173173
},
174174
OutputSchema: &jsonschema.Schema{
175-
Type: "array",
176-
Items: &jsonschema.Schema{
177-
Type: "object",
178-
Properties: map[string]*jsonschema.Schema{
179-
"id": {
180-
Type: "integer",
181-
Description: "Unique identifier for the collection",
182-
},
183-
"name": {
184-
Type: "string",
185-
Description: "Name of the collection",
186-
},
187-
"created_at": {
188-
Type: "string",
189-
Description: "Timestamp when the collection was created",
175+
Type: "object",
176+
Properties: map[string]*jsonschema.Schema{
177+
"collections": {
178+
Type: "array",
179+
Items: &jsonschema.Schema{
180+
Type: "object",
181+
Properties: map[string]*jsonschema.Schema{
182+
"id": {
183+
Type: "integer",
184+
Description: "Unique identifier for the collection",
185+
},
186+
"name": {
187+
Type: "string",
188+
Description: "Name of the collection",
189+
},
190+
"created_at": {
191+
Type: "string",
192+
Description: "Timestamp when the collection was created",
193+
},
194+
},
195+
Required: []string{"id", "name", "created_at"},
190196
},
191197
},
192-
Required: []string{"id", "name", "created_at"},
193198
},
199+
Required: []string{"collections"},
194200
},
195201
},
196202
vs.handleListCollections,
@@ -370,7 +376,11 @@ func (vs *VectorServer) handleListCollections(ctx context.Context, req *mcp.Call
370376
collections = append(collections, c)
371377
}
372378

373-
resultJSON, err := json.MarshalIndent(collections, "", " ")
379+
result := map[string]any{
380+
"collections": collections,
381+
}
382+
383+
resultJSON, err := json.MarshalIndent(result, "", " ")
374384
if err != nil {
375385
return nil, fmt.Errorf("failed to marshal collections: %w", err)
376386
}

examples/tool_registrations/embeddings.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,14 @@ https://github.com/docker/mcp-gateway
6666

6767
# Dynamic Embeddings
6868

69-
| Model | time(s) /tool | dim | ctx len | size | Notes |
70-
| :--- | :---- | :--- | :--- |
71-
| DMR - embeddinggemma (302M) | 1.2 | 768 | 2048 | 307M | needs summary |
72-
| DMR - nomic (137M) | | 768 | 2048 | 0.5G | needs summary |
73-
| DMR - qwen3-embedding (4B) | 3.2 | 2560 | 40960 | 2.32G | ok |
74-
| GPT (text-embedding-3-small) | 0.3 | 1536 | 8191 | - | ok |
69+
| Model | time(ms)/tool | dim | ctx len | size | Notes |
70+
| :--- | :-- | :--- | :--- | :--- | :---- |
71+
| DMR - embeddinggemma (302M) | 4871 | 768 | 2048 | 307M | needs tool summarization |
72+
| DMR - qwen3-embedding (4B) | 920 | 2560 | 40960 | 2.32G | can embed un-summarized tool def |
73+
| GPT (text-embedding-3-small) | 307 | 1536 | 8191 | - | can embed un-summarized tool def |
74+
| DMR - nomic (137M) | | 768 | 2048 | 0.5G | needs tool summarization |
75+
76+
* 40 servers will be about 4 megs for larger vec dimensions like qwen3. Roughly half that for text-embedding-3-small, and half again for the smaller dimensions.
7577

7678
Pre-summary to use smaller models
7779

test/embeddings/clj/dmr.clj

Lines changed: 0 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,12 @@
22
(:require
33
[babashka.curl :as curl]
44
[cheshire.core :as json]
5-
[clj-yaml.core :as yaml]
6-
[clojure.core.async :as async]
7-
[tolkien.core :as tolkien]
85
[vector-db-process :as vec-db]))
96

107
;; ==================================================
118
;; DMR
129
;; ==================================================
1310

14-
(def embedding-model "ai/embeddinggemma:latest")
15-
(def summary-model "ai/gemma3-qat:latest")
1611
(def url "localhost/exp/vDD4.40/engines/llama.cpp/v1/embeddings")
1712
(def models-url "localhost/exp/vDD4.40/engines/llama.cpp/v1/models")
1813
(def create-models-url "localhost/exp/vDD4.40/models/create")
@@ -138,194 +133,3 @@
138133
(let [vec (create-embedding embedding-fn s)]
139134
(vec-db/search-vectors connection vec options)))
140135

141-
;; ==================================================
142-
;; Perform Embeddings
143-
;; ==================================================
144-
(defn summarize-registration [registration]
145-
(str
146-
#_(format "This tool comes from %s\n%s\n" (:server_name registration) (:server_title registration))
147-
(format "It provides the tool %s %s - %s\n" (-> registration :tool :name) (or (-> registration :tool :title) "") (-> registration :tool :description))
148-
(format "Input parameters are %s" (->> registration
149-
:tool
150-
:inputSchema
151-
:properties
152-
(map (fn [[k v]] (format "%s %s\n" (name k) (:description v))))
153-
(apply str)))))
154-
155-
(defn summarize-tools [tool-registrations]
156-
(doseq [tool-registration tool-registrations]
157-
(println "-------" (-> tool-registration :tool :name) "--------" (count (json/generate-string tool-registration)))
158-
(println (try
159-
(summarize-tool
160-
(partial dmr-completion summary-model)
161-
(json/generate-string tool-registration))
162-
(catch Throwable _ "failed to summarize")))))
163-
164-
(defn embed-servers
165-
"embed the server descriptions"
166-
[{:keys [embedding-fn summarize-fn connection]} collection servers]
167-
(println "> embed " (:name collection))
168-
(async/go
169-
(async/<! (vec-db/delete-collection connection (:name collection)))
170-
(async/<! (vec-db/create-collection connection (:name collection)))
171-
(doseq [server servers :let [summary
172-
(summarize-fn server)]]
173-
(println " > embed " (-> server :name) " -> " (count summary))
174-
(let [vec (create-embedding embedding-fn summary)]
175-
(async/<!! (vec-db/add-vector connection (:name collection) vec (select-keys server [:name])))))))
176-
177-
(defn embed-server-tools
178-
"embed the server descriptions"
179-
[{:keys [embedding-fn summarize-fn connection]} collection tool-registrations]
180-
(println "> embed " (:name collection))
181-
(async/go
182-
(async/<! (vec-db/delete-collection connection (:name collection)))
183-
(async/<! (vec-db/create-collection connection (:name collection)))
184-
(doseq [tool-registration tool-registrations :let [summary (summarize-fn tool-registration)]]
185-
(let [vec (time (create-embedding embedding-fn summary))]
186-
(println " > embed " (-> tool-registration :tool :name) " -> " (count summary))
187-
(async/<!! (vec-db/add-vector connection (:name collection) vec {:tool (select-keys (:tool tool-registration) [:name])}))))))
188-
189-
(defn json-with-token-check [tool-registration]
190-
(let [json (json/generate-string tool-registration)]
191-
(if (< 2048 (tolkien/count-tokens "text-embedding-3-small" json))
192-
(-> tool-registration
193-
(update :tool dissoc :outputSchema)
194-
(json/generate-string))
195-
json)))
196-
197-
(def servers
198-
["github-official" "gitmcp" "slack" "fetch" "duckduckgo"
199-
"brave" "context7" "dockerhub" "playwright" "wikipedia-mcp" "SQLite" "notion-remote" "rust-mcp-filesystem" "arxiv-mcp-server" "google-maps" "google-maps-comprehensive" "hugging-face" "linkedin-mcp-server" "desktop-commander"
200-
"openbnb-airbnb"
201-
"youtube_transcript"
202-
"time"
203-
"sequentialthinking"
204-
"semgrep"
205-
"resend"
206-
"papersearch"
207-
"openweather"
208-
"openapi-schema"
209-
"openapi"
210-
"node-code-sandbox"
211-
"minecraft-wiki"
212-
"microsoft-learn"
213-
"memory"
214-
"mcp-hackernews"
215-
"maven-tools-mcp"
216-
"markitdown"
217-
"gemini-api-docs"
218-
"filesystem"
219-
"everart"
220-
"stripe"
221-
"elevenlabs"])
222-
223-
(def fetch (memoize (fn [url] (try (:body (curl/get url)) (catch Throwable _ "")))))
224-
225-
(defn filter-names [coll] (->> coll (map :name)))
226-
227-
(defn read-catalog []
228-
(->> (slurp "/Users/slim/.docker/mcp/catalogs/docker-mcp.yaml")
229-
(yaml/parse-string)
230-
:registry
231-
(map (fn [[k v]] (assoc (select-keys v [:title :description :type :readme :toolsUrl]) :name (name k))))
232-
#_(map (fn [m] (update m :readme fetch)))
233-
(map (fn [m] (update m :toolsUrl (comp filter-names (fn [s] (json/parse-string s keyword)) fetch))))
234-
(map #(assoc % :tokens ((comp (partial tolkien/count-tokens "text-embedding-3-small") json/generate-string) %)))))
235-
236-
(comment
237-
;; make 3 connections
238-
(def connection (vec-db/vector-db-stdio-server {:dimension 1536 :db "vectors.db"}))
239-
(async/<!! (vec-db/create-collection connection "hello2"))
240-
(async/<!! (vec-db/list-collections connection))
241-
242-
(count servers)
243-
(reduce +
244-
(for [s servers]
245-
(count
246-
(vals
247-
(json/parse-string (slurp (format "/Users/slim/docker/mcp-gateway/examples/tool_registrations/tool-json/%s.json" s)))))))
248-
(float (/ (reduce + (for [s servers]
249-
(count (slurp (format "/Users/slim/docker/mcp-gateway/examples/tool_registrations/tool-json/%s.json" s))))) 4))
250-
251-
;; cleanup
252-
(async/<!!
253-
(async/go
254-
(doseq [item (async/<! (vec-db/list-collections vec-db-connection))]
255-
(println "delete " item)
256-
(async/<! (vec-db/delete-collection vec-db-connection (:name item))))))
257-
258-
;; make sure the model has been pulled
259-
(dmr-models)
260-
(dmr-get-model "ai" "embeddinggemma:latest")
261-
(dmr-create-model embedding-model)
262-
(dmr-create-model summary-model)
263-
264-
;; sembeds about 1 tool / second
265-
;; embed using GPT text-embedding-3-small (dimension is 1536)
266-
;; average 400ms per tool at 2m21s total
267-
(time
268-
(doseq [s servers]
269-
(async/<!!
270-
(embed-server-tools
271-
{:embedding-fn (partial dmr-embeddings "ai/qwen3-embedding") ;gpt-embeddings
272-
:summarize-fn json-with-token-check}
273-
{:name s}
274-
(vals
275-
(json/parse-string
276-
(slurp
277-
(format "/Users/slim/docker/mcp-gateway/examples/tool_registrations/tool-json/%s.json" s)) keyword))))))
278-
279-
;; embed servers
280-
(def catalog (read-catalog))
281-
(->> catalog
282-
(filter #(< 8191 (:tokens %)))
283-
(map #(select-keys % [:name :tokens])))
284-
(time
285-
(async/<!!
286-
(embed-servers
287-
{:embedding-fn (partial dmr-embeddings "ai/qwen3-embedding") ;gpt-embeddings
288-
:summarize-fn json/generate-string}
289-
{:name "mcp-server-collection"}
290-
catalog)))
291-
292-
;; search tools
293-
(def search-config {:embedding-fn (partial dmr-embeddings "ai/qwen3-embedding") ;gpt-embeddings
294-
:exclude_collections ["mcp-server-collection"]})
295-
(async/<!! (search search-config "I need to find github pull requests and I don't care about issues"))
296-
(async/<!! (search search-config "create a new pull request on github"))
297-
(async/<!! (search search-config "run bash on something"))
298-
(async/<!! (search search-config "do a wikipedia search"))
299-
(async/<!! (search search-config "are there any air bnb apartments in SF"))
300-
(async/<!! (search search-config "I need to do a security scan"))
301-
302-
;; search servers
303-
(def server-search-config {:collection_name "mcp-server-collection"
304-
:embedding-fn (partial dmr-embeddings "ai/qwen3-embedding")})
305-
(async/<!! (search server-search-config "what if I need to integrate with different chat systems")))
306-
307-
(comment
308-
309-
; semgrep_scan 10781 bigger than 4096.
310-
(doseq [s servers]
311-
(println
312-
s
313-
" -> "
314-
(->
315-
(vals (json/parse-string (slurp (format "/Users/slim/docker/mcp-gateway/examples/tool_registrations/tool-json/%s.json" s)) keyword))
316-
(json/generate-string)
317-
(count))))
318-
319-
; experiment - summarize all of the tool metadata
320-
(doseq [s servers]
321-
(summarize-tools
322-
(vals (json/parse-string (slurp (format "/Users/slim/docker/mcp-gateway/examples/tool_registrations/tool-json/%s.json" s)) keyword))))
323-
324-
;; all tools should have less than 2048 tokens in the data being embedded - should be empty
325-
(->>
326-
(for [s servers]
327-
(for [tool (vals (json/parse-string (slurp (format "/Users/slim/docker/mcp-gateway/examples/tool_registrations/tool-json/%s.json" s)) keyword))]
328-
[s (-> tool :tool :name) (tolkien/count-tokens "text-embedding-3-small" (json-with-token-check tool))]))
329-
(apply concat)
330-
(filter (fn [[_ _ n]] (< 2048 n)))))
331-

0 commit comments

Comments
 (0)