mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-11 02:33:51 +08:00
feat: Add CCW MCP server and tools integration
- Introduced `ccw-mcp` command for running CCW tools as an MCP server. - Updated `package.json` to include new MCP dependencies and scripts. - Enhanced CLI with new options for `codex_lens` tool. - Implemented MCP server logic to expose CCW tools via Model Context Protocol. - Added new tools and updated existing ones for better functionality and documentation. - Created quick start and full documentation for MCP server usage. - Added tests for MCP server functionality to ensure reliability.
This commit is contained in:
@@ -579,20 +579,66 @@ async function createMcpServerWithConfig(name, serverConfig) {
|
||||
showRefreshToast(`Failed to create MCP server: ${err.message}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// ========== CCW Tools MCP Installation ==========
|
||||
async function installCcwToolsMcp() {
|
||||
// Define CCW Tools MCP server configuration
|
||||
// Use npx for better cross-platform compatibility (handles PATH issues)
|
||||
const ccwToolsConfig = {
|
||||
|
||||
// Get selected tools from checkboxes
|
||||
function getSelectedCcwTools() {
|
||||
const checkboxes = document.querySelectorAll('.ccw-tool-checkbox:checked');
|
||||
return Array.from(checkboxes).map(cb => cb.dataset.tool);
|
||||
}
|
||||
|
||||
// Select tools by category
|
||||
function selectCcwTools(type) {
|
||||
const checkboxes = document.querySelectorAll('.ccw-tool-checkbox');
|
||||
const coreTools = ['write_file', 'edit_file', 'codex_lens', 'smart_search'];
|
||||
|
||||
checkboxes.forEach(cb => {
|
||||
if (type === 'all') {
|
||||
cb.checked = true;
|
||||
} else if (type === 'none') {
|
||||
cb.checked = false;
|
||||
} else if (type === 'core') {
|
||||
cb.checked = coreTools.includes(cb.dataset.tool);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Build CCW Tools config with selected tools
|
||||
function buildCcwToolsConfig(selectedTools) {
|
||||
const config = {
|
||||
command: "npx",
|
||||
args: ["-y", "ccw-mcp"]
|
||||
};
|
||||
|
||||
// Add env if not all tools or not default 4 core tools
|
||||
const coreTools = ['write_file', 'edit_file', 'codex_lens', 'smart_search'];
|
||||
const isDefault = selectedTools.length === 4 &&
|
||||
coreTools.every(t => selectedTools.includes(t)) &&
|
||||
selectedTools.every(t => coreTools.includes(t));
|
||||
|
||||
if (selectedTools.length === 15) {
|
||||
config.env = { CCW_ENABLED_TOOLS: 'all' };
|
||||
} else if (!isDefault && selectedTools.length > 0) {
|
||||
config.env = { CCW_ENABLED_TOOLS: selectedTools.join(',') };
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
async function installCcwToolsMcp() {
|
||||
const selectedTools = getSelectedCcwTools();
|
||||
|
||||
if (selectedTools.length === 0) {
|
||||
showRefreshToast('Please select at least one tool', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
const ccwToolsConfig = buildCcwToolsConfig(selectedTools);
|
||||
|
||||
try {
|
||||
// Show loading toast
|
||||
showRefreshToast('Installing CCW Tools MCP...', 'info');
|
||||
|
||||
// Use the existing copyMcpServerToProject function
|
||||
const response = await fetch('/api/mcp-copy-server', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
@@ -609,7 +655,7 @@ async function installCcwToolsMcp() {
|
||||
if (result.success) {
|
||||
await loadMcpConfig();
|
||||
renderMcpManager();
|
||||
showRefreshToast('CCW Tools MCP installed successfully', 'success');
|
||||
showRefreshToast(`CCW Tools installed (${selectedTools.length} tools)`, 'success');
|
||||
} else {
|
||||
showRefreshToast(result.error || 'Failed to install CCW Tools MCP', 'error');
|
||||
}
|
||||
@@ -618,3 +664,42 @@ async function installCcwToolsMcp() {
|
||||
showRefreshToast(`Failed to install CCW Tools MCP: ${err.message}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function updateCcwToolsMcp() {
|
||||
const selectedTools = getSelectedCcwTools();
|
||||
|
||||
if (selectedTools.length === 0) {
|
||||
showRefreshToast('Please select at least one tool', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
const ccwToolsConfig = buildCcwToolsConfig(selectedTools);
|
||||
|
||||
try {
|
||||
showRefreshToast('Updating CCW Tools MCP...', 'info');
|
||||
|
||||
const response = await fetch('/api/mcp-copy-server', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
projectPath: projectPath,
|
||||
serverName: 'ccw-tools',
|
||||
serverConfig: ccwToolsConfig
|
||||
})
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error('Failed to update CCW Tools MCP');
|
||||
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
await loadMcpConfig();
|
||||
renderMcpManager();
|
||||
showRefreshToast(`CCW Tools updated (${selectedTools.length} tools)`, 'success');
|
||||
} else {
|
||||
showRefreshToast(result.error || 'Failed to update CCW Tools MCP', 'error');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to update CCW Tools MCP:', err);
|
||||
showRefreshToast(`Failed to update CCW Tools MCP: ${err.message}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,33 @@
|
||||
// MCP Manager View
|
||||
// Renders the MCP server management interface
|
||||
|
||||
// CCW Tools available for MCP
|
||||
const CCW_MCP_TOOLS = [
|
||||
// Core tools (always recommended)
|
||||
{ name: 'write_file', desc: 'Write/create files', core: true },
|
||||
{ name: 'edit_file', desc: 'Edit/replace content', core: true },
|
||||
{ name: 'codex_lens', desc: 'Code index & search', core: true },
|
||||
{ name: 'smart_search', desc: 'Quick regex/NL search', core: true },
|
||||
// Optional tools
|
||||
{ name: 'session_manager', desc: 'Workflow sessions', core: false },
|
||||
{ name: 'generate_module_docs', desc: 'Generate docs', core: false },
|
||||
{ name: 'update_module_claude', desc: 'Update CLAUDE.md', core: false },
|
||||
{ name: 'cli_executor', desc: 'Gemini/Qwen/Codex CLI', core: false },
|
||||
];
|
||||
|
||||
// Get currently enabled tools from installed config
|
||||
function getCcwEnabledTools() {
|
||||
const currentPath = projectPath.replace(/\//g, '\\');
|
||||
const projectData = mcpAllProjects[currentPath] || {};
|
||||
const ccwConfig = projectData.mcpServers?.['ccw-tools'];
|
||||
if (ccwConfig?.env?.CCW_ENABLED_TOOLS) {
|
||||
const val = ccwConfig.env.CCW_ENABLED_TOOLS;
|
||||
if (val.toLowerCase() === 'all') return CCW_MCP_TOOLS.map(t => t.name);
|
||||
return val.split(',').map(t => t.trim());
|
||||
}
|
||||
return CCW_MCP_TOOLS.filter(t => t.core).map(t => t.name);
|
||||
}
|
||||
|
||||
async function renderMcpManager() {
|
||||
const container = document.getElementById('mainContent');
|
||||
if (!container) return;
|
||||
@@ -36,7 +63,7 @@ async function renderMcpManager() {
|
||||
.filter(([name, info]) => !currentProjectServerNames.includes(name) && !info.isGlobal);
|
||||
// Check if CCW Tools is already installed
|
||||
const isCcwToolsInstalled = currentProjectServerNames.includes("ccw-tools");
|
||||
|
||||
const enabledTools = getCcwEnabledTools();
|
||||
|
||||
container.innerHTML = `
|
||||
<div class="mcp-manager">
|
||||
@@ -54,7 +81,7 @@ async function renderMcpManager() {
|
||||
${isCcwToolsInstalled ? `
|
||||
<span class="inline-flex items-center gap-1 px-2 py-0.5 text-xs font-semibold rounded-full bg-success-light text-success">
|
||||
<i data-lucide="check" class="w-3 h-3"></i>
|
||||
Installed
|
||||
${enabledTools.length} tools
|
||||
</span>
|
||||
` : `
|
||||
<span class="inline-flex items-center gap-1 px-2 py-0.5 text-xs font-semibold rounded-full bg-primary/20 text-primary">
|
||||
@@ -63,36 +90,35 @@ async function renderMcpManager() {
|
||||
</span>
|
||||
`}
|
||||
</div>
|
||||
<p class="text-sm text-muted-foreground mb-3">
|
||||
CCW built-in tools for file editing, code search, session management, and more
|
||||
</p>
|
||||
<div class="flex items-center gap-4 text-xs text-muted-foreground">
|
||||
<span class="flex items-center gap-1">
|
||||
<i data-lucide="layers" class="w-3 h-3"></i>
|
||||
15 tools available
|
||||
</span>
|
||||
<span class="flex items-center gap-1">
|
||||
<i data-lucide="zap" class="w-3 h-3"></i>
|
||||
Native integration
|
||||
</span>
|
||||
<span class="flex items-center gap-1">
|
||||
<i data-lucide="shield-check" class="w-3 h-3"></i>
|
||||
Built-in & tested
|
||||
</span>
|
||||
<!-- Tool Selection Grid -->
|
||||
<div class="grid grid-cols-3 sm:grid-cols-5 gap-2 mb-3">
|
||||
${CCW_MCP_TOOLS.map(tool => `
|
||||
<label class="flex items-center gap-1.5 text-xs cursor-pointer hover:bg-muted/50 rounded px-1.5 py-1 transition-colors">
|
||||
<input type="checkbox" class="ccw-tool-checkbox w-3 h-3"
|
||||
data-tool="${tool.name}"
|
||||
${enabledTools.includes(tool.name) ? 'checked' : ''}>
|
||||
<span class="${tool.core ? 'font-medium' : 'text-muted-foreground'}">${tool.desc}</span>
|
||||
</label>
|
||||
`).join('')}
|
||||
</div>
|
||||
<div class="flex items-center gap-3 text-xs">
|
||||
<button class="text-primary hover:underline" onclick="selectCcwTools('core')">Core only</button>
|
||||
<button class="text-primary hover:underline" onclick="selectCcwTools('all')">All</button>
|
||||
<button class="text-muted-foreground hover:underline" onclick="selectCcwTools('none')">None</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="shrink-0">
|
||||
${isCcwToolsInstalled ? `
|
||||
<button class="px-4 py-2 text-sm bg-muted text-muted-foreground rounded-lg cursor-not-allowed" disabled>
|
||||
<i data-lucide="check" class="w-4 h-4 inline mr-1"></i>
|
||||
Installed
|
||||
<button class="px-4 py-2 text-sm bg-primary text-primary-foreground rounded-lg hover:opacity-90 transition-opacity"
|
||||
onclick="updateCcwToolsMcp()">
|
||||
Update
|
||||
</button>
|
||||
` : `
|
||||
<button class="px-4 py-2 text-sm bg-primary text-primary-foreground rounded-lg hover:opacity-90 transition-opacity flex items-center gap-2"
|
||||
onclick="installCcwToolsMcp()">
|
||||
<i data-lucide="download" class="w-4 h-4"></i>
|
||||
Install CCW Tools
|
||||
Install
|
||||
</button>
|
||||
`}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user