@deimoscloud/coreai 0.1.8 → 0.1.10
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/dist/cli/index.js +5 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/package.json +6 -1
- package/.prettierrc +0 -9
- package/AGENT_SPEC.md +0 -347
- package/ARCHITECTURE.md +0 -547
- package/DRAFT_PRD.md +0 -1440
- package/IMPLEMENTATION_PLAN.md +0 -256
- package/PRODUCT.md +0 -473
- package/WORKFLOWS.md +0 -295
- package/commands/core/check-inbox.md +0 -34
- package/commands/core/delegate.md +0 -30
- package/commands/core/git-commit.md +0 -144
- package/commands/core/pr-create.md +0 -193
- package/commands/core/review.md +0 -56
- package/commands/core/sprint-status.md +0 -65
- package/commands/optional/docs-update.md +0 -200
- package/commands/optional/jira-create.md +0 -200
- package/commands/optional/jira-transition.md +0 -184
- package/commands/optional/worktree-cleanup.md +0 -167
- package/commands/optional/worktree-setup.md +0 -110
- package/eslint.config.js +0 -29
- package/jest.config.js +0 -22
- package/knowledge-library/README.md +0 -118
- package/knowledge-library/android-engineer/context/current.txt +0 -42
- package/knowledge-library/android-engineer/control/decisions.txt +0 -9
- package/knowledge-library/android-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/android-engineer/control/objectives.txt +0 -26
- package/knowledge-library/android-engineer/history/.gitkeep +0 -0
- package/knowledge-library/android-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/android-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/android-engineer/tech/.gitkeep +0 -0
- package/knowledge-library/architecture.txt +0 -61
- package/knowledge-library/backend-engineer/context/current.txt +0 -42
- package/knowledge-library/backend-engineer/control/decisions.txt +0 -9
- package/knowledge-library/backend-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/backend-engineer/control/objectives.txt +0 -26
- package/knowledge-library/backend-engineer/history/.gitkeep +0 -0
- package/knowledge-library/backend-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/backend-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/backend-engineer/tech/.gitkeep +0 -0
- package/knowledge-library/context.txt +0 -52
- package/knowledge-library/devops-engineer/context/current.txt +0 -42
- package/knowledge-library/devops-engineer/control/decisions.txt +0 -9
- package/knowledge-library/devops-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/devops-engineer/control/objectives.txt +0 -26
- package/knowledge-library/devops-engineer/history/.gitkeep +0 -0
- package/knowledge-library/devops-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/devops-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/devops-engineer/tech/.gitkeep +0 -0
- package/knowledge-library/engineering-manager/context/current.txt +0 -40
- package/knowledge-library/engineering-manager/control/decisions.txt +0 -9
- package/knowledge-library/engineering-manager/control/objectives.txt +0 -27
- package/knowledge-library/engineering-manager/history/.gitkeep +0 -0
- package/knowledge-library/engineering-manager/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/engineering-manager/outbox/.gitkeep +0 -0
- package/knowledge-library/engineering-manager/tech/.gitkeep +0 -0
- package/knowledge-library/prd.txt +0 -81
- package/knowledge-library/product-manager/context/current.txt +0 -42
- package/knowledge-library/product-manager/control/decisions.txt +0 -9
- package/knowledge-library/product-manager/control/dependencies.txt +0 -19
- package/knowledge-library/product-manager/control/objectives.txt +0 -26
- package/knowledge-library/product-manager/history/.gitkeep +0 -0
- package/knowledge-library/product-manager/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/product-manager/outbox/.gitkeep +0 -0
- package/knowledge-library/product-manager/tech/.gitkeep +0 -0
- package/knowledge-library/qa-engineer/context/current.txt +0 -42
- package/knowledge-library/qa-engineer/control/decisions.txt +0 -9
- package/knowledge-library/qa-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/qa-engineer/control/objectives.txt +0 -26
- package/knowledge-library/qa-engineer/history/.gitkeep +0 -0
- package/knowledge-library/qa-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/qa-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/qa-engineer/tech/.gitkeep +0 -0
- package/knowledge-library/security-engineer/context/current.txt +0 -42
- package/knowledge-library/security-engineer/control/decisions.txt +0 -9
- package/knowledge-library/security-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/security-engineer/control/objectives.txt +0 -26
- package/knowledge-library/security-engineer/history/.gitkeep +0 -0
- package/knowledge-library/security-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/security-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/security-engineer/tech/.gitkeep +0 -0
- package/knowledge-library/solutions-architect/context/current.txt +0 -42
- package/knowledge-library/solutions-architect/control/decisions.txt +0 -9
- package/knowledge-library/solutions-architect/control/dependencies.txt +0 -19
- package/knowledge-library/solutions-architect/control/objectives.txt +0 -26
- package/knowledge-library/solutions-architect/history/.gitkeep +0 -0
- package/knowledge-library/solutions-architect/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/solutions-architect/outbox/.gitkeep +0 -0
- package/knowledge-library/solutions-architect/tech/.gitkeep +0 -0
- package/knowledge-library/wearos-engineer/context/current.txt +0 -42
- package/knowledge-library/wearos-engineer/control/decisions.txt +0 -9
- package/knowledge-library/wearos-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/wearos-engineer/control/objectives.txt +0 -26
- package/knowledge-library/wearos-engineer/history/.gitkeep +0 -0
- package/knowledge-library/wearos-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/wearos-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/wearos-engineer/tech/.gitkeep +0 -0
- package/scripts/add-agent.sh +0 -323
- package/scripts/install.sh +0 -354
- package/src/adapters/factory.test.ts +0 -386
- package/src/adapters/factory.ts +0 -305
- package/src/adapters/index.ts +0 -113
- package/src/adapters/interfaces.ts +0 -268
- package/src/adapters/mcp/client.test.ts +0 -130
- package/src/adapters/mcp/client.ts +0 -451
- package/src/adapters/mcp/discovery.test.ts +0 -315
- package/src/adapters/mcp/discovery.ts +0 -340
- package/src/adapters/mcp/index.ts +0 -66
- package/src/adapters/mcp/mapper.test.ts +0 -218
- package/src/adapters/mcp/mapper.ts +0 -536
- package/src/adapters/mcp/registry.test.ts +0 -433
- package/src/adapters/mcp/registry.ts +0 -550
- package/src/adapters/mcp/types.ts +0 -258
- package/src/adapters/native/filesystem.test.ts +0 -350
- package/src/adapters/native/filesystem.ts +0 -393
- package/src/adapters/native/github.test.ts +0 -173
- package/src/adapters/native/github.ts +0 -627
- package/src/adapters/native/index.ts +0 -22
- package/src/adapters/native/selector.test.ts +0 -224
- package/src/adapters/native/selector.ts +0 -150
- package/src/adapters/types.ts +0 -270
- package/src/agents/compiler.test.ts +0 -399
- package/src/agents/compiler.ts +0 -422
- package/src/agents/index.ts +0 -37
- package/src/agents/loader.test.ts +0 -319
- package/src/agents/loader.ts +0 -143
- package/src/agents/resolver.test.ts +0 -282
- package/src/agents/resolver.ts +0 -262
- package/src/agents/types.ts +0 -97
- package/src/cache/index.ts +0 -38
- package/src/cache/interfaces.ts +0 -283
- package/src/cache/manager.test.ts +0 -266
- package/src/cache/manager.ts +0 -388
- package/src/cache/provider.test.ts +0 -485
- package/src/cache/provider.ts +0 -745
- package/src/cache/types.test.ts +0 -192
- package/src/cache/types.ts +0 -313
- package/src/cli/commands/build.test.ts +0 -248
- package/src/cli/commands/build.ts +0 -284
- package/src/cli/commands/cache.test.ts +0 -221
- package/src/cli/commands/cache.ts +0 -229
- package/src/cli/commands/index.ts +0 -63
- package/src/cli/commands/init.test.ts +0 -173
- package/src/cli/commands/init.ts +0 -296
- package/src/cli/commands/skills.test.ts +0 -272
- package/src/cli/commands/skills.ts +0 -348
- package/src/cli/commands/status.test.ts +0 -392
- package/src/cli/commands/status.ts +0 -332
- package/src/cli/commands/sync.test.ts +0 -213
- package/src/cli/commands/sync.ts +0 -251
- package/src/cli/commands/validate.test.ts +0 -216
- package/src/cli/commands/validate.ts +0 -340
- package/src/cli/index.test.ts +0 -190
- package/src/cli/index.ts +0 -493
- package/src/commands/context.test.ts +0 -163
- package/src/commands/context.ts +0 -111
- package/src/commands/index.ts +0 -56
- package/src/commands/loader.test.ts +0 -273
- package/src/commands/loader.ts +0 -355
- package/src/commands/registry.test.ts +0 -384
- package/src/commands/registry.ts +0 -248
- package/src/commands/runner.test.ts +0 -297
- package/src/commands/runner.ts +0 -222
- package/src/commands/types.ts +0 -361
- package/src/config/index.ts +0 -19
- package/src/config/loader.test.ts +0 -262
- package/src/config/loader.ts +0 -188
- package/src/config/types.ts +0 -154
- package/src/context/index.ts +0 -14
- package/src/context/loader.test.ts +0 -334
- package/src/context/loader.ts +0 -357
- package/src/index.test.ts +0 -13
- package/src/index.ts +0 -268
- package/src/knowledge-library/index.ts +0 -44
- package/src/knowledge-library/manager.test.ts +0 -536
- package/src/knowledge-library/manager.ts +0 -804
- package/src/knowledge-library/types.ts +0 -432
- package/src/skills/generator.test.ts +0 -602
- package/src/skills/generator.ts +0 -491
- package/src/skills/index.ts +0 -27
- package/src/skills/templates.ts +0 -520
- package/src/skills/types.ts +0 -251
- package/templates/completion-report.md +0 -72
- package/templates/feedback.md +0 -56
- package/templates/project-files/CLAUDE.md.template +0 -109
- package/templates/project-files/coreai.json.example +0 -47
- package/templates/project-files/mcp.json.template +0 -20
- package/templates/review-complete.md +0 -64
- package/templates/review-request.md +0 -67
- package/templates/task-assignment.md +0 -51
- package/tsconfig.build.json +0 -4
- package/tsconfig.json +0 -26
- package/tsup.config.ts +0 -23
|
@@ -1,451 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MCP Client Wrapper
|
|
3
|
-
*
|
|
4
|
-
* Provides a simplified interface for connecting to and communicating with MCP servers.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
8
|
-
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
9
|
-
import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
|
|
10
|
-
import type {
|
|
11
|
-
McpServerConfig,
|
|
12
|
-
McpServerInfo,
|
|
13
|
-
McpTool,
|
|
14
|
-
McpResource,
|
|
15
|
-
McpToolResult,
|
|
16
|
-
McpCapabilities,
|
|
17
|
-
McpContent,
|
|
18
|
-
StdioServerConfig,
|
|
19
|
-
} from './types.js';
|
|
20
|
-
import { McpError } from './types.js';
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Options for creating an MCP client
|
|
24
|
-
*/
|
|
25
|
-
export interface McpClientOptions {
|
|
26
|
-
/**
|
|
27
|
-
* Client name to report to servers
|
|
28
|
-
*/
|
|
29
|
-
clientName?: string;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Client version to report to servers
|
|
33
|
-
*/
|
|
34
|
-
clientVersion?: string;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Timeout for operations in milliseconds
|
|
38
|
-
*/
|
|
39
|
-
timeout?: number;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const DEFAULT_OPTIONS: Required<McpClientOptions> = {
|
|
43
|
-
clientName: 'coreai',
|
|
44
|
-
clientVersion: '0.1.0',
|
|
45
|
-
timeout: 30000,
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* MCP Client Wrapper
|
|
50
|
-
*
|
|
51
|
-
* Manages a connection to a single MCP server and provides
|
|
52
|
-
* a simplified API for tool calls, resource access, etc.
|
|
53
|
-
*/
|
|
54
|
-
export class McpClient {
|
|
55
|
-
private client: Client | null = null;
|
|
56
|
-
private transport: Transport | null = null;
|
|
57
|
-
private _serverInfo: McpServerInfo | null = null;
|
|
58
|
-
private options: Required<McpClientOptions>;
|
|
59
|
-
private serverName: string;
|
|
60
|
-
private config: McpServerConfig;
|
|
61
|
-
|
|
62
|
-
constructor(serverName: string, config: McpServerConfig, options?: McpClientOptions) {
|
|
63
|
-
this.serverName = serverName;
|
|
64
|
-
this.config = config;
|
|
65
|
-
this.options = { ...DEFAULT_OPTIONS, ...options };
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Connect to the MCP server
|
|
70
|
-
*/
|
|
71
|
-
async connect(): Promise<void> {
|
|
72
|
-
if (this.client && this.isConnected()) {
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
try {
|
|
77
|
-
// Create the appropriate transport
|
|
78
|
-
this.transport = await this.createTransport();
|
|
79
|
-
|
|
80
|
-
// Create the MCP client
|
|
81
|
-
this.client = new Client(
|
|
82
|
-
{
|
|
83
|
-
name: this.options.clientName,
|
|
84
|
-
version: this.options.clientVersion,
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
capabilities: {
|
|
88
|
-
roots: { listChanged: true },
|
|
89
|
-
},
|
|
90
|
-
}
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
// Connect to the server
|
|
94
|
-
await this.client.connect(this.transport);
|
|
95
|
-
|
|
96
|
-
// Store server info
|
|
97
|
-
const serverVersion = this.client.getServerVersion();
|
|
98
|
-
const serverCapabilities = this.client.getServerCapabilities();
|
|
99
|
-
|
|
100
|
-
const info: McpServerInfo = {
|
|
101
|
-
name: this.serverName,
|
|
102
|
-
connected: true,
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
if (serverVersion?.version) {
|
|
106
|
-
info.version = serverVersion.version;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const caps = this.parseCapabilities(serverCapabilities);
|
|
110
|
-
if (caps) {
|
|
111
|
-
info.capabilities = caps;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const instructions = this.client.getInstructions();
|
|
115
|
-
if (instructions) {
|
|
116
|
-
info.instructions = instructions;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
this._serverInfo = info;
|
|
120
|
-
} catch (error) {
|
|
121
|
-
throw new McpError(
|
|
122
|
-
`Failed to connect to MCP server "${this.serverName}": ${error instanceof Error ? error.message : String(error)}`,
|
|
123
|
-
'connection_failed',
|
|
124
|
-
this.serverName,
|
|
125
|
-
error instanceof Error ? error : undefined
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Disconnect from the MCP server
|
|
132
|
-
*/
|
|
133
|
-
async disconnect(): Promise<void> {
|
|
134
|
-
if (this.transport) {
|
|
135
|
-
await this.transport.close();
|
|
136
|
-
this.transport = null;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
this.client = null;
|
|
140
|
-
|
|
141
|
-
if (this._serverInfo) {
|
|
142
|
-
this._serverInfo.connected = false;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Check if connected to the server
|
|
148
|
-
*/
|
|
149
|
-
isConnected(): boolean {
|
|
150
|
-
return this._serverInfo?.connected ?? false;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Get server information
|
|
155
|
-
*/
|
|
156
|
-
getServerInfo(): McpServerInfo | null {
|
|
157
|
-
return this._serverInfo;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* List available tools from the server
|
|
162
|
-
*/
|
|
163
|
-
async listTools(): Promise<McpTool[]> {
|
|
164
|
-
const client = this.ensureConnected();
|
|
165
|
-
|
|
166
|
-
const result = await client.listTools();
|
|
167
|
-
|
|
168
|
-
return result.tools.map((tool) => {
|
|
169
|
-
// Build inputSchema with only defined properties
|
|
170
|
-
const inputSchema: McpTool['inputSchema'] = { type: 'object' };
|
|
171
|
-
if (tool.inputSchema.properties) {
|
|
172
|
-
inputSchema.properties = tool.inputSchema.properties as Record<string, unknown>;
|
|
173
|
-
}
|
|
174
|
-
if (tool.inputSchema.required) {
|
|
175
|
-
inputSchema.required = tool.inputSchema.required;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const mapped: McpTool = {
|
|
179
|
-
name: tool.name,
|
|
180
|
-
inputSchema,
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
if (tool.description) {
|
|
184
|
-
mapped.description = tool.description;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if (tool.annotations) {
|
|
188
|
-
const annotations: McpTool['annotations'] = {};
|
|
189
|
-
if (tool.annotations.title) annotations.title = tool.annotations.title;
|
|
190
|
-
if (tool.annotations.readOnlyHint !== undefined)
|
|
191
|
-
annotations.readOnlyHint = tool.annotations.readOnlyHint;
|
|
192
|
-
if (tool.annotations.destructiveHint !== undefined)
|
|
193
|
-
annotations.destructiveHint = tool.annotations.destructiveHint;
|
|
194
|
-
if (tool.annotations.idempotentHint !== undefined)
|
|
195
|
-
annotations.idempotentHint = tool.annotations.idempotentHint;
|
|
196
|
-
if (Object.keys(annotations).length > 0) {
|
|
197
|
-
mapped.annotations = annotations;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
return mapped;
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Call a tool on the server
|
|
207
|
-
*/
|
|
208
|
-
async callTool(name: string, args?: Record<string, unknown>): Promise<McpToolResult> {
|
|
209
|
-
const client = this.ensureConnected();
|
|
210
|
-
|
|
211
|
-
try {
|
|
212
|
-
const result = await client.callTool({
|
|
213
|
-
name,
|
|
214
|
-
arguments: args,
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
// Handle the different result formats
|
|
218
|
-
if ('content' in result && Array.isArray(result.content)) {
|
|
219
|
-
const content: McpContent[] = [];
|
|
220
|
-
|
|
221
|
-
for (const c of result.content) {
|
|
222
|
-
if (typeof c === 'object' && c !== null && 'type' in c) {
|
|
223
|
-
const item = c as { type: string; [key: string]: unknown };
|
|
224
|
-
if (item.type === 'text' && typeof item.text === 'string') {
|
|
225
|
-
content.push({ type: 'text', text: item.text });
|
|
226
|
-
} else if (
|
|
227
|
-
item.type === 'image' &&
|
|
228
|
-
typeof item.data === 'string' &&
|
|
229
|
-
typeof item.mimeType === 'string'
|
|
230
|
-
) {
|
|
231
|
-
content.push({ type: 'image', data: item.data, mimeType: item.mimeType });
|
|
232
|
-
} else if (item.type === 'resource' && typeof item.resource === 'object') {
|
|
233
|
-
const res = item.resource as {
|
|
234
|
-
uri: string;
|
|
235
|
-
text?: string;
|
|
236
|
-
blob?: string;
|
|
237
|
-
mimeType?: string;
|
|
238
|
-
};
|
|
239
|
-
const resourceContent: {
|
|
240
|
-
uri: string;
|
|
241
|
-
text?: string;
|
|
242
|
-
blob?: string;
|
|
243
|
-
mimeType?: string;
|
|
244
|
-
} = {
|
|
245
|
-
uri: res.uri,
|
|
246
|
-
};
|
|
247
|
-
if (res.text) resourceContent.text = res.text;
|
|
248
|
-
if (res.blob) resourceContent.blob = res.blob;
|
|
249
|
-
if (res.mimeType) resourceContent.mimeType = res.mimeType;
|
|
250
|
-
content.push({
|
|
251
|
-
type: 'resource',
|
|
252
|
-
resource: resourceContent,
|
|
253
|
-
});
|
|
254
|
-
} else {
|
|
255
|
-
// Default to text for unknown types
|
|
256
|
-
content.push({ type: 'text', text: JSON.stringify(c) });
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
const toolResult: McpToolResult = { content };
|
|
262
|
-
|
|
263
|
-
if (typeof result.isError === 'boolean') {
|
|
264
|
-
toolResult.isError = result.isError;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
if (typeof result.structuredContent === 'object' && result.structuredContent !== null) {
|
|
268
|
-
toolResult.structuredContent = result.structuredContent as Record<string, unknown>;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
return toolResult;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// Handle legacy toolResult format
|
|
275
|
-
if ('toolResult' in result) {
|
|
276
|
-
return {
|
|
277
|
-
content: [{ type: 'text', text: JSON.stringify(result.toolResult) }],
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
return {
|
|
282
|
-
content: [],
|
|
283
|
-
};
|
|
284
|
-
} catch (error) {
|
|
285
|
-
throw new McpError(
|
|
286
|
-
`Failed to call tool "${name}": ${error instanceof Error ? error.message : String(error)}`,
|
|
287
|
-
'protocol_error',
|
|
288
|
-
this.serverName,
|
|
289
|
-
error instanceof Error ? error : undefined
|
|
290
|
-
);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* List available resources from the server
|
|
296
|
-
*/
|
|
297
|
-
async listResources(): Promise<McpResource[]> {
|
|
298
|
-
const client = this.ensureConnected();
|
|
299
|
-
|
|
300
|
-
const result = await client.listResources();
|
|
301
|
-
|
|
302
|
-
return result.resources.map((resource) => {
|
|
303
|
-
const mapped: McpResource = {
|
|
304
|
-
uri: resource.uri,
|
|
305
|
-
name: resource.name,
|
|
306
|
-
};
|
|
307
|
-
if (resource.description) {
|
|
308
|
-
mapped.description = resource.description;
|
|
309
|
-
}
|
|
310
|
-
if (resource.mimeType) {
|
|
311
|
-
mapped.mimeType = resource.mimeType;
|
|
312
|
-
}
|
|
313
|
-
return mapped;
|
|
314
|
-
});
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
/**
|
|
318
|
-
* Read a resource from the server
|
|
319
|
-
*/
|
|
320
|
-
async readResource(uri: string): Promise<string> {
|
|
321
|
-
const client = this.ensureConnected();
|
|
322
|
-
|
|
323
|
-
const result = await client.readResource({ uri });
|
|
324
|
-
|
|
325
|
-
// Return the first text content, or blob as base64
|
|
326
|
-
for (const content of result.contents) {
|
|
327
|
-
if ('text' in content) {
|
|
328
|
-
return content.text;
|
|
329
|
-
}
|
|
330
|
-
if ('blob' in content) {
|
|
331
|
-
return content.blob;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
return '';
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* Create the appropriate transport for the server config
|
|
340
|
-
*/
|
|
341
|
-
private async createTransport(): Promise<Transport> {
|
|
342
|
-
if (this.config.transport === 'stdio') {
|
|
343
|
-
return this.createStdioTransport(this.config);
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
// HTTP/SSE transports would be added here
|
|
347
|
-
throw new McpError(
|
|
348
|
-
`Unsupported transport type: ${this.config.transport}`,
|
|
349
|
-
'invalid_config',
|
|
350
|
-
this.serverName
|
|
351
|
-
);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/**
|
|
355
|
-
* Create a stdio transport for local MCP servers
|
|
356
|
-
*/
|
|
357
|
-
private createStdioTransport(config: StdioServerConfig): Transport {
|
|
358
|
-
const params: {
|
|
359
|
-
command: string;
|
|
360
|
-
args?: string[];
|
|
361
|
-
env?: Record<string, string>;
|
|
362
|
-
cwd?: string;
|
|
363
|
-
} = {
|
|
364
|
-
command: config.command,
|
|
365
|
-
};
|
|
366
|
-
|
|
367
|
-
if (config.args) {
|
|
368
|
-
params.args = config.args;
|
|
369
|
-
}
|
|
370
|
-
if (config.env) {
|
|
371
|
-
params.env = config.env;
|
|
372
|
-
}
|
|
373
|
-
if (config.cwd) {
|
|
374
|
-
params.cwd = config.cwd;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
return new StdioClientTransport(params);
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* Parse server capabilities into our format
|
|
382
|
-
*/
|
|
383
|
-
private parseCapabilities(capabilities?: Record<string, unknown>): McpCapabilities | undefined {
|
|
384
|
-
if (!capabilities) return undefined;
|
|
385
|
-
|
|
386
|
-
return {
|
|
387
|
-
tools: !!capabilities.tools,
|
|
388
|
-
resources: !!capabilities.resources,
|
|
389
|
-
prompts: !!capabilities.prompts,
|
|
390
|
-
logging: !!capabilities.logging,
|
|
391
|
-
};
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
/**
|
|
395
|
-
* Ensure the client is connected and return the client instance
|
|
396
|
-
*/
|
|
397
|
-
private ensureConnected(): Client {
|
|
398
|
-
if (!this.client || !this.isConnected()) {
|
|
399
|
-
throw new McpError(
|
|
400
|
-
`Not connected to MCP server "${this.serverName}"`,
|
|
401
|
-
'connection_closed',
|
|
402
|
-
this.serverName
|
|
403
|
-
);
|
|
404
|
-
}
|
|
405
|
-
return this.client;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/**
|
|
409
|
-
* Set server info (for mock/testing purposes)
|
|
410
|
-
*/
|
|
411
|
-
protected setServerInfo(info: McpServerInfo): void {
|
|
412
|
-
this._serverInfo = info;
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
/**
|
|
417
|
-
* Create a mock MCP client for testing
|
|
418
|
-
*/
|
|
419
|
-
export function createMockMcpClient(
|
|
420
|
-
serverName: string,
|
|
421
|
-
tools: McpTool[] = [],
|
|
422
|
-
resources: McpResource[] = []
|
|
423
|
-
): McpClient {
|
|
424
|
-
// Create a client with in-memory transport for testing
|
|
425
|
-
const client = new McpClient(serverName, { transport: 'stdio', command: 'mock' });
|
|
426
|
-
|
|
427
|
-
// Store mock data
|
|
428
|
-
const mockTools = tools;
|
|
429
|
-
const mockResources = resources;
|
|
430
|
-
|
|
431
|
-
// Override connect to set up mock state
|
|
432
|
-
client.connect = async function (this: McpClient) {
|
|
433
|
-
const info: McpServerInfo = {
|
|
434
|
-
name: serverName,
|
|
435
|
-
version: '1.0.0',
|
|
436
|
-
connected: true,
|
|
437
|
-
capabilities: { tools: true, resources: true },
|
|
438
|
-
};
|
|
439
|
-
(this as McpClient & { setServerInfo(info: McpServerInfo): void }).setServerInfo(info);
|
|
440
|
-
};
|
|
441
|
-
|
|
442
|
-
client.listTools = async function () {
|
|
443
|
-
return mockTools;
|
|
444
|
-
};
|
|
445
|
-
|
|
446
|
-
client.listResources = async function () {
|
|
447
|
-
return mockResources;
|
|
448
|
-
};
|
|
449
|
-
|
|
450
|
-
return client;
|
|
451
|
-
}
|