feat(mcp): 添加 CCW_DISABLE_SANDBOX 环境变量支持禁用工作空间访问限制

- 在 path-validator.ts 中添加 isSandboxDisabled() 函数
- 修改 validatePath() 在沙箱禁用时跳过路径限制检查
- MCP server 启动日志显示沙箱状态
- /api/mcp-install-ccw API 支持 disableSandbox 参数
- Dashboard UI 添加禁用沙箱的复选框选项
- 添加中英文 i18n 翻译支持
This commit is contained in:
catlog22
2026-01-20 11:50:23 +08:00
parent eea859dd6f
commit c1d12384c3
6 changed files with 69 additions and 11 deletions

View File

@@ -1085,12 +1085,27 @@ function selectCcwTools(type) {
function getCcwPathConfig() {
const projectRootInput = document.querySelector('.ccw-project-root-input');
const allowedDirsInput = document.querySelector('.ccw-allowed-dirs-input');
const disableSandboxCheckbox = document.querySelector('.ccw-disable-sandbox-checkbox');
return {
projectRoot: projectRootInput?.value || '',
allowedDirs: allowedDirsInput?.value || ''
allowedDirs: allowedDirsInput?.value || '',
disableSandbox: disableSandboxCheckbox?.checked || false
};
}
// Get CCW_DISABLE_SANDBOX checkbox status for Claude Code mode
function getCcwDisableSandbox() {
// Check if already installed and has the setting
const ccwToolsConfig = projectMcpServers?.['ccw-tools'] || globalServers?.['ccw-tools'];
return ccwToolsConfig?.env?.CCW_DISABLE_SANDBOX === '1' || ccwToolsConfig?.env?.CCW_DISABLE_SANDBOX === 'true';
}
// Get CCW_DISABLE_SANDBOX checkbox status for Codex mode
function getCcwDisableSandboxCodex() {
const ccwToolsConfig = codexMcpServers?.['ccw-tools'];
return ccwToolsConfig?.env?.CCW_DISABLE_SANDBOX === '1' || ccwToolsConfig?.env?.CCW_DISABLE_SANDBOX === 'true';
}
// Set CCW_PROJECT_ROOT to current project path
function setCcwProjectRootToCurrent() {
const input = document.querySelector('.ccw-project-root-input');
@@ -1102,7 +1117,7 @@ function setCcwProjectRootToCurrent() {
// Build CCW Tools config with selected tools
// Uses globally installed ccw-mcp command (from claude-code-workflow package)
function buildCcwToolsConfig(selectedTools, pathConfig = {}) {
const { projectRoot, allowedDirs } = pathConfig;
const { projectRoot, allowedDirs, disableSandbox } = pathConfig;
// Use globally installed ccw-mcp command directly
// Requires: npm install -g claude-code-workflow
const config = {
@@ -1134,6 +1149,10 @@ function buildCcwToolsConfig(selectedTools, pathConfig = {}) {
if (allowedDirs && allowedDirs.trim()) {
config.env.CCW_ALLOWED_DIRS = allowedDirs.trim();
}
// Add sandbox disable option
if (disableSandbox) {
config.env.CCW_DISABLE_SANDBOX = '1';
}
// Remove env object if empty
if (config.env && Object.keys(config.env).length === 0) {

View File

@@ -972,6 +972,7 @@ const i18n = {
'mcp.useCurrentDir': 'Use current directory',
'mcp.useCurrentProject': 'Use current project',
'mcp.allowedDirsPlaceholder': 'Comma-separated paths (optional)',
'mcp.disableSandboxDesc': 'Allow access to any directory',
// Codex MCP
'mcp.codex.globalServers': 'Codex Global MCP Servers',
@@ -3299,6 +3300,7 @@ const i18n = {
'mcp.useCurrentDir': '使用当前目录',
'mcp.useCurrentProject': '使用当前项目',
'mcp.allowedDirsPlaceholder': '逗号分隔的路径列表(可选)',
'mcp.disableSandboxDesc': '允许访问任意目录',
// Codex MCP
'mcp.codex.globalServers': 'Codex 全局 MCP 服务器',

View File

@@ -298,6 +298,14 @@ async function renderMcpManager() {
placeholder="${t('mcp.allowedDirsPlaceholder')}"
value="${getCcwAllowedDirsCodex()}">
</div>
<div class="flex items-center gap-2">
<label class="text-xs text-muted-foreground w-36 shrink-0">CCW_DISABLE_SANDBOX</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="checkbox" class="ccw-disable-sandbox-checkbox-codex w-3 h-3"
${getCcwDisableSandboxCodex() ? 'checked' : ''}>
<span class="text-xs text-muted-foreground">${t('mcp.disableSandboxDesc')}</span>
</label>
</div>
</div>
</div>
</div>
@@ -512,6 +520,14 @@ async function renderMcpManager() {
placeholder="${t('mcp.allowedDirsPlaceholder')}"
value="${getCcwAllowedDirs()}">
</div>
<div class="flex items-center gap-2">
<label class="text-xs text-muted-foreground w-36 shrink-0">CCW_DISABLE_SANDBOX</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="checkbox" class="ccw-disable-sandbox-checkbox w-3 h-3"
${getCcwDisableSandbox() ? 'checked' : ''}>
<span class="text-xs text-muted-foreground">${t('mcp.disableSandboxDesc')}</span>
</label>
</div>
</div>
</div>
</div>