dodo-mcp 1.0.6 → 1.2.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 +74 -20
- package/dist/cli/main.js +152 -28
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/menu.js +2 -2
- package/dist/cli/menu.js.map +1 -1
- package/dist/config/globalConfig.js +7 -3
- package/dist/config/globalConfig.js.map +1 -1
- package/dist/config/tunnelConfig.js +2 -1
- package/dist/config/tunnelConfig.js.map +1 -1
- package/dist/projects/ownerAdmin.js +86 -0
- package/dist/projects/ownerAdmin.js.map +1 -0
- package/dist/projects/registry.js +90 -9
- package/dist/projects/registry.js.map +1 -1
- package/dist/security/projectAccess.js +69 -0
- package/dist/security/projectAccess.js.map +1 -0
- package/dist/security/projectAuthority.js +5 -1
- package/dist/security/projectAuthority.js.map +1 -1
- package/dist/server/appServer.js +23 -9
- package/dist/server/appServer.js.map +1 -1
- package/dist/server/bootstrap.js +9 -1
- package/dist/server/bootstrap.js.map +1 -1
- package/dist/server/configUi/app.css +8 -0
- package/dist/server/configUi/app.js +142 -18
- package/dist/server/configUi/index.html +50 -13
- package/dist/server/installationRuntime.js +6 -2
- package/dist/server/installationRuntime.js.map +1 -1
- package/dist/server/instructions.js +1 -1
- package/dist/server/instructions.js.map +1 -1
- package/dist/server/ipcDispatch.js +3 -0
- package/dist/server/ipcDispatch.js.map +1 -1
- package/dist/server/localConfig.js +80 -13
- package/dist/server/localConfig.js.map +1 -1
- package/dist/services/ai/subagents.js +1 -1
- package/dist/services/ai/subagents.js.map +1 -1
- package/dist/services/android/adbBackend.js +106 -0
- package/dist/services/android/adbBackend.js.map +1 -0
- package/dist/services/android/androidPolicy.js +61 -0
- package/dist/services/android/androidPolicy.js.map +1 -0
- package/dist/services/android/androidService.js +444 -0
- package/dist/services/android/androidService.js.map +1 -0
- package/dist/services/android/protocol.js +39 -0
- package/dist/services/android/protocol.js.map +1 -0
- package/dist/services/multimodal/storage.js +10 -1
- package/dist/services/multimodal/storage.js.map +1 -1
- package/dist/services/schedules/scheduleService.js +8 -1
- package/dist/services/schedules/scheduleService.js.map +1 -1
- package/dist/setup/componentProbes.js +7 -1
- package/dist/setup/componentProbes.js.map +1 -1
- package/dist/setup/setup.js +11 -1
- package/dist/setup/setup.js.map +1 -1
- package/dist/store/db.js +14 -0
- package/dist/store/db.js.map +1 -1
- package/dist/tools/agentRuntimeTools.js +2 -3
- package/dist/tools/agentRuntimeTools.js.map +1 -1
- package/dist/tools/androidTools.js +113 -0
- package/dist/tools/androidTools.js.map +1 -0
- package/dist/tools/catalog.js +3 -0
- package/dist/tools/catalog.js.map +1 -1
- package/dist/tools/context.js +85 -5
- package/dist/tools/context.js.map +1 -1
- package/dist/tools/projectTools.js +1 -1
- package/dist/tools/projectTools.js.map +1 -1
- package/dist/tools/surface.js +18 -11
- package/dist/tools/surface.js.map +1 -1
- package/dist/tunnel/control.js +11 -4
- package/dist/tunnel/control.js.map +1 -1
- package/dist/tunnel/log.js +32 -0
- package/dist/tunnel/log.js.map +1 -1
- package/dist/tunnel/supervisor.js +103 -24
- package/dist/tunnel/supervisor.js.map +1 -1
- package/docs/ANDROID.md +105 -28
- package/docs/ARCHITECTURE.md +16 -7
- package/docs/AUTH.md +6 -0
- package/docs/COMPATIBILITY.md +14 -7
- package/docs/MANUAL_ACCEPTANCE.md +40 -6
- package/docs/PROJECTS.md +73 -2
- package/docs/RELEASE_1.1.0.md +69 -0
- package/docs/RELEASE_1.2.0.md +75 -0
- package/docs/RELEASE_NOTES.md +30 -0
- package/docs/SECURITY.md +45 -6
- package/docs/TEST_REPORT.md +96 -0
- package/docs/TUNNEL.md +79 -16
- package/docs/adr/048-persistent-connection-mode.md +3 -1
- package/docs/adr/049-android-adb-control.md +52 -0
- package/docs/adr/050-cloudflare-local-and-project-access.md +67 -0
- package/docs/adr/README.md +2 -0
- package/package.json +6 -2
- package/schemas/global-config.schema.json +1 -0
- package/schemas/tools.compact.json +312 -9
- package/schemas/tools.hybrid.json +485 -152
- package/schemas/tools.json +3610 -534
package/docs/TEST_REPORT.md
CHANGED
|
@@ -1,5 +1,51 @@
|
|
|
1
1
|
# DODO MCP — Test Report
|
|
2
2
|
|
|
3
|
+
## Release 1.2.0 — Cloudflare Local และ Simple Project Access
|
|
4
|
+
|
|
5
|
+
ผล candidate บน macOS arm64 วันที่ 2026-09-16:
|
|
6
|
+
|
|
7
|
+
- build: **AUTOMATED_PASS** — Complete Full 138, live Full default 134, Compact 20,
|
|
8
|
+
Hybrid 49 และ config schemas 2 ชุด
|
|
9
|
+
- typecheck/lint: **AUTOMATED_PASS**
|
|
10
|
+
- core/integration/security/compatibility: **AUTOMATED_PASS** — 726 passed /
|
|
11
|
+
35 skipped / 0 failed ใน 107 ไฟล์ที่ผ่านและ 3 ไฟล์ที่ skip
|
|
12
|
+
- packaging: **AUTOMATED_PASS** — 16/16 รวม release document, ADR, generated UI
|
|
13
|
+
assets และ fresh tarball checks ตาม manifest
|
|
14
|
+
- focused connection/project/OAuth/security/Chromium: **AUTOMATED_PASS** — 92 passed,
|
|
15
|
+
1 skipped, 0 failed; ทดสอบสาม connection modes, write-only credential boundary,
|
|
16
|
+
Remote Config ผ่าน owner-managed public mode, per-project `read/edit/full`,
|
|
17
|
+
project-name routing และ real browser UI
|
|
18
|
+
- production dependency audit: **AUTOMATED_PASS** — 0 vulnerabilities
|
|
19
|
+
- Cloudflare Local ผ่าน public hostname/process จริงของเจ้าของ: **MANUAL_NOT_RUN**
|
|
20
|
+
- DODO Tunnel credential store/readiness ผ่าน public hostname จริงของ 1.2.0:
|
|
21
|
+
**MANUAL_NOT_RUN**
|
|
22
|
+
|
|
23
|
+
Regression รอบแรกพบ security fixture คาด marker `Project Registry` ที่หายจากหัวข้อไทย
|
|
24
|
+
จึงคืน marker ใน UI แล้วรัน focused และ full suite ใหม่จนผ่าน ไม่ได้ลด assertion
|
|
25
|
+
หรือ security requirement
|
|
26
|
+
|
|
27
|
+
## Release 1.1.0 — Android ADB tool family
|
|
28
|
+
|
|
29
|
+
ผล candidate บน macOS วันที่ 2026-09-16:
|
|
30
|
+
|
|
31
|
+
- build: **AUTOMATED_PASS** — Complete Full 138, live Full default 134, Compact 20,
|
|
32
|
+
Hybrid 49 และ config schemas 2 ชุด
|
|
33
|
+
- typecheck/lint: **AUTOMATED_PASS**
|
|
34
|
+
- core/integration/security/compatibility: **AUTOMATED_PASS** — 698 passed /
|
|
35
|
+
35 skipped / 0 failed ใน 103 ไฟล์ที่ผ่านและ 3 ไฟล์ที่ skip
|
|
36
|
+
- packaging: **AUTOMATED_PASS** — 16/16
|
|
37
|
+
- Android focused: **AUTOMATED_PASS** — parser/PNG/UI redaction, exact serial,
|
|
38
|
+
OAuth scope, compact image passthrough, approval binding, idempotency, secret/path
|
|
39
|
+
guards, expected-hash conflict, private staging cleanup, Local Config owner auth,
|
|
40
|
+
real HTTP+OAuth dispatch ของทั้ง 13 operation families และ Chromium UI
|
|
41
|
+
- production dependency audit: **AUTOMATED_PASS** — 0 vulnerabilities
|
|
42
|
+
- physical Android hardware/emulator: **MANUAL_NOT_RUN**
|
|
43
|
+
- Android/Termux host acceptance: **MANUAL_NOT_RUN**
|
|
44
|
+
|
|
45
|
+
Automated ADB ใช้ backend fixture ที่บันทึก argv/ผลลัพธ์จริงของ invocation pipeline
|
|
46
|
+
โดยไม่แตะอุปกรณ์เจ้าของ จึงพิสูจน์ routing/security/content-block contract แต่ไม่แทน
|
|
47
|
+
USB/Wireless debugging, RSA prompt, OEM Android behavior หรือ real device permission
|
|
48
|
+
|
|
3
49
|
## Release 1.0.6 — Android-safe Sharp loading
|
|
4
50
|
|
|
5
51
|
ผล macOS วันที่ 2026-09-16:
|
|
@@ -74,6 +120,56 @@ Hybrid 49 tools; `npm run test:all` ผ่าน core/security/compatibility 99
|
|
|
74
120
|
Live Cloudflare hostname และ OS credential store ด้วย credential ของเจ้าของสำหรับ source
|
|
75
121
|
นี้: **MANUAL_NOT_RUN** — ไม่ถือว่า fixture cloudflared เป็นหลักฐานของ public network จริง
|
|
76
122
|
|
|
123
|
+
## Pre-release project access, project names and tunnel readiness — 2026-09-16
|
|
124
|
+
|
|
125
|
+
หลักฐานชุดนี้สร้างก่อนรวมเข้า 1.2.0 งานรอบนี้: Simple Project Access Policy (read/edit/full),
|
|
126
|
+
เรียกโปรเจกต์ด้วยชื่อ (`targetProject`), แก้ข้อความที่บังคับ ACL ในโหมดส่วนตัว และแก้
|
|
127
|
+
Cloudflare readiness ที่สถานะกระพริบ
|
|
128
|
+
|
|
129
|
+
**รันจริงบน macOS arm64, Node v22.23.2:**
|
|
130
|
+
|
|
131
|
+
- `npm run typecheck` / `npm run lint` / `npm run build` — **AUTOMATED_PASS** (exit 0)
|
|
132
|
+
- `npm run test:all` — **AUTOMATED_PASS**: 705 passed / 34 skipped / 0 failed (106 ไฟล์)
|
|
133
|
+
+ packaging 16/16
|
|
134
|
+
- `npx vitest run tests/security/projectAccessLevel.test.ts` (ใหม่, 11 ข้อ) —
|
|
135
|
+
**AUTOMATED_PASS**: mapping ระดับ→scope, `full` token ถูกบีบตามระดับ, token `read`
|
|
136
|
+
เขียน/exec ไม่ได้แม้โปรเจกต์ `full`, managed mode ยังต้องมี ACL แล้วระดับบีบซ้ำ,
|
|
137
|
+
workspace ที่ไม่ได้ลงทะเบียนไม่ถูกบีบ, ค่าที่อ่านไม่ออก → `read` (fail closed),
|
|
138
|
+
row เก่า migrate เป็น `full` (ไม่ถอนสิทธิ์), ระดับผิด → ไม่มีโปรเจกต์ค้าง,
|
|
139
|
+
ชื่อซ้ำถูกปฏิเสธแบบไม่สนตัวพิมพ์, resolve ชื่อ/ชื่อกำกวม/ชื่อไม่รู้จัก
|
|
140
|
+
- `npx vitest run tests/integration/projectByName.test.ts` (ใหม่) — **AUTOMATED_PASS**
|
|
141
|
+
ผ่าน HTTP + OAuth จริง: route ด้วยชื่อ, เขียนลงโปรเจกต์ถูกตัว, ตัวพิมพ์/ช่องว่างไม่สำคัญ,
|
|
142
|
+
ระดับ `edit` บล็อก exec แล้วยกเป็น `full` ทำได้, ชื่อไม่รู้จัก → NOT_FOUND,
|
|
143
|
+
id+ชื่อขัดกัน → INVALID_INPUT, ชื่อกำกวม → CONFLICT พร้อม candidate,
|
|
144
|
+
`targetProject` ใน nested args ถูกปฏิเสธและไม่มีไฟล์ถูกเขียน
|
|
145
|
+
- `npx vitest run tests/unit/tunnelReadiness.test.ts` (ใหม่, 8 ข้อ) — **AUTOMATED_PASS**:
|
|
146
|
+
probe 200/503/ปิด/ค้าง, ไม่ใช้ socket ซ้ำ (นับ connection = 2), schema รองรับทุก phase,
|
|
147
|
+
state.json รุ่นเก่า parse ได้, ปฏิเสธ field แปลกปลอม
|
|
148
|
+
- `npx vitest run tests/integration/tunnelSupervisor.test.ts` (เพิ่ม 3 ข้อ) —
|
|
149
|
+
**AUTOMATED_PASS** ด้วย fake cloudflared จริง: readiness ตกชั่วคราว → `degraded`
|
|
150
|
+
และ `connected` ยังเป็น true, ไม่มีบรรทัด "is not connected"; ล้มติดกันครบเกณฑ์ →
|
|
151
|
+
`disconnected` แล้ว recover กลับ `connected`; ไม่เคยรายงาน connected โดยไม่มีหลักฐาน
|
|
152
|
+
- `npx vitest run tests/integration/projectAccessUi.test.ts` (ใหม่, 2 ข้อ) —
|
|
153
|
+
**AUTOMATED_PASS** ใน Chromium จริง: เพิ่มโปรเจกต์ครบในหน้าเดียว (path/ชื่อ/ระดับ),
|
|
154
|
+
การ์ดแสดงระดับที่ backend เก็บจริง, เปลี่ยนระดับแล้วยืนยันหลัง backend ตอบ,
|
|
155
|
+
reload ยังเห็นค่าเดิม, ชื่อซ้ำขึ้น error (ไม่ขึ้น success), personal ซ่อนฟอร์ม ACL /
|
|
156
|
+
managed แสดงครบ, 390px ไม่มี horizontal scroll, `pageerror` = 0
|
|
157
|
+
- `npm run test:linux:docker` — **AUTOMATED_PASS** (node v22.23.2, arm64, Chromium)
|
|
158
|
+
- `npm pack` + fresh install จาก tarball — **AUTOMATED_PASS**: 461 ไฟล์, ไม่มี
|
|
159
|
+
state.db/.env/jwks/.sock, `dist/projects/ownerAdmin.js` และ
|
|
160
|
+
`dist/security/projectAccess.js` อยู่ในแพ็กเกจ, และรัน
|
|
161
|
+
`dodo project add --access read` → `dodo project access "auto-upload" --mode full`
|
|
162
|
+
→ `dodo project list` ได้จริงจาก tarball ที่ติดตั้งสด
|
|
163
|
+
- `npm run test:windows` บน macOS — 56 passed / 30 skipped: **ไม่ใช่หลักฐาน Windows**
|
|
164
|
+
(ข้อที่เป็น Windows-only ถูก skip)
|
|
165
|
+
|
|
166
|
+
**MANUAL_NOT_RUN** (ยังไม่มีหลักฐาน):
|
|
167
|
+
- Windows native (windows-ci-02) — ยังไม่ได้รัน รอบนี้แก้สาเหตุที่เป็น Windows-specific
|
|
168
|
+
ไว้แล้ว (event-loop starvation จากการเขียน log, keep-alive socket) แต่ยังไม่มีหลักฐานจริง
|
|
169
|
+
- การยืนยันบน tunnel จริง `https://mcp.baanseriesnow.com/mcp` กับ cloudflared จริง
|
|
170
|
+
(เทสต์ใช้ fake cloudflared ที่ควบคุม `/ready` ได้)
|
|
171
|
+
- การอัปเกรดจาก state ของ 1.0.2/1.0.3 จริง (migration ตรวจด้วย fixture เท่านั้น)
|
|
172
|
+
|
|
77
173
|
## Scope
|
|
78
174
|
|
|
79
175
|
รายงานนี้ใช้กับ DODO MCP 1.0.3 source และแยกผล automated กับ manual อย่างชัดเจน
|
package/docs/TUNNEL.md
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
# DODO MCP — Local และ
|
|
1
|
+
# DODO MCP — Loopback, Cloudflare Local และ DODO Tunnel
|
|
2
2
|
|
|
3
3
|
DODO มีโหมดเชื่อมต่อระดับ installation เพียงหนึ่งโหมดในแต่ละเวลา:
|
|
4
4
|
|
|
5
|
-
- `local` — ใช้ MCP ที่
|
|
5
|
+
- `local` — **เฉพาะเครื่อง (Loopback)** ใช้ MCP ที่
|
|
6
|
+
`http://127.0.0.1:21730/mcp` และไม่ใช้ Cloudflare
|
|
7
|
+
- `external` — **Cloudflare Local (ติดตั้งในเครื่อง)** เจ้าของติดตั้งและรัน `cloudflared` เอง
|
|
8
|
+
DODO advertise public HTTPS origin แต่ไม่รับ token และไม่เริ่ม/หยุด process
|
|
6
9
|
- `tunnel` — ใช้ public HTTPS origin เป็น MCP URL หลัก และ DODO เริ่ม/หยุด
|
|
7
10
|
`cloudflared` ของตัวเองพร้อมทุก `dodo start`
|
|
8
11
|
|
|
@@ -14,7 +17,7 @@ DODO มีโหมดเชื่อมต่อระดับ installation
|
|
|
14
17
|
|
|
15
18
|
| บริการ | ค่าเริ่มต้น | การเปิดเผย |
|
|
16
19
|
|---|---:|---|
|
|
17
|
-
| MCP + OAuth upstream | `127.0.0.1:21730` |
|
|
20
|
+
| MCP + OAuth upstream | `127.0.0.1:21730` | bind loopback เสมอ; Cloudflare ทั้งสองโหมด route มาที่พอร์ตนี้ |
|
|
18
21
|
| Local Config | `127.0.0.1:21731` | Loopback เท่านั้นเสมอ |
|
|
19
22
|
| Tunnel readiness/metrics | `127.0.0.1:21732` | Loopback เท่านั้นเสมอ |
|
|
20
23
|
|
|
@@ -22,14 +25,14 @@ Cloudflare public hostname ต้อง route **ทุก path** มาที่
|
|
|
22
25
|
`http://127.0.0.1:21730` เพื่อให้ health, OAuth discovery, authorization และ `/mcp`
|
|
23
26
|
ทำงานครบ ห้าม route พอร์ต 21731, 21732, private IPC หรือ debug endpoint ออก public
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
แต่ DODO จะ advertise public HTTPS URL เป็น endpoint ที่มีผล ส่วน Local Config ยังคง
|
|
28
|
+
โหมด Cloudflare ทั้งสองแบบยังต้องมี listener 21730 เป็น private upstream ให้
|
|
29
|
+
`cloudflared` แต่ DODO จะ advertise public HTTPS URL เป็น endpoint ที่มีผล ส่วน Local Config ยังคง
|
|
27
30
|
เข้าผ่าน loopback ยกเว้น bounded `/config` lease ที่เจ้าของเปิดชั่วคราวเอง
|
|
28
31
|
|
|
29
|
-
##
|
|
32
|
+
## เลือกเฉพาะเครื่อง (Loopback)
|
|
30
33
|
|
|
31
34
|
```bash
|
|
32
|
-
dodo tunnel configure --
|
|
35
|
+
dodo tunnel configure --loopback
|
|
33
36
|
dodo start
|
|
34
37
|
```
|
|
35
38
|
|
|
@@ -39,9 +42,30 @@ dodo start
|
|
|
39
42
|
dodo tunnel status
|
|
40
43
|
```
|
|
41
44
|
|
|
42
|
-
|
|
45
|
+
Loopback mode ไม่ใช้ public origin และไม่เริ่ม Tunnel หากต้องการกลับไป Cloudflare ต้องเลือก
|
|
43
46
|
ใหม่อย่างชัดเจนด้วยคำสั่งหรือหน้า Local Config แล้ว restart DODO
|
|
44
47
|
|
|
48
|
+
`--local` ยังเป็น alias เดิมของ `--loopback` เพื่อไม่ทำให้สคริปต์เก่าตีความต่างไป
|
|
49
|
+
|
|
50
|
+
## เลือก Cloudflare Local (ติดตั้งในเครื่อง)
|
|
51
|
+
|
|
52
|
+
โหมดนี้ใช้เมื่อผู้ใช้ติดตั้งและรัน `cloudflared` เอง เช่นผ่าน terminal, launchd,
|
|
53
|
+
systemd หรือ Windows Service DODO ไม่ขอ Tunnel token และไม่อ้างว่า process เชื่อมต่อแล้ว
|
|
54
|
+
เพียงเพราะบันทึก public URL
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
dodo tunnel configure \
|
|
58
|
+
--cloudflare-local \
|
|
59
|
+
--public-url https://mcp.example.com
|
|
60
|
+
|
|
61
|
+
# รัน cloudflared ด้วยวิธีที่ผู้ใช้จัดการเอง แล้วจึงเปิด DODO
|
|
62
|
+
dodo start
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Cloudflare ต้อง route ทุก path ไป `http://127.0.0.1:21730` เช่นเดียวกับ DODO Tunnel
|
|
66
|
+
ตรวจปลายทางจริงด้วย `dodo tunnel doctor` ค่า public health ที่ผ่านยืนยันเพียงว่า origin
|
|
67
|
+
ตอบ DODO health ไม่ได้ยืนยันว่ามี AI client เชื่อมอยู่
|
|
68
|
+
|
|
45
69
|
## เลือก DODO Tunnel
|
|
46
70
|
|
|
47
71
|
เจ้าของต้องสร้าง remotely-managed Tunnel, public hostname และ DNS ใน Cloudflare ก่อน
|
|
@@ -89,16 +113,17 @@ CLI argument, config JSON, log, audit, MCP response, browser storage หรื
|
|
|
89
113
|
**การเชื่อมต่อ MCP**:
|
|
90
114
|
|
|
91
115
|
1. ตั้ง Public origin เป็น HTTPS origin ของ Tunnel
|
|
92
|
-
2. เลือก `DODO Tunnel`
|
|
93
|
-
|
|
116
|
+
2. เลือก `Cloudflare Local (ติดตั้งในเครื่อง)` หากจะรัน cloudflared เอง หรือ `DODO Tunnel` หากให้
|
|
117
|
+
DODO ดูแล process
|
|
118
|
+
3. ใส่ Cloudflare Tunnel token เฉพาะ `DODO Tunnel`
|
|
94
119
|
4. กดบันทึกและ restart DODO
|
|
95
120
|
|
|
96
|
-
หรือเลือก `
|
|
121
|
+
หรือเลือก `เฉพาะเครื่อง (Loopback)` แล้วบันทึกและ restart ค่าในหน้าเว็บไม่เปลี่ยน endpoint ของ process
|
|
97
122
|
ที่กำลังรันอยู่ทันที หน้าเว็บจะแสดงสถานะ restart ที่ตรงกับ runtime จริง
|
|
98
123
|
|
|
99
124
|
## Remote Config ไม่เกินหนึ่งชั่วโมง
|
|
100
125
|
|
|
101
|
-
Remote Config
|
|
126
|
+
Remote Config ใช้ได้เมื่อเลือก Cloudflare Local (ติดตั้งในเครื่อง) หรือ DODO Tunnel:
|
|
102
127
|
|
|
103
128
|
```bash
|
|
104
129
|
dodo --web
|
|
@@ -109,6 +134,9 @@ dodo web --status
|
|
|
109
134
|
dodo web --close
|
|
110
135
|
```
|
|
111
136
|
|
|
137
|
+
ในโหมด Cloudflare Local (ติดตั้งในเครื่อง) เจ้าของต้องรัน tunnel และ route ครบเอง ส่วน DODO Tunnel
|
|
138
|
+
จะตรวจว่า supervisor ที่ DODO เป็นเจ้าของกำลังรันก่อนเปิด lease
|
|
139
|
+
|
|
112
140
|
`/config` ตอบ 404 ตามค่าเริ่มต้น คำสั่ง `dodo --web` เปิดหรือเปลี่ยน lease ผ่าน
|
|
113
141
|
authenticated private IPC โดยไม่ restart MCP และไม่รับ Tunnel token ผ่าน IPC URL ไม่มี
|
|
114
142
|
query/fragment secret Pairing code มีอายุสั้นและใช้ได้ครั้งเดียว หลังจับคู่ browser ได้
|
|
@@ -128,10 +156,45 @@ dodo tunnel logs --lines 100
|
|
|
128
156
|
dodo tunnel stop
|
|
129
157
|
```
|
|
130
158
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
159
|
+
### สถานะของ Tunnel (state machine)
|
|
160
|
+
|
|
161
|
+
`phase` ของ supervisor มีค่าเหล่านี้ และเปลี่ยนตามหลักฐานจริงเท่านั้น:
|
|
162
|
+
|
|
163
|
+
| phase | ความหมาย |
|
|
164
|
+
|---|---|
|
|
165
|
+
| `starting` | supervisor เริ่มทำงาน ยังไม่ spawn cloudflared |
|
|
166
|
+
| `connecting` | cloudflared รันแล้ว แต่ยัง **ไม่เคย** มีหลักฐาน readiness |
|
|
167
|
+
| `connected` | `/ready` ตอบ 200 — ต้องมีหลักฐานจริงเท่านั้นจึงแสดงสถานะนี้ |
|
|
168
|
+
| `degraded` | เคย connected แล้ว probe เริ่มล้ม แต่ยังไม่ถึงเกณฑ์ (กำลัง reconnect) |
|
|
169
|
+
| `disconnected` | probe ล้มติดกันครบเกณฑ์ หรือ cloudflared exit |
|
|
170
|
+
| `backoff` | รอ restart แบบมีขอบเขต |
|
|
171
|
+
| `stopping` / `stopped` / `failed` | เจ้าของสั่งหยุด / หยุดแล้ว / restart หมดโควตา |
|
|
172
|
+
|
|
173
|
+
สถานะยังมี `lastReadyAt`, `lastFailureAt` และ `consecutiveReadyFailures` เพื่อให้ดูได้ว่า
|
|
174
|
+
readiness สำเร็จครั้งสุดท้ายเมื่อไร
|
|
175
|
+
|
|
176
|
+
**ทำไมเมื่อก่อนสถานะกระพริบ** — เดิม probe ทุก 1 วินาทีโดย timeout 1.5 วินาที
|
|
177
|
+
จึงซ้อนกันได้ ผลเก่าเขียนทับผลใหม่ และ probe ที่ล้ม **ครั้งเดียว** ก็พลิกสถานะและพิมพ์
|
|
178
|
+
`readiness endpoint is not connected` ทันที ตอนนี้:
|
|
179
|
+
|
|
180
|
+
- probe ทำทีละครั้ง ไม่ซ้อนกัน และมี generation fence ผลจาก child เก่าถูกทิ้ง
|
|
181
|
+
- ต้องล้มติดกันครบเกณฑ์จึงจะเป็น `disconnected` — ล้มครั้งเดียวเป็นแค่ `degraded`
|
|
182
|
+
และ `connected` ยังเป็น true เพื่อไม่ให้ UI กระพริบ
|
|
183
|
+
- ใช้ socket ใหม่ทุกครั้ง (`agent: false`) กัน keep-alive socket ที่ถูกปิดแล้ว
|
|
184
|
+
กลายเป็น error ปลอม
|
|
185
|
+
- เขียน log ของ cloudflared แบบรวมกลุ่ม ไม่เขียนทับไฟล์ 512 KiB ทุกบรรทัด
|
|
186
|
+
(บน Windows การ retry rename ใช้ `Atomics.wait` ซึ่งบล็อก event loop จน probe timeout)
|
|
187
|
+
- cloudflared exit → `disconnected` ทันที, restart มีขอบเขตตาม `maxRestarts` เสมอ
|
|
188
|
+
- ไม่มี fallback เงียบ ๆ จาก tunnel ไป local และ token ไม่ปรากฏใน log หรือ error
|
|
189
|
+
|
|
190
|
+
Tunnel เป็นระดับ installation รองรับทุกโปรเจกต์ การเพิ่มหรือเลือกโปรเจกต์ไม่ restart tunnel
|
|
191
|
+
|
|
192
|
+
`status` ไม่อ่าน credential ส่วน `doctor` ตรวจ executable, local health และ public
|
|
193
|
+
health ทุกโหมด แต่ตรวจ credential/supervisor readiness เฉพาะ DODO Tunnel ใน
|
|
194
|
+
Cloudflare Local รายงาน process ownership เป็น `owner` และไม่ควบคุม process Public
|
|
195
|
+
health ที่ผ่านพิสูจน์เพียงว่า origin ตอบ DODO health ไม่ได้พิสูจน์ว่า AI client
|
|
196
|
+
เชื่อมต่อแล้ว `stop` ส่งสัญญาณเฉพาะ live child handle ที่ DODO supervisor ปัจจุบัน
|
|
197
|
+
สร้าง ไม่ค้นหรือ kill process ตามชื่อ/PID เก่า
|
|
135
198
|
|
|
136
199
|
## ตั้งค่า MCP client
|
|
137
200
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# ADR-049 — Owner-approved Android control through ADB
|
|
2
|
+
|
|
3
|
+
## Decision
|
|
4
|
+
|
|
5
|
+
DODO exposes a bounded Android capability family through an `AndroidService`. The
|
|
6
|
+
native backend invokes a reviewed `adb` executable with `shell:false` and an exact
|
|
7
|
+
owner-approved device serial. Full surface has individual `android_*` operations;
|
|
8
|
+
Compact uses one `dodo_mobile` gateway so the Compact catalog remains at 20 tools.
|
|
9
|
+
|
|
10
|
+
The local owner chooses `off`, `view`, or `control` and an exact serial allowlist.
|
|
11
|
+
A temporary grant is bound to one workspace identity and epoch. A persistent grant
|
|
12
|
+
belongs to the installation and survives project switches until the owner disables it.
|
|
13
|
+
Neither kind grants OAuth scopes, project access, trust, an action approval, or a
|
|
14
|
+
sandbox exception.
|
|
15
|
+
|
|
16
|
+
Pairing, connecting, root mode, ADB server management and port forwarding remain
|
|
17
|
+
owner actions outside the MCP catalog. The advanced operation accepts only
|
|
18
|
+
device-side shell/exec-out/logcat/state/features command families. Dedicated install
|
|
19
|
+
and push operations require a workspace source, shared path/secret/link checks and an
|
|
20
|
+
expected SHA-256. They pass an immutable private staging copy to ADB and remove it
|
|
21
|
+
after the command.
|
|
22
|
+
|
|
23
|
+
Every effectful operation uses the shared invocation and idempotency pipeline. Screen
|
|
24
|
+
input consumes a fresh principal-bound snapshot. Output, time and concurrency are
|
|
25
|
+
bounded; one serial is process-wide serialized across project runtimes so concurrent
|
|
26
|
+
agents cannot interleave device commands. Device output is untrusted content. Audit stores operation metadata and
|
|
27
|
+
digests, never screenshots, UI text, logs or file bytes.
|
|
28
|
+
|
|
29
|
+
## Why
|
|
30
|
+
|
|
31
|
+
ADB offers one portable control plane for physical devices and emulators on macOS,
|
|
32
|
+
Linux, Windows and Termux. Exact device consent prevents a connected phone from
|
|
33
|
+
becoming available merely because the executable exists. Reusing the normal DODO
|
|
34
|
+
scope, workspace and approval checks keeps mobile automation from becoming a second
|
|
35
|
+
authorization system.
|
|
36
|
+
|
|
37
|
+
## Consequences
|
|
38
|
+
|
|
39
|
+
- `dodo:exec` is required even for device observation because connected-device state
|
|
40
|
+
is private host information.
|
|
41
|
+
- ADB runs with the Android shell user's effective permissions and is not a device
|
|
42
|
+
sandbox. Owners must review `control` grants accordingly.
|
|
43
|
+
- Operations whose outcome becomes uncertain are not silently retried.
|
|
44
|
+
- Android/Termux as the DODO host remains experimental independently of the ADB tool
|
|
45
|
+
family.
|
|
46
|
+
|
|
47
|
+
## Evidence
|
|
48
|
+
|
|
49
|
+
- `tests/unit/androidAdb.test.ts`
|
|
50
|
+
- `tests/security/androidAdb.test.ts`
|
|
51
|
+
- `tests/integration/androidAdb.test.ts`
|
|
52
|
+
- generated Full/Compact/Hybrid schema consistency and packaging gates
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# ADR-050 — Cloudflare Local mode and visible per-project access
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted for DODO 1.2.0. This extends ADR-048; its credential isolation and
|
|
6
|
+
DODO-owned supervisor rules remain in force.
|
|
7
|
+
|
|
8
|
+
## Context
|
|
9
|
+
|
|
10
|
+
The owner UI used the label “Local” for loopback-only MCP. Owners also use the word
|
|
11
|
+
local for a `cloudflared` binary installed and managed on the same machine, so the
|
|
12
|
+
two-process ownership models were easy to confuse. The personal access UI also hid
|
|
13
|
+
the detailed Trust and Client ACL cards without replacing them with a visible,
|
|
14
|
+
simple project-level control. Authority still existed, but owners could not see or
|
|
15
|
+
change the intended project ceiling from the Projects page.
|
|
16
|
+
|
|
17
|
+
## Decision
|
|
18
|
+
|
|
19
|
+
DODO exposes three mutually exclusive installation connection modes:
|
|
20
|
+
|
|
21
|
+
- `local`: loopback-only MCP; no Cloudflare process or public origin is used.
|
|
22
|
+
- `external`: **Cloudflare Local**; the owner installs, starts and stops
|
|
23
|
+
`cloudflared`. DODO advertises the reviewed public HTTPS origin but never accepts
|
|
24
|
+
a Tunnel token and never supervises that process.
|
|
25
|
+
- `tunnel`: **DODO Tunnel**; DODO reads a credential through the reviewed credential
|
|
26
|
+
provider, starts one owned child, waits for readiness and stops that child.
|
|
27
|
+
|
|
28
|
+
The UI never uses “Local” by itself. It labels the choices “เฉพาะเครื่อง (Loopback)”,
|
|
29
|
+
“Cloudflare Local (ติดตั้งในเครื่อง)” and “DODO Tunnel”. `--local` remains a
|
|
30
|
+
deprecated loopback alias because changing an old flag to a public mode would be an
|
|
31
|
+
unsafe compatibility break; new commands are `--loopback` and
|
|
32
|
+
`--cloudflare-local`.
|
|
33
|
+
|
|
34
|
+
Every registered project has one visible access ceiling: `read`, `edit` or `full`.
|
|
35
|
+
The Projects page displays and saves it in both personal and managed installations.
|
|
36
|
+
In personal mode this replaces repeated Trust/Client ACL configuration; in managed
|
|
37
|
+
mode the existing per-client ACL remains required. Effective authority is always:
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
token scopes ∩ live grant scopes ∩ managed ACL (when enabled) ∩ project access ceiling
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The ceiling cannot grant a missing OAuth scope and does not bypass workspace
|
|
44
|
+
identity/epoch, approval, sandbox, path/secret guards, expected hashes, idempotency
|
|
45
|
+
or audit.
|
|
46
|
+
|
|
47
|
+
## Consequences
|
|
48
|
+
|
|
49
|
+
- Saving Cloudflare Local never reads, writes or validates a DODO Tunnel token.
|
|
50
|
+
- Remote Config can use either public Cloudflare mode; external mode depends on the
|
|
51
|
+
owner-managed route, while tunnel mode additionally requires the owned supervisor.
|
|
52
|
+
- Existing `local` config remains loopback-only. Legacy external config migrates to
|
|
53
|
+
the explicit `external` mode.
|
|
54
|
+
- Existing project rows migrate to `full` so the upgrade does not silently revoke
|
|
55
|
+
authority. Invalid stored levels fail closed to `read`.
|
|
56
|
+
- Connection-mode and project-access changes require no repository configuration and
|
|
57
|
+
expose no owner operation through MCP.
|
|
58
|
+
|
|
59
|
+
## Evidence
|
|
60
|
+
|
|
61
|
+
- `tests/integration/connectionMode.test.ts`
|
|
62
|
+
- `tests/integration/configUiComponents.test.ts`
|
|
63
|
+
- `tests/security/tunnelCredentials.test.ts`
|
|
64
|
+
- `tests/security/remoteConfig.test.ts`
|
|
65
|
+
- `tests/integration/projectAccessUi.test.ts`
|
|
66
|
+
- `tests/integration/projectByName.test.ts`
|
|
67
|
+
- `tests/security/projectAccessLevel.test.ts`
|
package/docs/adr/README.md
CHANGED
|
@@ -64,3 +64,5 @@ decisions; ADR-011+ resolve implementation ambiguities without reducing security
|
|
|
64
64
|
- [046 — Personal add-and-use mode](046-personal-access-mode.md)
|
|
65
65
|
- [047 — Temporary Remote Config on the tunneled listener](047-temporary-remote-config.md)
|
|
66
66
|
- [048 — Persistent exclusive Local/Tunnel connection mode](048-persistent-connection-mode.md)
|
|
67
|
+
- [049 — Owner-approved Android control through ADB](049-android-adb-control.md)
|
|
68
|
+
- [050 — Cloudflare Local mode and visible per-project access](050-cloudflare-local-and-project-access.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dodo-mcp",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"author": "Arthittakun",
|
|
5
5
|
"description": "DODO — local-first MCP server with multi-project coding, AI providers, sub-agents, context, memory, media and workflow tools; embedded OAuth and workspace permissions.",
|
|
6
6
|
"type": "module",
|
|
@@ -46,6 +46,8 @@
|
|
|
46
46
|
"docs/RELEASE_1.0.4.md",
|
|
47
47
|
"docs/RELEASE_1.0.5.md",
|
|
48
48
|
"docs/RELEASE_1.0.6.md",
|
|
49
|
+
"docs/RELEASE_1.1.0.md",
|
|
50
|
+
"docs/RELEASE_1.2.0.md",
|
|
49
51
|
"docs/RELEASE_NOTES.md",
|
|
50
52
|
"docs/SCHEDULES.md",
|
|
51
53
|
"docs/SECURITY.md",
|
|
@@ -140,7 +142,9 @@
|
|
|
140
142
|
"browser-automation",
|
|
141
143
|
"video",
|
|
142
144
|
"speech-to-text",
|
|
143
|
-
"workflow"
|
|
145
|
+
"workflow",
|
|
146
|
+
"android",
|
|
147
|
+
"adb"
|
|
144
148
|
],
|
|
145
149
|
"repository": {
|
|
146
150
|
"type": "git",
|