Skip to content

Commit decdb0e

Browse files
committed
Add ollama support for tools/mcp
1 parent d4955c6 commit decdb0e

File tree

11 files changed

+68
-34
lines changed

11 files changed

+68
-34
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Unreleased
44

55
- Add built-in tools: filesystem
6+
- Add MCP/tool support for ollama models.
67

78
## 0.1.0
89

docs/capabilities.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Provides access to filesystem under workspace root, listing and reading files an
1414
|-----------|-------------|---------------------|
1515
| OpenAI || X |
1616
| Anthropic || X |
17-
| Ollama | X | X |
17+
| Ollama | | X |
1818

1919
### OpenAI
2020

docs/configuration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ interface Config {
117117
"openaiApiKey" : null,
118118
"anthropicApiKey" : null,
119119
"rules" : [ ],
120-
"built-in-tools": {"filesystem": {"enabled": true}},
120+
"builtInTools": {"filesystem": {"enabled": true}},
121121
"mcpTimeoutSeconds" : 10,
122122
"mcpServers" : [ ],
123123
"ollama" : {

src/eca/config.clj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@
1919
{:openaiApiKey nil
2020
:anthropicApiKey nil
2121
:rules []
22-
:built-in-tools {:filesystem {:enabled true}}
22+
:builtInTools {:filesystem {:enabled true}}
2323
:mcpTimeoutSeconds 60
2424
:mcpServers {}
2525
:ollama {:host "http://localhost"
2626
:port 11434
27-
:useTools false}
27+
:useTools true}
2828
:chat {:welcomeMessage "Welcome to ECA! What you have in mind?\n\n"}
2929
:index {:ignoreFiles [{:type :gitignore}]}})
3030

src/eca/features/tools.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
(defn built-in-definitions [config]
1313
(merge {}
14-
(when (get-in config [:built-in-tools :filesystem :enabled])
14+
(when (get-in config [:builtInTools :filesystem :enabled])
1515
f.tools.filesystem/definitions)))
1616

1717
(defn all-tools [db config]

src/eca/features/tools/filesystem.clj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
:error (boolean error)}]})
1313

1414
(defn ^:private not-allowed-path [path db]
15-
(when-not (some #(fs/starts-with? path (shared/uri->filename (:uri %)))
15+
(when (not-any? #(fs/starts-with? path (shared/uri->filename (:uri %)))
1616
(:workspace-folders db))
17-
(single-text-content "Access denied - path outside workspace root" :error)))
17+
(single-text-content "Access denied - path outside workspace root, call list_allowed_dirs first" :error)))
1818

1919
(defn ^:private list-allowed-directories [_arguments db]
2020
(single-text-content
@@ -23,7 +23,7 @@
2323
(map (comp shared/uri->filename :uri) (:workspace-folders db))))))
2424

2525
(defn ^:private list-directory [arguments db]
26-
(let [path (get arguments "path")]
26+
(let [path (fs/canonicalize (:path arguments))]
2727
(or (not-allowed-path path db)
2828
(single-text-content
2929
(reduce

src/eca/handlers.clj

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,16 @@
1010

1111
(set! *warn-on-reflection* true)
1212

13-
(defn ^:private initialize-extra-models! [db*]
14-
(let [config (config/all @db*)]
15-
(when-let [ollama-models (seq (llm-api/extra-models config))]
16-
(swap! db* update :models merge
17-
(reduce
18-
(fn [models {:keys [model]}]
19-
(assoc models
20-
(str config/ollama-model-prefix model)
21-
{:mcp-tools (get-in config [:ollama :useTools] false)}))
22-
{}
23-
ollama-models)))))
13+
(defn ^:private initialize-extra-models! [db* config]
14+
(when-let [ollama-models (seq (llm-api/extra-models config))]
15+
(swap! db* update :models merge
16+
(reduce
17+
(fn [models {:keys [model]}]
18+
(assoc models
19+
(str config/ollama-model-prefix model)
20+
{:mcp-tools (get-in config [:ollama :useTools] false)}))
21+
{}
22+
ollama-models))))
2423

2524
(defn initialize [{:keys [db* messenger]} params]
2625
(logger/logging-task
@@ -31,7 +30,7 @@
3130
:client-capabilities (:capabilities params)
3231
:chat-behavior (or (-> params :initialization-options :chat-behavior) (:chat-behavior @db*)))
3332
(let [config (config/all @db*)]
34-
(initialize-extra-models! db*)
33+
(initialize-extra-models! db* config)
3534
(future
3635
(f.mcp/initialize-servers-async!
3736
{:on-server-updated (fn [server]

src/eca/llm_api.clj

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
[eca.config :as config]
55
[eca.llm-providers.anthropic :as llm-providers.anthropic]
66
[eca.llm-providers.ollama :as llm-providers.ollama]
7-
[eca.llm-providers.openai :as llm-providers.openai]))
7+
[eca.llm-providers.openai :as llm-providers.openai]
8+
[eca.logger :as logger]))
89

910
(set! *warn-on-reflection* true)
1011

@@ -30,6 +31,9 @@
3031
(reset! first-message-received* true)
3132
(apply on-first-message-received args))
3233
(apply on-message-received args))
34+
on-error-wrapper (fn [& args]
35+
(apply logger/error args)
36+
(apply on-error args))
3337
tools (when (:mcp-tools model-config)
3438
(mapv mcp-tool->llm-tool mcp-tools))
3539
web-search (:web-search model-config)]
@@ -46,7 +50,7 @@
4650
:web-search web-search
4751
:api-key (:openaiApiKey config)}
4852
{:on-message-received on-message-received-wrapper
49-
:on-error on-error
53+
:on-error on-error-wrapper
5054
:on-prepare-tool-call on-prepare-tool-call
5155
:on-tool-called on-tool-called
5256
:on-reason on-reason})
@@ -63,7 +67,7 @@
6367
:web-search web-search
6468
:api-key (:anthropicApiKey config)}
6569
{:on-message-received on-message-received-wrapper
66-
:on-error on-error
70+
:on-error on-error-wrapper
6771
:on-prepare-tool-call on-prepare-tool-call
6872
:on-tool-called on-tool-called})
6973

@@ -77,7 +81,8 @@
7781
:tools tools
7882
:user-prompt user-prompt}
7983
{:on-message-received on-message-received-wrapper
80-
:on-error on-error
84+
:on-error on-error-wrapper
85+
:on-prepare-tool-call on-prepare-tool-call
8186
:on-tool-called on-tool-called})
8287

8388
:else

src/eca/llm_providers/ollama.clj

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,22 +66,48 @@
6666
tools))
6767

6868
(defn completion! [{:keys [model user-prompt context host port past-messages tools]}
69-
{:keys [on-message-received on-error _on-tool-called]}]
69+
{:keys [on-message-received on-error on-prepare-tool-call on-tool-called]}]
7070
(let [messages (if (empty? past-messages)
7171
[{:role "user" :content (->message-with-context context user-prompt)}]
7272
(conj past-messages {:role "user" :content user-prompt}))
7373
body {:model model
7474
:messages messages
75+
:think false
7576
:tools (->tools tools)
7677
:stream true}
7778
url (format chat-url (base-url host port))
7879
on-response-fn (fn handle-response [event data]
7980
(llm-util/log-response logger-tag event data)
8081
(let [{:keys [message done_reason]} data]
81-
(on-message-received
82-
(cond-> {}
83-
message (assoc :type :text :text (:content message))
84-
done_reason (assoc :type :finish :finish-reason done_reason)))))]
82+
(cond
83+
(seq (:tool_calls message))
84+
(let [function (:function (first (seq (:tool_calls message))))
85+
id (str (random-uuid))
86+
_ (on-prepare-tool-call {:id id
87+
:name (:name function)
88+
:argumentsText ""})
89+
response (on-tool-called {:id id
90+
:name (:name function)
91+
:arguments (:arguments function)})]
92+
(base-completion-request!
93+
{:url url
94+
:body (assoc body :messages (concat messages
95+
[message]
96+
(mapv
97+
(fn [{:keys [_type content]}]
98+
{:role "tool"
99+
:content content})
100+
(:contents response))))
101+
:on-error on-error
102+
:on-response handle-response}))
103+
104+
done_reason
105+
(on-message-received {:type :finish
106+
:finish-reason done_reason})
107+
108+
message
109+
(on-message-received {:type :text
110+
:text (:content message)}))))]
85111
(base-completion-request!
86112
{:url url
87113
:body body

src/eca/logger.clj

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,15 @@
1515
(binding [*out* *err*]
1616
(apply println args))))
1717

18-
(defn info [& args]
19-
(apply stderr-print :info args))
18+
(defn error [& args]
19+
(apply stderr-print :error args))
2020

2121
(defn warn [& args]
2222
(apply stderr-print :warn args))
2323

24+
(defn info [& args]
25+
(apply stderr-print :info args))
26+
2427
(defn debug [& args]
2528
(apply stderr-print :debug args))
2629

0 commit comments

Comments
 (0)