dot-mcp
Single-file MCP agent แบบ dots สำหรับ Termux / Linux — shell + files + memory + goals + inbox + scheduler ในไฟล์เดียว (dot_mcp.py)
⚠️ URL สะอาด (
/mcp/) — auth เป็น Bearer 2 แบบ: JWT จาก OAuth (ให้ ChatGPT/Claude/Gemini) หรือ secret เดิมใน header (ให้สคริปต์ local) ไม่มี header = 401 แม้ localhost
Endpoint: http://127.0.0.1:33041/mcp/ · Health: /health
Features
- Shell:
run_command(background session + timeout) +read_output - Files:
list_dir,read_file(paginated + sha256),write_file(atomic + sha guard),append_file,edit_file(unique-match) - Memory:
remember,recall,forget— จำข้ามแชท (~/.dot-mcp/memory.json) - Goals/Tasks:
set_goal,add_update,get_state,add_task,complete_task - Inbox (ข้ามแชท):
notify_user,poll_inbox,ack_inbox - Scheduler:
add_schedule,list_schedules,remove_schedule— งานประจำรันเองตอนไม่มีแชท ผลเข้า inbox - Embedded UI:
open_workspace— MCP Apps dashboard สไตล์ Codex แสดง tasks, memory, command sessions และ schedules - รวม 22 tools
Quickstart
ติดตั้งจาก PyPI:
pip install dot-mcp
dot-mcp start # server + tunnel + public URL (port 33041, secret ประจำเครื่อง)
dot-mcp status # เช็คว่ารันอยู่ไหม
dot-mcp stop # หยุด server + tunnel
dot-mcp start รัน server ในพื้นหลังแล้วคืน shell ทันที — จะได้ URL,
owner secret, OAuth client ID/secret ให้เอาไปตั้ง connector เลย
รันจาก source checkout:
./setup.sh # สร้าง .venv + ติดตั้ง deps + editable install
./dots start # เหมือนด้านบน
สำรอง: ./run.sh (server เฉยๆ ไม่มี tunnel) · ./test.sh (health + initialize) ·
./expose.sh (tunnel เฉยๆสำหรับ ChatGPT connector)
คุยแบบ local-only (ไม่ต้อง tunnel, ไม่ต้องจ่าย sub):
export OPENAI_API_KEY=sk-...
python -m dot_mcp.local_agent # chat loop
python -m dot_mcp.local_agent --list # ดู tools เฉยๆ
เทสผ่าน MCP client จริง:
.venv/bin/python agent_test.py
.venv/bin/python agent_test.py http://127.0.0.1:33041/mcp/ # อ่าน secret จาก env/ไฟล์ให้เอง
เปิดให้ ChatGPT web เรียกผ่าน tunnel:
วิธีแนะนำ: tunnl.gg (URL สุ่มแต่คงเดิมเมื่อใช้ key เดิม)
git clone https://github.com/Ashveil1/dot-mcp.git
cd dot-mcp
./setup.sh
./expose.sh
ครั้งแรกสคริปต์จะสร้าง SSH key และ owner secret ให้อัตโนมัติ เก็บไว้ใน ~/.config/dot-mcp/ (owner_secret 0600) แล้วแสดง URL /mcp/ เส้นสะอาดสำหรับตั้งค่า connector (auth = OAuth) การรันครั้งต่อไปใช้ key และ secret เดิม URL และ consent ไม่เปลี่ยน ตราบใดที่ยังเก็บโฟลเดอร์นี้ไว้
ข้อจำกัดแผนฟรีของ tunnl.gg: URL เป็นชื่อสุ่มที่ผู้ให้บริการกำหนด (ไม่สามารถเลือก prefix dot-mcp- เองได้); tunnel หมดอายุหลัง 24 ชั่วโมง หรือหลังไม่มี traffic 2 ชั่วโมง ต้องรัน ./expose.sh ใหม่เพื่อเชื่อมต่ออีกครั้ง แต่ URL จะคงเดิมเมื่อใช้ SSH key เดิม ต้องมี OpenSSH (ssh และ ssh-keygen) และเครื่องต้องออนไลน์ขณะใช้ MCP อย่าเผยแพร่ private key ใน ~/.config/dot-mcp/
สคริปต์จะตรวจ MCP initialize ผ่าน public HTTPS ก่อนแสดง URL หากการทดสอบไม่ผ่านจะรายงานข้อผิดพลาดแทนการบอกว่าเชื่อมต่อสำเร็จ MCP สคริปต์จะรายงานว่าไม่ผ่านแทนการแสดงว่าใช้งานได้ URL แบบสุ่มนี้ ไม่คงเดิมเมื่อรันใหม่ และชื่อที่ขึ้นต้น dot-mcp- ไม่ได้แปลว่าถูกจองถาวร
Cloudflare Quick Tunnel (URL สุ่ม):
TUNNEL_PROVIDER=cloudflare ./expose.sh
URL คงที่ด้วย ngrok (ต้องตั้งค่าบัญชีครั้งเดียว):
- สร้างบัญชี ngrok และคัดลอก authtoken จาก dashboard
- คัดลอกโดเมนฟรีที่ ngrok assign ให้บัญชี (เช่น
example.ngrok-free.app) จาก dashboard - ติดตั้ง ngrok binary ให้ตรงกับ OS/architecture ของเครื่อง แล้วตั้งค่าตัวแปรและเริ่ม:
export TUNNEL_PROVIDER=ngrok
export NGROK_AUTHTOKEN='ใส่-authtoken-ของคุณ'
export NGROK_DOMAIN='โดเมนที่-ngrok-assign-ให้คุณ'
./expose.sh
สคริปต์จะตรวจสอบ /health และส่ง MCP initialize ผ่าน public URL ก่อนแสดง URL สำหรับ ChatGPT หากใช้ ngrok ต้องใช้ NGROK_DOMAIN เดิมทุกครั้ง และเก็บ authtoken เป็นความลับ การมี URL คงที่ไม่ได้หมายความว่าเซิร์ฟเวอร์จะออนไลน์เมื่อเครื่องปิดอยู่
หมายเหตุ: expose.sh ไม่ดาวน์โหลด ngrok ให้อัตโนมัติ เพราะต้องใช้ binary ที่เหมาะกับระบบปฏิบัติการ/สถาปัตยกรรมของเครื่อง โดยเฉพาะ Android/Termux อาจต้องใช้วิธีติดตั้งที่รองรับ Termux โดยตรง
เมื่อเริ่มสำเร็จ ให้เอา MCP URL ที่สคริปต์แสดงไปใส่ Settings > Apps > Advanced > Developer Mode > Add connector (ไม่ต้องตั้ง token)
Embedded UI in ChatGPT
When connected through a ChatGPT MCP connector that supports MCP Apps, call open_workspace to render the responsive Dots Workspace panel. It provides Overview, Tasks, Memory, Activity/Schedules and Rules views. This is an embedded app surface; it cannot change ChatGPT's global sidebar, composer, or native Codex interface. Use MCP SDK v2 for the interactive UI path; the older SDK fallback returns text only.
Env
| ตัวแปร | ค่าเริ่มต้น | หมายถึง |
|---|---|---|
MCP_HOST / MCP_PORT |
127.0.0.1 / 33041 |
bind server |
MCP_PUBLIC_HOST |
"" |
tunnel host ที่ allow (expose.sh ตั้งให้เอง) |
DOT_MCP_DATA |
~/.dot-mcp |
ที่เก็บ memory/state/inbox/schedules/oauth/audit |
MCP_TRUNC_LIMIT |
8192 |
ตัด stdout ยาวๆ แล้วให้ต่อด้วย read_output |
MCP_RATE_MCP_PER_MIN |
300 |
rate limit ต่อ IP บน /mcp* (เกิน → 429) |
MCP_RATE_AUTH_PER_MIN |
30 |
rate limit ต่อ IP บน /register /authorize /token |
MCP_SESSION_CAP |
50 |
จำนวน background session สูงสุด |
HOME / TMPDIR |
— | resolve() จำกัด path อยู่ใน HOME/TMPDIR//sdcard, /tmp ถูก map ไป $TMPDIR (Android ไม่มี /tmp) |
ไฟล์ข้อมูล: memory.json, state.json, inbox.json, schedules.json, oauth.json (0600), audit.jsonl
Files
src/dot_mcp/server.py # MCP server (22 tools + OAuth 2.1)
src/dot_mcp/cli.py # CLI: dot-mcp start/status/stop
src/dot_mcp/orchestrator.py # boot → tunnel → verify flow
src/dot_mcp/ui/workspace.html # embedded workspace UI (MCP Apps)
src/dot_mcp/local_agent.py # ChatGPT model + MCP local (ไม่ต้อง tunnel)
src/dot_mcp/agent_test.py # client smoke test
tests/test_server.py # pytest suite (รัน: .venv/bin/python -m pytest tests/ -q)
dots # repo shim (./dots start)
setup.sh / run.sh / test.sh / expose.sh
pyproject.toml # pip packaging (console scripts dot-mcp + dots)
requirements.txt # mcp>=1,<3, uvicorn>=0.30, rich>=13
bin/cloudflared # auto-download (arm64) — ไม่ commit
Security
⚠️ เซิร์ฟเวอร์นี้ให้ shell เต็มเครื่องแก่ผู้ถือ credential — ถือว่าเป็น production เฉพาะเมื่อใช้คนเดียว + ปฏิบัติตามนี้
/mcp/ต้องมีAuthorization: Bearerเสมอ (JWT จาก OAuth หรือ owner secret) — ไม่มี = 401 แม้ localhost (ตั้งใจ: traffic จาก tunnel ดูเหมือน loopback แยกไม่ออก)- Owner secret อยู่ใน header/consent form ไม่โผล่ใน URL; log (
mcp.log,tunnel.log) ตั้ง600+ ปิด access log; เปิด tunnel เฉพาะตอนใช้ + ปิดทันที - Rate limit:
/mcp*300 req/min/IP,/register/authorize/token30 req/min/IP (เกิน → 429) — ปรับผ่านMCP_RATE_MCP_PER_MIN/MCP_RATE_AUTH_PER_MIN - ทุก request ถูกบันทึก
audit.jsonl(เวลา/IP/method/path/status/tool) — ตรวจย้อนหลังได้ - Consent POST ตรวจ
Origin/Refererว่าตรง issuer (กัน CSRF ข้ามเว็บ) - Refresh token เก็บแบบ hash + หมุนทุกครั้งที่ใช้; JWT ตรวจลายเซ็น/issuer/audience/expiry/scope
- ไฟล์ state ล็อกข้าม process (
fcntl) + เขียน atomic (tmp + rename) — รัน server ซ้อนกันไม่ทำข้อมูลพัง - ข้อจำกัดที่ต้องรู้: provider ของ tunnel (tunnl/cloudflare) เห็น traffic เพราะ TLS จบที่ edge เขา; rate limit/audit เป็น per-process (รันหลาย process ให้นับแยกกัน); backup
~/.dot-mcpเอง (ไม่มีระบบ backup ในตัว)
OAuth (ChatGPT / Claude / Gemini)
ฟรี ทำเองในไฟล์เดียว ไม่ต้องมี IdP เจ้าอื่น — server นี้เป็นทั้งคนออกและคนตรวจ token:
- Metadata:
/.well-known/oauth-authorization-server+/.well-known/oauth-protected-resource POST /register— Dynamic Client Registration (รับredirect_urishttps, หรือhttp://localhost/127.0.0.1)GET/POST /authorize— หน้า consent ครั้งเดียว ปลดล็อกด้วย owner secret (code + PKCE S256, อายุ 10 นาที, ใช้ครั้งเดียว)POST /token— แลก code เป็น JWT (1 ชม.) + refresh token (30 วัน, หมุนทุกครั้งที่ใช้)- เรียก MCP ใส่
Authorization: Bearer <jwt>ได้เลย (OAuth) หรือBearer <owner secret>(สคริปต์ local) - ตั้งค่า connector: URL =
https://<host>/mcp/, auth = OAuth, issuer =https://<host>(ดูจาก/.well-known/...ได้) - connector แบบ DCR (ChatGPT) สมัคร client เอง + PKCE; แบบกรอกมือ (Claude) ใช้ OAuth client ID/secret ประจำเครื่องที่
dots startโชว์ (เก็บในoauth.json0600, ไม่ต้อง register)
License
MIT
Metadata
Release files for dot-mcp 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| dot_mcp-0.1.0.tar.gz | 37.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dot_mcp-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 75.7 kB
Release files / dot_mcp-0.1.0.tar.gz
| Download URL | dot_mcp-0.1.0.tar.gz |
|---|---|
| Size | 37.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
59b643d062ada39d768e303fe1af1924986e3a83184f1b32b388a2fd17491a9f
|
|
BLAKE2b-256 checksum How to use checksums |
8bf09b2b478b1b3a73da4378338bd22768fa77a35d9a7b7f411f5aa4c12ad435
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.
Transparency logRelease files / dot_mcp-0.1.0-py3-none-any.whl
| Download URL | dot_mcp-0.1.0-py3-none-any.whl |
|---|---|
| Size | 37.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b63b9e25ba733b579d742878d55eab47b4c88ac72dadfd99e10cf8a8872316dc
|
|
BLAKE2b-256 checksum How to use checksums |
326a76a573bbc66725d783065156382e5af90fadfbcaecff6625d45e46eadc5c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.
Transparency log