claude-code-workflow 6.3.48 → 6.3.49

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.
Files changed (211) hide show
  1. package/.claude/CLAUDE.md +6 -8
  2. package/.claude/agents/action-planning-agent.md +28 -45
  3. package/.claude/agents/cli-lite-planning-agent.md +93 -1
  4. package/.claude/agents/code-developer.md +144 -27
  5. package/.claude/commands/ccw-coordinator.md +175 -21
  6. package/.claude/commands/ccw-debug.md +832 -0
  7. package/.claude/commands/ccw.md +90 -9
  8. package/.claude/commands/cli/cli-init.md +1 -0
  9. package/.claude/commands/issue/convert-to-plan.md +718 -0
  10. package/.claude/commands/issue/from-brainstorm.md +382 -0
  11. package/.claude/commands/memory/tips.md +332 -0
  12. package/.claude/commands/workflow/analyze-with-file.md +804 -0
  13. package/.claude/commands/workflow/brainstorm/auto-parallel.md +18 -43
  14. package/.claude/commands/workflow/brainstorm/role-analysis.md +705 -0
  15. package/.claude/commands/workflow/brainstorm-with-file.md +1153 -0
  16. package/.claude/commands/workflow/debug-with-file.md +7 -5
  17. package/.claude/commands/workflow/execute.md +6 -4
  18. package/.claude/commands/workflow/lite-plan.md +2 -2
  19. package/.claude/commands/workflow/plan-verify.md +162 -327
  20. package/.claude/commands/workflow/plan.md +162 -26
  21. package/.claude/commands/workflow/replan.md +78 -2
  22. package/.claude/commands/workflow/{review-fix.md → review-cycle-fix.md} +6 -6
  23. package/.claude/commands/workflow/review-module-cycle.md +2 -2
  24. package/.claude/commands/workflow/review-session-cycle.md +2 -2
  25. package/.claude/commands/workflow/tools/conflict-resolution.md +16 -26
  26. package/.claude/commands/workflow/tools/context-gather.md +81 -118
  27. package/.claude/commands/workflow/tools/task-generate-agent.md +94 -10
  28. package/.claude/skills/ccw-help/command.json +4 -4
  29. package/.claude/skills/lite-skill-generator/SKILL.md +650 -0
  30. package/.claude/skills/lite-skill-generator/templates/simple-skill.md +68 -0
  31. package/.claude/skills/lite-skill-generator/templates/style-guide.md +64 -0
  32. package/.claude/skills/skill-generator/SKILL.md +277 -85
  33. package/.claude/skills/skill-generator/phases/01-requirements-discovery.md +4 -15
  34. package/.claude/skills/skill-generator/phases/02-structure-generation.md +72 -17
  35. package/.claude/skills/skill-generator/phases/03-phase-generation.md +218 -51
  36. package/.claude/skills/skill-generator/phases/04-specs-templates.md +111 -41
  37. package/.claude/skills/skill-generator/phases/05-validation.md +139 -56
  38. package/.claude/skills/skill-generator/templates/autonomous-action.md +78 -268
  39. package/.claude/skills/skill-generator/templates/autonomous-orchestrator.md +14 -0
  40. package/.claude/skills/skill-generator/templates/code-analysis-action.md +12 -0
  41. package/.claude/skills/skill-generator/templates/llm-action.md +12 -0
  42. package/.claude/skills/skill-generator/templates/script-template.md +368 -0
  43. package/.claude/skills/skill-generator/templates/sequential-phase.md +14 -0
  44. package/.claude/skills/skill-generator/templates/skill-md.md +14 -0
  45. package/.claude/skills/skill-tuning/SKILL.md +130 -266
  46. package/.claude/skills/skill-tuning/phases/orchestrator.md +95 -283
  47. package/.claude/skills/skill-tuning/specs/problem-taxonomy.md +90 -198
  48. package/.claude/skills/skill-tuning/specs/tuning-strategies.md +193 -1345
  49. package/.claude/workflows/cli-templates/schemas/plan-verify-agent-schema.json +47 -0
  50. package/.claude/workflows/cli-templates/schemas/verify-json-schema.json +158 -0
  51. package/.claude/workflows/cli-tools-usage.md +1 -1
  52. package/.codex/AGENTS.md +1 -3
  53. package/.codex/prompts/analyze-with-file.md +607 -0
  54. package/.codex/prompts/brainstorm-to-cycle.md +455 -0
  55. package/.codex/prompts/brainstorm-with-file.md +933 -0
  56. package/.codex/prompts/debug-with-file.md +15 -20
  57. package/.codex/skills/ccw-cli-tools/SKILL.md +559 -0
  58. package/ccw/dist/commands/cli.d.ts.map +1 -1
  59. package/ccw/dist/commands/cli.js +29 -5
  60. package/ccw/dist/commands/cli.js.map +1 -1
  61. package/ccw/dist/commands/issue.d.ts +2 -0
  62. package/ccw/dist/commands/issue.d.ts.map +1 -1
  63. package/ccw/dist/commands/issue.js +62 -20
  64. package/ccw/dist/commands/issue.js.map +1 -1
  65. package/ccw/dist/config/litellm-api-config-manager.d.ts.map +1 -1
  66. package/ccw/dist/config/litellm-api-config-manager.js +5 -3
  67. package/ccw/dist/config/litellm-api-config-manager.js.map +1 -1
  68. package/ccw/dist/config/litellm-provider-models.d.ts +73 -0
  69. package/ccw/dist/config/litellm-provider-models.d.ts.map +1 -0
  70. package/ccw/dist/config/litellm-provider-models.js +172 -0
  71. package/ccw/dist/config/litellm-provider-models.js.map +1 -0
  72. package/ccw/dist/config/provider-models.d.ts +25 -51
  73. package/ccw/dist/config/provider-models.d.ts.map +1 -1
  74. package/ccw/dist/config/provider-models.js +84 -149
  75. package/ccw/dist/config/provider-models.js.map +1 -1
  76. package/ccw/dist/config/storage-paths.d.ts.map +1 -1
  77. package/ccw/dist/config/storage-paths.js +23 -5
  78. package/ccw/dist/config/storage-paths.js.map +1 -1
  79. package/ccw/dist/core/auth/csrf-middleware.js +3 -3
  80. package/ccw/dist/core/auth/csrf-middleware.js.map +1 -1
  81. package/ccw/dist/core/dashboard-generator.d.ts.map +1 -1
  82. package/ccw/dist/core/dashboard-generator.js +3 -1
  83. package/ccw/dist/core/dashboard-generator.js.map +1 -1
  84. package/ccw/dist/core/routes/claude-routes.d.ts.map +1 -1
  85. package/ccw/dist/core/routes/claude-routes.js +206 -14
  86. package/ccw/dist/core/routes/claude-routes.js.map +1 -1
  87. package/ccw/dist/core/routes/cli-routes.d.ts.map +1 -1
  88. package/ccw/dist/core/routes/cli-routes.js.map +1 -1
  89. package/ccw/dist/core/routes/commands-routes.d.ts +7 -0
  90. package/ccw/dist/core/routes/commands-routes.d.ts.map +1 -0
  91. package/ccw/dist/core/routes/commands-routes.js +480 -0
  92. package/ccw/dist/core/routes/commands-routes.js.map +1 -0
  93. package/ccw/dist/core/routes/model-routes.d.ts +11 -0
  94. package/ccw/dist/core/routes/model-routes.d.ts.map +1 -0
  95. package/ccw/dist/core/routes/model-routes.js +112 -0
  96. package/ccw/dist/core/routes/model-routes.js.map +1 -0
  97. package/ccw/dist/core/routes/nav-status-routes.d.ts.map +1 -1
  98. package/ccw/dist/core/routes/nav-status-routes.js +84 -1
  99. package/ccw/dist/core/routes/nav-status-routes.js.map +1 -1
  100. package/ccw/dist/core/routes/provider-routes.d.ts +11 -0
  101. package/ccw/dist/core/routes/provider-routes.d.ts.map +1 -0
  102. package/ccw/dist/core/routes/provider-routes.js +67 -0
  103. package/ccw/dist/core/routes/provider-routes.js.map +1 -0
  104. package/ccw/dist/core/routes/skills-routes.d.ts.map +1 -1
  105. package/ccw/dist/core/routes/skills-routes.js +219 -7
  106. package/ccw/dist/core/routes/skills-routes.js.map +1 -1
  107. package/ccw/dist/core/routes/system-routes.d.ts.map +1 -1
  108. package/ccw/dist/core/routes/system-routes.js +58 -6
  109. package/ccw/dist/core/routes/system-routes.js.map +1 -1
  110. package/ccw/dist/core/server.d.ts.map +1 -1
  111. package/ccw/dist/core/server.js +13 -0
  112. package/ccw/dist/core/server.js.map +1 -1
  113. package/ccw/dist/mcp-server/index.js +2 -2
  114. package/ccw/dist/mcp-server/index.js.map +1 -1
  115. package/ccw/dist/tools/claude-cli-tools.d.ts +48 -11
  116. package/ccw/dist/tools/claude-cli-tools.d.ts.map +1 -1
  117. package/ccw/dist/tools/claude-cli-tools.js +146 -50
  118. package/ccw/dist/tools/claude-cli-tools.js.map +1 -1
  119. package/ccw/dist/tools/cli-config-manager.d.ts +1 -13
  120. package/ccw/dist/tools/cli-config-manager.d.ts.map +1 -1
  121. package/ccw/dist/tools/cli-config-manager.js +3 -27
  122. package/ccw/dist/tools/cli-config-manager.js.map +1 -1
  123. package/ccw/dist/tools/cli-executor-core.d.ts.map +1 -1
  124. package/ccw/dist/tools/cli-executor-core.js +7 -2
  125. package/ccw/dist/tools/cli-executor-core.js.map +1 -1
  126. package/ccw/dist/tools/cli-executor-state.d.ts.map +1 -1
  127. package/ccw/dist/tools/cli-history-store.d.ts +11 -0
  128. package/ccw/dist/tools/cli-history-store.d.ts.map +1 -1
  129. package/ccw/dist/tools/cli-history-store.js +82 -2
  130. package/ccw/dist/tools/cli-history-store.js.map +1 -1
  131. package/ccw/dist/tools/command-registry.d.ts +7 -0
  132. package/ccw/dist/tools/command-registry.d.ts.map +1 -1
  133. package/ccw/dist/tools/command-registry.js +14 -1
  134. package/ccw/dist/tools/command-registry.js.map +1 -1
  135. package/ccw/dist/tools/generate-module-docs.d.ts.map +1 -1
  136. package/ccw/dist/tools/generate-module-docs.js +11 -7
  137. package/ccw/dist/tools/generate-module-docs.js.map +1 -1
  138. package/ccw/dist/tools/litellm-executor.d.ts +1 -0
  139. package/ccw/dist/tools/litellm-executor.d.ts.map +1 -1
  140. package/ccw/dist/tools/litellm-executor.js +11 -9
  141. package/ccw/dist/tools/litellm-executor.js.map +1 -1
  142. package/ccw/dist/types/skill-types.d.ts +97 -0
  143. package/ccw/dist/types/skill-types.d.ts.map +1 -0
  144. package/ccw/dist/types/skill-types.js +6 -0
  145. package/ccw/dist/types/skill-types.js.map +1 -0
  146. package/ccw/src/commands/cli.ts +36 -5
  147. package/ccw/src/commands/issue.ts +81 -26
  148. package/ccw/src/config/litellm-api-config-manager.ts +5 -3
  149. package/ccw/src/config/litellm-provider-models.ts +222 -0
  150. package/ccw/src/config/provider-models.ts +91 -190
  151. package/ccw/src/config/storage-paths.ts +20 -5
  152. package/ccw/src/core/auth/csrf-middleware.ts +3 -3
  153. package/ccw/src/core/dashboard-generator.ts +3 -1
  154. package/ccw/src/core/routes/claude-routes.ts +233 -15
  155. package/ccw/src/core/routes/cli-routes.ts +2 -3
  156. package/ccw/src/core/routes/commands-routes.ts +620 -0
  157. package/ccw/src/core/routes/nav-status-routes.ts +95 -1
  158. package/ccw/src/core/routes/provider-routes.ts +78 -0
  159. package/ccw/src/core/routes/skills-routes.ts +266 -45
  160. package/ccw/src/core/routes/system-routes.ts +102 -50
  161. package/ccw/src/core/server.ts +13 -0
  162. package/ccw/src/mcp-server/index.ts +2 -2
  163. package/ccw/src/templates/dashboard-css/18-cli-settings.css +35 -0
  164. package/ccw/src/templates/dashboard-css/37-commands.css +193 -0
  165. package/ccw/src/templates/dashboard-js/components/navigation.js +4 -0
  166. package/ccw/src/templates/dashboard-js/i18n.js +116 -0
  167. package/ccw/src/templates/dashboard-js/views/cli-manager.js +249 -4
  168. package/ccw/src/templates/dashboard-js/views/commands-manager.js +503 -0
  169. package/ccw/src/templates/dashboard-js/views/issue-manager.js +7 -7
  170. package/ccw/src/templates/dashboard-js/views/mcp-manager.js +2 -7
  171. package/ccw/src/templates/dashboard-js/views/skills-manager.js +164 -23
  172. package/ccw/src/templates/dashboard.html +7 -0
  173. package/ccw/src/tools/claude-cli-tools.ts +170 -56
  174. package/ccw/src/tools/cli-config-manager.ts +2 -33
  175. package/ccw/src/tools/cli-executor-core.ts +8 -2
  176. package/ccw/src/tools/cli-history-store.ts +92 -2
  177. package/ccw/src/tools/command-registry.ts +16 -1
  178. package/ccw/src/tools/generate-module-docs.ts +11 -7
  179. package/ccw/src/tools/litellm-executor.ts +13 -9
  180. package/ccw/src/types/skill-types.ts +99 -0
  181. package/package.json +1 -1
  182. package/.claude/commands/enhance-prompt.md +0 -93
  183. package/.claude/commands/memory/code-map-memory.md +0 -687
  184. package/.claude/commands/memory/docs.md +0 -615
  185. package/.claude/commands/memory/load-skill-memory.md +0 -182
  186. package/.claude/commands/memory/skill-memory.md +0 -525
  187. package/.claude/commands/memory/swagger-docs.md +0 -773
  188. package/.claude/commands/memory/tech-research-rules.md +0 -310
  189. package/.claude/commands/memory/workflow-skill-memory.md +0 -517
  190. package/.claude/commands/task/breakdown.md +0 -208
  191. package/.claude/commands/task/create.md +0 -152
  192. package/.claude/commands/task/execute.md +0 -270
  193. package/.claude/commands/task/replan.md +0 -441
  194. package/.claude/commands/version.md +0 -254
  195. package/.claude/commands/workflow/action-plan-verify.md +0 -485
  196. package/.claude/commands/workflow/brainstorm/api-designer.md +0 -587
  197. package/.claude/commands/workflow/brainstorm/data-architect.md +0 -220
  198. package/.claude/commands/workflow/brainstorm/product-manager.md +0 -200
  199. package/.claude/commands/workflow/brainstorm/product-owner.md +0 -200
  200. package/.claude/commands/workflow/brainstorm/scrum-master.md +0 -200
  201. package/.claude/commands/workflow/brainstorm/subject-matter-expert.md +0 -200
  202. package/.claude/commands/workflow/brainstorm/system-architect.md +0 -389
  203. package/.claude/commands/workflow/brainstorm/ui-designer.md +0 -221
  204. package/.claude/commands/workflow/brainstorm/ux-expert.md +0 -221
  205. package/.claude/commands/workflow/debug.md +0 -331
  206. package/.claude/commands/workflow/develop-with-file.md +0 -1044
  207. package/.claude/skills/ccw-loop/README.md +0 -303
  208. package/.claude/skills/skill-generator/templates/script-bash.md +0 -277
  209. package/.claude/skills/skill-generator/templates/script-python.md +0 -198
  210. package/.codex/prompts/debug.md +0 -318
  211. package/ccw/src/core/routes/mcp-routes.ts.backup +0 -549
@@ -1,549 +0,0 @@
1
- /**
2
- * MCP Routes Module
3
- * Handles all MCP-related API endpoints
4
- */
5
- import type { IncomingMessage, ServerResponse } from 'http';
6
- import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
7
- import { join, dirname } from 'path';
8
- import { homedir } from 'os';
9
-
10
- // Claude config file path
11
- const CLAUDE_CONFIG_PATH = join(homedir(), '.claude.json');
12
-
13
- export interface RouteContext {
14
- pathname: string;
15
- url: URL;
16
- req: IncomingMessage;
17
- res: ServerResponse;
18
- initialPath: string;
19
- handlePostRequest: (req: IncomingMessage, res: ServerResponse, handler: (body: unknown) => Promise<any>) => void;
20
- broadcastToClients: (data: unknown) => void;
21
- }
22
-
23
- // ========================================
24
- // Helper Functions
25
- // ========================================
26
-
27
- /**
28
- * Get enterprise managed MCP path (platform-specific)
29
- */
30
- function getEnterpriseMcpPath(): string {
31
- const platform = process.platform;
32
- if (platform === 'darwin') {
33
- return '/Library/Application Support/ClaudeCode/managed-mcp.json';
34
- } else if (platform === 'win32') {
35
- return 'C:\\Program Files\\ClaudeCode\\managed-mcp.json';
36
- } else {
37
- // Linux and WSL
38
- return '/etc/claude-code/managed-mcp.json';
39
- }
40
- }
41
-
42
- /**
43
- * Safely read and parse JSON file
44
- */
45
- function safeReadJson(filePath) {
46
- try {
47
- if (!existsSync(filePath)) return null;
48
- const content = readFileSync(filePath, 'utf8');
49
- return JSON.parse(content);
50
- } catch {
51
- return null;
52
- }
53
- }
54
-
55
- /**
56
- * Get MCP servers from a JSON file (expects mcpServers key at top level)
57
- * @param {string} filePath
58
- * @returns {Object} mcpServers object or empty object
59
- */
60
- function getMcpServersFromFile(filePath) {
61
- const config = safeReadJson(filePath);
62
- if (!config) return {};
63
- return config.mcpServers || {};
64
- }
65
-
66
- /**
67
- * Get MCP configuration from multiple sources (per official Claude Code docs):
68
- *
69
- * Priority (highest to lowest):
70
- * 1. Enterprise managed-mcp.json (cannot be overridden)
71
- * 2. Local scope (project-specific private in ~/.claude.json)
72
- * 3. Project scope (.mcp.json in project root)
73
- * 4. User scope (mcpServers in ~/.claude.json)
74
- *
75
- * Note: ~/.claude/settings.json is for MCP PERMISSIONS, NOT definitions!
76
- *
77
- * @returns {Object}
78
- */
79
- function getMcpConfig() {
80
- try {
81
- const result = {
82
- projects: {},
83
- userServers: {}, // User-level servers from ~/.claude.json mcpServers
84
- enterpriseServers: {}, // Enterprise managed servers (highest priority)
85
- configSources: [] // Track where configs came from for debugging
86
- };
87
-
88
- // 1. Read Enterprise managed MCP servers (highest priority)
89
- const enterprisePath = getEnterpriseMcpPath();
90
- if (existsSync(enterprisePath)) {
91
- const enterpriseConfig = safeReadJson(enterprisePath);
92
- if (enterpriseConfig?.mcpServers) {
93
- result.enterpriseServers = enterpriseConfig.mcpServers;
94
- result.configSources.push({ type: 'enterprise', path: enterprisePath, count: Object.keys(enterpriseConfig.mcpServers).length });
95
- }
96
- }
97
-
98
- // 2. Read from ~/.claude.json
99
- if (existsSync(CLAUDE_CONFIG_PATH)) {
100
- const claudeConfig = safeReadJson(CLAUDE_CONFIG_PATH);
101
- if (claudeConfig) {
102
- // 2a. User-level mcpServers (top-level mcpServers key)
103
- if (claudeConfig.mcpServers) {
104
- result.userServers = claudeConfig.mcpServers;
105
- result.configSources.push({ type: 'user', path: CLAUDE_CONFIG_PATH, count: Object.keys(claudeConfig.mcpServers).length });
106
- }
107
-
108
- // 2b. Project-specific configurations (projects[path].mcpServers)
109
- if (claudeConfig.projects) {
110
- result.projects = claudeConfig.projects;
111
- }
112
- }
113
- }
114
-
115
- // 3. For each known project, check for .mcp.json (project-level config)
116
- const projectPaths = Object.keys(result.projects);
117
- for (const projectPath of projectPaths) {
118
- const mcpJsonPath = join(projectPath, '.mcp.json');
119
- if (existsSync(mcpJsonPath)) {
120
- const mcpJsonConfig = safeReadJson(mcpJsonPath);
121
- if (mcpJsonConfig?.mcpServers) {
122
- // Merge .mcp.json servers into project config
123
- // Project's .mcp.json has lower priority than ~/.claude.json projects[path].mcpServers
124
- const existingServers = result.projects[projectPath]?.mcpServers || {};
125
- result.projects[projectPath] = {
126
- ...result.projects[projectPath],
127
- mcpServers: {
128
- ...mcpJsonConfig.mcpServers, // .mcp.json (lower priority)
129
- ...existingServers // ~/.claude.json projects[path] (higher priority)
130
- },
131
- mcpJsonPath: mcpJsonPath // Track source for debugging
132
- };
133
- result.configSources.push({ type: 'project-mcp-json', path: mcpJsonPath, count: Object.keys(mcpJsonConfig.mcpServers).length });
134
- }
135
- }
136
- }
137
-
138
- // Build globalServers by merging user and enterprise servers
139
- // Enterprise servers override user servers
140
- result.globalServers = {
141
- ...result.userServers,
142
- ...result.enterpriseServers
143
- };
144
-
145
- return result;
146
- } catch (error: unknown) {
147
- console.error('Error reading MCP config:', error);
148
- return { projects: {}, globalServers: {}, userServers: {}, enterpriseServers: {}, configSources: [], error: (error as Error).message };
149
- }
150
- }
151
-
152
- /**
153
- * Normalize project path for .claude.json (Windows backslash format)
154
- * @param {string} path
155
- * @returns {string}
156
- */
157
- function normalizeProjectPathForConfig(path) {
158
- // Convert forward slashes to backslashes for Windows .claude.json format
159
- let normalized = path.replace(/\//g, '\\');
160
-
161
- // Handle /d/path format -> D:\path
162
- if (normalized.match(/^\\[a-zA-Z]\\/)) {
163
- normalized = normalized.charAt(1).toUpperCase() + ':' + normalized.slice(2);
164
- }
165
-
166
- return normalized;
167
- }
168
-
169
- /**
170
- * Toggle MCP server enabled/disabled
171
- * @param {string} projectPath
172
- * @param {string} serverName
173
- * @param {boolean} enable
174
- * @returns {Object}
175
- */
176
- function toggleMcpServerEnabled(projectPath, serverName, enable) {
177
- try {
178
- if (!existsSync(CLAUDE_CONFIG_PATH)) {
179
- return { error: '.claude.json not found' };
180
- }
181
-
182
- const content = readFileSync(CLAUDE_CONFIG_PATH, 'utf8');
183
- const config = JSON.parse(content);
184
-
185
- const normalizedPath = normalizeProjectPathForConfig(projectPath);
186
-
187
- if (!config.projects || !config.projects[normalizedPath]) {
188
- return { error: `Project not found: ${normalizedPath}` };
189
- }
190
-
191
- const projectConfig = config.projects[normalizedPath];
192
-
193
- // Ensure disabledMcpServers array exists
194
- if (!projectConfig.disabledMcpServers) {
195
- projectConfig.disabledMcpServers = [];
196
- }
197
-
198
- if (enable) {
199
- // Remove from disabled list
200
- projectConfig.disabledMcpServers = projectConfig.disabledMcpServers.filter(s => s !== serverName);
201
- } else {
202
- // Add to disabled list if not already there
203
- if (!projectConfig.disabledMcpServers.includes(serverName)) {
204
- projectConfig.disabledMcpServers.push(serverName);
205
- }
206
- }
207
-
208
- // Write back to file
209
- writeFileSync(CLAUDE_CONFIG_PATH, JSON.stringify(config, null, 2), 'utf8');
210
-
211
- return {
212
- success: true,
213
- serverName,
214
- enabled: enable,
215
- disabledMcpServers: projectConfig.disabledMcpServers
216
- };
217
- } catch (error: unknown) {
218
- console.error('Error toggling MCP server:', error);
219
- return { error: (error as Error).message };
220
- }
221
- }
222
-
223
- /**
224
- * Add MCP server to project
225
- * @param {string} projectPath
226
- * @param {string} serverName
227
- * @param {Object} serverConfig
228
- * @returns {Object}
229
- */
230
- function addMcpServerToProject(projectPath, serverName, serverConfig) {
231
- try {
232
- if (!existsSync(CLAUDE_CONFIG_PATH)) {
233
- return { error: '.claude.json not found' };
234
- }
235
-
236
- const content = readFileSync(CLAUDE_CONFIG_PATH, 'utf8');
237
- const config = JSON.parse(content);
238
-
239
- const normalizedPath = normalizeProjectPathForConfig(projectPath);
240
-
241
- // Create project entry if it doesn't exist
242
- if (!config.projects) {
243
- config.projects = {};
244
- }
245
-
246
- if (!config.projects[normalizedPath]) {
247
- config.projects[normalizedPath] = {
248
- allowedTools: [],
249
- mcpContextUris: [],
250
- mcpServers: {},
251
- enabledMcpjsonServers: [],
252
- disabledMcpjsonServers: [],
253
- hasTrustDialogAccepted: false,
254
- projectOnboardingSeenCount: 0,
255
- hasClaudeMdExternalIncludesApproved: false,
256
- hasClaudeMdExternalIncludesWarningShown: false
257
- };
258
- }
259
-
260
- const projectConfig = config.projects[normalizedPath];
261
-
262
- // Ensure mcpServers exists
263
- if (!projectConfig.mcpServers) {
264
- projectConfig.mcpServers = {};
265
- }
266
-
267
- // Add the server
268
- projectConfig.mcpServers[serverName] = serverConfig;
269
-
270
- // Write back to file
271
- writeFileSync(CLAUDE_CONFIG_PATH, JSON.stringify(config, null, 2), 'utf8');
272
-
273
- return {
274
- success: true,
275
- serverName,
276
- serverConfig
277
- };
278
- } catch (error: unknown) {
279
- console.error('Error adding MCP server:', error);
280
- return { error: (error as Error).message };
281
- }
282
- }
283
-
284
- /**
285
- * Remove MCP server from project
286
- * @param {string} projectPath
287
- * @param {string} serverName
288
- * @returns {Object}
289
- */
290
- function removeMcpServerFromProject(projectPath, serverName) {
291
- try {
292
- if (!existsSync(CLAUDE_CONFIG_PATH)) {
293
- return { error: '.claude.json not found' };
294
- }
295
-
296
- const content = readFileSync(CLAUDE_CONFIG_PATH, 'utf8');
297
- const config = JSON.parse(content);
298
-
299
- const normalizedPath = normalizeProjectPathForConfig(projectPath);
300
-
301
- if (!config.projects || !config.projects[normalizedPath]) {
302
- return { error: `Project not found: ${normalizedPath}` };
303
- }
304
-
305
- const projectConfig = config.projects[normalizedPath];
306
-
307
- if (!projectConfig.mcpServers || !projectConfig.mcpServers[serverName]) {
308
- return { error: `Server not found: ${serverName}` };
309
- }
310
-
311
- // Remove the server
312
- delete projectConfig.mcpServers[serverName];
313
-
314
- // Also remove from disabled list if present
315
- if (projectConfig.disabledMcpServers) {
316
- projectConfig.disabledMcpServers = projectConfig.disabledMcpServers.filter(s => s !== serverName);
317
- }
318
-
319
- // Write back to file
320
- writeFileSync(CLAUDE_CONFIG_PATH, JSON.stringify(config, null, 2), 'utf8');
321
-
322
- return {
323
- success: true,
324
- serverName,
325
- removed: true
326
- };
327
- } catch (error: unknown) {
328
- console.error('Error removing MCP server:', error);
329
- return { error: (error as Error).message };
330
- }
331
- }
332
-
333
- /**
334
- * Add MCP server to global/user scope (top-level mcpServers in ~/.claude.json)
335
- * @param {string} serverName
336
- * @param {Object} serverConfig
337
- * @returns {Object}
338
- */
339
- function addGlobalMcpServer(serverName, serverConfig) {
340
- try {
341
- if (!existsSync(CLAUDE_CONFIG_PATH)) {
342
- return { error: '.claude.json not found' };
343
- }
344
-
345
- const content = readFileSync(CLAUDE_CONFIG_PATH, 'utf8');
346
- const config = JSON.parse(content);
347
-
348
- // Ensure top-level mcpServers exists
349
- if (!config.mcpServers) {
350
- config.mcpServers = {};
351
- }
352
-
353
- // Add the server to top-level mcpServers
354
- config.mcpServers[serverName] = serverConfig;
355
-
356
- // Write back to file
357
- writeFileSync(CLAUDE_CONFIG_PATH, JSON.stringify(config, null, 2), 'utf8');
358
-
359
- return {
360
- success: true,
361
- serverName,
362
- serverConfig,
363
- scope: 'global'
364
- };
365
- } catch (error: unknown) {
366
- console.error('Error adding global MCP server:', error);
367
- return { error: (error as Error).message };
368
- }
369
- }
370
-
371
- /**
372
- * Remove MCP server from global/user scope (top-level mcpServers)
373
- * @param {string} serverName
374
- * @returns {Object}
375
- */
376
- function removeGlobalMcpServer(serverName) {
377
- try {
378
- if (!existsSync(CLAUDE_CONFIG_PATH)) {
379
- return { error: '.claude.json not found' };
380
- }
381
-
382
- const content = readFileSync(CLAUDE_CONFIG_PATH, 'utf8');
383
- const config = JSON.parse(content);
384
-
385
- if (!config.mcpServers || !config.mcpServers[serverName]) {
386
- return { error: `Global server not found: ${serverName}` };
387
- }
388
-
389
- // Remove the server from top-level mcpServers
390
- delete config.mcpServers[serverName];
391
-
392
- // Write back to file
393
- writeFileSync(CLAUDE_CONFIG_PATH, JSON.stringify(config, null, 2), 'utf8');
394
-
395
- return {
396
- success: true,
397
- serverName,
398
- removed: true,
399
- scope: 'global'
400
- };
401
- } catch (error: unknown) {
402
- console.error('Error removing global MCP server:', error);
403
- return { error: (error as Error).message };
404
- }
405
- }
406
-
407
- /**
408
- * Read settings file safely
409
- * @param {string} filePath
410
- * @returns {Object}
411
- */
412
- function readSettingsFile(filePath) {
413
- try {
414
- if (!existsSync(filePath)) {
415
- return {};
416
- }
417
- const content = readFileSync(filePath, 'utf8');
418
- return JSON.parse(content);
419
- } catch (error: unknown) {
420
- console.error(`Error reading settings file ${filePath}:`, error);
421
- return {};
422
- }
423
- }
424
-
425
- /**
426
- * Write settings file safely
427
- * @param {string} filePath
428
- * @param {Object} settings
429
- */
430
- function writeSettingsFile(filePath, settings) {
431
- const dirPath = dirname(filePath);
432
- // Ensure directory exists
433
- if (!existsSync(dirPath)) {
434
- mkdirSync(dirPath, { recursive: true });
435
- }
436
- writeFileSync(filePath, JSON.stringify(settings, null, 2), 'utf8');
437
- }
438
-
439
- /**
440
- * Get project settings path
441
- * @param {string} projectPath
442
- * @returns {string}
443
- */
444
- function getProjectSettingsPath(projectPath) {
445
- const normalizedPath = projectPath.replace(/\//g, '\\').replace(/^\\([a-zA-Z])\\/, '$1:\\');
446
- return join(normalizedPath, '.claude', 'settings.json');
447
- }
448
-
449
- // ========================================
450
- // Route Handlers
451
- // ========================================
452
-
453
- /**
454
- * Handle MCP routes
455
- * @returns true if route was handled, false otherwise
456
- */
457
- export async function handleMcpRoutes(ctx: RouteContext): Promise<boolean> {
458
- const { pathname, url, req, res, initialPath, handlePostRequest, broadcastToClients } = ctx;
459
-
460
- // API: Get MCP configuration
461
- if (pathname === '/api/mcp-config') {
462
- const mcpData = getMcpConfig();
463
- res.writeHead(200, { 'Content-Type': 'application/json' });
464
- res.end(JSON.stringify(mcpData));
465
- return true;
466
- }
467
-
468
- // API: Toggle MCP server enabled/disabled
469
- if (pathname === '/api/mcp-toggle' && req.method === 'POST') {
470
- handlePostRequest(req, res, async (body) => {
471
- const { projectPath, serverName, enable } = body;
472
- if (!projectPath || !serverName) {
473
- return { error: 'projectPath and serverName are required', status: 400 };
474
- }
475
- return toggleMcpServerEnabled(projectPath, serverName, enable);
476
- });
477
- return true;
478
- }
479
-
480
- // API: Copy MCP server to project
481
- if (pathname === '/api/mcp-copy-server' && req.method === 'POST') {
482
- handlePostRequest(req, res, async (body) => {
483
- const { projectPath, serverName, serverConfig } = body;
484
- if (!projectPath || !serverName || !serverConfig) {
485
- return { error: 'projectPath, serverName, and serverConfig are required', status: 400 };
486
- }
487
- return addMcpServerToProject(projectPath, serverName, serverConfig);
488
- });
489
- return true;
490
- }
491
-
492
- // API: Install CCW MCP server to project
493
- if (pathname === '/api/mcp-install-ccw' && req.method === 'POST') {
494
- handlePostRequest(req, res, async (body) => {
495
- const { projectPath } = body;
496
- if (!projectPath) {
497
- return { error: 'projectPath is required', status: 400 };
498
- }
499
-
500
- // Generate CCW MCP server config
501
- const ccwMcpConfig = {
502
- command: "ccw-mcp",
503
- args: []
504
- };
505
-
506
- // Use existing addMcpServerToProject to install CCW MCP
507
- return addMcpServerToProject(projectPath, 'ccw-mcp', ccwMcpConfig);
508
- });
509
- return true;
510
- }
511
-
512
- // API: Remove MCP server from project
513
- if (pathname === '/api/mcp-remove-server' && req.method === 'POST') {
514
- handlePostRequest(req, res, async (body) => {
515
- const { projectPath, serverName } = body;
516
- if (!projectPath || !serverName) {
517
- return { error: 'projectPath and serverName are required', status: 400 };
518
- }
519
- return removeMcpServerFromProject(projectPath, serverName);
520
- });
521
- return true;
522
- }
523
-
524
- // API: Add MCP server to global scope (top-level mcpServers in ~/.claude.json)
525
- if (pathname === '/api/mcp-add-global-server' && req.method === 'POST') {
526
- handlePostRequest(req, res, async (body) => {
527
- const { serverName, serverConfig } = body;
528
- if (!serverName || !serverConfig) {
529
- return { error: 'serverName and serverConfig are required', status: 400 };
530
- }
531
- return addGlobalMcpServer(serverName, serverConfig);
532
- });
533
- return true;
534
- }
535
-
536
- // API: Remove MCP server from global scope
537
- if (pathname === '/api/mcp-remove-global-server' && req.method === 'POST') {
538
- handlePostRequest(req, res, async (body) => {
539
- const { serverName } = body;
540
- if (!serverName) {
541
- return { error: 'serverName is required', status: 400 };
542
- }
543
- return removeGlobalMcpServer(serverName);
544
- });
545
- return true;
546
- }
547
-
548
- return false;
549
- }