@briefroom/mcp
Advanced tools
| import { z } from 'zod'; | ||
| import { runCliAsToolResult, } from '../lib/tool-result.js'; | ||
| export const deployHtmlDescription = 'Zip a local directory of HTML/CSS/JS and upload it to briefroom, returning a share URL. Supports a share-link expiry (also applied to the existing link on redeploy), a room display `name` (any language, e.g. Japanese; distinct from `room` slug — see below), and password protection (Pro+ plans). Uses BRIEFROOM_TOKEN (or the briefroom CLI login) for authentication. Non-interactive.'; | ||
| export const deployHtmlDescription = 'Zip a local directory of HTML/CSS/JS and upload it to briefroom, returning a share URL. Supports a share-link expiry (also applied to the existing link on redeploy), a room display `name` (any language, e.g. Japanese; distinct from `room` slug — see below), password protection (Pro+ plans), and `private: true` for a room only the signed-in owner can open (every plan). Uses BRIEFROOM_TOKEN (or the briefroom CLI login) for authentication. Non-interactive.'; | ||
| // Flag injection 防御: `-` 始まりの値は CLI の argv パーサ (citty/mri) に | ||
@@ -49,5 +49,9 @@ // フラグとして解釈され、`--api-url=http://evil/` を注入して PAT を攻撃者に | ||
| visibility: z | ||
| .enum(['unlisted', 'password_protected']) | ||
| .enum(['unlisted', 'password_protected', 'email_invite_only']) | ||
| .optional() | ||
| .describe("Share link visibility. 'unlisted' removes an existing password; 'password_protected' requires the password field."), | ||
| .describe("Share link visibility. 'unlisted' removes an existing password; 'password_protected' requires the password field; 'email_invite_only' makes the room private (identical to private: true)."), | ||
| private: z | ||
| .boolean() | ||
| .optional() | ||
| .describe('Make the room private: only the signed-in owner can open the URL. Available on every plan, does not count toward the shared-room limit, and can be combined with expires "never". Shorthand for visibility "email_invite_only".'), | ||
| }; | ||
@@ -70,2 +74,29 @@ export const DEPLOY_TIMEOUT_MS = 120_000; | ||
| } | ||
| // 判断 #111 (T-PRIVATE-ROOM-3): private は visibility 'email_invite_only' の別名。 | ||
| // password と同居させると「保護しつつ解除」になるので、上と同じ理由で早期に弾く。 | ||
| if (input.private === true && input.password !== undefined) { | ||
| return { | ||
| content: [ | ||
| { | ||
| type: 'text', | ||
| text: "Invalid input: 'password' cannot be combined with 'private'. A private room is already restricted to the signed-in owner.", | ||
| }, | ||
| ], | ||
| isError: true, | ||
| }; | ||
| } | ||
| if (input.private === true && | ||
| input.visibility !== undefined && | ||
| input.visibility !== 'email_invite_only') { | ||
| return { | ||
| content: [ | ||
| { | ||
| type: 'text', | ||
| text: `Invalid input: 'private' cannot be combined with visibility '${input.visibility}'. 'private' is shorthand for visibility 'email_invite_only'.`, | ||
| }, | ||
| ], | ||
| isError: true, | ||
| }; | ||
| } | ||
| const visibility = input.private === true ? 'email_invite_only' : input.visibility; | ||
| // 全 flag は path より前に置く (`--` 以降は全て positional 扱いになるため)。 | ||
@@ -80,4 +111,4 @@ // value flag は `--key=value` inline 形式 (中身に `--` があっても flag 化しない)。 | ||
| args.push(`--expires=${input.expires}`); | ||
| if (input.visibility) | ||
| args.push(`--visibility=${input.visibility}`); | ||
| if (visibility) | ||
| args.push(`--visibility=${visibility}`); | ||
| if (input.new) | ||
@@ -84,0 +115,0 @@ args.push('--new'); |
+2
-2
| { | ||
| "name": "@briefroom/mcp", | ||
| "version": "0.3.0", | ||
| "version": "0.4.0", | ||
| "description": "briefroom stdio MCP server — expose the briefroom CLI to Claude Code, Codex, and other agents.", | ||
@@ -46,3 +46,3 @@ "license": "MIT", | ||
| "zod": "^4.4.3", | ||
| "@briefroom/cli": "^0.3.0" | ||
| "@briefroom/cli": "^0.4.0" | ||
| }, | ||
@@ -49,0 +49,0 @@ "devDependencies": { |
39018
4.33%388
8.68%+ Added
- Removed
Updated