claude-code-workflow 6.3.48 → 6.3.50

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 (228) 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/issue/new.md +1 -2
  12. package/.claude/commands/memory/tips.md +332 -0
  13. package/.claude/commands/workflow/analyze-with-file.md +804 -0
  14. package/.claude/commands/workflow/brainstorm/auto-parallel.md +18 -43
  15. package/.claude/commands/workflow/brainstorm/role-analysis.md +705 -0
  16. package/.claude/commands/workflow/brainstorm-with-file.md +1153 -0
  17. package/.claude/commands/workflow/debug-with-file.md +7 -5
  18. package/.claude/commands/workflow/execute.md +6 -4
  19. package/.claude/commands/workflow/lite-plan.md +2 -2
  20. package/.claude/commands/workflow/plan-verify.md +162 -327
  21. package/.claude/commands/workflow/plan.md +162 -26
  22. package/.claude/commands/workflow/replan.md +78 -2
  23. package/.claude/commands/workflow/{review-fix.md → review-cycle-fix.md} +6 -6
  24. package/.claude/commands/workflow/review-module-cycle.md +2 -2
  25. package/.claude/commands/workflow/review-session-cycle.md +2 -2
  26. package/.claude/commands/workflow/tools/conflict-resolution.md +16 -26
  27. package/.claude/commands/workflow/tools/context-gather.md +81 -118
  28. package/.claude/commands/workflow/tools/task-generate-agent.md +94 -10
  29. package/.claude/skills/ccw-help/command.json +4 -4
  30. package/.claude/skills/lite-skill-generator/SKILL.md +650 -0
  31. package/.claude/skills/lite-skill-generator/templates/simple-skill.md +68 -0
  32. package/.claude/skills/lite-skill-generator/templates/style-guide.md +64 -0
  33. package/.claude/skills/skill-generator/SKILL.md +277 -85
  34. package/.claude/skills/skill-generator/phases/01-requirements-discovery.md +4 -15
  35. package/.claude/skills/skill-generator/phases/02-structure-generation.md +72 -17
  36. package/.claude/skills/skill-generator/phases/03-phase-generation.md +218 -51
  37. package/.claude/skills/skill-generator/phases/04-specs-templates.md +111 -41
  38. package/.claude/skills/skill-generator/phases/05-validation.md +139 -56
  39. package/.claude/skills/skill-generator/templates/autonomous-action.md +78 -268
  40. package/.claude/skills/skill-generator/templates/autonomous-orchestrator.md +14 -0
  41. package/.claude/skills/skill-generator/templates/code-analysis-action.md +12 -0
  42. package/.claude/skills/skill-generator/templates/llm-action.md +12 -0
  43. package/.claude/skills/skill-generator/templates/script-template.md +368 -0
  44. package/.claude/skills/skill-generator/templates/sequential-phase.md +14 -0
  45. package/.claude/skills/skill-generator/templates/skill-md.md +14 -0
  46. package/.claude/skills/skill-tuning/SKILL.md +130 -266
  47. package/.claude/skills/skill-tuning/phases/orchestrator.md +95 -283
  48. package/.claude/skills/skill-tuning/specs/problem-taxonomy.md +90 -198
  49. package/.claude/skills/skill-tuning/specs/tuning-strategies.md +193 -1345
  50. package/.claude/workflows/cli-templates/schemas/plan-verify-agent-schema.json +47 -0
  51. package/.claude/workflows/cli-templates/schemas/verify-json-schema.json +158 -0
  52. package/.claude/workflows/cli-tools-usage.md +1 -1
  53. package/.codex/AGENTS.md +1 -3
  54. package/.codex/prompts/analyze-with-file.md +610 -0
  55. package/.codex/prompts/brainstorm-to-cycle.md +456 -0
  56. package/.codex/prompts/brainstorm-with-file.md +937 -0
  57. package/.codex/prompts/clean.md +7 -2
  58. package/.codex/prompts/compact.md +5 -3
  59. package/.codex/prompts/debug-with-file.md +21 -22
  60. package/.codex/prompts/execute.md +6 -2
  61. package/.codex/prompts/issue-execute.md +10 -2
  62. package/.codex/prompts/issue-new.md +390 -285
  63. package/.codex/prompts/lite-execute.md +8 -7
  64. package/.codex/prompts/lite-fix.md +6 -2
  65. package/.codex/prompts/lite-plan-a.md +6 -2
  66. package/.codex/prompts/lite-plan-b.md +6 -2
  67. package/.codex/prompts/lite-plan-c.md +6 -2
  68. package/.codex/skills/ccw-cli-tools/SKILL.md +559 -0
  69. package/ccw/dist/cli.d.ts.map +1 -1
  70. package/ccw/dist/cli.js +1 -0
  71. package/ccw/dist/cli.js.map +1 -1
  72. package/ccw/dist/commands/cli.d.ts +1 -0
  73. package/ccw/dist/commands/cli.d.ts.map +1 -1
  74. package/ccw/dist/commands/cli.js +80 -9
  75. package/ccw/dist/commands/cli.js.map +1 -1
  76. package/ccw/dist/commands/issue.d.ts +2 -0
  77. package/ccw/dist/commands/issue.d.ts.map +1 -1
  78. package/ccw/dist/commands/issue.js +62 -20
  79. package/ccw/dist/commands/issue.js.map +1 -1
  80. package/ccw/dist/config/litellm-api-config-manager.d.ts.map +1 -1
  81. package/ccw/dist/config/litellm-api-config-manager.js +5 -3
  82. package/ccw/dist/config/litellm-api-config-manager.js.map +1 -1
  83. package/ccw/dist/config/litellm-provider-models.d.ts +73 -0
  84. package/ccw/dist/config/litellm-provider-models.d.ts.map +1 -0
  85. package/ccw/dist/config/litellm-provider-models.js +172 -0
  86. package/ccw/dist/config/litellm-provider-models.js.map +1 -0
  87. package/ccw/dist/config/provider-models.d.ts +25 -51
  88. package/ccw/dist/config/provider-models.d.ts.map +1 -1
  89. package/ccw/dist/config/provider-models.js +84 -149
  90. package/ccw/dist/config/provider-models.js.map +1 -1
  91. package/ccw/dist/config/storage-paths.d.ts.map +1 -1
  92. package/ccw/dist/config/storage-paths.js +23 -5
  93. package/ccw/dist/config/storage-paths.js.map +1 -1
  94. package/ccw/dist/core/auth/csrf-middleware.js +3 -3
  95. package/ccw/dist/core/auth/csrf-middleware.js.map +1 -1
  96. package/ccw/dist/core/dashboard-generator.d.ts.map +1 -1
  97. package/ccw/dist/core/dashboard-generator.js +3 -1
  98. package/ccw/dist/core/dashboard-generator.js.map +1 -1
  99. package/ccw/dist/core/routes/claude-routes.d.ts.map +1 -1
  100. package/ccw/dist/core/routes/claude-routes.js +206 -14
  101. package/ccw/dist/core/routes/claude-routes.js.map +1 -1
  102. package/ccw/dist/core/routes/cli-routes.d.ts.map +1 -1
  103. package/ccw/dist/core/routes/cli-routes.js +16 -1
  104. package/ccw/dist/core/routes/cli-routes.js.map +1 -1
  105. package/ccw/dist/core/routes/commands-routes.d.ts +7 -0
  106. package/ccw/dist/core/routes/commands-routes.d.ts.map +1 -0
  107. package/ccw/dist/core/routes/commands-routes.js +480 -0
  108. package/ccw/dist/core/routes/commands-routes.js.map +1 -0
  109. package/ccw/dist/core/routes/model-routes.d.ts +11 -0
  110. package/ccw/dist/core/routes/model-routes.d.ts.map +1 -0
  111. package/ccw/dist/core/routes/model-routes.js +112 -0
  112. package/ccw/dist/core/routes/model-routes.js.map +1 -0
  113. package/ccw/dist/core/routes/nav-status-routes.d.ts.map +1 -1
  114. package/ccw/dist/core/routes/nav-status-routes.js +84 -1
  115. package/ccw/dist/core/routes/nav-status-routes.js.map +1 -1
  116. package/ccw/dist/core/routes/provider-routes.d.ts +11 -0
  117. package/ccw/dist/core/routes/provider-routes.d.ts.map +1 -0
  118. package/ccw/dist/core/routes/provider-routes.js +67 -0
  119. package/ccw/dist/core/routes/provider-routes.js.map +1 -0
  120. package/ccw/dist/core/routes/skills-routes.d.ts.map +1 -1
  121. package/ccw/dist/core/routes/skills-routes.js +219 -7
  122. package/ccw/dist/core/routes/skills-routes.js.map +1 -1
  123. package/ccw/dist/core/routes/system-routes.d.ts.map +1 -1
  124. package/ccw/dist/core/routes/system-routes.js +58 -6
  125. package/ccw/dist/core/routes/system-routes.js.map +1 -1
  126. package/ccw/dist/core/server.d.ts.map +1 -1
  127. package/ccw/dist/core/server.js +13 -0
  128. package/ccw/dist/core/server.js.map +1 -1
  129. package/ccw/dist/mcp-server/index.js +2 -2
  130. package/ccw/dist/mcp-server/index.js.map +1 -1
  131. package/ccw/dist/tools/claude-cli-tools.d.ts +48 -11
  132. package/ccw/dist/tools/claude-cli-tools.d.ts.map +1 -1
  133. package/ccw/dist/tools/claude-cli-tools.js +146 -50
  134. package/ccw/dist/tools/claude-cli-tools.js.map +1 -1
  135. package/ccw/dist/tools/cli-config-manager.d.ts +1 -13
  136. package/ccw/dist/tools/cli-config-manager.d.ts.map +1 -1
  137. package/ccw/dist/tools/cli-config-manager.js +3 -27
  138. package/ccw/dist/tools/cli-config-manager.js.map +1 -1
  139. package/ccw/dist/tools/cli-executor-core.d.ts.map +1 -1
  140. package/ccw/dist/tools/cli-executor-core.js +7 -2
  141. package/ccw/dist/tools/cli-executor-core.js.map +1 -1
  142. package/ccw/dist/tools/cli-executor-state.d.ts.map +1 -1
  143. package/ccw/dist/tools/cli-history-store.d.ts +11 -0
  144. package/ccw/dist/tools/cli-history-store.d.ts.map +1 -1
  145. package/ccw/dist/tools/cli-history-store.js +82 -2
  146. package/ccw/dist/tools/cli-history-store.js.map +1 -1
  147. package/ccw/dist/tools/command-registry.d.ts +7 -0
  148. package/ccw/dist/tools/command-registry.d.ts.map +1 -1
  149. package/ccw/dist/tools/command-registry.js +14 -1
  150. package/ccw/dist/tools/command-registry.js.map +1 -1
  151. package/ccw/dist/tools/generate-module-docs.d.ts.map +1 -1
  152. package/ccw/dist/tools/generate-module-docs.js +11 -7
  153. package/ccw/dist/tools/generate-module-docs.js.map +1 -1
  154. package/ccw/dist/tools/litellm-executor.d.ts +1 -0
  155. package/ccw/dist/tools/litellm-executor.d.ts.map +1 -1
  156. package/ccw/dist/tools/litellm-executor.js +11 -9
  157. package/ccw/dist/tools/litellm-executor.js.map +1 -1
  158. package/ccw/dist/types/skill-types.d.ts +97 -0
  159. package/ccw/dist/types/skill-types.d.ts.map +1 -0
  160. package/ccw/dist/types/skill-types.js +6 -0
  161. package/ccw/dist/types/skill-types.js.map +1 -0
  162. package/ccw/src/cli.ts +1 -0
  163. package/ccw/src/commands/cli.ts +87 -9
  164. package/ccw/src/commands/issue.ts +81 -26
  165. package/ccw/src/config/litellm-api-config-manager.ts +5 -3
  166. package/ccw/src/config/litellm-provider-models.ts +222 -0
  167. package/ccw/src/config/provider-models.ts +91 -190
  168. package/ccw/src/config/storage-paths.ts +20 -5
  169. package/ccw/src/core/auth/csrf-middleware.ts +3 -3
  170. package/ccw/src/core/dashboard-generator.ts +3 -1
  171. package/ccw/src/core/routes/claude-routes.ts +233 -15
  172. package/ccw/src/core/routes/cli-routes.ts +18 -4
  173. package/ccw/src/core/routes/commands-routes.ts +620 -0
  174. package/ccw/src/core/routes/nav-status-routes.ts +95 -1
  175. package/ccw/src/core/routes/provider-routes.ts +78 -0
  176. package/ccw/src/core/routes/skills-routes.ts +266 -45
  177. package/ccw/src/core/routes/system-routes.ts +102 -50
  178. package/ccw/src/core/server.ts +13 -0
  179. package/ccw/src/mcp-server/index.ts +2 -2
  180. package/ccw/src/templates/dashboard-css/18-cli-settings.css +35 -0
  181. package/ccw/src/templates/dashboard-css/37-commands.css +193 -0
  182. package/ccw/src/templates/dashboard-js/components/navigation.js +4 -0
  183. package/ccw/src/templates/dashboard-js/i18n.js +116 -0
  184. package/ccw/src/templates/dashboard-js/views/cli-manager.js +249 -4
  185. package/ccw/src/templates/dashboard-js/views/commands-manager.js +503 -0
  186. package/ccw/src/templates/dashboard-js/views/issue-manager.js +7 -7
  187. package/ccw/src/templates/dashboard-js/views/mcp-manager.js +2 -7
  188. package/ccw/src/templates/dashboard-js/views/skills-manager.js +164 -23
  189. package/ccw/src/templates/dashboard.html +7 -0
  190. package/ccw/src/tools/claude-cli-tools.ts +170 -56
  191. package/ccw/src/tools/cli-config-manager.ts +2 -33
  192. package/ccw/src/tools/cli-executor-core.ts +8 -2
  193. package/ccw/src/tools/cli-history-store.ts +92 -2
  194. package/ccw/src/tools/command-registry.ts +16 -1
  195. package/ccw/src/tools/generate-module-docs.ts +11 -7
  196. package/ccw/src/tools/litellm-executor.ts +13 -9
  197. package/ccw/src/types/skill-types.ts +99 -0
  198. package/package.json +1 -1
  199. package/.claude/commands/enhance-prompt.md +0 -93
  200. package/.claude/commands/memory/code-map-memory.md +0 -687
  201. package/.claude/commands/memory/docs.md +0 -615
  202. package/.claude/commands/memory/load-skill-memory.md +0 -182
  203. package/.claude/commands/memory/skill-memory.md +0 -525
  204. package/.claude/commands/memory/swagger-docs.md +0 -773
  205. package/.claude/commands/memory/tech-research-rules.md +0 -310
  206. package/.claude/commands/memory/workflow-skill-memory.md +0 -517
  207. package/.claude/commands/task/breakdown.md +0 -208
  208. package/.claude/commands/task/create.md +0 -152
  209. package/.claude/commands/task/execute.md +0 -270
  210. package/.claude/commands/task/replan.md +0 -441
  211. package/.claude/commands/version.md +0 -254
  212. package/.claude/commands/workflow/action-plan-verify.md +0 -485
  213. package/.claude/commands/workflow/brainstorm/api-designer.md +0 -587
  214. package/.claude/commands/workflow/brainstorm/data-architect.md +0 -220
  215. package/.claude/commands/workflow/brainstorm/product-manager.md +0 -200
  216. package/.claude/commands/workflow/brainstorm/product-owner.md +0 -200
  217. package/.claude/commands/workflow/brainstorm/scrum-master.md +0 -200
  218. package/.claude/commands/workflow/brainstorm/subject-matter-expert.md +0 -200
  219. package/.claude/commands/workflow/brainstorm/system-architect.md +0 -389
  220. package/.claude/commands/workflow/brainstorm/ui-designer.md +0 -221
  221. package/.claude/commands/workflow/brainstorm/ux-expert.md +0 -221
  222. package/.claude/commands/workflow/debug.md +0 -331
  223. package/.claude/commands/workflow/develop-with-file.md +0 -1044
  224. package/.claude/skills/ccw-loop/README.md +0 -303
  225. package/.claude/skills/skill-generator/templates/script-bash.md +0 -277
  226. package/.claude/skills/skill-generator/templates/script-python.md +0 -198
  227. package/.codex/prompts/debug.md +0 -318
  228. 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
- }