monacloud-mcp 0.9.2 → 0.10.1

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
@@ -150,6 +150,25 @@ Mỗi tool có alias `vibecloud_base_*` cùng schema và handler. Cần DB/Supab
150
150
 
151
151
  `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.
152
152
 
153
+ ### MONA Domain — tên miền cho app (monadomain.vn)
154
+
155
+ AI tra tên, báo giá VND đã VAT, hỏi chủ thể, mua .vn/.com bằng ví MONA Cloud rồi trỏ DNS + SSL vào app. Tra giá **không cần đăng nhập**; người dùng chưa có tài khoản vẫn mua được trong phiên bằng đường giữ chỗ → quét QR → bấm claim (đăng nhập MONA Pass 1 bước = tạo ví = mua).
156
+
157
+ | Tool | Công dụng |
158
+ |---|---|
159
+ | `cloud_domain_search` | Còn trống + giá theo TLD; **guest gọi được** |
160
+ | `cloud_domain_reserve` | Giữ chỗ 30' không trừ tiền; hỏi email + sđt (+ opt-in ưu đãi); trả QR đúng giá + `claim_url` + `claim_token`/`guest_token` |
161
+ | `cloud_domain_reserve_status` | reserved / paid / claimed / expired + `next_step` |
162
+ | `cloud_domain_claim` | Đăng nhập Pass → nhận reservation, kéo tiền về ví, mua ngay (idempotent) |
163
+ | `cloud_domain_reserve_release` | Nhả chỗ khi chưa có tiền vào |
164
+ | `cloud_domain_registrant_get` / `cloud_domain_registrant_set` | Chủ thể đăng ký (.vn cá nhân cần CCCD, tổ chức cần MST) |
165
+ | `cloud_domain_buy` | Mua thẳng bằng ví khi đã đăng nhập; 402 → `cloud_topup` in QR |
166
+ | `cloud_domain_verify_start` / `cloud_domain_verify_status` / `cloud_domain_wait` | Hồ sơ .vn + chờ active |
167
+ | `cloud_domain_renew` | Gia hạn: dry_run báo giá → duyệt → trừ ví VND |
168
+ | `cloud_domain_dns_*` / `cloud_domain_ns_set` / `cloud_domain_attach` / `cloud_domain_health` | DNS, NS, gắn app, sức khoẻ |
169
+
170
+ Giữ chỗ chỉ khoá tên trong hệ MONA Cloud (`hold_scope=monacloud`), không giữ ở registry — tên đẹp thì trả sớm. Không gọi registrar tới khi tiền vào và có tài khoản nhận. Prompt `mua-ten-mien-monacloud(keyword?, app_id?)` dẫn trọn luồng.
171
+
153
172
  ### MONA Mail
154
173
 
155
174
  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.
package/dist/clients.d.ts CHANGED
@@ -44,6 +44,18 @@ export declare class CloudClients {
44
44
  headers?: Record<string, string>;
45
45
  timeoutMs?: number;
46
46
  }): Promise<T>;
47
+ /**
48
+ * Gọi endpoint MONA Cloud mở cho guest (spec monadomain §12: search/reserve/status không cần Pass).
49
+ * Có token trên máy thì vẫn gửi (để backend ghi lead + gắn chủ); chưa login thì đi ẩn danh
50
+ * hoặc dùng guest_token của reservation — KHÔNG ném login_required.
51
+ */
52
+ vibecloudGuestOk<T = unknown>(path: string, options?: {
53
+ method?: string;
54
+ body?: unknown;
55
+ query?: Record<string, string | number | undefined>;
56
+ headers?: Record<string, string>;
57
+ guestToken?: string;
58
+ }): Promise<T>;
47
59
  guardedVibecloud(path: string, options?: {
48
60
  method?: string;
49
61
  body?: unknown;
package/dist/clients.js CHANGED
@@ -222,6 +222,29 @@ export class CloudClients {
222
222
  fetchImpl: this.fetchImpl,
223
223
  });
224
224
  }
225
+ /**
226
+ * Gọi endpoint MONA Cloud mở cho guest (spec monadomain §12: search/reserve/status không cần Pass).
227
+ * Có token trên máy thì vẫn gửi (để backend ghi lead + gắn chủ); chưa login thì đi ẩn danh
228
+ * hoặc dùng guest_token của reservation — KHÔNG ném login_required.
229
+ */
230
+ async vibecloudGuestOk(path, options = {}) {
231
+ const { guestToken, ...rest } = options;
232
+ let token;
233
+ try {
234
+ token = await this.vibecloudToken();
235
+ }
236
+ catch (error) {
237
+ if (!(error instanceof CloudError) || error.code !== 'login_required')
238
+ throw error;
239
+ token = guestToken;
240
+ }
241
+ return requestJson(`${this.config.vibecloudApi}${path}`, {
242
+ timeoutMs: 30_000,
243
+ ...rest,
244
+ token,
245
+ fetchImpl: this.fetchImpl,
246
+ });
247
+ }
225
248
  async guardedVibecloud(path, options = {}, requestedSandbox = false, requiredVnd) {
226
249
  const sandbox = this.sandboxEnabled(requestedSandbox);
227
250
  if (!sandbox)
package/dist/domains.js CHANGED
@@ -25,7 +25,7 @@ const registrantSchema = z.object({
25
25
  export function registerDomainTools(server, clients) {
26
26
  server.registerTool('cloud_domain_search', {
27
27
  title: 'Tìm kiếm + báo giá tên miền',
28
- description: 'Kiểm tra tên miền còn trống và xem giá mua. Dùng trước khi mua để AI biết available/price.',
28
+ description: 'Kiểm tra tên miền còn trống và xem giá mua (VND, đã VAT). KHÔNG cần đăng nhập MONA Pass — gọi được ngay cả khi người dùng chưa có tài khoản; dùng trước khi mua/giữ chỗ để biết available/price.',
29
29
  inputSchema: z.object({
30
30
  q: z.string().min(1).max(253).describe('Tên miền hoặc từ khoá (vd: "myapp" hoặc "myapp.vn").'),
31
31
  tlds: z.string().max(200).optional().describe('Đuôi muốn tìm, phân cách phẩy (vd: "vn,com"). Mặc định: vn,com.'),
@@ -37,7 +37,7 @@ export function registerDomainTools(server, clients) {
37
37
  params.set('tlds', tlds);
38
38
  if (years)
39
39
  params.set('years', String(years));
40
- return clients.vibecloud(`/api/domains/search?${params}`);
40
+ return clients.vibecloudGuestOk(`/api/domains/search?${params}`);
41
41
  }));
42
42
  server.registerTool('cloud_domain_registrant_get', {
43
43
  title: 'Xem thông tin chủ thể đăng ký tên miền',
@@ -81,6 +81,63 @@ export function registerDomainTools(server, clients) {
81
81
  body.registrant_id = registrant_id;
82
82
  return clients.guardedVibecloud('/api/domains', { method: 'POST', body }, sandbox === true);
83
83
  }));
84
+ // --- Guest → reserve → claim (spec monadomain §12): mua TRƯỚC khi có tài khoản ---------------
85
+ server.registerTool('cloud_domain_reserve', {
86
+ title: 'Giữ chỗ tên miền + QR trả tiền (không cần tài khoản)',
87
+ description: [
88
+ 'Giữ chỗ tên miền 30 phút cho người dùng CHƯA có MONA Pass (hoặc chưa login trên máy này) — không trừ tiền, không đăng ký thật, chỉ khoá tên trong hệ MONA Cloud.',
89
+ 'Dùng khi người dùng muốn mua ngay trong phiên mà không muốn "đi đăng ký" trước: bạn đã dựng app, chọn tên, chỉ cần người bấm.',
90
+ 'Bắt buộc hỏi người dùng: tên miền (xác nhận chính tả → spelling_confirmed), email, số điện thoại (kênh nhận link claim + hoá đơn). Hỏi thêm 1 câu nhẹ: "nhận thông báo ưu đãi MONA Cloud không?" → marketing_consent; không tick thì để false.',
91
+ 'Nếu người dùng đã đưa đủ thông tin chủ thể (.vn cần CCCD/MST) thì gửi luôn ở registrant — lúc claim khỏi hỏi lại.',
92
+ 'Kết quả: payment.qr_url (QR VietQR đúng số tiền) + claim_url + claim_token + guest_token (giữ lại để gọi cloud_domain_reserve_status). Đưa QR cho người dùng quét NGAY; tiền vào → hệ giữ cho reservation này. Sau đó người dùng mở claim_url: đăng nhập/đăng ký MONA Pass (Google/GitHub/email, 1 bước) → hệ tự lấy tiền + mua + tạo ví. Nếu người dùng ĐÃ có Pass trên máy này thì gọi thẳng cloud_domain_claim.',
93
+ 'Giữ chỗ chỉ trong hệ MONA Cloud (hold_scope=monacloud) — người ngoài vẫn có thể đăng ký tên đó ở registry khác trong 30 phút; nói rõ điều này nếu tên đẹp.',
94
+ ].join(' '),
95
+ inputSchema: z.object({
96
+ name: domainName,
97
+ years: z.number().int().min(1).max(10).optional().describe('Số năm đăng ký. Mặc định 1.'),
98
+ email: z.string().email().describe('Email người dùng — nhận claim_url + hoá đơn.'),
99
+ phone: z.string().min(8).max(20).describe('Số điện thoại người dùng.'),
100
+ spelling_confirmed: z.boolean().describe('true = người dùng đã xác nhận chính tả tên miền.'),
101
+ marketing_consent: z.boolean().optional().describe('true CHỈ KHI người dùng đồng ý nhận thông báo ưu đãi MONA Cloud. Mặc định false.'),
102
+ registrant: registrantSchema.optional().describe('Thông tin chủ thể nếu đã hỏi được đủ trong phiên (tuỳ chọn).'),
103
+ context: z.string().max(500).optional().describe('Ngữ cảnh ngắn (vd: "Cursor dựng shop Next.js") — giúp MONA hỗ trợ đúng.'),
104
+ sandbox: z.boolean().optional().describe('sandbox=true: giả lập, không tạo QR thật.'),
105
+ }).strict(),
106
+ }, ({ sandbox, ...body }) => runTool(() => clients.vibecloudGuestOk('/api/domains/reserve', {
107
+ method: 'POST',
108
+ body,
109
+ ...(clients.sandboxEnabled(sandbox === true) ? { headers: { 'X-Vibecloud-Sandbox': '1' } } : {}),
110
+ })));
111
+ server.registerTool('cloud_domain_reserve_status', {
112
+ title: 'Trạng thái giữ chỗ tên miền',
113
+ description: 'Xem reservation đã nhận tiền chưa / đã claim chưa / còn hạn không. Guest truyền claim_token (hoặc guest_token) nhận từ cloud_domain_reserve; chủ reservation đã login thì không cần. Đọc next_step trong kết quả để biết bước kế.',
114
+ inputSchema: z.object({
115
+ reservation_id: objectId.describe('ID reservation từ cloud_domain_reserve.'),
116
+ claim_token: z.string().min(16).max(128).optional().describe('claim_token hoặc guest_token từ cloud_domain_reserve (bắt buộc khi chưa login).'),
117
+ }).strict(),
118
+ }, ({ reservation_id, claim_token }) => runTool(() => clients.vibecloudGuestOk(`/api/domains/reserve/${encodeURIComponent(reservation_id)}`, { query: claim_token ? { t: claim_token } : undefined, guestToken: claim_token })));
119
+ server.registerTool('cloud_domain_claim', {
120
+ title: 'Nhận reservation về tài khoản + mua (claim = đăng ký = trả tiền)',
121
+ description: [
122
+ 'Gắn reservation vào MONA Pass đang đăng nhập, kéo tiền đã chuyển (nếu có) về ví rồi MUA ngay. Cần đăng nhập (monacloud-mcp login) — lần đầu đăng nhập MONA Cloud tự tạo hồ sơ + ví, không có form đăng ký riêng.',
123
+ 'Idempotent: gọi lại khi trả 402 (ví chưa đủ → cloud_topup hoặc chờ tiền QR vào) hoặc 422 registrant_required (→ cloud_domain_registrant_set rồi claim lại; tiền vẫn nằm trong ví).',
124
+ 'Kết quả như cloud_domain_buy (order id, status, suggested_next).',
125
+ ].join(' '),
126
+ inputSchema: z.object({
127
+ reservation_id: objectId.describe('ID reservation từ cloud_domain_reserve.'),
128
+ claim_token: z.string().min(16).max(128).describe('claim_token từ cloud_domain_reserve (hoặc tham số t trong claim_url).'),
129
+ registrant_id: objectId.optional().describe('ID registrant muốn dùng (mặc định: registrant của user hoặc từ reservation).'),
130
+ marketing_consent: z.boolean().optional().describe('true nếu người dùng đồng ý nhận ưu đãi lúc này.'),
131
+ }).strict(),
132
+ }, ({ reservation_id, ...body }) => runTool(() => clients.vibecloud(`/api/domains/reserve/${encodeURIComponent(reservation_id)}/claim`, { method: 'POST', body })));
133
+ server.registerTool('cloud_domain_reserve_release', {
134
+ title: 'Nhả chỗ tên miền đã giữ',
135
+ description: 'Huỷ reservation chưa nhận tiền (người dùng đổi ý / chọn tên khác). Đã có tiền vào thì không huỷ được — dùng cloud_domain_claim.',
136
+ inputSchema: z.object({
137
+ reservation_id: objectId,
138
+ claim_token: z.string().min(16).max(128).optional().describe('Bắt buộc khi chưa login.'),
139
+ }).strict(),
140
+ }, ({ reservation_id, claim_token }) => runTool(() => clients.vibecloudGuestOk(`/api/domains/reserve/${encodeURIComponent(reservation_id)}`, { method: 'DELETE', query: claim_token ? { t: claim_token } : undefined, guestToken: claim_token })));
84
141
  server.registerTool('cloud_domain_list', {
85
142
  title: 'Danh sách tên miền đã import/mua',
86
143
  description: 'Liệt kê tên miền đã đưa vào MONA Cloud (import + mua). sandbox=true → xem domain sandbox.',
@@ -114,6 +171,18 @@ export function registerDomainTools(server, clients) {
114
171
  id: objectId.describe('Order ID tên miền cần kiểm tra.'),
115
172
  }).strict(),
116
173
  }, ({ id }) => runTool(() => clients.vibecloud(`/api/domains/${encodeURIComponent(id)}/health`)));
174
+ server.registerTool('cloud_domain_renew', {
175
+ title: 'Gia hạn tên miền (trừ ví VND)',
176
+ description: [
177
+ 'Gia hạn tên miền đã mua qua MONA Cloud. LUÔN gọi dry_run=true trước để lấy price_vnd (đã VAT), HỎI người dùng duyệt số tiền, rồi gọi lại dry_run=false — lúc đó trừ ví VND và gia hạn thật ở registrar.',
178
+ '402 insufficient_balance → cloud_topup in QR cho người dùng quét, chờ paid rồi gọi lại. 502 retryable → tiền đang giữ chờ đối soát, đừng gọi lại liên tục; báo người dùng.',
179
+ ].join(' '),
180
+ inputSchema: z.object({
181
+ id: objectId.describe('Order ID tên miền (từ cloud_domain_list / cloud_domain_buy).'),
182
+ billing_cycle: z.number().int().min(12).max(120).describe('Số tháng gia hạn, bội số 12 (12 = 1 năm).'),
183
+ dry_run: z.boolean().optional().describe('true = chỉ báo giá, không trừ tiền. Mặc định true để an toàn.'),
184
+ }).strict(),
185
+ }, ({ id, billing_cycle, dry_run }) => runTool(() => clients.guardedVibecloud(`/api/domains/${encodeURIComponent(id)}/renew`, { method: 'POST', body: { billing_cycle, dry_run: dry_run !== false } }, false)));
117
186
  server.registerTool('cloud_domain_wait', {
118
187
  title: 'Chờ tên miền active',
119
188
  description: 'Long-poll cho đến khi tên miền chuyển sang active/failed (mặc định timeout=60s). Dùng sau cloud_domain_buy để chờ MONA Host xử lý.',
@@ -207,6 +276,7 @@ export function registerDomainTools(server, clients) {
207
276
  3. cloud_domain_registrant_set: HỎI TÔI thông tin chủ thể ngay trong phiên — họ tên, email, điện thoại, địa chỉ; nếu là .vn cá nhân hỏi thêm CCCD 12 số + ngày sinh + giới tính (tổ chức: tên công ty + MST + người đại diện). Đừng tự bịa.
208
277
  4. Kiểm ví bằng cloud_balance. Nếu thiếu tiền, gọi cloud_topup rồi IN NGUYÊN KHỐI qr_ascii (QR VietQR) cho tôi quét bằng app ngân hàng ngay trong terminal; chờ cloud_topup_status=paid.
209
278
  5. cloud_domain_buy (spelling_confirmed=true) — trừ ví, mua thật.
279
+ ⚠️ Nếu tôi CHƯA có tài khoản MONA Pass / tool trả login_required: KHÔNG bảo tôi đi đăng ký trước. Dùng cloud_domain_reserve (hỏi email + sđt, hỏi 1 câu "nhận ưu đãi MONA Cloud không?") → đưa tôi QR trong payment để quét trả tiền ngay + claim_url để tôi bấm đăng nhập 1 bước (Google/GitHub/email) → hệ tự tạo ví + mua. Theo dõi bằng cloud_domain_reserve_status; nếu tôi đã login trên máy này thì gọi cloud_domain_claim.
210
280
  6. Nếu là .vn: cloud_domain_verify_start đưa tôi link eKYC/bản khai (chụp CCCD + chân dung / ký), rồi cloud_domain_wait tới khi active.
211
281
  7. ${app_id ? `Gắn vào app ${app_id} bằng cloud_domain_attach` : 'Gợi ý tôi deploy app lên MONA Cloud (cloud_app_create) rồi gắn domain bằng cloud_domain_attach'} — trỏ DNS + SSL tự động.
212
282
  Trả VND, không cần thẻ quốc tế, không mở dashboard.`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monacloud-mcp",
3
- "version": "0.9.2",
3
+ "version": "0.10.1",
4
4
  "description": "MCP server for MONA Cloud — deploy apps (Vercel alternative), Supabase-compatible Postgres/Auth/Storage bases (Supabase alternative), VND wallet, MONA Pay & Mail — for AI agents (Claude, Cursor, Codex) in Vietnam.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://monacloud.vn",