@portel/photon-core 1.4.0 → 2.1.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.
Files changed (169) hide show
  1. package/README.md +123 -0
  2. package/dist/auto-ui.d.ts +103 -0
  3. package/dist/auto-ui.d.ts.map +1 -0
  4. package/dist/auto-ui.js +275 -0
  5. package/dist/auto-ui.js.map +1 -0
  6. package/dist/base.d.ts +9 -2
  7. package/dist/base.d.ts.map +1 -1
  8. package/dist/base.js +23 -10
  9. package/dist/base.js.map +1 -1
  10. package/dist/cli-ui-renderer.d.ts +31 -0
  11. package/dist/cli-ui-renderer.d.ts.map +1 -0
  12. package/dist/cli-ui-renderer.js +224 -0
  13. package/dist/cli-ui-renderer.js.map +1 -0
  14. package/dist/dependency-manager.d.ts.map +1 -1
  15. package/dist/dependency-manager.js +0 -1
  16. package/dist/dependency-manager.js.map +1 -1
  17. package/dist/design-system/index.d.ts +21 -0
  18. package/dist/design-system/index.d.ts.map +1 -0
  19. package/dist/design-system/index.js +27 -0
  20. package/dist/design-system/index.js.map +1 -0
  21. package/dist/design-system/tokens.d.ts +149 -0
  22. package/dist/design-system/tokens.d.ts.map +1 -0
  23. package/dist/design-system/tokens.js +413 -0
  24. package/dist/design-system/tokens.js.map +1 -0
  25. package/dist/design-system/transaction-ui.d.ts +70 -0
  26. package/dist/design-system/transaction-ui.d.ts.map +1 -0
  27. package/dist/design-system/transaction-ui.js +982 -0
  28. package/dist/design-system/transaction-ui.js.map +1 -0
  29. package/dist/generator.d.ts +58 -8
  30. package/dist/generator.d.ts.map +1 -1
  31. package/dist/generator.js +9 -4
  32. package/dist/generator.js.map +1 -1
  33. package/dist/index.d.ts +10 -7
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +48 -44
  36. package/dist/index.js.map +1 -1
  37. package/dist/io.d.ts +395 -0
  38. package/dist/io.d.ts.map +1 -0
  39. package/dist/io.js +304 -0
  40. package/dist/io.js.map +1 -0
  41. package/dist/path-resolver.d.ts.map +1 -1
  42. package/dist/path-resolver.js +2 -1
  43. package/dist/path-resolver.js.map +1 -1
  44. package/dist/rendering/components.d.ts +29 -0
  45. package/dist/rendering/components.d.ts.map +1 -0
  46. package/dist/rendering/components.js +773 -0
  47. package/dist/rendering/components.js.map +1 -0
  48. package/dist/rendering/field-analyzer.d.ts +48 -0
  49. package/dist/rendering/field-analyzer.d.ts.map +1 -0
  50. package/dist/rendering/field-analyzer.js +270 -0
  51. package/dist/rendering/field-analyzer.js.map +1 -0
  52. package/dist/rendering/field-renderers.d.ts +64 -0
  53. package/dist/rendering/field-renderers.d.ts.map +1 -0
  54. package/dist/rendering/field-renderers.js +317 -0
  55. package/dist/rendering/field-renderers.js.map +1 -0
  56. package/dist/rendering/index.d.ts +28 -0
  57. package/dist/rendering/index.d.ts.map +1 -0
  58. package/dist/rendering/index.js +60 -0
  59. package/dist/rendering/index.js.map +1 -0
  60. package/dist/rendering/layout-selector.d.ts +48 -0
  61. package/dist/rendering/layout-selector.d.ts.map +1 -0
  62. package/dist/rendering/layout-selector.js +347 -0
  63. package/dist/rendering/layout-selector.js.map +1 -0
  64. package/dist/rendering/template-engine.d.ts +41 -0
  65. package/dist/rendering/template-engine.d.ts.map +1 -0
  66. package/dist/rendering/template-engine.js +236 -0
  67. package/dist/rendering/template-engine.js.map +1 -0
  68. package/dist/schema-extractor.d.ts +30 -0
  69. package/dist/schema-extractor.d.ts.map +1 -1
  70. package/dist/schema-extractor.js +205 -12
  71. package/dist/schema-extractor.js.map +1 -1
  72. package/dist/stateful.d.ts +63 -0
  73. package/dist/stateful.d.ts.map +1 -1
  74. package/dist/stateful.js +222 -0
  75. package/dist/stateful.js.map +1 -1
  76. package/dist/types.d.ts +9 -1
  77. package/dist/types.d.ts.map +1 -1
  78. package/dist/types.js.map +1 -1
  79. package/dist/ucp/ap2/handlers.d.ts +242 -0
  80. package/dist/ucp/ap2/handlers.d.ts.map +1 -0
  81. package/dist/ucp/ap2/handlers.js +482 -0
  82. package/dist/ucp/ap2/handlers.js.map +1 -0
  83. package/dist/ucp/ap2/mandates.d.ts +95 -0
  84. package/dist/ucp/ap2/mandates.d.ts.map +1 -0
  85. package/dist/ucp/ap2/mandates.js +234 -0
  86. package/dist/ucp/ap2/mandates.js.map +1 -0
  87. package/dist/ucp/ap2/types.d.ts +305 -0
  88. package/dist/ucp/ap2/types.d.ts.map +1 -0
  89. package/dist/ucp/ap2/types.js +8 -0
  90. package/dist/ucp/ap2/types.js.map +1 -0
  91. package/dist/ucp/capabilities/checkout.d.ts +118 -0
  92. package/dist/ucp/capabilities/checkout.d.ts.map +1 -0
  93. package/dist/ucp/capabilities/checkout.js +344 -0
  94. package/dist/ucp/capabilities/checkout.js.map +1 -0
  95. package/dist/ucp/capabilities/identity.d.ts +130 -0
  96. package/dist/ucp/capabilities/identity.d.ts.map +1 -0
  97. package/dist/ucp/capabilities/identity.js +290 -0
  98. package/dist/ucp/capabilities/identity.js.map +1 -0
  99. package/dist/ucp/capabilities/order.d.ts +142 -0
  100. package/dist/ucp/capabilities/order.d.ts.map +1 -0
  101. package/dist/ucp/capabilities/order.js +383 -0
  102. package/dist/ucp/capabilities/order.js.map +1 -0
  103. package/dist/ucp/index.d.ts +18 -0
  104. package/dist/ucp/index.d.ts.map +1 -0
  105. package/dist/ucp/index.js +19 -0
  106. package/dist/ucp/index.js.map +1 -0
  107. package/dist/ucp/manifest.d.ts +62 -0
  108. package/dist/ucp/manifest.d.ts.map +1 -0
  109. package/dist/ucp/manifest.js +180 -0
  110. package/dist/ucp/manifest.js.map +1 -0
  111. package/dist/ucp/types.d.ts +327 -0
  112. package/dist/ucp/types.d.ts.map +1 -0
  113. package/dist/ucp/types.js +8 -0
  114. package/dist/ucp/types.js.map +1 -0
  115. package/package.json +3 -4
  116. package/src/auto-ui.ts +413 -0
  117. package/src/base.ts +22 -9
  118. package/src/cli-ui-renderer.ts +264 -0
  119. package/src/dependency-manager.ts +0 -1
  120. package/src/design-system/index.ts +30 -0
  121. package/src/design-system/tokens.ts +451 -0
  122. package/src/design-system/transaction-ui.ts +1038 -0
  123. package/src/generator.ts +68 -8
  124. package/src/index.ts +159 -101
  125. package/src/io.ts +493 -0
  126. package/src/path-resolver.ts +2 -1
  127. package/src/rendering/components.ts +785 -0
  128. package/src/rendering/field-analyzer.ts +299 -0
  129. package/src/rendering/field-renderers.ts +356 -0
  130. package/src/rendering/index.ts +63 -0
  131. package/src/rendering/layout-selector.ts +390 -0
  132. package/src/rendering/template-engine.ts +254 -0
  133. package/src/schema-extractor.ts +225 -12
  134. package/src/stateful.ts +301 -0
  135. package/src/types.ts +10 -1
  136. package/src/ucp/ap2/handlers.ts +779 -0
  137. package/src/ucp/ap2/mandates.ts +354 -0
  138. package/src/ucp/ap2/types.ts +441 -0
  139. package/src/ucp/capabilities/checkout.ts +497 -0
  140. package/src/ucp/capabilities/identity.ts +425 -0
  141. package/src/ucp/capabilities/order.ts +549 -0
  142. package/src/ucp/index.ts +27 -0
  143. package/src/ucp/manifest.ts +257 -0
  144. package/src/ucp/types.ts +454 -0
  145. package/dist/cli-formatter.d.ts +0 -92
  146. package/dist/cli-formatter.d.ts.map +0 -1
  147. package/dist/cli-formatter.js +0 -486
  148. package/dist/cli-formatter.js.map +0 -1
  149. package/dist/elicit.d.ts +0 -93
  150. package/dist/elicit.d.ts.map +0 -1
  151. package/dist/elicit.js +0 -373
  152. package/dist/elicit.js.map +0 -1
  153. package/dist/mcp-client.d.ts +0 -218
  154. package/dist/mcp-client.d.ts.map +0 -1
  155. package/dist/mcp-client.js +0 -424
  156. package/dist/mcp-client.js.map +0 -1
  157. package/dist/mcp-sdk-transport.d.ts +0 -88
  158. package/dist/mcp-sdk-transport.d.ts.map +0 -1
  159. package/dist/mcp-sdk-transport.js +0 -360
  160. package/dist/mcp-sdk-transport.js.map +0 -1
  161. package/dist/photon-config.d.ts +0 -86
  162. package/dist/photon-config.d.ts.map +0 -1
  163. package/dist/photon-config.js +0 -156
  164. package/dist/photon-config.js.map +0 -1
  165. package/src/cli-formatter.ts +0 -579
  166. package/src/elicit.ts +0 -438
  167. package/src/mcp-client.ts +0 -561
  168. package/src/mcp-sdk-transport.ts +0 -449
  169. package/src/photon-config.ts +0 -201
package/src/mcp-client.ts DELETED
@@ -1,561 +0,0 @@
1
- /**
2
- * MCP Protocol Client for Photons
3
- *
4
- * Enables Photons to call external MCPs via the MCP protocol.
5
- * This is runtime-agnostic - the actual transport is provided by the runtime (NCP, Lumina, etc.)
6
- *
7
- * Usage in Photon:
8
- * ```typescript
9
- * export default class MyPhoton extends PhotonMCP {
10
- * async doSomething() {
11
- * const github = this.mcp('github');
12
- * const issues = await github.call('list_issues', { repo: 'foo/bar' });
13
- * }
14
- * }
15
- * ```
16
- */
17
-
18
- /**
19
- * Tool information returned from MCP discovery
20
- */
21
- export interface MCPToolInfo {
22
- name: string;
23
- description?: string;
24
- inputSchema?: {
25
- type: 'object';
26
- properties?: Record<string, any>;
27
- required?: string[];
28
- };
29
- }
30
-
31
- /**
32
- * Result from an MCP tool call
33
- */
34
- export interface MCPToolResult {
35
- content: Array<{
36
- type: 'text' | 'image' | 'resource';
37
- text?: string;
38
- data?: string;
39
- mimeType?: string;
40
- }>;
41
- isError?: boolean;
42
- }
43
-
44
- /**
45
- * Interface that runtimes must implement to provide MCP connectivity
46
- * This keeps photon-core runtime-agnostic
47
- */
48
- export interface MCPTransport {
49
- /**
50
- * Call a tool on an MCP server
51
- * @param mcpName The MCP server name
52
- * @param toolName The tool to call
53
- * @param parameters Tool parameters
54
- */
55
- callTool(
56
- mcpName: string,
57
- toolName: string,
58
- parameters: Record<string, any>
59
- ): Promise<MCPToolResult>;
60
-
61
- /**
62
- * List available tools on an MCP server
63
- * @param mcpName The MCP server name
64
- */
65
- listTools(mcpName: string): Promise<MCPToolInfo[]>;
66
-
67
- /**
68
- * Check if an MCP server is connected/available
69
- * @param mcpName The MCP server name
70
- */
71
- isConnected(mcpName: string): Promise<boolean>;
72
- }
73
-
74
- /**
75
- * Factory interface for creating MCP clients
76
- * Runtimes implement this to provide MCP access to Photons
77
- */
78
- export interface MCPClientFactory {
79
- /**
80
- * Create an MCP client for a specific server
81
- * @param mcpName The MCP server name
82
- */
83
- create(mcpName: string): MCPClient;
84
-
85
- /**
86
- * List all available MCP servers
87
- */
88
- listServers(): Promise<string[]>;
89
- }
90
-
91
- /**
92
- * MCP Client - Protocol wrapper for calling external MCPs
93
- *
94
- * Provides a clean async interface for Photons to call MCP tools.
95
- * The actual protocol communication is handled by the transport layer.
96
- */
97
- export class MCPClient {
98
- private toolsCache: MCPToolInfo[] | null = null;
99
-
100
- constructor(
101
- private mcpName: string,
102
- private transport: MCPTransport
103
- ) {}
104
-
105
- /**
106
- * Get the MCP server name
107
- */
108
- get name(): string {
109
- return this.mcpName;
110
- }
111
-
112
- /**
113
- * Call a tool on this MCP server
114
- *
115
- * @param toolName The tool to call
116
- * @param parameters Tool parameters
117
- * @returns Tool result (parsed from MCP response)
118
- *
119
- * @example
120
- * ```typescript
121
- * const github = this.mcp('github');
122
- * const issues = await github.call('list_issues', { repo: 'owner/repo', state: 'open' });
123
- * ```
124
- */
125
- async call(toolName: string, parameters: Record<string, any> = {}): Promise<any> {
126
- // Check connection first
127
- const connected = await this.transport.isConnected(this.mcpName);
128
- if (!connected) {
129
- throw new MCPNotConnectedError(this.mcpName);
130
- }
131
-
132
- try {
133
- const result = await this.transport.callTool(this.mcpName, toolName, parameters);
134
-
135
- if (result.isError) {
136
- const errorText = result.content.find(c => c.type === 'text')?.text || 'Unknown error';
137
- throw new MCPToolError(this.mcpName, toolName, errorText);
138
- }
139
-
140
- // Extract and parse the result
141
- return this.parseResult(result);
142
- } catch (error) {
143
- if (error instanceof MCPError) {
144
- throw error;
145
- }
146
- throw new MCPToolError(
147
- this.mcpName,
148
- toolName,
149
- error instanceof Error ? error.message : String(error)
150
- );
151
- }
152
- }
153
-
154
- /**
155
- * List all available tools on this MCP server
156
- *
157
- * @returns Array of tool information
158
- *
159
- * @example
160
- * ```typescript
161
- * const github = this.mcp('github');
162
- * const tools = await github.list();
163
- * // [{ name: 'list_issues', description: '...' }, ...]
164
- * ```
165
- */
166
- async list(): Promise<MCPToolInfo[]> {
167
- if (this.toolsCache) {
168
- return this.toolsCache;
169
- }
170
-
171
- const connected = await this.transport.isConnected(this.mcpName);
172
- if (!connected) {
173
- throw new MCPNotConnectedError(this.mcpName);
174
- }
175
-
176
- this.toolsCache = await this.transport.listTools(this.mcpName);
177
- return this.toolsCache;
178
- }
179
-
180
- /**
181
- * Find tools matching a query
182
- *
183
- * @param query Search query (matches name or description)
184
- * @returns Matching tools
185
- *
186
- * @example
187
- * ```typescript
188
- * const github = this.mcp('github');
189
- * const issueTools = await github.find('issue');
190
- * ```
191
- */
192
- async find(query: string): Promise<MCPToolInfo[]> {
193
- const tools = await this.list();
194
- const lowerQuery = query.toLowerCase();
195
- return tools.filter(
196
- t =>
197
- t.name.toLowerCase().includes(lowerQuery) ||
198
- t.description?.toLowerCase().includes(lowerQuery)
199
- );
200
- }
201
-
202
- /**
203
- * Check if this MCP server is connected
204
- */
205
- async isConnected(): Promise<boolean> {
206
- return this.transport.isConnected(this.mcpName);
207
- }
208
-
209
- /**
210
- * Clear the tools cache (useful after reconnection)
211
- */
212
- clearCache(): void {
213
- this.toolsCache = null;
214
- }
215
-
216
- /**
217
- * Parse MCP tool result into a usable value
218
- */
219
- private parseResult(result: MCPToolResult): any {
220
- if (!result.content || result.content.length === 0) {
221
- return null;
222
- }
223
-
224
- // Single text result - try to parse as JSON
225
- if (result.content.length === 1 && result.content[0].type === 'text') {
226
- const text = result.content[0].text || '';
227
- try {
228
- return JSON.parse(text);
229
- } catch {
230
- return text;
231
- }
232
- }
233
-
234
- // Multiple results or non-text - return as-is
235
- return result.content.map(c => {
236
- if (c.type === 'text') {
237
- try {
238
- return JSON.parse(c.text || '');
239
- } catch {
240
- return c.text;
241
- }
242
- }
243
- return c;
244
- });
245
- }
246
- }
247
-
248
- /**
249
- * Base class for MCP-related errors
250
- */
251
- export class MCPError extends Error {
252
- constructor(
253
- public readonly mcpName: string,
254
- message: string
255
- ) {
256
- super(message);
257
- this.name = 'MCPError';
258
- }
259
- }
260
-
261
- /**
262
- * Error thrown when MCP server is not connected
263
- */
264
- export class MCPNotConnectedError extends MCPError {
265
- constructor(mcpName: string) {
266
- super(mcpName, `MCP server '${mcpName}' is not connected`);
267
- this.name = 'MCPNotConnectedError';
268
- }
269
- }
270
-
271
- /**
272
- * Error thrown when MCP tool call fails
273
- */
274
- export class MCPToolError extends MCPError {
275
- constructor(
276
- mcpName: string,
277
- public readonly toolName: string,
278
- public readonly details: string
279
- ) {
280
- super(mcpName, `MCP tool '${mcpName}:${toolName}' failed: ${details}`);
281
- this.name = 'MCPToolError';
282
- }
283
- }
284
-
285
- /**
286
- * MCP source type - how the MCP was declared
287
- */
288
- export type MCPSourceType = 'npm' | 'github' | 'local' | 'url' | 'unknown';
289
-
290
- /**
291
- * Information about a missing MCP dependency
292
- */
293
- export interface MissingMCPInfo {
294
- name: string;
295
- source: string;
296
- sourceType: MCPSourceType;
297
- declaredIn?: string; // Photon file that declared this dependency
298
- originalError?: string;
299
- }
300
-
301
- /**
302
- * Error thrown when MCP is not configured correctly
303
- * Provides detailed, actionable guidance for users
304
- */
305
- export class MCPConfigurationError extends MCPError {
306
- public readonly configPath: string;
307
- public readonly missingMCPs: MissingMCPInfo[];
308
-
309
- constructor(missingMCPs: MissingMCPInfo[]) {
310
- const configPath = `~/.photon/mcp-servers.json`;
311
- const message = MCPConfigurationError.formatMessage(missingMCPs, configPath);
312
- super(missingMCPs[0]?.name || 'unknown', message);
313
- this.name = 'MCPConfigurationError';
314
- this.configPath = configPath;
315
- this.missingMCPs = missingMCPs;
316
- }
317
-
318
- /**
319
- * Format detailed error message with configuration instructions
320
- */
321
- private static formatMessage(missingMCPs: MissingMCPInfo[], configPath: string): string {
322
- const lines: string[] = [
323
- '',
324
- '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
325
- '❌ MCP Configuration Required',
326
- '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
327
- '',
328
- ];
329
-
330
- // List missing MCPs
331
- lines.push(`The following MCP server${missingMCPs.length > 1 ? 's are' : ' is'} required but not configured:`);
332
- lines.push('');
333
-
334
- for (const mcp of missingMCPs) {
335
- lines.push(` • ${mcp.name}`);
336
- if (mcp.source) {
337
- lines.push(` Source: ${mcp.source} (${mcp.sourceType})`);
338
- }
339
- if (mcp.declaredIn) {
340
- lines.push(` Declared in: ${mcp.declaredIn}`);
341
- }
342
- if (mcp.originalError) {
343
- lines.push(` Error: ${mcp.originalError}`);
344
- }
345
- lines.push('');
346
- }
347
-
348
- // Configuration instructions
349
- lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
350
- lines.push('🔧 How to Fix');
351
- lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
352
- lines.push('');
353
- lines.push(`Add the following to ${configPath}:`);
354
- lines.push('');
355
-
356
- // Generate example config
357
- const exampleConfig = MCPConfigurationError.generateExampleConfig(missingMCPs);
358
- lines.push(exampleConfig);
359
- lines.push('');
360
-
361
- // Step-by-step instructions
362
- lines.push('Steps:');
363
- lines.push(` 1. Create or edit ${configPath}`);
364
- lines.push(' 2. Add the configuration above');
365
- lines.push(' 3. Replace placeholder values with your actual configuration');
366
- lines.push(' 4. Restart the Photon');
367
- lines.push('');
368
-
369
- // Per-source-type guidance
370
- const uniqueTypes = new Set(missingMCPs.map(m => m.sourceType));
371
- if (uniqueTypes.size > 0) {
372
- lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
373
- lines.push('📖 Configuration Guide');
374
- lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
375
- lines.push('');
376
-
377
- for (const type of uniqueTypes) {
378
- lines.push(...MCPConfigurationError.getSourceTypeGuide(type));
379
- lines.push('');
380
- }
381
- }
382
-
383
- lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
384
-
385
- return lines.join('\n');
386
- }
387
-
388
- /**
389
- * Generate example JSON config for missing MCPs
390
- */
391
- private static generateExampleConfig(missingMCPs: MissingMCPInfo[]): string {
392
- const servers: Record<string, any> = {};
393
-
394
- for (const mcp of missingMCPs) {
395
- servers[mcp.name] = MCPConfigurationError.getExampleServerConfig(mcp);
396
- }
397
-
398
- const config = { mcpServers: servers };
399
- return JSON.stringify(config, null, 2)
400
- .split('\n')
401
- .map(line => ' ' + line)
402
- .join('\n');
403
- }
404
-
405
- /**
406
- * Get example server config based on source type
407
- */
408
- private static getExampleServerConfig(mcp: MissingMCPInfo): Record<string, any> {
409
- switch (mcp.sourceType) {
410
- case 'npm':
411
- return {
412
- command: 'npx',
413
- args: ['-y', mcp.source],
414
- env: {
415
- '// Add required environment variables here': '',
416
- },
417
- };
418
-
419
- case 'github': {
420
- // Parse github source: owner/repo or owner/repo#branch
421
- const [repo, branch] = mcp.source.split('#');
422
- const args = ['-y', `github:${repo}`];
423
- if (branch) {
424
- args[1] = `github:${repo}#${branch}`;
425
- }
426
- return {
427
- command: 'npx',
428
- args,
429
- env: {
430
- '// Add required environment variables here': '',
431
- },
432
- };
433
- }
434
-
435
- case 'url':
436
- if (mcp.source.startsWith('ws://') || mcp.source.startsWith('wss://')) {
437
- return {
438
- url: mcp.source,
439
- transport: 'websocket',
440
- };
441
- }
442
- return {
443
- url: mcp.source,
444
- transport: 'sse',
445
- };
446
-
447
- case 'local':
448
- return {
449
- command: mcp.source,
450
- args: [],
451
- cwd: '// Optional: working directory',
452
- };
453
-
454
- default:
455
- return {
456
- '// Configure this MCP server': '',
457
- command: 'npx',
458
- args: ['-y', '<package-name>'],
459
- };
460
- }
461
- }
462
-
463
- /**
464
- * Get source-type specific guidance
465
- */
466
- private static getSourceTypeGuide(type: MCPSourceType): string[] {
467
- switch (type) {
468
- case 'npm':
469
- return [
470
- '📦 NPM Packages:',
471
- ' MCP servers from npm are run via npx.',
472
- ' Example: @modelcontextprotocol/server-github',
473
- '',
474
- ' {',
475
- ' "command": "npx",',
476
- ' "args": ["-y", "@modelcontextprotocol/server-github"],',
477
- ' "env": {',
478
- ' "GITHUB_TOKEN": "ghp_your_token_here"',
479
- ' }',
480
- ' }',
481
- ];
482
-
483
- case 'github':
484
- return [
485
- '🐙 GitHub Repositories:',
486
- ' MCP servers from GitHub repos are cloned and run.',
487
- ' Format: owner/repo or owner/repo#branch',
488
- '',
489
- ' {',
490
- ' "command": "npx",',
491
- ' "args": ["-y", "github:anthropics/mcp-server-github"],',
492
- ' "env": {',
493
- ' "GITHUB_TOKEN": "ghp_your_token_here"',
494
- ' }',
495
- ' }',
496
- ];
497
-
498
- case 'url':
499
- return [
500
- '🌐 Remote URLs:',
501
- ' MCP servers running on remote hosts.',
502
- '',
503
- ' HTTP/SSE:',
504
- ' {',
505
- ' "url": "https://mcp.example.com/api",',
506
- ' "transport": "sse",',
507
- ' "headers": { "Authorization": "Bearer token" }',
508
- ' }',
509
- '',
510
- ' WebSocket:',
511
- ' {',
512
- ' "url": "wss://mcp.example.com/ws",',
513
- ' "transport": "websocket"',
514
- ' }',
515
- ];
516
-
517
- case 'local':
518
- return [
519
- '💻 Local Commands:',
520
- ' MCP servers running as local processes.',
521
- '',
522
- ' {',
523
- ' "command": "/path/to/mcp-server",',
524
- ' "args": ["--port", "3000"],',
525
- ' "cwd": "/working/directory",',
526
- ' "env": { "CONFIG": "value" }',
527
- ' }',
528
- ];
529
-
530
- default:
531
- return [
532
- '⚙️ Custom Configuration:',
533
- ' Configure the MCP server based on its documentation.',
534
- ];
535
- }
536
- }
537
- }
538
-
539
- /**
540
- * Create a proxy-based MCP client that allows direct method calls
541
- *
542
- * This enables a more fluent API:
543
- * ```typescript
544
- * const github = this.mcp('github');
545
- * // Instead of: await github.call('list_issues', { repo: 'foo/bar' })
546
- * // You can do: await github.list_issues({ repo: 'foo/bar' })
547
- * ```
548
- */
549
- export function createMCPProxy(client: MCPClient): MCPClient & Record<string, (params?: any) => Promise<any>> {
550
- return new Proxy(client, {
551
- get(target, prop: string) {
552
- // Return existing methods
553
- if (prop in target) {
554
- return (target as any)[prop];
555
- }
556
-
557
- // Return a function that calls the tool
558
- return (params: Record<string, any> = {}) => target.call(prop, params);
559
- },
560
- }) as MCPClient & Record<string, (params?: any) => Promise<any>>;
561
- }