aws-runtime-bridge 1.3.0 → 1.3.2

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 (73) hide show
  1. package/README.md +75 -77
  2. package/dist/config.d.ts +1 -7
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js +2 -18
  5. package/dist/index.js +0 -0
  6. package/dist/middleware/auth.d.ts +2 -2
  7. package/dist/middleware/auth.d.ts.map +1 -1
  8. package/dist/middleware/auth.js +4 -10
  9. package/dist/routes/instance.d.ts.map +1 -1
  10. package/dist/routes/instance.js +8 -2
  11. package/dist/routes/properties.test.js +4 -4
  12. package/dist/routes/runtime-binding.d.ts.map +1 -1
  13. package/dist/routes/runtime-binding.js +3 -11
  14. package/dist/services/auto-register.d.ts.map +1 -1
  15. package/dist/services/auto-register.js +15 -8
  16. package/dist/services/auto-register.test.js +4 -0
  17. package/dist/services/aws-client-agent-mcp.d.ts.map +1 -1
  18. package/dist/services/aws-client-agent-mcp.js +1 -6
  19. package/dist/services/aws-client-agent-mcp.test.js +0 -2
  20. package/dist/services/orphan-monitor.d.ts.map +1 -1
  21. package/dist/services/orphan-monitor.js +8 -2
  22. package/dist/services/runtime-binding.d.ts +1 -0
  23. package/dist/services/runtime-binding.d.ts.map +1 -1
  24. package/dist/services/runtime-binding.js +31 -3
  25. package/dist/services/runtime-binding.test.js +42 -2
  26. package/dist/services/session-output.d.ts.map +1 -1
  27. package/dist/services/session-output.js +21 -4
  28. package/dist/utils/file-utils.d.ts.map +1 -1
  29. package/dist/utils/file-utils.js +7 -2
  30. package/dist/utils/file-utils.test.js +3 -1
  31. package/dist/utils/yaml-utils.test.js +129 -129
  32. package/node_modules/@cc-switch/sdk/README.md +540 -540
  33. package/node_modules/@cc-switch/sdk/package.json +31 -31
  34. package/package/aws-client-agent-mcp/README.md +287 -288
  35. package/package/aws-client-agent-mcp/dist/agent-client.test.js +24 -1
  36. package/package/aws-client-agent-mcp/dist/agent-client.test.js.map +1 -1
  37. package/package/aws-client-agent-mcp/dist/config.d.ts.map +1 -1
  38. package/package/aws-client-agent-mcp/dist/config.js +0 -1
  39. package/package/aws-client-agent-mcp/dist/config.js.map +1 -1
  40. package/package/aws-client-agent-mcp/dist/config.test.js +0 -7
  41. package/package/aws-client-agent-mcp/dist/config.test.js.map +1 -1
  42. package/package/aws-client-agent-mcp/dist/http-client.test.js +0 -1
  43. package/package/aws-client-agent-mcp/dist/http-client.test.js.map +1 -1
  44. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.d.ts.map +1 -1
  45. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js +0 -3
  46. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js.map +1 -1
  47. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js +14 -5
  48. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js.map +1 -1
  49. package/package/aws-client-agent-mcp/dist/types.d.ts +4 -0
  50. package/package/aws-client-agent-mcp/dist/types.d.ts.map +1 -1
  51. package/package/aws-client-agent-mcp/dist/types.js.map +1 -1
  52. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts +3 -0
  53. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts.map +1 -1
  54. package/package/aws-client-agent-mcp/dist/websocket-client.js +64 -5
  55. package/package/aws-client-agent-mcp/dist/websocket-client.js.map +1 -1
  56. package/package/aws-client-agent-mcp/dist/websocket-client.test.js +218 -0
  57. package/package/aws-client-agent-mcp/dist/websocket-client.test.js.map +1 -1
  58. package/package/aws-client-agent-mcp/package.json +52 -52
  59. package/package/cc-switch-sdk/README.md +540 -540
  60. package/package/cc-switch-sdk/package.json +31 -31
  61. package/package.json +78 -78
  62. package/dist/routes/runtime-mcp-proxy.d.ts +0 -3
  63. package/dist/routes/runtime-mcp-proxy.d.ts.map +0 -1
  64. package/dist/routes/runtime-mcp-proxy.js +0 -102
  65. package/dist/routes/runtime-mcp-proxy.test.d.ts +0 -2
  66. package/dist/routes/runtime-mcp-proxy.test.d.ts.map +0 -1
  67. package/dist/routes/runtime-mcp-proxy.test.js +0 -111
  68. package/node_modules/@cc-switch/sdk/dist/sdk-import.test.d.ts +0 -2
  69. package/node_modules/@cc-switch/sdk/dist/sdk-import.test.d.ts.map +0 -1
  70. package/node_modules/@cc-switch/sdk/dist/sdk-import.test.js +0 -119
  71. package/package/cc-switch-sdk/dist/sdk-import.test.d.ts +0 -2
  72. package/package/cc-switch-sdk/dist/sdk-import.test.d.ts.map +0 -1
  73. package/package/cc-switch-sdk/dist/sdk-import.test.js +0 -119
@@ -1,541 +1,541 @@
1
- # @cc-switch/sdk
2
-
3
- Node SDK for MCP and Skill management, mirroring CC Switch's unified storage + per-app sync architecture.
4
-
5
- ## Features
6
-
7
- - **MCP Servers**: CRUD + app enable/disable + import from apps (Claude, Claudecode, OpenCode)
8
- - **Skills**: Install/uninstall + directory sync (copy/symlink) + import from apps
9
- - **Config Backup/Restore**: Auto backup before first Opencode/Claudecode sync + restore methods
10
- - **Extensible**: Placeholder adapters for Codex/Gemini/OpenClaw (easy to implement)
11
-
12
- ## Installation
13
-
14
- ```bash
15
- npm install @cc-switch/sdk
16
- ```
17
-
18
- ## Quick Start
19
-
20
- ```typescript
21
- import { CcSwitchSdk } from "@cc-switch/sdk";
22
-
23
- const sdk = new CcSwitchSdk();
24
- await sdk.load();
25
-
26
- // Create MCP server
27
- const server = await sdk.createMcpServer({
28
- name: "my-mcp",
29
- server: { type: "stdio", command: "node", args: ["server.js"] },
30
- apps: { claude: true },
31
- });
32
-
33
- // Toggle app
34
- await sdk.toggleMcpApp(server.id, "opencode", true);
35
-
36
- // Import from apps
37
- await sdk.importMcpFromApps();
38
-
39
- // Install skill
40
- await sdk.installSkill({
41
- sourceDir: "/path/to/skill",
42
- name: "my-skill",
43
- apps: { claude: true, opencode: true },
44
- });
45
- ```
46
-
47
- ## Configuration
48
-
49
- ```typescript
50
- const sdk = new CcSwitchSdk({
51
- rootDir: "/custom/path", // Base directory
52
- skillSyncMethod: "symlink", // "auto" | "copy" | "symlink"
53
- paths: {
54
- stateFile: "...",
55
- backupDir: "...", // backup directory
56
- claudeConfigFile: "...",
57
- claudeSkillsDir: "...",
58
- claudecodeConfigFile: "...", // claudecode mcp config
59
- claudecodeSkillsDir: "...",
60
- opencodeConfigFile: "...",
61
- opencodeSkillsDir: "...",
62
- ssotSkillsDir: "...",
63
- },
64
- // Custom adapters
65
- adapters: {
66
- mcp: { codex: new MyCodexAdapter() },
67
- skill: { codex: new MyCodexSkillAdapter() },
68
- },
69
- });
70
- ```
71
-
72
- ---
73
-
74
- ## API Reference
75
-
76
- ### Class: `CcSwitchSdk`
77
-
78
- Main SDK class for managing MCP servers and Skills.
79
-
80
- #### Constructor
81
-
82
- ```typescript
83
- constructor(options?: SdkOptions)
84
- ```
85
-
86
- **Parameters:**
87
- - `options.rootDir` (string, optional): Base directory for all SDK operations
88
- - `options.skillSyncMethod` ("auto" | "copy" | "symlink", optional): Method for syncing skill directories
89
- - `options.paths` (Partial\<SdkPaths\>, optional): Custom paths for config files
90
- - `options.adapters` (AdapterOverrides, optional): Custom adapters for MCP and Skill management
91
-
92
- ---
93
-
94
- ### MCP Server Management
95
-
96
- #### `load(): Promise<void>`
97
-
98
- Load SDK state from disk. **Must be called before any operations.**
99
-
100
- ```typescript
101
- await sdk.load();
102
- ```
103
-
104
- ---
105
-
106
- #### `save(): Promise<void>`
107
-
108
- Manually save SDK state to disk.
109
-
110
- ```typescript
111
- await sdk.save();
112
- ```
113
-
114
- ---
115
-
116
- #### `createMcpServer(input: CreateMcpInput): Promise<McpServer>`
117
-
118
- Create a new MCP server and sync to enabled apps.
119
-
120
- **Parameters:**
121
- - `input.name` (string): Unique server name
122
- - `input.server` (McpServerSpec): Server configuration
123
- - `input.apps` (Partial\<AppFlags\>, optional): Target apps
124
- - `input.description` (string, optional): Server description
125
-
126
- **Returns:** `McpServer` - Created server object
127
-
128
- ```typescript
129
- const server = await sdk.createMcpServer({
130
- name: "aws-mcp",
131
- server: {
132
- type: "stdio",
133
- command: "node",
134
- args: ["index.js"],
135
- env: { API_KEY: "secret" }
136
- },
137
- apps: { claude: true, opencode: true },
138
- description: "AWS MCP Server"
139
- });
140
- ```
141
-
142
- ---
143
-
144
- #### `getAllMcpServers(): McpServer[]`
145
-
146
- Get all MCP servers.
147
-
148
- ```typescript
149
- const servers = sdk.getAllMcpServers();
150
- // Returns: McpServer[]
151
- ```
152
-
153
- ---
154
-
155
- #### `getMcpServerById(id: string): McpServer | undefined`
156
-
157
- Get MCP server by ID.
158
-
159
- ```typescript
160
- const server = sdk.getMcpServerById("mcp_abc123");
161
- ```
162
-
163
- ---
164
-
165
- #### `updateMcpServer(id: string, patch: UpdateMcpInput): Promise<McpServer>`
166
-
167
- Update MCP server configuration.
168
-
169
- **Parameters:**
170
- - `id`: Server ID
171
- - `patch`: Partial server update
172
-
173
- ```typescript
174
- const updated = await sdk.updateMcpServer(server.id, {
175
- description: "Updated description",
176
- apps: { claudecode: true }
177
- });
178
- ```
179
-
180
- ---
181
-
182
- #### `deleteMcpServer(id: string): Promise<void>`
183
-
184
- Delete MCP server and remove from all apps.
185
-
186
- ```typescript
187
- await sdk.deleteMcpServer(server.id);
188
- ```
189
-
190
- ---
191
-
192
- #### `toggleMcpApp(serverId: string, appId: AppId, enabled: boolean): Promise<McpServer>`
193
-
194
- Enable or disable MCP server for a specific app.
195
-
196
- ```typescript
197
- await sdk.toggleMcpApp(server.id, "opencode", true);
198
- ```
199
-
200
- ---
201
-
202
- #### `importMcpFromApps(): Promise<number>`
203
-
204
- Import MCP servers from all apps into SDK state.
205
-
206
- **Returns:** Number of imported servers
207
-
208
- ```typescript
209
- const count = await sdk.importMcpFromApps();
210
- console.log(`Imported ${count} servers`);
211
- ```
212
-
213
- ---
214
-
215
- ### Skill Management
216
-
217
- #### `installSkill(input: CreateSkillInput): Promise<InstalledSkill>`
218
-
219
- Install a skill and sync to enabled apps.
220
-
221
- **Parameters:**
222
- - `input.sourceDir` (string): Source directory containing skill files
223
- - `input.name` (string): Skill name
224
- - `input.apps` (Partial\<AppFlags\>, optional): Target apps
225
- - `input.description` (string, optional): Skill description
226
-
227
- ```typescript
228
- const skill = await sdk.installSkill({
229
- sourceDir: "/path/to/skill/source",
230
- name: "frontend-design",
231
- apps: { claude: true, opencode: true },
232
- description: "Frontend design skill"
233
- });
234
- ```
235
-
236
- ---
237
-
238
- #### `getAllSkills(): InstalledSkill[]`
239
-
240
- Get all installed skills.
241
-
242
- ```typescript
243
- const skills = sdk.getAllSkills();
244
- ```
245
-
246
- ---
247
-
248
- #### `getSkillById(id: string): InstalledSkill | undefined`
249
-
250
- Get skill by ID.
251
-
252
- ```typescript
253
- const skill = sdk.getSkillById("skill_abc123");
254
- ```
255
-
256
- ---
257
-
258
- #### `updateSkill(id: string, patch: UpdateSkillInput): Promise<InstalledSkill>`
259
-
260
- Update skill configuration.
261
-
262
- ```typescript
263
- const updated = await sdk.updateSkill(skill.id, {
264
- description: "Updated description"
265
- });
266
- ```
267
-
268
- ---
269
-
270
- #### `uninstallSkill(id: string): Promise<void>`
271
-
272
- Uninstall skill and remove from all apps.
273
-
274
- ```typescript
275
- await sdk.uninstallSkill(skill.id);
276
- ```
277
-
278
- ---
279
-
280
- #### `toggleSkillApp(skillId: string, appId: AppId, enabled: boolean): Promise<InstalledSkill>`
281
-
282
- Enable or disable skill for a specific app.
283
-
284
- ```typescript
285
- await sdk.toggleSkillApp(skill.id, "claude", false);
286
- ```
287
-
288
- ---
289
-
290
- #### `importSkillsFromApps(): Promise<number>`
291
-
292
- Import skills from all apps into SDK state.
293
-
294
- ```typescript
295
- const count = await sdk.importSkillsFromApps();
296
- ```
297
-
298
- ---
299
-
300
- ### Backup & Restore
301
-
302
- #### `backupAiConfigs(appIds?: AppId[]): Promise<void>`
303
-
304
- Backup AI config files before modification.
305
-
306
- ```typescript
307
- await sdk.backupAiConfigs(["opencode", "claudecode"]);
308
- ```
309
-
310
- ---
311
-
312
- #### `restoreAiConfig(appId: AppId): Promise<boolean>`
313
-
314
- Restore AI config from backup.
315
-
316
- **Returns:** `true` if restored successfully
317
-
318
- ```typescript
319
- const restored = await sdk.restoreAiConfig("opencode");
320
- if (restored) {
321
- console.log("Config restored");
322
- }
323
- ```
324
-
325
- ---
326
-
327
- #### `restoreAiConfigs(appIds?: AppId[]): Promise<Record<string, boolean>>`
328
-
329
- Restore multiple AI configs.
330
-
331
- ```typescript
332
- const results = await sdk.restoreAiConfigs(["opencode", "claudecode"]);
333
- // Returns: { opencode: true, claudecode: false }
334
- ```
335
-
336
- ---
337
-
338
- ### Utility Methods
339
-
340
- #### `getPaths(): SdkPaths`
341
-
342
- Get current SDK paths configuration.
343
-
344
- ```typescript
345
- const paths = sdk.getPaths();
346
- console.log(paths.stateFile);
347
- ```
348
-
349
- ---
350
-
351
- ## Types
352
-
353
- ### `AppId`
354
-
355
- ```typescript
356
- type AppId = "claude" | "claudecode" | "codex" | "gemini" | "opencode" | "openclaw";
357
- ```
358
-
359
- ### `McpServerSpec`
360
-
361
- ```typescript
362
- interface McpServerSpec {
363
- type?: "stdio" | "sse" | "http";
364
- command?: string;
365
- args?: string[];
366
- env?: Record<string, string>;
367
- cwd?: string;
368
- url?: string;
369
- headers?: Record<string, string>;
370
- }
371
- ```
372
-
373
- ### `McpServer`
374
-
375
- ```typescript
376
- interface McpServer {
377
- id: string;
378
- name: string;
379
- server: McpServerSpec;
380
- description?: string;
381
- apps: AppFlags;
382
- }
383
- ```
384
-
385
- ### `InstalledSkill`
386
-
387
- ```typescript
388
- interface InstalledSkill {
389
- id: string;
390
- name: string;
391
- directory: string;
392
- description?: string;
393
- apps: AppFlags;
394
- installedAt: number;
395
- }
396
- ```
397
-
398
- ### `AppFlags`
399
-
400
- ```typescript
401
- interface AppFlags {
402
- claude: boolean;
403
- claudecode: boolean;
404
- codex: boolean;
405
- gemini: boolean;
406
- opencode: boolean;
407
- openclaw: boolean;
408
- }
409
- ```
410
-
411
- ---
412
-
413
- ## Extending
414
-
415
- ### Custom MCP Adapter
416
-
417
- Implement `IMcpAdapter` to add support for new apps:
418
-
419
- ```typescript
420
- import type { IMcpAdapter, McpServer } from "@cc-switch/sdk";
421
-
422
- class MyCodexAdapter implements IMcpAdapter {
423
- readonly appId = "codex" as const;
424
-
425
- async importServers(): Promise<McpServer[]> {
426
- // Read existing MCP servers from Codex config
427
- // Return array of McpServer objects
428
- }
429
-
430
- async syncServer(server: McpServer): Promise<void> {
431
- // Write MCP server to Codex config
432
- }
433
-
434
- async removeServer(server: McpServer): Promise<void> {
435
- // Remove MCP server from Codex config
436
- }
437
- }
438
- ```
439
-
440
- ### Custom Skill Adapter
441
-
442
- Implement `ISkillAdapter` for skill management:
443
-
444
- ```typescript
445
- import type { ISkillAdapter, InstalledSkill, SkillSyncMethod } from "@cc-switch/sdk";
446
-
447
- class MyCodexSkillAdapter implements ISkillAdapter {
448
- readonly appId = "codex" as const;
449
-
450
- async importSkills(): Promise<Array<Pick<InstalledSkill, "id" | "name" | "directory" | "description">>> {
451
- // Scan skill directories
452
- // Return array of skill info
453
- }
454
-
455
- async syncSkill(skill: InstalledSkill, sourceDir: string, method: SkillSyncMethod): Promise<void> {
456
- // Copy or symlink skill directory
457
- }
458
-
459
- async removeSkill(skill: InstalledSkill): Promise<void> {
460
- // Remove skill directory
461
- }
462
- }
463
- ```
464
-
465
- ### Using Custom Adapters
466
-
467
- ```typescript
468
- const sdk = new CcSwitchSdk({
469
- adapters: {
470
- mcp: { codex: new MyCodexAdapter() },
471
- skill: { codex: new MyCodexSkillAdapter() }
472
- }
473
- });
474
- ```
475
-
476
- ---
477
-
478
- ## Error Handling
479
-
480
- SDK throws `SdkError` for known errors:
481
-
482
- ```typescript
483
- import { SdkError } from "@cc-switch/sdk";
484
-
485
- try {
486
- await sdk.updateMcpServer("invalid-id", {});
487
- } catch (err) {
488
- if (err instanceof SdkError) {
489
- console.log(err.code); // "MCP_NOT_FOUND"
490
- console.log(err.message); // "MCP server not found: invalid-id"
491
- console.log(err.details); // { id: "invalid-id" }
492
- }
493
- }
494
- ```
495
-
496
- **Error Codes:**
497
- - `MCP_NOT_FOUND`: MCP server not found
498
- - `SKILL_NOT_FOUND`: Skill not found
499
-
500
- ---
501
-
502
- ## Scripts
503
-
504
- ```bash
505
- pnpm typecheck # TypeScript check
506
- pnpm build # Compile
507
- pnpm test # Run tests
508
- ```
509
-
510
- ---
511
-
512
- ## Architecture
513
-
514
- ```
515
- ┌─────────────────────────────────────┐
516
- │ CcSwitchSdk (Core) │
517
- │ - State Management │
518
- │ - CRUD Operations │
519
- │ - Import/Export │
520
- └──────────────┬──────────────────────┘
521
-
522
- ┌──────────┴──────────┐
523
- │ │
524
- ┌───▼────┐ ┌────▼───┐
525
- │ MCP │ │ Skill │
526
- │ Service│ │ Service│
527
- └───┬────┘ └────┬───┘
528
- │ │
529
- ┌───▼────────────────────▼───┐
530
- │ Adapters Layer │
531
- │ - Claude / Claudecode │
532
- │ - OpenCode │
533
- │ - Codex / Gemini / ... │
534
- └────────────────────────────┘
535
- ```
536
-
537
- ---
538
-
539
- ## License
540
-
1
+ # @cc-switch/sdk
2
+
3
+ Node SDK for MCP and Skill management, mirroring CC Switch's unified storage + per-app sync architecture.
4
+
5
+ ## Features
6
+
7
+ - **MCP Servers**: CRUD + app enable/disable + import from apps (Claude, Claudecode, OpenCode)
8
+ - **Skills**: Install/uninstall + directory sync (copy/symlink) + import from apps
9
+ - **Config Backup/Restore**: Auto backup before first Opencode/Claudecode sync + restore methods
10
+ - **Extensible**: Placeholder adapters for Codex/Gemini/OpenClaw (easy to implement)
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install @cc-switch/sdk
16
+ ```
17
+
18
+ ## Quick Start
19
+
20
+ ```typescript
21
+ import { CcSwitchSdk } from "@cc-switch/sdk";
22
+
23
+ const sdk = new CcSwitchSdk();
24
+ await sdk.load();
25
+
26
+ // Create MCP server
27
+ const server = await sdk.createMcpServer({
28
+ name: "my-mcp",
29
+ server: { type: "stdio", command: "node", args: ["server.js"] },
30
+ apps: { claude: true },
31
+ });
32
+
33
+ // Toggle app
34
+ await sdk.toggleMcpApp(server.id, "opencode", true);
35
+
36
+ // Import from apps
37
+ await sdk.importMcpFromApps();
38
+
39
+ // Install skill
40
+ await sdk.installSkill({
41
+ sourceDir: "/path/to/skill",
42
+ name: "my-skill",
43
+ apps: { claude: true, opencode: true },
44
+ });
45
+ ```
46
+
47
+ ## Configuration
48
+
49
+ ```typescript
50
+ const sdk = new CcSwitchSdk({
51
+ rootDir: "/custom/path", // Base directory
52
+ skillSyncMethod: "symlink", // "auto" | "copy" | "symlink"
53
+ paths: {
54
+ stateFile: "...",
55
+ backupDir: "...", // backup directory
56
+ claudeConfigFile: "...",
57
+ claudeSkillsDir: "...",
58
+ claudecodeConfigFile: "...", // claudecode mcp config
59
+ claudecodeSkillsDir: "...",
60
+ opencodeConfigFile: "...",
61
+ opencodeSkillsDir: "...",
62
+ ssotSkillsDir: "...",
63
+ },
64
+ // Custom adapters
65
+ adapters: {
66
+ mcp: { codex: new MyCodexAdapter() },
67
+ skill: { codex: new MyCodexSkillAdapter() },
68
+ },
69
+ });
70
+ ```
71
+
72
+ ---
73
+
74
+ ## API Reference
75
+
76
+ ### Class: `CcSwitchSdk`
77
+
78
+ Main SDK class for managing MCP servers and Skills.
79
+
80
+ #### Constructor
81
+
82
+ ```typescript
83
+ constructor(options?: SdkOptions)
84
+ ```
85
+
86
+ **Parameters:**
87
+ - `options.rootDir` (string, optional): Base directory for all SDK operations
88
+ - `options.skillSyncMethod` ("auto" | "copy" | "symlink", optional): Method for syncing skill directories
89
+ - `options.paths` (Partial\<SdkPaths\>, optional): Custom paths for config files
90
+ - `options.adapters` (AdapterOverrides, optional): Custom adapters for MCP and Skill management
91
+
92
+ ---
93
+
94
+ ### MCP Server Management
95
+
96
+ #### `load(): Promise<void>`
97
+
98
+ Load SDK state from disk. **Must be called before any operations.**
99
+
100
+ ```typescript
101
+ await sdk.load();
102
+ ```
103
+
104
+ ---
105
+
106
+ #### `save(): Promise<void>`
107
+
108
+ Manually save SDK state to disk.
109
+
110
+ ```typescript
111
+ await sdk.save();
112
+ ```
113
+
114
+ ---
115
+
116
+ #### `createMcpServer(input: CreateMcpInput): Promise<McpServer>`
117
+
118
+ Create a new MCP server and sync to enabled apps.
119
+
120
+ **Parameters:**
121
+ - `input.name` (string): Unique server name
122
+ - `input.server` (McpServerSpec): Server configuration
123
+ - `input.apps` (Partial\<AppFlags\>, optional): Target apps
124
+ - `input.description` (string, optional): Server description
125
+
126
+ **Returns:** `McpServer` - Created server object
127
+
128
+ ```typescript
129
+ const server = await sdk.createMcpServer({
130
+ name: "aws-mcp",
131
+ server: {
132
+ type: "stdio",
133
+ command: "node",
134
+ args: ["index.js"],
135
+ env: { API_KEY: "secret" }
136
+ },
137
+ apps: { claude: true, opencode: true },
138
+ description: "AWS MCP Server"
139
+ });
140
+ ```
141
+
142
+ ---
143
+
144
+ #### `getAllMcpServers(): McpServer[]`
145
+
146
+ Get all MCP servers.
147
+
148
+ ```typescript
149
+ const servers = sdk.getAllMcpServers();
150
+ // Returns: McpServer[]
151
+ ```
152
+
153
+ ---
154
+
155
+ #### `getMcpServerById(id: string): McpServer | undefined`
156
+
157
+ Get MCP server by ID.
158
+
159
+ ```typescript
160
+ const server = sdk.getMcpServerById("mcp_abc123");
161
+ ```
162
+
163
+ ---
164
+
165
+ #### `updateMcpServer(id: string, patch: UpdateMcpInput): Promise<McpServer>`
166
+
167
+ Update MCP server configuration.
168
+
169
+ **Parameters:**
170
+ - `id`: Server ID
171
+ - `patch`: Partial server update
172
+
173
+ ```typescript
174
+ const updated = await sdk.updateMcpServer(server.id, {
175
+ description: "Updated description",
176
+ apps: { claudecode: true }
177
+ });
178
+ ```
179
+
180
+ ---
181
+
182
+ #### `deleteMcpServer(id: string): Promise<void>`
183
+
184
+ Delete MCP server and remove from all apps.
185
+
186
+ ```typescript
187
+ await sdk.deleteMcpServer(server.id);
188
+ ```
189
+
190
+ ---
191
+
192
+ #### `toggleMcpApp(serverId: string, appId: AppId, enabled: boolean): Promise<McpServer>`
193
+
194
+ Enable or disable MCP server for a specific app.
195
+
196
+ ```typescript
197
+ await sdk.toggleMcpApp(server.id, "opencode", true);
198
+ ```
199
+
200
+ ---
201
+
202
+ #### `importMcpFromApps(): Promise<number>`
203
+
204
+ Import MCP servers from all apps into SDK state.
205
+
206
+ **Returns:** Number of imported servers
207
+
208
+ ```typescript
209
+ const count = await sdk.importMcpFromApps();
210
+ console.log(`Imported ${count} servers`);
211
+ ```
212
+
213
+ ---
214
+
215
+ ### Skill Management
216
+
217
+ #### `installSkill(input: CreateSkillInput): Promise<InstalledSkill>`
218
+
219
+ Install a skill and sync to enabled apps.
220
+
221
+ **Parameters:**
222
+ - `input.sourceDir` (string): Source directory containing skill files
223
+ - `input.name` (string): Skill name
224
+ - `input.apps` (Partial\<AppFlags\>, optional): Target apps
225
+ - `input.description` (string, optional): Skill description
226
+
227
+ ```typescript
228
+ const skill = await sdk.installSkill({
229
+ sourceDir: "/path/to/skill/source",
230
+ name: "frontend-design",
231
+ apps: { claude: true, opencode: true },
232
+ description: "Frontend design skill"
233
+ });
234
+ ```
235
+
236
+ ---
237
+
238
+ #### `getAllSkills(): InstalledSkill[]`
239
+
240
+ Get all installed skills.
241
+
242
+ ```typescript
243
+ const skills = sdk.getAllSkills();
244
+ ```
245
+
246
+ ---
247
+
248
+ #### `getSkillById(id: string): InstalledSkill | undefined`
249
+
250
+ Get skill by ID.
251
+
252
+ ```typescript
253
+ const skill = sdk.getSkillById("skill_abc123");
254
+ ```
255
+
256
+ ---
257
+
258
+ #### `updateSkill(id: string, patch: UpdateSkillInput): Promise<InstalledSkill>`
259
+
260
+ Update skill configuration.
261
+
262
+ ```typescript
263
+ const updated = await sdk.updateSkill(skill.id, {
264
+ description: "Updated description"
265
+ });
266
+ ```
267
+
268
+ ---
269
+
270
+ #### `uninstallSkill(id: string): Promise<void>`
271
+
272
+ Uninstall skill and remove from all apps.
273
+
274
+ ```typescript
275
+ await sdk.uninstallSkill(skill.id);
276
+ ```
277
+
278
+ ---
279
+
280
+ #### `toggleSkillApp(skillId: string, appId: AppId, enabled: boolean): Promise<InstalledSkill>`
281
+
282
+ Enable or disable skill for a specific app.
283
+
284
+ ```typescript
285
+ await sdk.toggleSkillApp(skill.id, "claude", false);
286
+ ```
287
+
288
+ ---
289
+
290
+ #### `importSkillsFromApps(): Promise<number>`
291
+
292
+ Import skills from all apps into SDK state.
293
+
294
+ ```typescript
295
+ const count = await sdk.importSkillsFromApps();
296
+ ```
297
+
298
+ ---
299
+
300
+ ### Backup & Restore
301
+
302
+ #### `backupAiConfigs(appIds?: AppId[]): Promise<void>`
303
+
304
+ Backup AI config files before modification.
305
+
306
+ ```typescript
307
+ await sdk.backupAiConfigs(["opencode", "claudecode"]);
308
+ ```
309
+
310
+ ---
311
+
312
+ #### `restoreAiConfig(appId: AppId): Promise<boolean>`
313
+
314
+ Restore AI config from backup.
315
+
316
+ **Returns:** `true` if restored successfully
317
+
318
+ ```typescript
319
+ const restored = await sdk.restoreAiConfig("opencode");
320
+ if (restored) {
321
+ console.log("Config restored");
322
+ }
323
+ ```
324
+
325
+ ---
326
+
327
+ #### `restoreAiConfigs(appIds?: AppId[]): Promise<Record<string, boolean>>`
328
+
329
+ Restore multiple AI configs.
330
+
331
+ ```typescript
332
+ const results = await sdk.restoreAiConfigs(["opencode", "claudecode"]);
333
+ // Returns: { opencode: true, claudecode: false }
334
+ ```
335
+
336
+ ---
337
+
338
+ ### Utility Methods
339
+
340
+ #### `getPaths(): SdkPaths`
341
+
342
+ Get current SDK paths configuration.
343
+
344
+ ```typescript
345
+ const paths = sdk.getPaths();
346
+ console.log(paths.stateFile);
347
+ ```
348
+
349
+ ---
350
+
351
+ ## Types
352
+
353
+ ### `AppId`
354
+
355
+ ```typescript
356
+ type AppId = "claude" | "claudecode" | "codex" | "gemini" | "opencode" | "openclaw";
357
+ ```
358
+
359
+ ### `McpServerSpec`
360
+
361
+ ```typescript
362
+ interface McpServerSpec {
363
+ type?: "stdio" | "sse" | "http";
364
+ command?: string;
365
+ args?: string[];
366
+ env?: Record<string, string>;
367
+ cwd?: string;
368
+ url?: string;
369
+ headers?: Record<string, string>;
370
+ }
371
+ ```
372
+
373
+ ### `McpServer`
374
+
375
+ ```typescript
376
+ interface McpServer {
377
+ id: string;
378
+ name: string;
379
+ server: McpServerSpec;
380
+ description?: string;
381
+ apps: AppFlags;
382
+ }
383
+ ```
384
+
385
+ ### `InstalledSkill`
386
+
387
+ ```typescript
388
+ interface InstalledSkill {
389
+ id: string;
390
+ name: string;
391
+ directory: string;
392
+ description?: string;
393
+ apps: AppFlags;
394
+ installedAt: number;
395
+ }
396
+ ```
397
+
398
+ ### `AppFlags`
399
+
400
+ ```typescript
401
+ interface AppFlags {
402
+ claude: boolean;
403
+ claudecode: boolean;
404
+ codex: boolean;
405
+ gemini: boolean;
406
+ opencode: boolean;
407
+ openclaw: boolean;
408
+ }
409
+ ```
410
+
411
+ ---
412
+
413
+ ## Extending
414
+
415
+ ### Custom MCP Adapter
416
+
417
+ Implement `IMcpAdapter` to add support for new apps:
418
+
419
+ ```typescript
420
+ import type { IMcpAdapter, McpServer } from "@cc-switch/sdk";
421
+
422
+ class MyCodexAdapter implements IMcpAdapter {
423
+ readonly appId = "codex" as const;
424
+
425
+ async importServers(): Promise<McpServer[]> {
426
+ // Read existing MCP servers from Codex config
427
+ // Return array of McpServer objects
428
+ }
429
+
430
+ async syncServer(server: McpServer): Promise<void> {
431
+ // Write MCP server to Codex config
432
+ }
433
+
434
+ async removeServer(server: McpServer): Promise<void> {
435
+ // Remove MCP server from Codex config
436
+ }
437
+ }
438
+ ```
439
+
440
+ ### Custom Skill Adapter
441
+
442
+ Implement `ISkillAdapter` for skill management:
443
+
444
+ ```typescript
445
+ import type { ISkillAdapter, InstalledSkill, SkillSyncMethod } from "@cc-switch/sdk";
446
+
447
+ class MyCodexSkillAdapter implements ISkillAdapter {
448
+ readonly appId = "codex" as const;
449
+
450
+ async importSkills(): Promise<Array<Pick<InstalledSkill, "id" | "name" | "directory" | "description">>> {
451
+ // Scan skill directories
452
+ // Return array of skill info
453
+ }
454
+
455
+ async syncSkill(skill: InstalledSkill, sourceDir: string, method: SkillSyncMethod): Promise<void> {
456
+ // Copy or symlink skill directory
457
+ }
458
+
459
+ async removeSkill(skill: InstalledSkill): Promise<void> {
460
+ // Remove skill directory
461
+ }
462
+ }
463
+ ```
464
+
465
+ ### Using Custom Adapters
466
+
467
+ ```typescript
468
+ const sdk = new CcSwitchSdk({
469
+ adapters: {
470
+ mcp: { codex: new MyCodexAdapter() },
471
+ skill: { codex: new MyCodexSkillAdapter() }
472
+ }
473
+ });
474
+ ```
475
+
476
+ ---
477
+
478
+ ## Error Handling
479
+
480
+ SDK throws `SdkError` for known errors:
481
+
482
+ ```typescript
483
+ import { SdkError } from "@cc-switch/sdk";
484
+
485
+ try {
486
+ await sdk.updateMcpServer("invalid-id", {});
487
+ } catch (err) {
488
+ if (err instanceof SdkError) {
489
+ console.log(err.code); // "MCP_NOT_FOUND"
490
+ console.log(err.message); // "MCP server not found: invalid-id"
491
+ console.log(err.details); // { id: "invalid-id" }
492
+ }
493
+ }
494
+ ```
495
+
496
+ **Error Codes:**
497
+ - `MCP_NOT_FOUND`: MCP server not found
498
+ - `SKILL_NOT_FOUND`: Skill not found
499
+
500
+ ---
501
+
502
+ ## Scripts
503
+
504
+ ```bash
505
+ pnpm typecheck # TypeScript check
506
+ pnpm build # Compile
507
+ pnpm test # Run tests
508
+ ```
509
+
510
+ ---
511
+
512
+ ## Architecture
513
+
514
+ ```
515
+ ┌─────────────────────────────────────┐
516
+ │ CcSwitchSdk (Core) │
517
+ │ - State Management │
518
+ │ - CRUD Operations │
519
+ │ - Import/Export │
520
+ └──────────────┬──────────────────────┘
521
+
522
+ ┌──────────┴──────────┐
523
+ │ │
524
+ ┌───▼────┐ ┌────▼───┐
525
+ │ MCP │ │ Skill │
526
+ │ Service│ │ Service│
527
+ └───┬────┘ └────┬───┘
528
+ │ │
529
+ ┌───▼────────────────────▼───┐
530
+ │ Adapters Layer │
531
+ │ - Claude / Claudecode │
532
+ │ - OpenCode │
533
+ │ - Codex / Gemini / ... │
534
+ └────────────────────────────┘
535
+ ```
536
+
537
+ ---
538
+
539
+ ## License
540
+
541
541
  MIT