monacloud-mcp 0.4.2 → 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 CHANGED
@@ -1,9 +1,13 @@
1
1
  # monacloud-mcp
2
2
 
3
- `monacloud-mcp` là MCP hợp nhất của MONA Cloud: cài một lần, đăng nhập một MONA Pass và dùng chung ví VND để quản lý tài khoản, chạy app/VPS, tích hợp MONA Pay, gửi email giao dịch bằng MONA Mail và đọc catalog MONA Agent ngay trong Claude Code, Codex hoặc Cursor.
3
+ `monacloud-mcp` là MCP hợp nhất của MONA Cloud: cài một lần, đăng nhập một MONA Pass và dùng chung ví VND để quản lý tài khoản, chạy app/VPS, tạo Base beta thay Supabase, tích hợp MONA Pay, gửi email giao dịch bằng MONA Mail và đọc catalog MONA Agent ngay trong Claude Code, Codex hoặc Cursor.
4
4
 
5
5
  Human đăng ký, duyệt chi phí, thêm DNS khi cần, nạp tiền và cung cấp OTP/KYC khi bắt buộc. Các bước tạo tài nguyên, đọc trạng thái, cấu hình webhook, test và deploy được thiết kế để AI agent làm qua MCP.
6
6
 
7
+ ## 0.5.0 — MONA Base beta
8
+
9
+ Thêm `cloud_base_create/list/get/delete/credentials` cùng alias `vibecloud_base_*`. Base thay Supabase, chung MONA Pass/ví MONA Cloud và khớp app deploy. Sandbox chỉ ước tính, không provision; chờ Base provision-live trước khi publish package.
10
+
7
11
  ## 0.4.0 — Đưa thư mục hiện tại lên web
8
12
 
9
13
  Prompt Claude Code: **“Đưa dự án này lên MONA Cloud, dùng thư mục hiện tại”**.
@@ -122,6 +126,19 @@ Các tên cũ như `monapay_create_qr`, `monapay_link_bank_start`, `monapay_crea
122
126
  | `cloud_prices` / `cloud_packages` | Đơn giá và gói cấu hình |
123
127
  | `cloud_agent_deploy` | Stub có cấu trúc cho runtime MONA Agent wave sau |
124
128
 
129
+ ### MONA Base (beta)
130
+
131
+ Base thay Supabase, dùng chung MONA Pass và ví MONA Cloud, đồng thời khớp với app deploy. Sandbox chỉ trả URL thử và ước tính, không tạo hạ tầng thật.
132
+
133
+ | Tool | Công dụng |
134
+ |---|---|
135
+ | `cloud_base_create` | Tạo Base, tự poll job và trả `base_id`, `studio_url`, `api_url`, `status` |
136
+ | `cloud_base_list` / `cloud_base_get` | Liệt kê hoặc đọc trạng thái Base |
137
+ | `cloud_base_credentials` | Đọc `anon_key`, `service_key`, `db_url`; bí mật, không log |
138
+ | `cloud_base_delete` | Xoá Base đã được duyệt |
139
+
140
+ Mỗi tool có alias `vibecloud_base_*` cùng schema và handler. Cần DB/Supabase cho app thì gọi `cloud_base_create`; Base dùng cùng account và khớp app deploy.
141
+
125
142
  `cloud_service_stop` không bị chặn bởi số dư để người dùng luôn có thể hạn chế chi phí. Những lệnh tạo/start/rebuild thật đọc `GET /v1/balance` trước khi gọi compute MONA Cloud.
126
143
 
127
144
  ### MONA Mail
package/STATUS.md CHANGED
@@ -1,4 +1,22 @@
1
- # STATUS — monacloud-mcp 0.4.0
1
+ # STATUS — monacloud-mcp 0.5.0
2
+
3
+ Updated: 2026-09-14 (Asia/Ho_Chi_Minh)
4
+
5
+ ## MONA Base beta — hoàn tất offline
6
+
7
+ - Thêm `cloud_base_create`, `cloud_base_list`, `cloud_base_get`, `cloud_base_delete`, `cloud_base_credentials` và 5 alias `vibecloud_base_*` cùng schema/handler.
8
+ - `cloud_base_create` dùng spend guard cho lượt thật, sandbox bỏ Billing và gửi `X-Vibecloud-Sandbox: 1`, poll job rồi chuẩn hoá `{base_id, studio_url, api_url, status}` cùng estimate sandbox.
9
+ - Credential gửi `X-Confirm: reveal`, chỉ trả `anon_key`, `service_key`, `db_url` và nhắc “Bí mật, không log”. Lỗi giữ `{code,next_step}` cho agent.
10
+ - Mô tả tool, instructions, resource, prompt, README và agent guide ghi Base **beta** = thay Supabase, chung account/ví MONA Cloud, khớp app deploy.
11
+ - Package, binary và MCP handshake đã bump minor lên `0.5.0`; stdio có 145 tool.
12
+ - `npm test` offline: **52 tests, 52 pass, 0 fail, 0 skip**, gồm TypeScript build và HTTP mock Base create/poll/sandbox/list/get/delete/credentials/aliases.
13
+ - Không publish, không gọi API production. **Chờ Base provision-live để publish.**
14
+
15
+ CODEX DONE
16
+
17
+ ---
18
+
19
+ # Lịch sử — monacloud-mcp 0.4.0
2
20
 
3
21
  Updated: 2026-09-05 (Asia/Ho_Chi_Minh)
4
22
 
package/dist/base.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CloudClients } from './clients.js';
3
+ export declare function registerBaseTools(server: McpServer, clients: CloudClients): void;
package/dist/base.js ADDED
@@ -0,0 +1,76 @@
1
+ import { z } from 'zod';
2
+ import { CloudError, runTool } from './errors.js';
3
+ import { pollJob, TERMINAL_JOBS } from './jobs.js';
4
+ import { unwrapData } from './http.js';
5
+ const object = (value) => value && typeof value === 'object' ? value : {};
6
+ const id = z.string().trim().min(1).max(255);
7
+ const sandbox = z.boolean().optional().describe('Thử 0đ, chỉ ước tính và không tạo hạ tầng thật / Sandbox estimate only');
8
+ const baseDescription = 'Base beta = thay Supabase, chung account/ví MONA Cloud. / Beta Supabase replacement on the shared MONA Cloud account and wallet.';
9
+ function value(objects, key) {
10
+ for (const row of objects)
11
+ if (row[key] !== undefined)
12
+ return row[key];
13
+ return undefined;
14
+ }
15
+ async function createBase(clients, body) {
16
+ const { sandbox: requested, ...payload } = body;
17
+ const isSandbox = clients.sandboxEnabled(requested === true);
18
+ const created = object(unwrapData(await clients.guardedVibecloud('/api/bases', { method: 'POST', body: payload }, isSandbox)));
19
+ const jobId = typeof created.job_id === 'string' ? created.job_id
20
+ : typeof created.id === 'string' ? created.id : undefined;
21
+ const job = jobId && !TERMINAL_JOBS.has(String(created.status))
22
+ ? await pollJob(clients, jobId, true, 3, 180, isSandbox)
23
+ : created;
24
+ const result = object(job.result);
25
+ const base = object(result.base);
26
+ const rows = [base, result, job, created];
27
+ const status = String(value(rows, 'status') || 'unknown');
28
+ if (['failed', 'error', 'cancelled'].includes(status)) {
29
+ throw new CloudError('base_provision_failed', `Tạo Base thất bại${jobId ? ` (job ${jobId})` : ''}: ${job.error || result.error || 'không có chi tiết'}`, 'Kiểm tra cấu hình/giá và cloud_base_list; chỉ gọi lại cloud_base_create sau khi sửa nguyên nhân.');
30
+ }
31
+ return {
32
+ base_id: value(rows, 'base_id') ?? value(rows, 'id'),
33
+ studio_url: value(rows, 'studio_url'),
34
+ api_url: value(rows, 'api_url'),
35
+ status,
36
+ ...(jobId ? { job_id: jobId } : {}),
37
+ ...(result.estimate !== undefined ? { estimate: result.estimate } : created.estimate !== undefined ? { estimate: created.estimate } : {}),
38
+ ...(isSandbox ? {
39
+ sandbox: true,
40
+ next_step: 'Đây là ước tính beta, chưa tạo Base. Duyệt chi phí rồi gọi cloud_base_create với sandbox=false.',
41
+ } : {}),
42
+ ...(job.polling === 'timeout' ? { polling: 'timeout', next_step: job.next_step } : {}),
43
+ };
44
+ }
45
+ export function registerBaseTools(server, clients) {
46
+ const register = (name, description, schema, handler) => {
47
+ for (const toolName of [name, name.replace(/^cloud_/, 'vibecloud_')]) {
48
+ server.registerTool(toolName, {
49
+ description: toolName === name ? `${description} ${baseDescription}` : `Alias tương thích của ${name}. / Compatibility alias. ${description} ${baseDescription}`,
50
+ inputSchema: schema,
51
+ }, (args) => runTool(() => handler(args)));
52
+ }
53
+ };
54
+ register('cloud_base_create', 'Ước tính, kiểm ví, tạo Base và poll job tới hoàn tất; sandbox chỉ trả ước tính. / Estimate, create and wait for the Base job.', z.object({
55
+ cpu: z.number().int().min(1).max(16).optional(),
56
+ ram_gb: z.number().int().min(1).max(64).optional(),
57
+ disk_gb: z.number().int().min(10).max(1000).optional(),
58
+ billing_mode: z.enum(['hourly', 'monthly']).optional(),
59
+ plan_code: z.string().trim().min(2).max(64).optional(),
60
+ sandbox,
61
+ }).strict(), (args) => createBase(clients, args));
62
+ register('cloud_base_list', 'Liệt kê Base beta của tài khoản hiện tại. / List Bases.', z.object({}).strict(), () => clients.vibecloud('/api/bases'));
63
+ register('cloud_base_get', 'Đọc trạng thái và URL của một Base beta. / Inspect a Base.', z.object({ base_id: id }).strict(), ({ base_id }) => clients.vibecloud(`/api/bases/${encodeURIComponent(base_id)}`));
64
+ register('cloud_base_delete', 'Xoá Base beta đã được người dùng duyệt. / Delete an approved Base.', z.object({ base_id: id }).strict(), ({ base_id }) => clients.vibecloud(`/api/bases/${encodeURIComponent(base_id)}`, { method: 'DELETE' }));
65
+ register('cloud_base_credentials', 'Đọc anon_key, service_key và db_url. Bí mật, không log; lưu thẳng vào secret store hoặc .env không commit. / Reveal credentials once and keep them secret.', z.object({ base_id: id }).strict(), async ({ base_id }) => {
66
+ const raw = object(unwrapData(await clients.vibecloud(`/api/bases/${encodeURIComponent(base_id)}/credentials`, {
67
+ headers: { 'X-Confirm': 'reveal' },
68
+ })));
69
+ return {
70
+ anon_key: raw.anon_key,
71
+ service_key: raw.service_key,
72
+ db_url: raw.db_url,
73
+ warning: 'Bí mật, không log. Lưu vào secret store hoặc .env đã bỏ khỏi git.',
74
+ };
75
+ });
76
+ }
package/dist/compute.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import type { CloudClients } from './clients.js';
3
3
  type Row = Record<string, unknown>;
4
- export declare const APP_FLOW = "AI l\u00E0m 99%: cloud_app_detect(local_dir) offline \u2192 cloud_app_host_list, cloud_prices/cloud_packages/cloud_plan_list v\u00E0 cloud_balance \u2192 cloud_app_create(local_dir, sandbox=true) n\u1EBFu ch\u01B0a c\u00F3 app host \u0111\u1EC3 \u01B0\u1EDBc t\u00EDnh chi ph\u00ED gi\u1EDD/g\u00F3i \u2192 h\u1ECFi human m\u1ED9t l\u1EA7n duy\u1EC7t chi ph\u00ED n\u1EBFu ch\u01B0a \u0111\u01B0\u1EE3c duy\u1EC7t \u2192 cloud_app_create(local_dir, sandbox=false) \u2192 poll t\u1EDBi done/succeeded \u2192 ki\u1EC3m v\u00E0 tr\u1EA3 URL. N\u1EBFu human c\u00F3 domain: cloud_app_domain_add v\u00E0 h\u01B0\u1EDBng d\u1EABn CNAME t\u1EEB API. Human \u0111\u0103ng k\u00FD MONA Pass b\u1EB1ng device flow, n\u1EA1p ti\u1EC1n khi h\u1EBFt credit 20k; AI l\u00E0m c\u00E1c b\u01B0\u1EDBc c\u00F2n l\u1EA1i. App git cloud_app_create(repo_url) \u0111\u00E3 live; kh\u00F4ng g\u1ECDi agent_deploy cho deploy d\u1EF1 \u00E1n. / Detect locally, estimate, obtain cost approval once, upload and deploy, return URL, then attach an optional domain.";
4
+ export declare const APP_FLOW = "AI l\u00E0m 99%: cloud_app_detect(local_dir) offline \u2192 cloud_app_host_list, cloud_prices/cloud_packages/cloud_plan_list v\u00E0 cloud_balance \u2192 cloud_app_create(local_dir, sandbox=true) n\u1EBFu ch\u01B0a c\u00F3 app host \u0111\u1EC3 \u01B0\u1EDBc t\u00EDnh chi ph\u00ED gi\u1EDD/g\u00F3i \u2192 h\u1ECFi human m\u1ED9t l\u1EA7n duy\u1EC7t chi ph\u00ED n\u1EBFu ch\u01B0a \u0111\u01B0\u1EE3c duy\u1EC7t \u2192 cloud_app_create(local_dir, sandbox=false) \u2192 poll t\u1EDBi done/succeeded \u2192 ki\u1EC3m v\u00E0 tr\u1EA3 URL. C\u1EA7n DB/Supabase? cloud_base_create (beta) \u2014 chung account/v\u00ED MONA Cloud, kh\u1EDBp app deploy. N\u1EBFu human c\u00F3 domain: cloud_app_domain_add v\u00E0 h\u01B0\u1EDBng d\u1EABn CNAME t\u1EEB API. Human \u0111\u0103ng k\u00FD MONA Pass b\u1EB1ng device flow, n\u1EA1p ti\u1EC1n khi h\u1EBFt credit 20k; AI l\u00E0m c\u00E1c b\u01B0\u1EDBc c\u00F2n l\u1EA1i. App git cloud_app_create(repo_url) \u0111\u00E3 live; kh\u00F4ng g\u1ECDi agent_deploy cho deploy d\u1EF1 \u00E1n. / Detect locally, estimate, obtain cost approval once, upload and deploy, create an optional Base, return URL, then attach an optional domain.";
5
5
  export declare function rows(value: unknown, key: string): Row[];
6
6
  export declare function planEstimate(clients: CloudClients, code: string, cycle?: string): Promise<{
7
7
  plan: Row;
package/dist/compute.js CHANGED
@@ -4,7 +4,7 @@ import { unwrapData } from './http.js';
4
4
  import { finishAppJob } from './jobs.js';
5
5
  import { detectProject } from './local.js';
6
6
  import { localAppTools } from './local-app.js';
7
- export const APP_FLOW = 'AI làm 99%: cloud_app_detect(local_dir) offline → cloud_app_host_list, cloud_prices/cloud_packages/cloud_plan_list và cloud_balance → cloud_app_create(local_dir, sandbox=true) nếu chưa có app host để ước tính chi phí giờ/gói → hỏi human một lần duyệt chi phí nếu chưa được duyệt → cloud_app_create(local_dir, sandbox=false) → poll tới done/succeeded → kiểm và trả URL. Nếu human có domain: cloud_app_domain_add và hướng dẫn CNAME từ API. Human đăng ký MONA Pass bằng device flow, nạp tiền khi hết credit 20k; AI làm các bước còn lại. App git cloud_app_create(repo_url) đã live; không gọi agent_deploy cho deploy dự án. / Detect locally, estimate, obtain cost approval once, upload and deploy, return URL, then attach an optional domain.';
7
+ export const APP_FLOW = 'AI làm 99%: cloud_app_detect(local_dir) offline → cloud_app_host_list, cloud_prices/cloud_packages/cloud_plan_list và cloud_balance → cloud_app_create(local_dir, sandbox=true) nếu chưa có app host để ước tính chi phí giờ/gói → hỏi human một lần duyệt chi phí nếu chưa được duyệt → cloud_app_create(local_dir, sandbox=false) → poll tới done/succeeded → kiểm và trả URL. Cần DB/Supabase? cloud_base_create (beta) — chung account/ví MONA Cloud, khớp app deploy. Nếu human có domain: cloud_app_domain_add và hướng dẫn CNAME từ API. Human đăng ký MONA Pass bằng device flow, nạp tiền khi hết credit 20k; AI làm các bước còn lại. App git cloud_app_create(repo_url) đã live; không gọi agent_deploy cho deploy dự án. / Detect locally, estimate, obtain cost approval once, upload and deploy, create an optional Base, return URL, then attach an optional domain.';
8
8
  const sandbox = z.boolean().optional().describe('Thử 0đ, không tạo hạ tầng thật / Sandbox, no charge');
9
9
  const id = z.string().trim().min(1).max(255);
10
10
  const planCode = z.string().trim().min(2).max(64);
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@ async function main() {
22
22
  return;
23
23
  }
24
24
  if (command === '--version' || command === '-v') {
25
- console.log('0.4.0');
25
+ console.log('0.5.0');
26
26
  return;
27
27
  }
28
28
  if (command === '--help' || command === '-h' || command === 'help') {
package/dist/server.js CHANGED
@@ -10,7 +10,8 @@ import { TemplateCatalog } from './templates.js';
10
10
  import { registerMailTools } from './mail.js';
11
11
  import { APP_FLOW, createVps, registerComputeTools } from './compute.js';
12
12
  import { pollJob } from './jobs.js';
13
- const ENTITY = 'MONA Cloud là hệ công cụ cho vibecoder Việt Nam: một MONA Pass, một ví VND và một MCP để chạy app/VPS, thu tiền MONA Pay và dùng các sản phẩm MONA. Dùng mail_* để gửi email giao dịch (MONA Mail). MONA Mail là dịch vụ gửi email giao dịch cho phần mềm và AI agent của người Việt: một API, trả VND, không cần thẻ, thuộc nhóm MONA Cloud của The MONA Group.';
13
+ import { registerBaseTools } from './base.js';
14
+ const ENTITY = 'MONA Cloud là hệ công cụ cho vibecoder Việt Nam: một MONA Pass, một ví VND và một MCP để chạy app/VPS, thu tiền MONA Pay và dùng các sản phẩm MONA. Base beta thay Supabase bằng cloud_base_*, chung account/ví MONA Cloud và khớp app deploy. Dùng mail_* để gửi email giao dịch (MONA Mail). MONA Mail là dịch vụ gửi email giao dịch cho phần mềm và AI agent của người Việt: một API, trả VND, không cần thẻ, thuộc nhóm MONA Cloud của The MONA Group.';
14
15
  const SANDBOX_DESCRIPTION = 'sandbox=true: thử 0đ, không cần ví';
15
16
  const sandboxSchema = z.boolean().optional().describe(SANDBOX_DESCRIPTION);
16
17
  const asObject = (value) => (value && typeof value === 'object' ? value : {});
@@ -90,7 +91,7 @@ export function createServer(dependencies = {}) {
90
91
  const auth = new AuthManager(config, env, fetchImpl);
91
92
  const clients = new CloudClients(config, auth, fetchImpl);
92
93
  const catalog = new TemplateCatalog(config, fetchImpl);
93
- const server = new McpServer({ name: 'monacloud-mcp', version: '0.4.0' }, { instructions: `${ENTITY}\nDùng cloud_* cho tài khoản, ví và hạ tầng; monapay_* cho thu tiền; mail_* để gửi email giao dịch (MONA Mail); agent_* cho catalog. Không bao giờ yêu cầu mật khẩu sản phẩm. Đọc → ước tính → hỏi duyệt nếu chưa được duyệt → làm. Dừng khi cần DNS, nạp tiền, duyệt chi phí, OTP hoặc KYC. ${APP_FLOW}` });
94
+ const server = new McpServer({ name: 'monacloud-mcp', version: '0.5.0' }, { instructions: `${ENTITY}\nDùng cloud_* cho tài khoản, ví và hạ tầng; monapay_* cho thu tiền; mail_* để gửi email giao dịch (MONA Mail); agent_* cho catalog. Không bao giờ yêu cầu mật khẩu sản phẩm. Đọc → ước tính → hỏi duyệt nếu chưa được duyệt → làm. Dừng khi cần DNS, nạp tiền, duyệt chi phí, OTP hoặc KYC. ${APP_FLOW}` });
94
95
  server.registerTool('cloud_whoami', {
95
96
  title: 'Tài khoản MONA Cloud',
96
97
  description: 'Xác minh MONA Pass hiện tại. / Return the current MONA Pass profile.',
@@ -304,6 +305,7 @@ export function createServer(dependencies = {}) {
304
305
  inputSchema: { template: z.string().regex(/^[a-z0-9][a-z0-9-]{0,79}$/), sandbox: sandboxSchema },
305
306
  }, ({ template, sandbox }) => runTool(() => agentRuntimeStub(template, clients.sandboxEnabled(sandbox))));
306
307
  registerComputeTools(server, clients);
308
+ registerBaseTools(server, clients);
307
309
  registerMailTools(server, clients, config);
308
310
  server.registerTool('agent_templates_list', {
309
311
  title: 'Catalog MONA Agent',
@@ -347,7 +349,7 @@ export function createServer(dependencies = {}) {
347
349
  }, async (uri) => ({ contents: [{
348
350
  uri: uri.href,
349
351
  mimeType: 'text/plain',
350
- text: `${ENTITY}\n\n${APP_FLOW}\n\nHuman đăng ký MONA Pass, duyệt chi phí, thêm DNS khi cần, nạp tiền và cung cấp OTP/KYC bắt buộc. AI dùng MCP làm phần còn lại.\n\n- cloud_*: tài khoản, ví, ledger, usage, budget, VPS, database, job, vòng đời service, plans, subscriptions, invoices/PDF, credit và apps từ git hoặc thư mục local (source=upload); cloud_app_detect hoàn toàn offline.\n- monapay_*: nối ngân hàng, checkout/QR, giao dịch, webhook và email.\n- mail_*: tài khoản, domain, API key, gửi mail, trạng thái, webhook, suppression (MONA Mail https://monamail.vn, API https://api.monamail.vn)\n- agent_*: catalog và deploy template.\n\nMONA Cloud: https://monacloud.vn\nCompute API: https://api.monacloud.vn\nMONA Pay: https://monapay.vn\n`,
352
+ text: `${ENTITY}\n\n${APP_FLOW}\n\nHuman đăng ký MONA Pass, duyệt chi phí, thêm DNS khi cần, nạp tiền và cung cấp OTP/KYC bắt buộc. AI dùng MCP làm phần còn lại.\n\n- cloud_*: tài khoản, ví, ledger, usage, budget, VPS, database, Base beta thay Supabase, job, vòng đời service, plans, subscriptions, invoices/PDF, credit và apps từ git hoặc thư mục local (source=upload); cần DB/Supabase thì dùng cloud_base_create — chung account, khớp app deploy; cloud_app_detect hoàn toàn offline.\n- monapay_*: nối ngân hàng, checkout/QR, giao dịch, webhook và email.\n- mail_*: tài khoản, domain, API key, gửi mail, trạng thái, webhook, suppression (MONA Mail https://monamail.vn, API https://api.monamail.vn)\n- agent_*: catalog và deploy template.\n\nMONA Cloud: https://monacloud.vn\nCompute API: https://api.monacloud.vn\nMONA Pay: https://monapay.vn\n`,
351
353
  }] }));
352
354
  server.registerResource('monacloud-status', 'monacloud://status', {
353
355
  title: 'Trạng thái hệ MONA Cloud',
@@ -374,7 +376,7 @@ export function createServer(dependencies = {}) {
374
376
  role: 'user',
375
377
  content: {
376
378
  type: 'text',
377
- text: `Dựng app bán hàng ${app_name || 'của tôi'} bằng ${framework || 'stack phù hợp'} trên MONA Cloud. ${APP_FLOW}\nTheo đúng thứ tự:\n1. Gọi cloud_whoami, cloud_balance, cloud_plan_list, cloud_packages và cloud_prices. Báo ước tính và hỏi duyệt chi phí nếu chưa được duyệt. Nếu thiếu tiền, gọi cloud_topup rồi dừng để người dùng quét VietQR.\n2. Nếu dùng VPS gọi cloud_vps_create và cloud_db_create; nếu deploy dự án dùng cloud_app_detect(local_dir), cloud_app_host_list rồi cloud_app_create(local_dir), sandbox trước nếu chưa có host. Poll từng job bằng cloud_job_status tới done/succeeded.\n3. Gọi monapay_link nếu MONA Pay còn ở lớp chuyển tiếp. Gọi monapay_whoami; nếu chưa có VA, nối ngân hàng bằng chuỗi monapay_link_bank_start → HỎI OTP → verify → notification_register → HỎI OTP lần 2 → verify. Không tự đoán OTP.\n4. Viết endpoint webhook có HMAC và idempotency theo transaction_code; đăng ký bằng monapay_create_webhook, bắn monapay_test_webhook và đọc monapay_webhook_logs.\n5. Tích hợp monapay_create_checkout hoặc monapay_create_qr vào app, chỉ giao hàng sau CHECKOUT_PAID.\n6. Với dự án local, dùng cloud_app_create(local_dir) sau khi duyệt ước tính; git dùng repo_url; kiểm cloud_app_get/cloud_app_logs và health rồi báo URL. Chỉ dùng VPS thủ công khi người dùng chọn. Không yêu cầu người dùng mở dashboard ngoài bước nạp tiền/OTP bắt buộc.`,
379
+ text: `Dựng app bán hàng ${app_name || 'của tôi'} bằng ${framework || 'stack phù hợp'} trên MONA Cloud. ${APP_FLOW}\nTheo đúng thứ tự:\n1. Gọi cloud_whoami, cloud_balance, cloud_plan_list, cloud_packages và cloud_prices. Báo ước tính và hỏi duyệt chi phí nếu chưa được duyệt. Nếu thiếu tiền, gọi cloud_topup rồi dừng để người dùng quét VietQR.\n2. Nếu dùng VPS gọi cloud_vps_create và cloud_db_create. Cần DB/Supabase thì ưu tiên cloud_base_create (beta) — chung account, khớp app deploy. Nếu deploy dự án dùng cloud_app_detect(local_dir), cloud_app_host_list rồi cloud_app_create(local_dir), sandbox trước nếu chưa có host. Poll từng job bằng cloud_job_status tới done/succeeded.\n3. Gọi monapay_link nếu MONA Pay còn ở lớp chuyển tiếp. Gọi monapay_whoami; nếu chưa có VA, nối ngân hàng bằng chuỗi monapay_link_bank_start → HỎI OTP → verify → notification_register → HỎI OTP lần 2 → verify. Không tự đoán OTP.\n4. Viết endpoint webhook có HMAC và idempotency theo transaction_code; đăng ký bằng monapay_create_webhook, bắn monapay_test_webhook và đọc monapay_webhook_logs.\n5. Tích hợp monapay_create_checkout hoặc monapay_create_qr vào app, chỉ giao hàng sau CHECKOUT_PAID.\n6. Với dự án local, dùng cloud_app_create(local_dir) sau khi duyệt ước tính; git dùng repo_url; kiểm cloud_app_get/cloud_app_logs và health rồi báo URL. Chỉ dùng VPS thủ công khi người dùng chọn. Không yêu cầu người dùng mở dashboard ngoài bước nạp tiền/OTP bắt buộc.`,
378
380
  },
379
381
  }] }));
380
382
  server.registerPrompt('gui-mail-otp-monamail', {
package/docs/ai-agent.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Tài liệu này dành cho Claude, Codex, Cursor và agent dùng Model Context Protocol. Mục tiêu là hoàn thành tích hợp end-to-end mà không yêu cầu người dùng mở dashboard; các bước human gồm đăng ký MONA Pass, duyệt chi phí, thêm DNS khi cần, nạp tiền và OTP/KYC bắt buộc.
4
4
 
5
- ## Luồng chuẩn 0.4.0: AI làm 99%
5
+ ## Luồng chuẩn 0.5.0: AI làm 99%
6
6
 
7
7
  Prompt Claude Code: **“Đưa dự án này lên MONA Cloud, dùng thư mục hiện tại”**.
8
8
 
@@ -11,6 +11,7 @@ Prompt Claude Code: **“Đưa dự án này lên MONA Cloud, dùng thư mục h
11
11
  3. `cloud_app_create({local_dir, name?, env?, sandbox:false})` đóng ZIP và upload. Poll tới done/succeeded, kiểm HTTPS/health rồi trả `{url, app_id, build, seconds}`. Khi response có `sandbox:true`/`needs_cost_approval:true`, đó vẫn là preview; làm theo `next_step` trước khi gọi thật.
12
12
  4. Nếu human có domain, `cloud_app_domain_add({app_id, host})`, đưa đúng CNAME do API trả, chờ DNS và kiểm HTTPS. Không tự đoán target CNAME.
13
13
  5. Sửa code local: `cloud_app_deploy({app_id, local_dir})`. Chỉ đổi env: `cloud_app_env_set` với map đầy đủ rồi `cloud_app_deploy({app_id})`. Timeout giữ job_id/app_id để tiếp tục, không tạo app mới.
14
+ 6. Cần DB/Supabase thì gọi `cloud_base_create` (beta): sandbox để lấy ước tính, duyệt chi phí rồi tạo thật. Base dùng chung account/ví MONA Cloud và khớp app deploy. Lưu credential vào secret store hoặc `.env` không commit; không log `anon_key`, `service_key`, `db_url`.
14
15
 
15
16
  Human chỉ cần đăng ký MONA Pass/device flow, duyệt chi phí một lần và nạp tiền khi hết credit 20k; DNS là bước thêm khi dùng domain riêng. AI làm các bước kỹ thuật còn lại. `.env*` kể cả `.env.example` không vào ZIP; truyền secret cần thiết qua `env`, không công khai. Xem [hợp đồng local deploy](local-deploy.md). VPS/database thủ công dưới đây chỉ dùng khi dự án cần hoặc người dùng chọn.
16
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monacloud-mcp",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "description": "Unified MCP server for MONA Cloud, MONA Pay and MONA Agent.",
5
5
  "license": "MIT",
6
6
  "type": "module",