toolfunnel 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +167 -324
- package/bin/toolfunnel.js +39 -4
- package/docs/KNOWN_BUGS.md +33 -0
- package/docs/MANUAL.pdf +0 -0
- package/docs/packaging.md +115 -0
- package/package.json +3 -1
- package/src/auth/config.js +4 -2
- package/src/auth/resource-server.js +28 -3
- package/src/core/config-home.js +134 -0
- package/src/core/logger.js +4 -2
- package/src/core/requires.js +138 -0
- package/src/core/server-config.js +77 -0
- package/src/extend/create-tool.md +24 -4
- package/src/extend/package.md +33 -0
- package/src/mcp/aggregator.js +12 -7
- package/src/mcp/http-transport.js +71 -21
- package/src/mcp/mcp-client.js +9 -3
- package/src/mcp/server.js +181 -16
- package/src/packages/packager.js +5 -3
- package/src/tools/registry.js +47 -2
- package/src/ui/server.js +49 -3
- package/tools/scripts/tf-env.js +43 -0
- package/tools/scripts/tf-hook-add.js +4 -5
- package/tools/scripts/tf-hook-set.js +4 -5
- package/tools/scripts/tf-list.js +9 -12
- package/tools/scripts/tf-log.js +4 -1
- package/tools/scripts/tf-mcp-add.js +4 -6
- package/tools/scripts/tf-mcp-set.js +4 -6
- package/tools/scripts/tf-pack.js +237 -0
- package/tools/scripts/tf-tool-add.js +16 -16
- package/tools/scripts/tf-tool-set.js +5 -11
- package/tools/tools.register.json +46 -1
- package/docs/admin-ui.md +0 -404
- package/docs/configuration.md +0 -402
- package/docs/hooks-and-gating.md +0 -428
- package/docs/logging.md +0 -223
- package/docs/management.md +0 -429
- package/docs/oauth.md +0 -103
- package/docs/setup.md +0 -352
- package/docs/tools-and-upstreams.md +0 -469
package/docs/admin-ui.md
DELETED
|
@@ -1,404 +0,0 @@
|
|
|
1
|
-
# Admin UI — the management console
|
|
2
|
-
|
|
3
|
-
ToolFunnel ships an **optional** local web console for viewing, searching, and configuring
|
|
4
|
-
everything the gateway exposes — first-party tools, upstream MCP connections, lifecycle hooks,
|
|
5
|
-
and the activity log — without hand-editing JSON. It is a convenience layer, not a dependency:
|
|
6
|
-
the gateway runs perfectly with the UI never started.
|
|
7
|
-
|
|
8
|
-
The console is built from vanilla HTML/CSS/JS served by a zero-dependency `node:http` server
|
|
9
|
-
(`src/ui/server.js`). There is nothing to `npm install`, no framework, no external fonts or
|
|
10
|
-
CDN — it works fully offline. The theme is dark and the whole app is a single page with five
|
|
11
|
-
tabs.
|
|
12
|
-
|
|
13
|
-
The most important thing to understand up front: **the UI is a front end over the same config
|
|
14
|
-
files the CLI and the management functions write.** It does not keep its own state. Every read
|
|
15
|
-
goes through the gateway's own stores and every write is atomic (temp file + rename) into the
|
|
16
|
-
same JSON the running server reads:
|
|
17
|
-
|
|
18
|
-
| Tab | Reads / writes | Same store the CLI uses |
|
|
19
|
-
|------------|-----------------------------------------|---------------------------------------|
|
|
20
|
-
| Tools | `tools/tools.register.json`, `tools/tools.state.json` | `tf_tool_add` / `tf_tool_set` |
|
|
21
|
-
| MCPs | `mcp/expose.json` | `tf_mcp_add` / `tf_mcp_set` |
|
|
22
|
-
| Hooks | `hooks/hooks.manifest.json`, `hooks/hooks.state.json` | `tf_hook_add` / `tf_hook_set` |
|
|
23
|
-
| Logs | `logs/log.config.json` + the JSONL log | `tf_log` |
|
|
24
|
-
| Auth | `auth/auth.config.json` | `toolfunnel install-oauth` (install) |
|
|
25
|
-
|
|
26
|
-
Because the running MCP server re-reads the register, state, and manifest on every call, a change
|
|
27
|
-
you make in the UI is **live immediately — no restart**. A UI edit is byte-identical to the same
|
|
28
|
-
edit made through `tf_tool_add`, `tf_mcp_add`, `tf_hook_add`, or `tf_log`. The reverse is also
|
|
29
|
-
true: anything you change via the CLI/management functions shows the next time the UI reads
|
|
30
|
-
(reload the page, switch tabs, or hit a tab's refresh). Each request reads fresh from disk.
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
## 1. Launching
|
|
35
|
-
|
|
36
|
-
Start the console from the repo root:
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
node bin/toolfunnel.js --ui
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
It binds **`127.0.0.1:9777`** and prints the URL to stderr:
|
|
43
|
-
|
|
44
|
-
```
|
|
45
|
-
[toolfunnel] config UI listening on http://127.0.0.1:9777
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
Open that URL in a browser on the same machine.
|
|
49
|
-
|
|
50
|
-
**Options:**
|
|
51
|
-
|
|
52
|
-
```bash
|
|
53
|
-
node bin/toolfunnel.js --ui --port 9000 # bind a specific port (0 = OS-assigned ephemeral)
|
|
54
|
-
node bin/toolfunnel.js --ui --host 127.0.0.1 # bind a specific loopback host
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
**Loopback only — by design.** The server binds `127.0.0.1` by default and, as defence in depth,
|
|
58
|
-
rejects any request whose `Host` header is not a recognised loopback name (`127.0.0.1`,
|
|
59
|
-
`localhost`, `::1`) — a DNS-rebinding guard. The console is meant for the trusted human operator
|
|
60
|
-
on the same machine, not remote access. (`--host` exists for advanced local setups, but the
|
|
61
|
-
loopback boundary is the intended one; leave it at the default unless you have a reason.)
|
|
62
|
-
|
|
63
|
-
**It runs in-process, with full authority.** Because it is loopback-only and operator-driven, the
|
|
64
|
-
UI talks to the stores directly rather than through the gated MCP path. That means the console can
|
|
65
|
-
do everything the (gated) management functions can — add/remove tools, switch execution modes,
|
|
66
|
-
wire hooks — so treat access to the port as administrative access to the gateway's configuration.
|
|
67
|
-
|
|
68
|
-
**Stopping it:** `Ctrl+C` (or `SIGTERM`) shuts it down cleanly. If the port is already in use the
|
|
69
|
-
process prints `failed to start config UI: …` and exits — rerun with a different `--port`.
|
|
70
|
-
|
|
71
|
-
**The header.** Across the top sits the brand and three live counts — **tools**, **mcps**,
|
|
72
|
-
**hooks** — that refresh after every successful change so you can see the effect of an edit at a
|
|
73
|
-
glance. Below that are the five tabs: **Tools** (open by default), **MCPs**, **Hooks**, **Logs**,
|
|
74
|
-
**Auth**. The Tools list loads on boot; the other tabs load the first time you open them.
|
|
75
|
-
|
|
76
|
-
Every action gives feedback: a short-lived **toast** at the bottom of the screen (green on
|
|
77
|
-
success, red on error) reports what happened, and destructive actions (Remove) ask for an inline
|
|
78
|
-
confirm first.
|
|
79
|
-
|
|
80
|
-
---
|
|
81
|
-
|
|
82
|
-
## 2. Tools tab
|
|
83
|
-
|
|
84
|
-
This is where you manage the first-party tool register.
|
|
85
|
-
|
|
86
|
-
### Search
|
|
87
|
-
|
|
88
|
-
The search box filters the list live (case-insensitive substring) across **name, summary,
|
|
89
|
-
category, id, and mode**. When a filter is active the count beside the box shows `shown/total`.
|
|
90
|
-
Clear the box to see everything again.
|
|
91
|
-
|
|
92
|
-
### Each tool row
|
|
93
|
-
|
|
94
|
-
A row shows the tool's **name**, its **category** chip, its **id**, and a one-line **summary**,
|
|
95
|
-
followed by a strip of controls:
|
|
96
|
-
|
|
97
|
-
- **Mode toggle** (small switch, labelled with the current mode). Off = **reference**, on =
|
|
98
|
-
**gateway**. This is the per-tool execution mode (see below).
|
|
99
|
-
- **Pre / Post** (two small switches) — wire a `PreToolUse` / `PostToolUse` gate to this tool.
|
|
100
|
-
- **Enabled** (the larger switch) — turn the tool on or off in the surface. A disabled tool's row
|
|
101
|
-
dims.
|
|
102
|
-
- **Details / edit** — expand an inline panel to view *and edit* everything about the tool (see
|
|
103
|
-
below).
|
|
104
|
-
- **Remove** — delete the tool from the register (with a confirm).
|
|
105
|
-
|
|
106
|
-
#### Details / edit — view and change one tool
|
|
107
|
-
|
|
108
|
-
Click **Details / edit** on any row to expand a lazy inline panel (loaded on first open from
|
|
109
|
-
`GET /api/tools/detail?id=<id>`). It shows the tool's **full** entry — name, summary, category,
|
|
110
|
-
instructions, the resolved invoke, and, for a **script** invoke, the **script body** read from
|
|
111
|
-
`tools/scripts/`. The fields are editable: change the name, summary, category, instructions,
|
|
112
|
-
execution mode, or the script source, then **Save** to write the change via
|
|
113
|
-
`POST /api/tools/update`. The update **shallow-merges** your patch into the entry, re-validates it,
|
|
114
|
-
and persists `tools/tools.register.json` atomically; a script edit is authored back under
|
|
115
|
-
`tools/scripts/` (path-guarded) before the entry is saved. Because the running server reads fresh,
|
|
116
|
-
the edit is live with no restart. An invalid edit (e.g. switching to `gateway` with no invoke)
|
|
117
|
-
comes back as a red error toast and nothing is written.
|
|
118
|
-
|
|
119
|
-
#### The execution-mode toggle (reference vs gateway)
|
|
120
|
-
|
|
121
|
-
Every tool runs in one of two modes, and the switch flips between them live:
|
|
122
|
-
|
|
123
|
-
- **reference** — the gateway only *describes* the tool. When the AI asks to run it, ToolFunnel
|
|
124
|
-
hands back the instructions and the AI executes it in its own environment.
|
|
125
|
-
- **gateway** — ToolFunnel *executes* the tool server-side itself, through the gated run path
|
|
126
|
-
(which fires the Pre/Post hooks).
|
|
127
|
-
|
|
128
|
-
Flipping the switch writes the new mode immediately. One thing to know: switching a **reference**
|
|
129
|
-
tool that has *no invoke defined* over to **gateway** will fail — there is nothing for the gateway
|
|
130
|
-
to run — and you'll get a red error toast explaining it. Give the tool a script or shell invoke
|
|
131
|
-
first (re-add it, or edit the register / use the management tools), then switch.
|
|
132
|
-
|
|
133
|
-
#### The Pre / Post hook toggles
|
|
134
|
-
|
|
135
|
-
These wire a per-tool gate without touching the Hooks tab. Turning **Pre** on appends a
|
|
136
|
-
`PreToolUse` hook to `hooks/hooks.manifest.json` whose matcher matches *this tool's gate name
|
|
137
|
-
exactly*; **Post** does the same for `PostToolUse`. When you enable one, the toast reports the
|
|
138
|
-
**script path** you now need to create — for example:
|
|
139
|
-
|
|
140
|
-
```
|
|
141
|
-
hooks/scripts/<tool-id>-pretooluse.js
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
The gate is wired, but **until that script file exists it has nothing to run.** Author the script
|
|
145
|
-
at the reported path to define the behaviour (a `PreToolUse` script can block the call; a
|
|
146
|
-
`PostToolUse` script observes the result). Turning the toggle off removes the matching gate entry
|
|
147
|
-
again. These gates are what fire on every gateway-run and forwarded call.
|
|
148
|
-
|
|
149
|
-
(These same gates also appear on the Hooks tab, shown read-only — see below.)
|
|
150
|
-
|
|
151
|
-
### Adding a tool
|
|
152
|
-
|
|
153
|
-
Click **+ Add tool** to open the form. Fields:
|
|
154
|
-
|
|
155
|
-
| Field | Notes |
|
|
156
|
-
|----------------|-----------------------------------------------------------------------|
|
|
157
|
-
| **id** * | Required, unique. The register key (e.g. `my_tool`). |
|
|
158
|
-
| **name** * | Required. Display name. |
|
|
159
|
-
| **category** | Optional grouping label (shown as a chip). |
|
|
160
|
-
| **mode** | `gateway — run here` (default) or `reference — AI runs it`. |
|
|
161
|
-
| **summary** | One-line description shown in the list. |
|
|
162
|
-
| **invoke type**| `script` / `shell` / `none` — *gateway mode only*. |
|
|
163
|
-
| **script path**| e.g. `scripts/my-tool.js` — *gateway + script only*. |
|
|
164
|
-
| **shell command** | e.g. `echo hello` — *gateway + shell only*. |
|
|
165
|
-
| **instructions** | How the connected AI should call this tool. |
|
|
166
|
-
| **script body**| Optional inline source, authored under `tools/scripts/` — *gateway + script only*. |
|
|
167
|
-
|
|
168
|
-
The form is mode-aware. Choose **reference** and the invoke fields disappear — a reference tool
|
|
169
|
-
needs no invoke, just its metadata and instructions. Choose **gateway** and the invoke type
|
|
170
|
-
selector appears: pick **script** to reveal the *script path* and *script body* fields, **shell**
|
|
171
|
-
to reveal the *shell command* field, or **none** for a gateway entry with no invoke yet.
|
|
172
|
-
|
|
173
|
-
A practical script tool, end to end:
|
|
174
|
-
|
|
175
|
-
1. mode = **gateway**, invoke type = **script**
|
|
176
|
-
2. **script path** = `scripts/my-tool.js`
|
|
177
|
-
3. paste the source into **script body** (it is written to `tools/scripts/my-tool.js` for you,
|
|
178
|
-
before the tool is registered — the path is guarded to stay inside `tools/scripts/`)
|
|
179
|
-
4. fill **id**, **name**, a **summary**, and **instructions**
|
|
180
|
-
5. **Add tool**
|
|
181
|
-
|
|
182
|
-
`id` and `name` are required (and a script invoke requires a path, a shell invoke a command) — the
|
|
183
|
-
form blocks submission and toasts if one is missing. A duplicate `id` is rejected by the register
|
|
184
|
-
with a clear error. New tools land in the register and appear in the list straight away.
|
|
185
|
-
|
|
186
|
-
### Enable / disable and remove
|
|
187
|
-
|
|
188
|
-
The **Enabled** switch flips the tool's entry in `tools/tools.state.json` — a disabled tool stays
|
|
189
|
-
in the register but drops out of the live surface. **Remove** deletes it from the register and
|
|
190
|
-
clears its state-overlay key (so a future re-add of the same id starts clean); the inline confirm
|
|
191
|
-
guards against a misclick.
|
|
192
|
-
|
|
193
|
-
---
|
|
194
|
-
|
|
195
|
-
## 3. MCPs tab
|
|
196
|
-
|
|
197
|
-
This tab manages upstream MCP servers and the tools curated from them, stored in `mcp/expose.json`.
|
|
198
|
-
|
|
199
|
-
### Search
|
|
200
|
-
|
|
201
|
-
Filters the upstream list by **id, command, args, and description**, with the same `shown/total`
|
|
202
|
-
counter.
|
|
203
|
-
|
|
204
|
-
### Each upstream row
|
|
205
|
-
|
|
206
|
-
A row shows the upstream **id** (monospace), a **transport** badge (`stdio`), an
|
|
207
|
-
**enabled/disabled** badge, the resolved **command line** (command + args), an optional
|
|
208
|
-
**description**, and an **Exposed tools** block. Each exposed entry reads `tool → as` with an
|
|
209
|
-
optional category chip and an on/off badge; an upstream with none shows *"No exposed tools."*
|
|
210
|
-
Controls: an **Enabled** switch and a **Remove** button.
|
|
211
|
-
|
|
212
|
-
### Adding an upstream
|
|
213
|
-
|
|
214
|
-
Click **+ Add MCP**. Fields:
|
|
215
|
-
|
|
216
|
-
| Field | Notes |
|
|
217
|
-
|---------------|----------------------------------------------------------------|
|
|
218
|
-
| **id** * | Required, unique upstream id. |
|
|
219
|
-
| **transport** | `stdio` (the supported transport). |
|
|
220
|
-
| **command** * | Required executable, e.g. `node`. |
|
|
221
|
-
| **args** | Space-separated, e.g. `path/to/server.js --flag`. |
|
|
222
|
-
| **description** | What this upstream provides. |
|
|
223
|
-
|
|
224
|
-
Below the basics is the **Exposed tools** subsection — the curated-direct selections. Click
|
|
225
|
-
**+ expose** to add a row, and fill in:
|
|
226
|
-
|
|
227
|
-
- **tool** — the upstream tool's name (required for the row to count)
|
|
228
|
-
- **as** — optional rename for how it surfaces through the gateway (defaults to `<id>_<tool>`)
|
|
229
|
-
- **category** — optional grouping label
|
|
230
|
-
|
|
231
|
-
Add as many rows as you need (the **×** removes a row). On submit, ToolFunnel registers the
|
|
232
|
-
upstream first, then attaches each expose selection to it. Leave the expose rows empty to add the
|
|
233
|
-
upstream now and curate its tools later.
|
|
234
|
-
|
|
235
|
-
`id` and `command` are required; a duplicate or otherwise invalid upstream is rejected with an
|
|
236
|
-
error toast.
|
|
237
|
-
|
|
238
|
-
### Enable / disable and remove
|
|
239
|
-
|
|
240
|
-
The **Enabled** switch turns the whole upstream on or off. **Remove** deletes the upstream **and
|
|
241
|
-
cascades** — its exposed-tool entries go with it — behind a confirm. (Fine-grained editing of an
|
|
242
|
-
individual expose entry after creation isn't surfaced in the UI; use the management tools / CLI
|
|
243
|
-
for that. The badges on each expose row reflect its state read-only.)
|
|
244
|
-
|
|
245
|
-
---
|
|
246
|
-
|
|
247
|
-
## 4. Hooks tab
|
|
248
|
-
|
|
249
|
-
This tab manages lifecycle hooks in `hooks/hooks.manifest.json` (the enabled state is overlaid
|
|
250
|
-
from `hooks/hooks.state.json`).
|
|
251
|
-
|
|
252
|
-
### Search
|
|
253
|
-
|
|
254
|
-
Filters by **id, event, matcher, and description**.
|
|
255
|
-
|
|
256
|
-
### Each hook row
|
|
257
|
-
|
|
258
|
-
A row shows the hook **id** (monospace), its **event** chip, the **matcher** (or `* (all)` when
|
|
259
|
-
blank), and an optional description. There are two kinds of row:
|
|
260
|
-
|
|
261
|
-
- **Named hooks** (have an id) carry an **Enabled** switch and a **Remove** button.
|
|
262
|
-
- **Per-tool gates** (the Pre/Post gates created on the Tools tab) have no id, so they show as
|
|
263
|
-
`(tool gate)` with an **auto** badge and an enabled/disabled badge, plus a *"managed on Tools
|
|
264
|
-
tab"* note. They are **read-only here** — toggle them from the tool's Pre/Post switches.
|
|
265
|
-
|
|
266
|
-
### The two shipped example hooks
|
|
267
|
-
|
|
268
|
-
A fresh install ships **two example hooks, both disabled**, so this tab is never empty and you have
|
|
269
|
-
working policy to copy:
|
|
270
|
-
|
|
271
|
-
- `pre-tool-use/example-deny-dangerous` — a `PreToolUse` gate that **blocks** any call whose
|
|
272
|
-
arguments contain an obviously-destructive shell pattern (`rm -rf`, `mkfs`, drive `format`, fork
|
|
273
|
-
bomb). Script: `hooks/scripts/example-deny-dangerous.js`.
|
|
274
|
-
- `post-tool-use/example-audit` — a `PostToolUse` observer that runs *after* a tool executes
|
|
275
|
-
(advisory — it cannot un-run it) and receives the result on stdin; the stub just exits 0. Script:
|
|
276
|
-
`hooks/scripts/example-audit.js`.
|
|
277
|
-
|
|
278
|
-
They ship **disabled**, so the default install is still allow-all — nothing gates until you opt in.
|
|
279
|
-
**To enable one:** flip its **Enabled** switch here (or set `"enabled": true` in
|
|
280
|
-
`hooks/hooks.manifest.json`). Edit the script at the path above to encode your own policy. They are
|
|
281
|
-
deliberately illustrative, not a security baseline.
|
|
282
|
-
|
|
283
|
-
### Adding a hook
|
|
284
|
-
|
|
285
|
-
Click **+ Add hook**. Fields:
|
|
286
|
-
|
|
287
|
-
| Field | Notes |
|
|
288
|
-
|--------------|-------------------------------------------------------------------------|
|
|
289
|
-
| **id** * | Required, unique (e.g. `pre-tool-use/my-gate`). |
|
|
290
|
-
| **event** * | Dropdown of the six lifecycle events (see below). |
|
|
291
|
-
| **matcher** | Regex to match tool/gate names; **blank = matches all**. |
|
|
292
|
-
| **command** *| Required, e.g. `node "${HOOKS_DIR}/scripts/my-gate.js"`. |
|
|
293
|
-
| **script body** | Optional inline source, authored under `hooks/scripts/`. |
|
|
294
|
-
|
|
295
|
-
The **event** dropdown offers all six events, defaulting to `PreToolUse`:
|
|
296
|
-
|
|
297
|
-
`SessionStart` · `UserPromptSubmit` · `PreToolUse` · `PostToolUse` · `Stop` · `PreCompact`
|
|
298
|
-
|
|
299
|
-
Use the **matcher** to scope which tools a `PreToolUse`/`PostToolUse` gate fires for (e.g.
|
|
300
|
-
`Bash|Write`); leave it blank to fire for all. The **command** is what runs when the hook fires —
|
|
301
|
-
note the portable `${HOOKS_DIR}` token, which the loader expands to the real hooks directory at
|
|
302
|
-
load time, so the manifest stays machine-independent. If you paste a **script body** and the
|
|
303
|
-
command points at a `scripts/<file>`, that file is written under `hooks/scripts/` for you.
|
|
304
|
-
|
|
305
|
-
**Important:** a newly added hook is created **disabled** — the toast says so ("disabled — enable
|
|
306
|
-
it to fire"). Flip its **Enabled** switch when you're ready for it to run. This lets you stage a
|
|
307
|
-
hook (and write its script) before it goes live.
|
|
308
|
-
|
|
309
|
-
### Enable / disable and remove
|
|
310
|
-
|
|
311
|
-
The **Enabled** switch toggles the hook through the state overlay. **Remove** deletes the hook
|
|
312
|
-
entry from the manifest — note its **script file is left in place** on disk (so you can re-add or
|
|
313
|
-
reuse it). Both are guarded by the usual confirm on remove.
|
|
314
|
-
|
|
315
|
-
---
|
|
316
|
-
|
|
317
|
-
## 5. Logs tab
|
|
318
|
-
|
|
319
|
-
ToolFunnel can record an append-only JSONL activity log of tool runs and gate decisions. It is
|
|
320
|
-
**off by default**; this tab is the simplest place to turn it on and watch it.
|
|
321
|
-
|
|
322
|
-
### The on/off toggle
|
|
323
|
-
|
|
324
|
-
At the top of the tab is a switch bound to the logger config (`logs/log.config.json`):
|
|
325
|
-
|
|
326
|
-
- **Off** (default) — nothing is recorded. The status reads *"logging is off."*
|
|
327
|
-
- **On** — flip the switch and recording starts immediately; the status reads *"logging is on"*
|
|
328
|
-
and the resolved log file **path** is shown beside it.
|
|
329
|
-
|
|
330
|
-
This is the same setting controlled by `tf_log {action: enable|disable|status}` and the
|
|
331
|
-
`logs/log.config.json` file — flipping the switch here is identical to those.
|
|
332
|
-
|
|
333
|
-
### Viewing entries
|
|
334
|
-
|
|
335
|
-
The list shows the **most recent ~100 records, newest first**. Hit **Refresh** to reload both the
|
|
336
|
-
config and the latest entries (the log doesn't stream — refresh to pull new activity). Each entry
|
|
337
|
-
has a **type badge** that tells you which kind of record it is:
|
|
338
|
-
|
|
339
|
-
- **gate** — a Pre/Post hook decision. The status badge reads **allow** or **deny** (deny shown in
|
|
340
|
-
red), and the secondary line shows the **reason** when one was given.
|
|
341
|
-
- **tool** — a tool execution. The status badge reads **ok**, **fail**, or **blocked** (a blocked
|
|
342
|
-
run is one a `PreToolUse` gate stopped; fail and blocked show in red), and the secondary line
|
|
343
|
-
shows the execution **mode** and **duration in ms**.
|
|
344
|
-
- **config** — a configuration change made through this UI (e.g. a tool toggled, an upstream added,
|
|
345
|
-
OAuth enabled). The badge names the change `event`, and the secondary line shows the changed
|
|
346
|
-
fields. These let you audit *who changed the gateway's posture and when* — see
|
|
347
|
-
[`docs/logging.md`](logging.md).
|
|
348
|
-
- **auth** — an OAuth denial at the HTTP transport gate (a rejected token). The status badge reads
|
|
349
|
-
**deny**, and the secondary line shows the `error` and HTTP `status` (401/403).
|
|
350
|
-
|
|
351
|
-
All kinds also show the subject (tool/gate name, config event, or auth path) and a **timestamp**.
|
|
352
|
-
When the log is off and empty the tab prompts you to flip the switch; when it's on but nothing has
|
|
353
|
-
been recorded yet it says so.
|
|
354
|
-
|
|
355
|
-
---
|
|
356
|
-
|
|
357
|
-
## 6. Auth tab
|
|
358
|
-
|
|
359
|
-
This tab configures the **optional** OAuth 2.1 resource-server validation, stored in
|
|
360
|
-
`auth/auth.config.json`. ToolFunnel is loopback-only and unauthenticated by default; this tab is
|
|
361
|
-
where you turn on bearer-token validation for a networked or multi-user deployment. The full
|
|
362
|
-
reference — fields, security rationale, what is and isn't implemented — lives in
|
|
363
|
-
[`docs/oauth.md`](oauth.md); this is just the UI walk-through.
|
|
364
|
-
|
|
365
|
-
### Installing the one dependency
|
|
366
|
-
|
|
367
|
-
OAuth is the **only** feature that adds a dependency (`jose`, itself zero-dependency). The tab
|
|
368
|
-
reports whether it is present. If it isn't, an **Install OAuth dependency** button appears — click
|
|
369
|
-
it and the gateway installs the pinned `jose` on demand (`POST /api/oauth/install`). If the
|
|
370
|
-
auto-install can't complete (an unusual Node layout, no network), the toast surfaces a copyable
|
|
371
|
-
`npm install jose@<pin>` command to run yourself. Everyone who never enables OAuth pulls nothing.
|
|
372
|
-
|
|
373
|
-
### The config form
|
|
374
|
-
|
|
375
|
-
- **Enable OAuth 2.1 resource-server validation** — the master switch. Enabling it while the config
|
|
376
|
-
is incoherent, or while `jose` is absent, is refused with an explanatory toast (fail-fast — the
|
|
377
|
-
same guard the HTTP host applies at start).
|
|
378
|
-
- **issuer** — the authorization server tokens must come from (`iss`). Required when enabled.
|
|
379
|
-
- **audience** — *this gateway's* resource URI (`aud`). Required when enabled — without it tokens
|
|
380
|
-
are unbound (the confused-deputy hole).
|
|
381
|
-
- **jwksUri** — explicit JWKS endpoint; blank = discover it from the issuer.
|
|
382
|
-
- **algorithms**, **requiredScopes**, **clockToleranceSec** — the pinned algorithm allowlist,
|
|
383
|
-
optional required scopes, and clock-skew tolerance.
|
|
384
|
-
|
|
385
|
-
Saving writes `auth/auth.config.json` (`POST /api/auth/config`, atomic, read fresh per request — the
|
|
386
|
-
change is live, no restart). The config is **off by default**; a missing file reads as disabled.
|
|
387
|
-
|
|
388
|
-
---
|
|
389
|
-
|
|
390
|
-
## Summary
|
|
391
|
-
|
|
392
|
-
- The console is **optional** and **loopback-only**: `node bin/toolfunnel.js --ui` →
|
|
393
|
-
`http://127.0.0.1:9777`.
|
|
394
|
-
- Five tabs — **Tools / MCPs / Hooks / Logs / Auth** — each with live search (where it applies), a
|
|
395
|
-
collapsible add form, and per-row controls.
|
|
396
|
-
- Every edit writes the **same config files** the CLI and management functions use, atomically,
|
|
397
|
-
and the running gateway picks it up **with no restart**.
|
|
398
|
-
- Per-tool **execution mode** (reference ↔ gateway) and **Pre/Post gates** are toggled on the Tools
|
|
399
|
-
tab; those gates also appear (read-only) on the Hooks tab. **Details / edit** opens an inline
|
|
400
|
-
panel to view and change a tool's full entry (including its script body).
|
|
401
|
-
- The **activity log** is off by default — turn it on from the Logs tab to watch gate decisions,
|
|
402
|
-
tool runs, **config changes**, and **auth denials**.
|
|
403
|
-
- The **Auth** tab configures the optional OAuth 2.1 resource server (and installs its single
|
|
404
|
-
dependency on demand). See [`docs/oauth.md`](oauth.md).
|