takma

takma MCP

ให้ Claude หรือ AI ตัวอื่นสร้าง อ่าน และแก้โปรเจคดีไซน์ใน takma ได้โดยตรงผ่าน Model Context Protocol โดยไม่ต้องใช้ token และ ข้ามรหัสผ่านของโปรเจค (ออกแบบมาให้เจ้าของระบบใช้เอง) สิ่งที่ AI สร้างจะเปิดดู/แก้ต่อในเว็บได้ทันทีผ่านลิงก์ /p/<id>

1. Endpoint

ใช้เมื่อURL
local (ผ่าน web)http://localhost:21401/mcp
local (ตรงเข้า api)http://localhost:21402/mcp
public (ผ่าน tunnel ของคุณเอง)https://takma.sabuytube.xyz/mcp — endpoint ไม่มี auth ระวังอย่าเปิดสาธารณะโดยไม่มีอะไรกั้น

2. วิธีต่อ

Claude Code (local)

claude mcp add --transport http takma http://localhost:21401/mcp

Claude Code (public)

claude mcp add --transport http takma https://takma.sabuytube.xyz/mcp

Client อื่น (Cursor / Codex / Gemini ที่ใช้รูปแบบ mcpServers)

{
  "mcpServers": {
    "takma": {
      "type": "http",
      "url": "http://localhost:21401/mcp"
    }
  }
}

stdio

{
  "mcpServers": {
    "takma": {
      "command": "pnpm",
      "args": [
        "--filter",
        "api",
        "mcp:stdio"
      ],
      "cwd": "<path-to-takma-repo>"
    }
  }
}

3. Tools ทั้ง 9

ToolInputOutputตัวอย่าง arguments
list_projects
รายการโปรเจคทั้งหมด (ใหม่สุดก่อน)
— (ไม่มี)[{id, title, visibility, updatedAt, url}]{}
get_project
อ่านโปรเจคพร้อม data (nodes) — ไม่มี password hash
id: string (required){id, title, visibility, createdAt, updatedAt, data:{version, nodes[], nextId}}{"id":"aB3dE5gH7j"}
create_project
สร้างโปรเจคใหม่ · private ต้องมี editPassword + viewPassword ที่ต่างกัน · public ไม่ใส่ editPassword = open (ใครมีลิงก์ก็แก้ได้) · รหัสยาว ≥ 4 ตัว
code?: string (รหัสงาน 4-32 ตัว a-z 0-9 ขีด; ซ้ำ=code_taken, สงวน=code_reserved) · title: string (required) · visibility: "public"|"private" (required) · editPassword?: string (บังคับเมื่อ private) · viewPassword?: string · data?: {version?, nodes[], nextId?}{id, url} (data ว่าง = {version:1, nodes:[], nextId:1}){"title":"Login screen","visibility":"private","editPassword":"edit1234","viewPassword":"view1234"}
update_project
แก้ชื่อ / visibility / รหัส / data ทั้งก้อน (ไม่ต้องใส่รหัสเดิม) — เปลี่ยนรหัสแล้ว token เก่าของเว็บใช้ไม่ได้ · open → private ต้องส่ง editPassword + viewPassword ครบ · ใส่ editPassword ให้ open project = ล็อก
id: string (required) · title?: string · visibility?: "public"|"private" · editPassword?: string · viewPassword?: string · data?: {version?, nodes[], nextId?}{id, updatedAt}{"id":"aB3dE5gH7j","title":"Login v2"}
delete_project
ลบโปรเจคถาวร
id: string (required){deleted: id}{"id":"aB3dE5gH7j"}
add_nodes
ต่อท้าย nodes (≥ 1) · node ที่ไม่ส่ง id จะได้ node-<nextId> · id ซ้ำ = error duplicate_node_id
id: string (required) · nodes: object[] (required, ≥ 1){added: [id, ...]}{"id":"aB3dE5gH7j","nodes":[{"type":"rect","name":"Button","x":24,"y":700,"w":342,"h":52,"fill":"#9a80ff","radius":12}]}
update_node
shallow-merge patch เข้า node เดียว (เปลี่ยน id ไม่ได้)
id: string (required) · nodeId: string (required) · patch: object (required){updated: nodeId} · ไม่พบ node = error node_not_found{"id":"aB3dE5gH7j","nodeId":"node-3","patch":{"fill":"#ff5577","text":"Sign in"}}
remove_nodes
ลบ nodes ตาม id (ไม่ลบลูกของ frame ให้อัตโนมัติ — ส่ง id ลูกมาด้วย)
id: string (required) · nodeIds: string[] (required, ≥ 1){removed: จำนวนที่ลบจริง}{"id":"aB3dE5gH7j","nodeIds":["node-2","node-3"]}
get_share_link
ลิงก์เปิดในเว็บ (PUBLIC_URL หรือ WEB_URL + /p/<id>) — ถ้าเป็น private คนเปิดยังต้องใช้รหัส
id: string (required){url, visibility}{"id":"aB3dE5gH7j"}

Error ของ tool จะกลับมาเป็น isError: true พร้อมข้อความ เช่น not_found, invalid_input, passwords_must_differ, view_password_required

4. โครงสร้าง node (สำหรับ add_nodes)

document คือ {version:1, nodes:[], nextId} — แต่ละ node เป็น object ธรรมดา editor ไม่เติมค่า default ให้ ดังนั้นควรส่ง field ร่วมให้ครบทุกชิ้น

กลุ่มFields (ค่า default ของ editor)
typerect · ellipse · text · path · frame · image
ร่วมทุกชนิดid · type · name · x y w h (px, 160×90) · fill (#ffffff, text = #20243a, ไม่มี = none) · stroke (none) · strokeWidth (1) · radius (0) · opacity (0–100, 100) · parentId (null) · hidden (false) · locked (false)
texttext · fontSize (22) · fontWeight (500) · align (left|center|right) · autoSize (false)
pathd (SVG path data) · baseW · baseH (ขนาดตั้งต้นของ d ใช้ย่อ/ขยายตาม w/h) · stroke · strokeWidth · fill
imagesrc — data URI (data:image/png;base64,…) · fill และ stroke ใช้ none
framecontainer — node อื่นอ้าง parentId เป็น id ของ frame
ข้อควรระวัง: พิกัด x/y ของลูกเป็นพิกัด canvas แบบ absolute (ไม่ใช่ offset จาก frame) · ถ้าจะให้ลูกชี้ parentId ถึง frame ที่เพิ่งสร้างใน call เดียวกัน ให้ระบุ id เองแบบ node-<n> (server จะขยับ nextId ให้) · ลำดับใน array = ลำดับซ้อน (ท้ายสุดอยู่บนสุด) · ใส่ id ซ้ำกับของเดิมไม่ได้

ตัวอย่าง arguments ของ add_nodes: frame มือถือ 390×844 + ข้อความ + ปุ่ม (frame อยู่ที่ 0,0 จึงใช้พิกัดตรงๆ)

{
  "id": "aB3dE5gH7j",
  "nodes": [
    {
      "id": "node-1",
      "type": "frame",
      "name": "Mobile 390x844",
      "x": 0,
      "y": 0,
      "w": 390,
      "h": 844,
      "fill": "#ffffff",
      "stroke": "none",
      "strokeWidth": 1,
      "radius": 0,
      "opacity": 100,
      "text": "",
      "fontSize": 22,
      "fontWeight": 500,
      "align": "left",
      "autoSize": false,
      "parentId": null,
      "hidden": false,
      "locked": false
    },
    {
      "id": "node-2",
      "type": "text",
      "name": "Title",
      "x": 24,
      "y": 120,
      "w": 342,
      "h": 40,
      "fill": "#20243a",
      "stroke": "none",
      "strokeWidth": 1,
      "radius": 0,
      "opacity": 100,
      "text": "Welcome back",
      "fontSize": 32,
      "fontWeight": 700,
      "align": "left",
      "autoSize": false,
      "parentId": "node-1",
      "hidden": false,
      "locked": false
    },
    {
      "id": "node-3",
      "type": "rect",
      "name": "Sign in button",
      "x": 24,
      "y": 700,
      "w": 342,
      "h": 52,
      "fill": "#9a80ff",
      "stroke": "none",
      "strokeWidth": 1,
      "radius": 12,
      "opacity": 100,
      "text": "",
      "fontSize": 22,
      "fontWeight": 500,
      "align": "left",
      "autoSize": false,
      "parentId": "node-1",
      "hidden": false,
      "locked": false
    }
  ]
}

5. ตัวอย่าง workflow

  1. create_project — {"title":"Login screen","visibility":"private","editPassword":"edit1234","viewPassword":"view1234"} → ได้ {id, url}
  2. add_nodes ด้วย id ที่ได้ + nodes ตามตัวอย่างด้านบน
  3. get_project เช็คผล (ดู nodes กลับมา)
  4. get_share_link → เปิดลิงก์ในเบราว์เซอร์ (private ใส่ view/edit password ที่ตั้งไว้)
  5. ปรับเพิ่มด้วย update_node / remove_nodes

ลองด้วย curl (JSON-RPC)

# 1) initialize
curl -s -X POST http://localhost:21401/mcp \
  -H 'content-type: application/json' \
  -H 'accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'

# 2) tools/list
curl -s -X POST http://localhost:21401/mcp \
  -H 'content-type: application/json' \
  -H 'accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

# 3) เรียก tool
curl -s -X POST http://localhost:21401/mcp \
  -H 'content-type: application/json' \
  -H 'accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"list_projects","arguments":{}}}'

6. ความปลอดภัย

MCP ไม่มี auth และ ข้ามรหัสผ่านของโปรเจค — ใครเข้า endpoint ได้ก็ อ่าน แก้ ลบ ทุกโปรเจคได้

← กลับหน้าแรก · รายละเอียดการรัน: ดู README.md ใน repo