monacloud-mcp 0.10.12 → 0.11.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
@@ -109,6 +109,9 @@ Tên tool dùng `snake_case` để giữ tương thích với prompt MONA Pay c
109
109
  | `cloud_budget_set` / `cloud_budget_get` | Đặt và đọc budget theo product/project/token |
110
110
  | `cloud_token_limit` | Đặt spend limit cho PAT/token |
111
111
  | `cloud_open_console` | Trả URL console chung |
112
+ | `cloud_affiliate_link` | Lấy mã, link giới thiệu, hạng và mức chia sẻ doanh thu; chỉ đăng sau khi người dùng duyệt và có disclosure |
113
+ | `cloud_affiliate_stats` | Đọc thống kê, số dư có thể nhận và tối đa 100 hoa hồng gần nhất |
114
+ | `cloud_affiliate_claim(code)` | Gắn mã giới thiệu vào tài khoản còn trong thời hạn nhận mã |
112
115
 
113
116
  ### MONA Pay
114
117
 
@@ -335,3 +338,5 @@ Monthly bỏ qua CPU/RAM/đĩa và package_slug, đọc cấu hình/giá từ pl
335
338
  Khi user nói “deploy repo”, đọc host; chưa có host thì sandbox `cloud_app_create` để ước tính, hỏi duyệt rồi tạo thật và kiểm URL. Tool chờ job tối đa 600 giây; dùng `wait:false` và `cloud_job_status` nếu host MCP có timeout ngắn. Endpoint Wave B đang mở, lỗi API được báo thật.
336
339
 
337
340
  Hợp đồng HTTP, đầy đủ tham số, ví dụ billing/deploy, PDF và giới hạn rollout: [docs/wave-ab.md](docs/wave-ab.md).
341
+
342
+ **MONA Cloud MCP thuộc bộ MONA Cloud của The MONA Group.**
@@ -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 registerAffiliateTools(server: McpServer, clients: CloudClients): void;
@@ -0,0 +1,65 @@
1
+ import { z } from 'zod';
2
+ import { runTool } from './errors.js';
3
+ import { unwrapData } from './http.js';
4
+ import { completeToolMetadata } from './monapay.js';
5
+ const asObject = (value) => (value && typeof value === 'object' ? value : {});
6
+ const affiliate = (value) => asObject(unwrapData(value));
7
+ const LINK_NEXT_STEP = "Chèn link vào README/docs/bài viết của người dùng kèm câu công khai 'link giới thiệu, MONA Cloud chia sẻ doanh thu cho người giới thiệu'. Không tự đăng lên đâu nếu người dùng chưa duyệt.";
8
+ export function registerAffiliateTools(server, clients) {
9
+ const register = (name, description, schema, handler) => {
10
+ for (const toolName of [name, name.replace(/^cloud_/, 'vibecloud_')]) {
11
+ const metadata = completeToolMetadata(toolName, undefined, undefined);
12
+ server.registerTool(toolName, {
13
+ title: metadata.title,
14
+ annotations: metadata.annotations,
15
+ description: toolName === name
16
+ ? description
17
+ : `Alias tương thích của ${name}. / Compatibility alias. ${description}`,
18
+ inputSchema: schema,
19
+ }, (args) => runTool(() => handler(args)));
20
+ }
21
+ };
22
+ register('cloud_affiliate_link', 'Lấy link giới thiệu MONA Cloud và mức chia sẻ doanh thu để người dùng duyệt trước khi đăng. / Get the MONA Cloud referral link and revenue-share rates.', z.object({}).strict(), async () => {
23
+ const result = affiliate(await clients.vibecloud('/api/me/affiliate'));
24
+ return {
25
+ referral_code: result.referral_code,
26
+ link: result.link,
27
+ console_link: result.console_link,
28
+ tier: result.tier,
29
+ rates: result.rates,
30
+ next_step: LINK_NEXT_STEP,
31
+ };
32
+ });
33
+ register('cloud_affiliate_stats', 'Đọc thống kê, số dư có thể nhận và các hoa hồng gần nhất. / Read affiliate stats, payout availability and recent commissions.', z.object({
34
+ status: z.enum(['pending', 'approved', 'paid', 'reversed', 'flagged']).optional(),
35
+ limit: z.number().int().min(1).max(100).default(20),
36
+ }).strict(), async ({ status, limit }) => {
37
+ const [profileResponse, commissionResponse] = await Promise.all([
38
+ clients.vibecloud('/api/me/affiliate'),
39
+ clients.vibecloud('/api/me/affiliate/commissions', { query: { status, limit } }),
40
+ ]);
41
+ const profile = affiliate(profileResponse);
42
+ const commissionData = affiliate(commissionResponse);
43
+ return {
44
+ stats: profile.stats,
45
+ payout_available_vnd: profile.payout_available_vnd,
46
+ can_request_payout: profile.can_request_payout,
47
+ commissions: Array.isArray(commissionData.commissions) ? commissionData.commissions : [],
48
+ next_step: profile.can_request_payout
49
+ ? 'Có thể yêu cầu thanh toán trong MONA Cloud Console; kiểm tra thông tin nhận tiền trước khi gửi yêu cầu.'
50
+ : 'Theo dõi hoa hồng approved và ngưỡng thanh toán; chưa tự yêu cầu thanh toán thay người dùng.',
51
+ };
52
+ });
53
+ register('cloud_affiliate_claim', 'Gắn mã giới thiệu vào tài khoản hiện tại trong thời hạn cho phép. / Claim a referral code for the current account.', z.object({ code: z.string().trim().min(4).max(16) }).strict(), async ({ code }) => {
54
+ const result = affiliate(await clients.vibecloud('/api/me/referral/claim', {
55
+ method: 'POST',
56
+ body: { code },
57
+ }));
58
+ return {
59
+ ...result,
60
+ next_step: typeof result.next_step === 'string'
61
+ ? result.next_step
62
+ : 'Mã giới thiệu đã được ghi nhận; dùng cloud_affiliate_link nếu muốn lấy link của chính tài khoản này.',
63
+ };
64
+ });
65
+ }
package/dist/config.d.ts CHANGED
@@ -15,5 +15,5 @@ export type Config = {
15
15
  monapayLinkPath: string;
16
16
  vibecloudLinkPath: string;
17
17
  };
18
- export declare const DEFAULT_TEMPLATES_URL = "https://raw.githubusercontent.com/themonagroup/mona-agent-templates/main";
18
+ export declare const DEFAULT_TEMPLATES_URL = "https://raw.githubusercontent.com/mona-software/mona-agent-templates/main";
19
19
  export declare function readConfig(env?: NodeJS.ProcessEnv): Config;
package/dist/config.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { homedir } from 'node:os';
2
2
  import { join } from 'node:path';
3
3
  const cleanBaseUrl = (value) => value.replace(/\/+$/, '');
4
- export const DEFAULT_TEMPLATES_URL = 'https://raw.githubusercontent.com/themonagroup/mona-agent-templates/main';
4
+ export const DEFAULT_TEMPLATES_URL = 'https://raw.githubusercontent.com/mona-software/mona-agent-templates/main';
5
5
  export function readConfig(env = process.env) {
6
6
  const configDir = env.MONACLOUD_CONFIG_DIR
7
7
  || join(env.XDG_CONFIG_HOME || join(homedir(), '.config'), 'monacloud');
package/dist/index.js CHANGED
File without changes
package/dist/monapay.js CHANGED
@@ -16,6 +16,8 @@ export function toolAnnotationsForName(name) {
16
16
  || canonical === 'mail_plans'
17
17
  || canonical === 'cloud_invoice_pdf'
18
18
  || canonical === 'cloud_base_credentials'
19
+ || canonical === 'cloud_affiliate_link'
20
+ || canonical === 'cloud_affiliate_stats'
19
21
  || canonical === 'mail_inbox_message'
20
22
  || canonical === 'mail_inbox_messages'
21
23
  || canonical === 'monapay_me'
package/dist/remote.js CHANGED
@@ -7,6 +7,7 @@ import express from "express";
7
7
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
8
8
  import { ProxyOAuthServerProvider } from "@modelcontextprotocol/sdk/server/auth/providers/proxyProvider.js";
9
9
  import { mcpAuthRouter } from "@modelcontextprotocol/sdk/server/auth/router.js";
10
+ import { InvalidClientMetadataError } from "@modelcontextprotocol/sdk/server/auth/errors.js";
10
11
  import { createServer as createMcpServer, PKG_VERSION } from "./server.js";
11
12
  import { createAccessTokenVerifier } from "./remote-verify.js";
12
13
  const SCOPES = ["openid", "profile", "email", "offline_access", "vibecloud-api", "billing-api"];
@@ -64,6 +65,24 @@ export async function createRemoteServer(options) {
64
65
  });
65
66
  const registrationUrl = `${issuer}/clients-registrations/openid-connect`;
66
67
  const callbackUrl = `${publicUrl}/callback`;
68
+ // Nơi được phép nhận code sau khi đăng nhập. Client MCP thật chỉ nằm ở mấy chỗ này; ai khai redirect_uri
69
+ // ngoài danh sách thì proxy từ chối ngay từ bước đăng ký, khỏi cần người dùng tự nhận ra mình bị lừa.
70
+ const REDIRECT_ALLOW_HOSTS = (options.env?.MCP_REMOTE_REDIRECT_HOSTS || process.env.MCP_REMOTE_REDIRECT_HOSTS
71
+ || "claude.ai,claude.com,anthropic.com,server.smithery.ai,smithery.ai,connect.smithery.ai,cursor.com,cursor.sh,chatgpt.com,openai.com,localhost,127.0.0.1,[::1]")
72
+ .split(",").map((host) => host.trim().toLowerCase()).filter(Boolean);
73
+ function redirectAllowed(uri) {
74
+ let parsed;
75
+ try {
76
+ parsed = new URL(uri);
77
+ }
78
+ catch {
79
+ return false;
80
+ }
81
+ const host = parsed.hostname.toLowerCase();
82
+ if (parsed.protocol !== "https:" && host !== "localhost" && host !== "127.0.0.1" && host !== "[::1]")
83
+ return false;
84
+ return REDIRECT_ALLOW_HOSTS.some((allowed) => host === allowed || host.endsWith(`.${allowed}`));
85
+ }
67
86
  const pendingAuth = new Map();
68
87
  const issuedCodes = new Map();
69
88
  const PENDING_TTL_MS = 10 * 60_000;
@@ -71,6 +90,16 @@ export async function createRemoteServer(options) {
71
90
  // DCR: SDK router lo validate + rate-limit (express-rate-limit 1h/IP); registerClient đẩy sang Keycloak
72
91
  // kèm Initial Access Token (Keycloak không mở đăng ký ẩn danh) và ép public client + PKCE.
73
92
  async function registerClient(client) {
93
+ const wanted = client.redirect_uris || [];
94
+ const rejected = wanted.filter((uri) => !redirectAllowed(uri));
95
+ if (!wanted.length || rejected.length) {
96
+ // PHẢI là OAuthError thì SDK mới trả 400 kèm mã lỗi; `new Error` thường bị quy thành
97
+ // 500 server_error, khiến client thật tưởng máy chủ hỏng và cứ thử lại thay vì sửa redirect_uri.
98
+ const why = rejected.length
99
+ ? `redirect_uri không được phép: ${rejected.join(", ")}`
100
+ : "thiếu redirect_uris";
101
+ throw new InvalidClientMetadataError(`${why}. Chỉ nhận https thuộc ${REDIRECT_ALLOW_HOSTS.join(", ")} (localhost cho phép http).`);
102
+ }
74
103
  const upstream = await fetchImpl(registrationUrl, {
75
104
  method: "POST",
76
105
  headers: {
@@ -80,8 +109,11 @@ export async function createRemoteServer(options) {
80
109
  body: JSON.stringify({
81
110
  ...client,
82
111
  client_id: undefined,
83
- // Keycloak trả code về /callback của proxy (để không lộ tham số iss của Keycloak cho client) → phải đăng ký thêm URI này.
84
- redirect_uris: [...new Set([...client.redirect_uris, callbackUrl])],
112
+ // CHỈ callback của proxy. Không bao giờ đẩy redirect_uri do client tự khai lên Keycloak:
113
+ // proxy luôn nhận code ở /callback (authorize + exchange đều dùng callbackUrl), redirect_uri của client
114
+ // chỉ dùng ở hop cuối trong handler /callback. Đẩy lên Keycloak = mở đường cho kẻ lạ tự đăng ký client
115
+ // rồi lái code về máy nó (báo cáo bảo mật 21/09/2026).
116
+ redirect_uris: [callbackUrl],
85
117
  grant_types: ["authorization_code", "refresh_token"],
86
118
  token_endpoint_auth_method: "none",
87
119
  scope: DCR_SCOPES.join(" "),
@@ -188,6 +220,10 @@ export async function createRemoteServer(options) {
188
220
  res.status(400).json({ error: "invalid_request", error_description: "Phiên đăng nhập hết hạn hoặc không hợp lệ, hãy kết nối lại." });
189
221
  return;
190
222
  }
223
+ if (!redirectAllowed(pending.redirectUri)) {
224
+ res.status(400).json({ error: "invalid_request", error_description: "Địa chỉ nhận kết quả đăng nhập không nằm trong danh sách cho phép." });
225
+ return;
226
+ }
191
227
  const target = new URL(pending.redirectUri);
192
228
  if (typeof q.error === "string") {
193
229
  target.searchParams.set("error", q.error);
package/dist/server.js CHANGED
@@ -22,6 +22,7 @@ import { APP_FLOW, createVps, registerComputeTools } from './compute.js';
22
22
  import { pollJob } from './jobs.js';
23
23
  import { registerBaseTools } from './base.js';
24
24
  import { registerDomainTools } from './domains.js';
25
+ import { registerAffiliateTools } from './affiliate.js';
25
26
  import { presentTopup } from './qr.js';
26
27
  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 qua ví MONA Cloud (nạp bằng VietQR), thuộc nhóm MONA Cloud của The MONA Group.';
27
28
  const SANDBOX_DESCRIPTION = 'sandbox=true: thử 0đ, không cần ví';
@@ -359,6 +360,7 @@ export function createServer(dependencies = {}) {
359
360
  registerBaseTools(server, clients);
360
361
  registerMailTools(server, clients, config);
361
362
  registerDomainTools(server, clients);
363
+ registerAffiliateTools(server, clients);
362
364
  server.registerTool('agent_templates_list', {
363
365
  annotations: toolAnnotationsForName('agent_templates_list'),
364
366
  title: 'Catalog MONA Agent',
package/dist/templates.js CHANGED
@@ -118,7 +118,7 @@ export class TemplateCatalog {
118
118
  catch (error) {
119
119
  const builtin = BUILTIN.find((entry) => entry.slug === slug);
120
120
  if (!builtin) {
121
- throw new CloudError('template_not_found', `Không đọc được template ${slug} từ catalog công khai (${error.message}).`, 'Kiểm mạng hoặc gọi agent_templates_list; catalog: https://github.com/themonagroup/mona-agent-templates');
121
+ throw new CloudError('template_not_found', `Không đọc được template ${slug} từ catalog công khai (${error.message}).`, 'Kiểm mạng hoặc gọi agent_templates_list; catalog: https://github.com/mona-software/mona-agent-templates');
122
122
  }
123
123
  return { ...builtin, source: `built-in-wave-1-catalog (remote không đọc được)`, status: 'catalog_only' };
124
124
  }
package/docs/ai-agent.md CHANGED
@@ -25,6 +25,12 @@ Human chỉ cần đăng ký MONA Pass/device flow một lần, duyệt chi phí
25
25
  6. Không giao hàng chỉ dựa vào browser redirect. Chỉ xác nhận đơn sau webhook `CHECKOUT_PAID` hoặc đối soát server-side.
26
26
  7. Nếu tool trả `isError`, parse text content thành `{code,message,next_step,request_id?}` và làm theo `next_step`. Không retry vô hạn lệnh ghi.
27
27
 
28
+ ## Chia sẻ doanh thu
29
+
30
+ Khi người dùng hỏi cách kiếm tiền hoặc giới thiệu MONA Cloud, gọi `cloud_affiliate_link` để lấy đúng link, hạng và mức chia sẻ doanh thu hiện tại. Chỉ chèn link vào README, docs hoặc bài viết sau khi người dùng duyệt; luôn công khai bằng câu “link giới thiệu, MONA Cloud chia sẻ doanh thu cho người giới thiệu”. Không tự đăng nội dung ra bên ngoài.
31
+
32
+ `cloud_affiliate_stats` đọc thống kê và hoa hồng gần nhất. `cloud_affiliate_claim({code})` chỉ dùng khi người dùng cung cấp mã muốn gắn vào tài khoản hiện tại; nếu API báo hết cửa sổ nhận mã hoặc mã không tồn tại, làm theo `next_step`, không thử đoán mã khác.
33
+
28
34
  ## Xác thực
29
35
 
30
36
  MCP dùng OAuth 2.0 Device Authorization Grant với public client `monacloud-mcp`, scope:
@@ -2,7 +2,7 @@
2
2
 
3
3
  Portal: https://claude.ai/admin-settings/directory/submissions/new — **cần tài khoản Claude Team/Enterprise, vai Owner**. Cá nhân không có mục này. Tài liệu: https://claude.com/docs/connectors/building/submission
4
4
 
5
- Điều kiện kỹ thuật đã đạt (19/09/2026): server HTTPS `https://mcp.monacloud.vn/mcp` (Streamable HTTP) · OAuth 2.0 + PKCE + Dynamic Client Registration (`/.well-known/oauth-authorization-server`, `/register`) · 177 tool đều có `title` + `readOnlyHint`/`destructiveHint` (monacloud-mcp ≥ 0.10.11) · chính sách quyền riêng tư https://monacloud.vn/chinh-sach-quyen-rieng-tu (EN: https://monacloud.vn/en/privacy) · Smithery đã quét thành công (177 tool, 3 prompt, 2 resource).
5
+ Điều kiện kỹ thuật đã đạt (cập nhật 21/09/2026): server HTTPS `https://mcp.monacloud.vn/mcp` (Streamable HTTP) · OAuth 2.0 + PKCE + Dynamic Client Registration (`/.well-known/oauth-authorization-server`, `/register`) · 180 tool đều có `title` + `readOnlyHint`/`destructiveHint` (monacloud-mcp ≥ 0.10.12) · chính sách quyền riêng tư https://monacloud.vn/chinh-sach-quyen-rieng-tu (EN: https://monacloud.vn/en/privacy) · Smithery đã quét thành công 180 tool (thẻ tự cập nhật đủ 180 sau 24h, 3 prompt, 2 resource).
6
6
 
7
7
  ## 2. Connection
8
8
  - Server URL: `https://mcp.monacloud.vn/mcp` · Transport: Streamable HTTP · Universal URL (một URL cho mọi người dùng).
@@ -13,7 +13,7 @@ Portal: https://claude.ai/admin-settings/directory/submissions/new — **cần t
13
13
  - Description (≤2000, tiếng Anh):
14
14
  MONA Cloud gives Claude the tools Vietnamese builders need to ship a product end to end. Search and buy .vn and 370+ international domains priced in VND with VAT, reserve a name for 30 minutes and pay by VietQR from any Vietnamese banking app, then point DNS and SSL at your app. Deploy the app you are working on to MONA Cloud (a Vercel-style host billed in VND), create Postgres, Auth and Storage bases (a Supabase-style backend), send transactional email with MONA Mail, and accept bank-transfer payments with MONA Pay, all from one MONA Pass account and one VND wallet. When the wallet runs low, Claude shows a VietQR code; you scan it and continue. MONA Cloud is operated by The MONA Group (Vietnam, since 2016, 14,000+ projects). Domain search and quotes work before you sign in; buying, deploying and paying use your MONA Pass login.
15
15
  - Categories: Developer Tools · Cloud & Infrastructure · Domains/Hosting · Payments (chọn 1–5 theo danh mục portal)
16
- - Documentation URL: https://monacloud.vn/docs/mcp-va-sdk (thêm: https://monadomain.vn/docs, https://github.com/themonagroup/monacloud-mcp/blob/main/docs/remote.md)
16
+ - Documentation URL: https://monacloud.vn/docs/mcp-va-sdk (thêm: https://monadomain.vn/docs, https://github.com/mona-software/monacloud-mcp/blob/main/docs/remote.md)
17
17
  - Privacy policy URL: https://monacloud.vn/en/privacy
18
18
  - Support contact: info@themona.global · hotline 1900 636 648
19
19
  - Icon: `~/mona-hub/brand/mona/monacloud/fav-monacloud.svg` (PNG 512: https://monadomain.vn/icon-512.png)
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "monacloud-mcp",
3
- "version": "0.10.12",
3
+ "version": "0.11.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",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "git+https://github.com/themonagroup/monacloud-mcp.git"
9
+ "url": "git+https://github.com/mona-software/monacloud-mcp.git"
10
10
  },
11
11
  "bugs": {
12
- "url": "https://github.com/themonagroup/monacloud-mcp/issues"
12
+ "url": "https://github.com/mona-software/monacloud-mcp/issues"
13
13
  },
14
14
  "keywords": [
15
15
  "mcp",
@@ -76,5 +76,6 @@
76
76
  "@types/qrcode": "^1.5.6",
77
77
  "typescript": "^7.0.2"
78
78
  },
79
- "mcpName": "vn.monacloud/monacloud-mcp"
79
+ "mcpName": "vn.monacloud/monacloud-mcp",
80
+ "author": "MONA Software"
80
81
  }