aws-runtime-bridge 1.2.0 → 1.3.0
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.
- package/README.md +77 -77
- package/dist/adapter/ClaudeSdkAdapter.d.ts +1 -0
- package/dist/adapter/ClaudeSdkAdapter.d.ts.map +1 -1
- package/dist/adapter/ClaudeSdkAdapter.js +7 -3
- package/dist/adapter/ClaudeSdkAdapter.test.js +2 -2
- package/dist/adapter/CodexSdkAdapter.d.ts.map +1 -1
- package/dist/adapter/CodexSdkAdapter.js +7 -4
- package/dist/adapter/CodexSdkAdapter.test.js +4 -2
- package/dist/adapter/OpencodeSdkAdapter.d.ts +2 -0
- package/dist/adapter/OpencodeSdkAdapter.d.ts.map +1 -1
- package/dist/adapter/OpencodeSdkAdapter.js +15 -1
- package/dist/adapter/OpencodeSdkAdapter.test.js +5 -0
- package/dist/index.js +0 -0
- package/dist/routes/properties.test.js +4 -4
- package/dist/routes/runtime-binding.d.ts.map +1 -1
- package/dist/routes/runtime-binding.js +8 -13
- package/dist/routes/runtime-mcp-proxy.d.ts +3 -0
- package/dist/routes/runtime-mcp-proxy.d.ts.map +1 -0
- package/dist/routes/runtime-mcp-proxy.js +102 -0
- package/dist/routes/runtime-mcp-proxy.test.d.ts +2 -0
- package/dist/routes/runtime-mcp-proxy.test.d.ts.map +1 -0
- package/dist/routes/runtime-mcp-proxy.test.js +111 -0
- package/dist/routes/terminal.js +2 -5
- package/dist/routes/terminal.test.js +3 -4
- package/dist/services/auto-register.d.ts +6 -0
- package/dist/services/auto-register.d.ts.map +1 -1
- package/dist/services/auto-register.js +63 -1
- package/dist/services/aws-client-agent-mcp.d.ts.map +1 -1
- package/dist/services/aws-client-agent-mcp.js +73 -7
- package/dist/services/aws-client-agent-mcp.test.js +83 -2
- package/dist/services/mcp-launch-binding-queue.d.ts +0 -2
- package/dist/services/mcp-launch-binding-queue.d.ts.map +1 -1
- package/dist/services/mcp-launch-binding-queue.js +44 -16
- package/dist/services/mcp-launch-binding-queue.test.js +42 -37
- package/dist/services/runtime-binding.d.ts +1 -0
- package/dist/services/runtime-binding.d.ts.map +1 -1
- package/dist/services/runtime-binding.js +39 -5
- package/dist/services/runtime-binding.test.d.ts +2 -0
- package/dist/services/runtime-binding.test.d.ts.map +1 -0
- package/dist/services/runtime-binding.test.js +11 -0
- package/dist/utils/yaml-utils.test.js +129 -129
- package/node_modules/@cc-switch/sdk/README.md +540 -540
- package/node_modules/@cc-switch/sdk/dist/sdk-import.test.d.ts +2 -0
- package/node_modules/@cc-switch/sdk/dist/sdk-import.test.d.ts.map +1 -0
- package/node_modules/@cc-switch/sdk/dist/sdk-import.test.js +119 -0
- package/node_modules/@cc-switch/sdk/package.json +31 -31
- package/package/aws-client-agent-mcp/README.md +288 -288
- package/package/aws-client-agent-mcp/dist/config.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/config.js +96 -13
- package/package/aws-client-agent-mcp/dist/config.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/config.test.js +26 -8
- package/package/aws-client-agent-mcp/dist/config.test.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/constants.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/constants.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/constants.js +0 -1
- package/package/aws-client-agent-mcp/dist/constants.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/http-client.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/http-client.js +49 -13
- package/package/aws-client-agent-mcp/dist/http-client.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/http-client.test.js +40 -13
- package/package/aws-client-agent-mcp/dist/http-client.test.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/index.js +11 -6
- package/package/aws-client-agent-mcp/dist/index.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/logger.d.ts +11 -1
- package/package/aws-client-agent-mcp/dist/logger.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/logger.js +91 -6
- package/package/aws-client-agent-mcp/dist/logger.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/logger.test.d.ts +2 -0
- package/package/aws-client-agent-mcp/dist/logger.test.d.ts.map +1 -0
- package/package/aws-client-agent-mcp/dist/logger.test.js +27 -0
- package/package/aws-client-agent-mcp/dist/logger.test.js.map +1 -0
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js +18 -14
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js +51 -21
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/types.d.ts +3 -2
- package/package/aws-client-agent-mcp/dist/types.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/types.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.d.ts +1 -0
- package/package/aws-client-agent-mcp/dist/websocket-client.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.js +18 -0
- package/package/aws-client-agent-mcp/dist/websocket-client.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.test.js +53 -2
- package/package/aws-client-agent-mcp/dist/websocket-client.test.js.map +1 -1
- package/package/aws-client-agent-mcp/package.json +52 -52
- package/package/cc-switch-sdk/README.md +540 -540
- package/package/cc-switch-sdk/dist/sdk-import.test.d.ts +2 -0
- package/package/cc-switch-sdk/dist/sdk-import.test.d.ts.map +1 -0
- package/package/cc-switch-sdk/dist/sdk-import.test.js +119 -0
- package/package/cc-switch-sdk/package.json +31 -31
- package/package.json +78 -78
|
@@ -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
|