Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions doc/mcp-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -2174,10 +2174,10 @@ CloudApp 域统一写入口。action=deployApp 会先 uploadCode 再 createApp
---

### `queryPermissions`
权限域统一只读入口。支持查询资源权限、角色列表/详情、应用用户列表/详情。
查询 CloudBase 权限与用户配置,支持查询资源权限(数据库/云函数/存储桶等)、角色列表/详情、应用用户列表/详情。

资源权限示例
- 查询存储桶 ACL:`action="getResourcePermission", resourceType="storage", resourceId="bucket-name"`(返回 permission 字段:READONLY/PRIVATE/ADMINWRITE/ADMINONLY/CUSTOM)
示例
- 查询存储桶权限:`action="getResourcePermission", resourceType="storage", resourceId="bucket-name"`

#### 参数

Expand Down Expand Up @@ -2236,7 +2236,13 @@ CloudApp 域统一写入口。action=deployApp 会先 uploadCode 再 createApp
---

### `managePermissions`
权限域统一写入口。支持修改资源权限、角色管理、成员与策略增删、应用用户 CRUD。`createUser` / `updateUser` 是环境侧应用用户管理能力,适合测试账号、管理员或预置用户,不应替代浏览器里的 Web SDK 注册表单;前端用户名密码注册应使用 `auth.signUp(\{ username, password \})`,登录应使用 `auth.signInWithPassword(\{ username, password \})`。注意:`securityRule` 的详细语义取决于 `resourceType`;`doc._openid`、`auth.openid`、查询条件子集校验,以及 `create` / `update` / `delete` JSON 模板仅适用于 `resourceType="noSqlDatabase"` 的文档数据库安全规则。配置 `function` 或 `storage` 时,请参考各自官方安全规则文档,而不是复用 NoSQL 模板。
管理 CloudBase 权限与用户配置,支持修改资源权限(数据库/云函数/存储桶等)、角色管理、成员与策略增删、应用用户 CRUD。

示例:
- 设置存储桶为私有:`action="updateResourcePermission", resourceType="storage", resourceId="bucket-name", permission="PRIVATE"`
- 创建角色:`action="createRole", roleName="admin", roleIdentity="admin"`

注意:`createUser` / `updateUser` 是环境侧应用用户管理能力,适合测试账号、管理员或预置用户,不应替代浏览器里的 Web SDK 注册表单。前端用户名密码注册应使用 `auth.signUp(\{ username, password \})`,登录应使用 `auth.signInWithPassword(\{ username, password \})`。`securityRule` 的详细语义取决于 `resourceType`,请参考对应官方文档。

#### 参数

Expand Down
22 changes: 22 additions & 0 deletions mcp/src/tools/hosting.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,28 @@ describe('hosting tools', () => {
expect(mockSendDeployNotification).toHaveBeenCalled();
});

it('manageHosting(action=upload) should fail fast when current env lacks static hosting storage config', async () => {
mockGetEnvInfo.mockResolvedValueOnce({
EnvInfo: {
StaticStorages: null,
},
});

const tools = createMockServer();
const payload = JSON.parse((await tools.manageHosting.handler({
action: 'upload',
localPath: '/tmp/site-dist',
cloudPath: '/todo',
ignore: ['node_modules', '.DS_Store', '*.map'],
})).content[0].text);

expect(payload.success).toBe(false);
expect(payload.errorCode).toBe('HOSTING_UPLOAD_FAILED');
expect(payload.message).toContain('当前环境 env-test 未发现静态托管资源配置');
expect(payload.message).toContain('auth(action="set_env"');
expect(mockUploadFiles).not.toHaveBeenCalled();
});

it('manageHosting(action=delete) should require explicit confirm=true', async () => {
const tools = createMockServer();
const payload = JSON.parse((await tools.manageHosting.handler({
Expand Down
20 changes: 20 additions & 0 deletions mcp/src/tools/hosting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,25 @@ async function resolveHostingStaticDomain(cloudbase: any, logger?: ExtendedMcpSe
}
}

async function assertHostingUploadEnvironmentReady(
cloudbase: any,
cloudBaseOptions?: { envId?: string },
logger?: ExtendedMcpServer['logger'],
) {
const envId = await getEnvId(cloudBaseOptions);
const envInfo = await cloudbase.env.getEnvInfo() as ExtendedEnvInfo;
logCloudBaseResult(logger, envInfo);

const staticStorage = envInfo.EnvInfo?.StaticStorages?.[0];
if (staticStorage?.Bucket) {
return;
}

throw new Error(
`当前环境 ${envId} 未发现静态托管资源配置,无法上传文件。请先确认 MCP 已绑定到已开通静态托管的 CloudBase 环境;如需切换环境,请调用 auth(action="set_env", envId="目标环境ID") 后重试。`,
);
}

function buildFailureResult(action: string, error: unknown) {
return buildJsonToolResult({
success: false,
Expand Down Expand Up @@ -657,6 +676,7 @@ export function registerHostingTools(server: ExtendedMcpServer) {

let result: unknown;
try {
await assertHostingUploadEnvironmentReady(cloudbase, cloudBaseOptions, server.logger);
result = await cloudbase.hosting.uploadFiles({
localPath: input.localPath,
cloudPath: input.cloudPath,
Expand Down
2 changes: 1 addition & 1 deletion mcp/src/tools/permissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ export function registerPermissionTools(server: ExtendedMcpServer) {
{
title: "管理 CloudBase 权限与用户配置",
description:
"管理 CloudBase 权限与用户配置,支持修改资源权限(数据库/云函数/存储桶等)、角色管理、成员与策略增删、应用用户 CRUD。\n\n示例:\n- 设置存储桶为私有:`action=\"setResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\", permission=\"PRIVATE\"`\n- 创建角色:`action=\"createRole\", roleName=\"admin\", roleIdentity=\"admin\"`\n\n注意:`createUser` / `updateUser` 是环境侧应用用户管理能力,适合测试账号、管理员或预置用户,不应替代浏览器里的 Web SDK 注册表单。前端用户名密码注册应使用 `auth.signUp({ username, password })`,登录应使用 `auth.signInWithPassword({ username, password })`。`securityRule` 的详细语义取决于 `resourceType`,请参考对应官方文档。",
"管理 CloudBase 权限与用户配置,支持修改资源权限(数据库/云函数/存储桶等)、角色管理、成员与策略增删、应用用户 CRUD。\n\n示例:\n- 设置存储桶为私有:`action=\"updateResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\", permission=\"PRIVATE\"`\n- 创建角色:`action=\"createRole\", roleName=\"admin\", roleIdentity=\"admin\"`\n\n注意:`createUser` / `updateUser` 是环境侧应用用户管理能力,适合测试账号、管理员或预置用户,不应替代浏览器里的 Web SDK 注册表单。前端用户名密码注册应使用 `auth.signUp({ username, password })`,登录应使用 `auth.signInWithPassword({ username, password })`。`securityRule` 的详细语义取决于 `resourceType`,请参考对应官方文档。",
inputSchema: {
action: z.enum(MANAGE_PERMISSION_ACTIONS),
resourceType: z
Expand Down
5 changes: 1 addition & 4 deletions mcp/webpack/base.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ function createBaseConfig() {
// 处理 TypeScript ESM 导入中的 .js 扩展名
'.js': ['.ts', '.js'],
},
alias: {
'graceful-fs': path.resolve(__dirname, '../node_modules/graceful-fs')
},
fallback: {
// 在 Node.js 环境中我们不需要这些 polyfills
"buffer": false,
Expand Down Expand Up @@ -74,4 +71,4 @@ function createBaseConfig() {
};
}

module.exports = createBaseConfig;
module.exports = createBaseConfig;
4 changes: 2 additions & 2 deletions scripts/tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -2348,7 +2348,7 @@
},
{
"name": "queryPermissions",
"description": "权限域统一只读入口。支持查询资源权限、角色列表/详情、应用用户列表/详情。\n\n资源权限示例:\n- 查询存储桶 ACL:`action=\"getResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\"`(返回 permission 字段:READONLY/PRIVATE/ADMINWRITE/ADMINONLY/CUSTOM)",
"description": "查询 CloudBase 权限与用户配置,支持查询资源权限(数据库/云函数/存储桶等)、角色列表/详情、应用用户列表/详情。\n\n示例:\n- 查询存储桶权限:`action=\"getResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\"`",
"inputSchema": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -2412,7 +2412,7 @@
},
{
"name": "managePermissions",
"description": "权限域统一写入口。支持修改资源权限、角色管理、成员与策略增删、应用用户 CRUD。`createUser` / `updateUser` 是环境侧应用用户管理能力,适合测试账号、管理员或预置用户,不应替代浏览器里的 Web SDK 注册表单前端用户名密码注册应使用 `auth.signUp({ username, password })`,登录应使用 `auth.signInWithPassword({ username, password })`。注意:`securityRule` 的详细语义取决于 `resourceType`;`doc._openid`、`auth.openid`、查询条件子集校验,以及 `create` / `update` / `delete` JSON 模板仅适用于 `resourceType=\"noSqlDatabase\"` 的文档数据库安全规则。配置 `function` 或 `storage` 时,请参考各自官方安全规则文档,而不是复用 NoSQL 模板。",
"description": "管理 CloudBase 权限与用户配置,支持修改资源权限(数据库/云函数/存储桶等)、角色管理、成员与策略增删、应用用户 CRUD。\n\n示例:\n- 设置存储桶为私有:`action=\"updateResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\", permission=\"PRIVATE\"`\n- 创建角色:`action=\"createRole\", roleName=\"admin\", roleIdentity=\"admin\"`\n\n注意:`createUser` / `updateUser` 是环境侧应用用户管理能力,适合测试账号、管理员或预置用户,不应替代浏览器里的 Web SDK 注册表单前端用户名密码注册应使用 `auth.signUp({ username, password })`,登录应使用 `auth.signInWithPassword({ username, password })`。`securityRule` 的详细语义取决于 `resourceType`,请参考对应官方文档。",
"inputSchema": {
"type": "object",
"properties": {
Expand Down
Loading