Skip to content

Commit

Permalink
Add tiles
Browse files Browse the repository at this point in the history
  • Loading branch information
slimslenderslacks committed Feb 26, 2025
1 parent 9832690 commit ec64bab
Showing 11 changed files with 180 additions and 36 deletions.
1 change: 1 addition & 0 deletions compose.yaml
Original file line number Diff line number Diff line change
@@ -15,4 +15,5 @@ services:
- github:docker/labs-ai-tools-for-devs?path=prompts/bootstrap.md
volumes:
docker-prompts:
name: docker-prompts
external: true
3 changes: 3 additions & 0 deletions docs/content/tools/docs/running_containers.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
---
title: defining container tools
---

* default is to run synchronously without stdin and in terminal model
* image is mandatory
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
---
title: Using with Gordon
title: QuickStart w/ Gordon
weight: 4
---

## gordon-mcp.yaml
{{% steps %}}

### Install Docker Desktop Extension

1. Install [Docker Labs AI Tools for Devs](https://open.docker.com/extensions/marketplace?extensionId=docker/labs-ai-tools-for-devs)
2. Click on the Claude button to add `mcp_docker` toolbox to your Claude Desktop.
3. Select any prompts you would like to add from the catalog to your toolbox.

### Add gordon-mcp.yaml

When you run `docker ai` from any directory, docker ai will search that directory for a gordon-mcp.yml file.
If that file is present, and configured with the `mcp/docker` container then Gordon will load tools from
@@ -11,16 +20,11 @@ this container and try to use them.
```yaml
services:
mcp_docker:
image: mcp/docker:latest
command: serve --mcp --register github:docker/labs-ai-tools-for-devs?path=prompts/bootstrap.md
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- docker-prompts:/prompts
image: alpine:socat:latest
command:
- STDIO
- TCP:host.docker.internal:8811
x-mcp-autoremove: true

volumes:
docker-prompts:
external: false
```
{{< callout type="info" >}}
@@ -29,8 +33,8 @@ volumes:

{{< /callout >}}

## debugging
### debugging

We suggest using `docker ai --debug` if you are trying to debug some of your tools while using the `docker ai` cli.


{{% /steps %}}
13 changes: 5 additions & 8 deletions docs/content/tools/quickstsart_cursor.md
Original file line number Diff line number Diff line change
@@ -5,15 +5,13 @@ weight: 3

{{% steps %}}

### Install
### Go to Cursor Settings

## Quick Start w/ Cursor

1. Use the Features menu of the Cursor Settings
Use the Features menu of the Cursor Settings

![Claude Features](claude_features.png)
![Claude Features](claude_features.png)

2. Choose `Command` mode and then copy and paste the following string into the field labeled "Command".
Choose `Command` mode and then copy and paste the following string into the field labeled "Command".

```
docker run --rm -i alpine/socat:latest STDIO TCP:host.docker.internal:8811
@@ -27,8 +25,7 @@ weight: 3
After updating the list of tools, users must click the refresh button to activate new tool definitions
{{< /callout >}}


## Use tools from compose agent
### Use tools in agent mode of Composer

Tools will only be available in the `agent` mode of the composer. Note that the composer tab has two distinct modes (`normal` and `agent`).

18 changes: 18 additions & 0 deletions prompts/catalog.yaml
Original file line number Diff line number Diff line change
@@ -556,3 +556,21 @@ registry:
name: curl
prompts: 2
resources: {}
stripe:
description: itegrate with Stripe APIs
ref: github:docker/labs-ai-tools-for-devs?path=prompts/mcp/stripe.md
icon: https://cdn.jsdelivr.net/npm/simple-icons@v7/icons/stripe.svg
secrets:
- name: stripe.api_key
brave:
description: Web and local search using Brave's Search API
ref: github:docker/labs-ai-tools-for-devs?path=prompts/mcp/brave.md
icon: https://cdn.jsdelivr.net/npm/simple-icons@v7/icons/brave.svg
secrets:
- name: brave.api_key
slack:
description: interact with Slack Workspaces
ref: github:docker/labs-ai-tools-for-devs?path=prompts/mcp/slack.md
icon: https://cdn.jsdelivr.net/npm/simple-icons@v7/icons/slack.svg
secrets:
- name: slack.team_id
9 changes: 9 additions & 0 deletions prompts/mcp/brave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
mcp:
- name: brave
container:
image: mcp/brave-search:latest
environment:
BRAVE_API_KEY: "{{ brave.api_key }}"
---

10 changes: 10 additions & 0 deletions prompts/mcp/slack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
mcp:
- name: slack
container:
image: mcp/slack:latest
environment:
SLACK_BOT_TOKEN: "{{ slack.bot_token }}"
SLACK_TEAM_ID: "{{ slack.team_id }} "
---

10 changes: 10 additions & 0 deletions prompts/mcp/stripe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
mcp:
- name: stripe
container:
image: mcp/stripe:latest
command:
- "--tools=all"
- "--api-key={{stripe.api_key}}"
---

104 changes: 97 additions & 7 deletions src/docker.clj
Original file line number Diff line number Diff line change
@@ -124,9 +124,9 @@
- coll of strings (e.g. [\"9222:9222\"])"
[coll]
(->>
(for [s coll :let [{:keys [container host]} (parse-port s)]]
[(format "%s/%s" (:port container) (:protocol container)) [{:HostPort (:port host)}]])
(into {})))
(for [s coll :let [{:keys [container host]} (parse-port s)]]
[(format "%s/%s" (:port container) (:protocol container)) [{:HostPort (:port host)}]])
(into {})))

(comment
(port-bindings ["9222:9222"])
@@ -142,15 +142,15 @@
;; Tty wraps the process in a pseudo terminal
;; StdinOnce closes the stdin after the first client detaches
;; OpenStdin just opens stdin
(defn create-container [{:keys [image entrypoint workdir command host-dir env thread-id opts mounts volumes ports network_mode]
(defn create-container [{:keys [image entrypoint workdir command host-dir environment thread-id opts mounts volumes ports network_mode]
:or {opts {:Tty true}}}]
(let [payload (json/generate-string
(merge
{:Image image}
opts
(when env {:env (->> env
(map (fn [[k v]] (format "%s=%s" (name k) v)))
(into []))})
(when environment {:Env (->> environment
(map (fn [[k v]] (format "%s=%s" (name k) v)))
(into []))})
{:HostConfig
(merge
{:Binds
@@ -433,6 +433,96 @@
(logger/error "processing docker engine attach bytes: " t)
"")))

(defn write-to-stdin
" params
client - SocketChannel for attached container"
[client s]
(let [buf (ByteBuffer/allocate (* 1024 20))]
(.clear ^ByteBuffer buf)
(try
(.put ^ByteBuffer buf (.getBytes ^String s))
(.flip ^ByteBuffer buf)
(while (.hasRemaining buf)
(.write ^SocketChannel client buf))
(catch Throwable t
(logger/error "write-string error " t)))))

(defn read-loop
" params
in - SocketChannel for attached container
c - channel to write multiplexed stdout stderr blocks"
[in c]
(async/go
(try
(let [header-buf (ByteBuffer/allocate 8)]
(loop [offset 0]
(let [result (.read ^SocketChannel in header-buf)]
(cond
;;;;;;;;;;
(= -1 result)
(async/close! c)

;;;;;;;;;;
(= 8 (+ offset result))
(do
(.flip ^ByteBuffer header-buf)
(let [size (.getInt (ByteBuffer/wrap (Arrays/copyOfRange ^bytes (.array ^ByteBuffer header-buf) 4 8)))
stream-type (case (int (nth (.array ^ByteBuffer header-buf) 0))
0 :stdin
1 :stdout
2 :stderr)
buf (ByteBuffer/allocate size)]
(loop [offset 0]
(let [result (.read ^SocketChannel in buf)]
(cond
;;;;;;;;;;
(= -1 result)
(async/close! c)

;;;;;;;;;;
(= size (+ offset result))
(async/>! c {stream-type (String. ^bytes (.array buf))})

;;;;;;;;;;
:else
(recur (+ offset result)))))
(do
(.clear ^ByteBuffer buf)
(recur 0))))

;;;;;;;;;;
:else
(do
(.clear ^ByteBuffer header-buf)
(recur (+ offset result)))))))
(catch Throwable t
(logger/error "streaming exception " t)
(async/close! c)))))

(defn attach-socket
" returns SocketChannel"
[container-id]
(let [buf (ByteBuffer/allocate (* 1024 20))
address (UnixDomainSocketAddress/of "/var/run/docker.sock")
client (SocketChannel/open address)]
(.configureBlocking client true)
(.clear buf)
;; make HTTP call
(.put buf (.getBytes (String. (format "POST /containers/%s/attach?stdin=true&stdout=true&stderr=true&stream=true HTTP/1.1\n" container-id))))
(.put buf (.getBytes (String. "Host: localhost\nConnection: Upgrade\nUpgrade: tcp\n\n")))
(try
(.flip ^ByteBuffer buf)
(while (.hasRemaining buf)
(.write client buf))
;; TODO if successful, we should get a 101 UPGRADED response that will be exactly 117 bytes
(let [buf (ByteBuffer/allocate 117)]
;; TODO read the HTTP upgrade message
(.read client buf)
(.read client buf))
(catch Throwable _
client))
client))

(defn function-call-with-stdin
"creates and starts container, then writes to stdin process
returns container map with Id, and socket - socket is open socket to stdin"
2 changes: 1 addition & 1 deletion src/extension/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
mcp_docker:
image: mcp/docker
image: mcp/docker:latest
ports:
- 8811:8811
volumes:
16 changes: 9 additions & 7 deletions src/tools.clj
Original file line number Diff line number Diff line change
@@ -83,14 +83,16 @@
{:workdir (first (interpolate arg-context wd))}))

(-> definition :container :stdin :file) (update-in [:stdin :file] (fn [s] (first (interpolate arg-context s))))

(-> definition :container :stdin :content) (update-in [:stdin :content] (fn [s] (first (interpolate arg-context s)))))]
(jsonrpc/notify
:message
{:debug (format "function call %s"
(with-out-str
(pp/pprint (-> function-call
(update :jwt (fn [s] (if s "xxxxxxx" "not-set")))))))})
(let [s (format "function call %s"
(with-out-str
(pp/pprint (-> function-call
(update :jwt (fn [s] (if s "xxxxxxx" "not-set")))))))]
(jsonrpc/notify
:message
{:debug s})
(logger/debug s))
(trace/container-call (update function-call :jwt (fn [s] (if s "xxxxxxx" "not-set"))))
(let [{:keys [pty-output exit-code done] :as result} (docker/run-container function-call)
exit-code-fail? (if (false? (:check-exit-code definition))

0 comments on commit ec64bab

Please sign in to comment.