@autonomaai/mcp-client 1.0.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/src/client.ts ADDED
@@ -0,0 +1,780 @@
1
+ /**
2
+ * Unified MCP Client for autonoma Trading System
3
+ *
4
+ * This client provides a unified interface for interacting with MCP servers
5
+ * across the autonoma ecosystem, with support for connection pooling,
6
+ * error handling, retries, and both sync and async operations.
7
+ */
8
+
9
+ // Use native fetch (Node.js 18+) or polyfill
10
+ declare const fetch: typeof globalThis.fetch;
11
+ import {
12
+ MCPClientConfig,
13
+ MCPClientOptions,
14
+ HummingbotHealthResponse,
15
+ HummingbotContext,
16
+ CreateControllerRequest,
17
+ ControllerResponse,
18
+ ControllerMetrics,
19
+ ExchangeListResponse,
20
+ ConnectExchangeRequest,
21
+ TradingConnectionResponse,
22
+ MarketDataResponse,
23
+ ExecuteSignalRequest,
24
+ SignalExecutionResponse,
25
+ CreateBotRequest,
26
+ BotResponse,
27
+ CreatePoolRequest,
28
+ PoolResponse,
29
+ ConfigurationObject,
30
+ HyperliquidOrderbook,
31
+ HyperliquidSummary,
32
+ ErrorResponse,
33
+ MCPRequest,
34
+ MCPResponse,
35
+ MCPToolsListResponse,
36
+ MCPToolCallRequest,
37
+ MCPToolCallResponse
38
+ } from './types';
39
+
40
+ /**
41
+ * HTTP Client Error for MCP operations
42
+ */
43
+ export class MCPClientError extends Error {
44
+ constructor(
45
+ message: string,
46
+ public status?: number,
47
+ public response?: any
48
+ ) {
49
+ super(message);
50
+ this.name = 'MCPClientError';
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Main MCP Client class
56
+ */
57
+ export class MCPClient {
58
+ private config: Required<MCPClientConfig>;
59
+ private headers: Record<string, string>;
60
+
61
+ constructor(config: MCPClientConfig) {
62
+ this.config = {
63
+ timeout: 30000,
64
+ retries: 3,
65
+ retryDelay: 1000,
66
+ enableLogging: false,
67
+ apiKey: '',
68
+ headers: {},
69
+ ...config
70
+ };
71
+
72
+ this.headers = {
73
+ 'Content-Type': 'application/json',
74
+ 'User-Agent': '@autonoma/mcp-client/1.0.0',
75
+ ...this.config.headers
76
+ };
77
+
78
+ if (this.config.apiKey) {
79
+ this.headers['Authorization'] = `Bearer ${this.config.apiKey}`;
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Make HTTP request with retry logic and error handling
85
+ */
86
+ private async request<T>(
87
+ endpoint: string,
88
+ options: MCPClientOptions & {
89
+ method?: string;
90
+ body?: any;
91
+ } = {}
92
+ ): Promise<T> {
93
+ const {
94
+ method = 'GET',
95
+ body,
96
+ timeout = this.config.timeout,
97
+ retries = this.config.retries,
98
+ retryDelay = this.config.retryDelay,
99
+ headers: optionHeaders = {}
100
+ } = options;
101
+
102
+ const url = `${this.config.baseUrl}${endpoint}`;
103
+ const requestHeaders = { ...this.headers, ...optionHeaders };
104
+
105
+ let lastError: Error | null = null;
106
+
107
+ for (let attempt = 0; attempt <= retries; attempt++) {
108
+ try {
109
+ if (this.config.enableLogging && attempt > 0) {
110
+ // Use structured logging format instead of plain console.log
111
+ const logEntry = {
112
+ timestamp: new Date().toISOString(),
113
+ level: 'INFO',
114
+ component: 'MCP Client',
115
+ message: 'Retry attempt',
116
+ attempt,
117
+ method,
118
+ url
119
+ };
120
+
121
+ // @ts-ignore - process may not be available in all environments
122
+ const isProduction = typeof process !== 'undefined' && process.env?.NODE_ENV === 'production';
123
+ if (isProduction) {
124
+ console.log(JSON.stringify(logEntry));
125
+ } else {
126
+ console.log(`[${logEntry.timestamp}] ${logEntry.level} [${logEntry.component}] ${logEntry.message} - attempt ${attempt} for ${method} ${url}`);
127
+ }
128
+ }
129
+
130
+ const response = await fetch(url, {
131
+ method,
132
+ headers: requestHeaders,
133
+ body: body ? JSON.stringify(body) : undefined,
134
+ // @ts-ignore - node-fetch timeout type issue
135
+ timeout
136
+ });
137
+
138
+ if (!response.ok) {
139
+ const errorText = await response.text();
140
+ let errorData: ErrorResponse | null = null;
141
+
142
+ try {
143
+ errorData = JSON.parse(errorText);
144
+ } catch {
145
+ // Not JSON, use plain text
146
+ }
147
+
148
+ const errorMessage = errorData?.error || `HTTP ${response.status}: ${response.statusText}`;
149
+ throw new MCPClientError(
150
+ errorMessage,
151
+ response.status,
152
+ errorData
153
+ );
154
+ }
155
+
156
+ const contentType = response.headers.get('content-type');
157
+ if (contentType?.includes('application/json')) {
158
+ return await response.json() as T;
159
+ } else {
160
+ return await response.text() as unknown as T;
161
+ }
162
+
163
+ } catch (error) {
164
+ lastError = error instanceof Error ? error : new Error(String(error));
165
+
166
+ if (this.config.enableLogging) {
167
+ console.error(`MCP Client: Request failed (attempt ${attempt + 1}):`, lastError.message);
168
+ }
169
+
170
+ // Don't retry on client errors (4xx) or final attempt
171
+ if (error instanceof MCPClientError && error.status && error.status < 500) {
172
+ break;
173
+ }
174
+
175
+ if (attempt === retries) {
176
+ break;
177
+ }
178
+
179
+ // Wait before retry
180
+ await new Promise(resolve => setTimeout(resolve, retryDelay * Math.pow(2, attempt)));
181
+ }
182
+ }
183
+
184
+ throw lastError || new MCPClientError('Request failed after all retries');
185
+ }
186
+
187
+ // =============================================================================
188
+ // Health and Context Methods
189
+ // =============================================================================
190
+
191
+ async getHealth(): Promise<HummingbotHealthResponse> {
192
+ return this.request<HummingbotHealthResponse>('/health');
193
+ }
194
+
195
+ async getContext(): Promise<HummingbotContext> {
196
+ return this.request<HummingbotContext>('/context');
197
+ }
198
+
199
+ // =============================================================================
200
+ // Controller Management Methods
201
+ // =============================================================================
202
+
203
+ async createController(params: CreateControllerRequest): Promise<ControllerResponse> {
204
+ return this.request<ControllerResponse>('/controllers/create', {
205
+ method: 'POST',
206
+ body: params
207
+ });
208
+ }
209
+
210
+ async getControllers(): Promise<ControllerResponse[]> {
211
+ return this.request<ControllerResponse[]>('/controllers');
212
+ }
213
+
214
+ async getController(id: string): Promise<ControllerResponse> {
215
+ return this.request<ControllerResponse>(`/controllers/${id}`);
216
+ }
217
+
218
+ async startController(id: string): Promise<{ success: boolean; message: string }> {
219
+ return this.request<{ success: boolean; message: string }>(`/controllers/${id}/start`, {
220
+ method: 'POST'
221
+ });
222
+ }
223
+
224
+ async stopController(id: string): Promise<{ success: boolean; message: string }> {
225
+ return this.request<{ success: boolean; message: string }>(`/controllers/${id}/stop`, {
226
+ method: 'POST'
227
+ });
228
+ }
229
+
230
+ async getControllerMetrics(id: string): Promise<ControllerMetrics> {
231
+ return this.request<ControllerMetrics>(`/controllers/${id}/metrics`);
232
+ }
233
+
234
+ async updateControllerConfig(id: string, config: ConfigurationObject): Promise<ControllerResponse> {
235
+ return this.request<ControllerResponse>(`/controllers/${id}/config`, {
236
+ method: 'PUT',
237
+ body: config
238
+ });
239
+ }
240
+
241
+ // =============================================================================
242
+ // Trading Operations Methods
243
+ // =============================================================================
244
+
245
+ async getExchanges(): Promise<ExchangeListResponse> {
246
+ return this.request<ExchangeListResponse>('/trading/exchanges');
247
+ }
248
+
249
+ async connectExchange(controllerId: string, params: ConnectExchangeRequest): Promise<TradingConnectionResponse> {
250
+ return this.request<TradingConnectionResponse>(`/trading/${controllerId}/connect`, {
251
+ method: 'POST',
252
+ body: params
253
+ });
254
+ }
255
+
256
+ async getMarketData(controllerId: string): Promise<MarketDataResponse> {
257
+ return this.request<MarketDataResponse>(`/trading/${controllerId}/market-data`);
258
+ }
259
+
260
+ async getAccountBalance(controllerId: string): Promise<Record<string, number>> {
261
+ return this.request<Record<string, number>>(`/trading/${controllerId}/balance`);
262
+ }
263
+
264
+ async getConnectionStatus(controllerId: string): Promise<{ connected: boolean; exchange: string; trading_pair: string }> {
265
+ return this.request<{ connected: boolean; exchange: string; trading_pair: string }>(`/trading/${controllerId}/connection-status`);
266
+ }
267
+
268
+ async executeSignal(params: ExecuteSignalRequest): Promise<SignalExecutionResponse> {
269
+ return this.request<SignalExecutionResponse>('/trading/execute-signal', {
270
+ method: 'POST',
271
+ body: params
272
+ });
273
+ }
274
+
275
+ // =============================================================================
276
+ // Bot Management Methods (Legacy)
277
+ // =============================================================================
278
+
279
+ async createBot(params: CreateBotRequest): Promise<BotResponse> {
280
+ return this.request<BotResponse>('/bots', {
281
+ method: 'POST',
282
+ body: params
283
+ });
284
+ }
285
+
286
+ async getBots(): Promise<BotResponse[]> {
287
+ return this.request<BotResponse[]>('/bots');
288
+ }
289
+
290
+ async getBot(id: string): Promise<BotResponse> {
291
+ return this.request<BotResponse>(`/bots/${id}`);
292
+ }
293
+
294
+ async getBotStatus(id: string): Promise<{ status: string; is_running: boolean }> {
295
+ return this.request<{ status: string; is_running: boolean }>(`/bots/${id}/status`);
296
+ }
297
+
298
+ // =============================================================================
299
+ // Pool Management Methods
300
+ // =============================================================================
301
+
302
+ async createPool(params: CreatePoolRequest): Promise<PoolResponse> {
303
+ return this.request<PoolResponse>('/pools/create', {
304
+ method: 'POST',
305
+ body: params
306
+ });
307
+ }
308
+
309
+ async getPools(): Promise<PoolResponse[]> {
310
+ return this.request<PoolResponse[]>('/pools');
311
+ }
312
+
313
+ async getPool(id: string): Promise<PoolResponse> {
314
+ return this.request<PoolResponse>(`/pools/${id}`);
315
+ }
316
+
317
+ // =============================================================================
318
+ // Hyperliquid Market Data Methods (Legacy)
319
+ // =============================================================================
320
+
321
+ async getHyperliquidOrderbook(pair: string): Promise<HyperliquidOrderbook> {
322
+ return this.request<HyperliquidOrderbook>(`/hyperliquid/orderbook/${pair}`);
323
+ }
324
+
325
+ async getHyperliquidSummary(pair: string): Promise<HyperliquidSummary> {
326
+ return this.request<HyperliquidSummary>(`/hyperliquid/summary/${pair}`);
327
+ }
328
+
329
+ // =============================================================================
330
+ // Utility Methods
331
+ // =============================================================================
332
+
333
+ /**
334
+ * Update client configuration
335
+ */
336
+ updateConfig(newConfig: Partial<MCPClientConfig>): void {
337
+ this.config = { ...this.config, ...newConfig };
338
+
339
+ if (newConfig.headers) {
340
+ this.headers = { ...this.headers, ...newConfig.headers };
341
+ }
342
+
343
+ if (newConfig.apiKey !== undefined) {
344
+ if (newConfig.apiKey) {
345
+ this.headers['Authorization'] = `Bearer ${newConfig.apiKey}`;
346
+ } else {
347
+ delete this.headers['Authorization'];
348
+ }
349
+ }
350
+ }
351
+
352
+ /**
353
+ * Get current configuration
354
+ */
355
+ getConfig(): MCPClientConfig {
356
+ return { ...this.config };
357
+ }
358
+
359
+ /**
360
+ * Enable or disable logging
361
+ */
362
+ setLogging(enabled: boolean): void {
363
+ this.config.enableLogging = enabled;
364
+ }
365
+
366
+ /**
367
+ * Test connection to MCP server
368
+ */
369
+ async testConnection(): Promise<boolean> {
370
+ try {
371
+ await this.getHealth();
372
+ return true;
373
+ } catch {
374
+ return false;
375
+ }
376
+ }
377
+
378
+ // =============================================================================
379
+ // MCP Tools Methods (Standardized Interface)
380
+ // =============================================================================
381
+
382
+ /**
383
+ * List available MCP tools
384
+ */
385
+ async listTools(): Promise<MCPToolsListResponse> {
386
+ const request: MCPRequest = {
387
+ jsonrpc: '2.0',
388
+ id: Date.now(),
389
+ method: 'tools/list'
390
+ };
391
+
392
+ const response = await this.request<MCPResponse>('/mcp', {
393
+ method: 'POST',
394
+ body: request
395
+ });
396
+
397
+ if (response.error) {
398
+ throw new MCPClientError(response.error.message, response.error.code, response.error.data);
399
+ }
400
+
401
+ return response.result as MCPToolsListResponse;
402
+ }
403
+
404
+ /**
405
+ * Call an MCP tool
406
+ */
407
+ async callTool(toolCall: MCPToolCallRequest): Promise<MCPToolCallResponse> {
408
+ const request: MCPRequest = {
409
+ jsonrpc: '2.0',
410
+ id: Date.now(),
411
+ method: 'tools/call',
412
+ params: toolCall
413
+ };
414
+
415
+ const response = await this.request<MCPResponse>('/mcp', {
416
+ method: 'POST',
417
+ body: request
418
+ });
419
+
420
+ if (response.error) {
421
+ throw new MCPClientError(response.error.message, response.error.code, response.error.data);
422
+ }
423
+
424
+ return response.result as MCPToolCallResponse;
425
+ }
426
+
427
+ /**
428
+ * Ping MCP server
429
+ */
430
+ async ping(): Promise<{ status: string; service?: string }> {
431
+ const request: MCPRequest = {
432
+ jsonrpc: '2.0',
433
+ id: Date.now(),
434
+ method: 'ping'
435
+ };
436
+
437
+ const response = await this.request<MCPResponse>('/mcp', {
438
+ method: 'POST',
439
+ body: request
440
+ });
441
+
442
+ if (response.error) {
443
+ throw new MCPClientError(response.error.message, response.error.code, response.error.data);
444
+ }
445
+
446
+ return response.result;
447
+ }
448
+
449
+ // =============================================================================
450
+ // Dexscreener MCP Tools (Convenience Methods)
451
+ // =============================================================================
452
+
453
+ async getTrendingTokens(): Promise<MCPToolCallResponse> {
454
+ return this.callTool({ name: 'get_trending_tokens' });
455
+ }
456
+
457
+ async getLatestTokens(): Promise<MCPToolCallResponse> {
458
+ return this.callTool({ name: 'get_latest_tokens' });
459
+ }
460
+
461
+ async analyzeTrendingTokens(): Promise<MCPToolCallResponse> {
462
+ return this.callTool({ name: 'analyze_trending_tokens' });
463
+ }
464
+
465
+ async getDexscreenerContext(): Promise<MCPToolCallResponse> {
466
+ return this.callTool({ name: 'get_server_context' });
467
+ }
468
+
469
+ // =============================================================================
470
+ // Data Collector MCP Tools (Convenience Methods)
471
+ // =============================================================================
472
+
473
+ async getTokenPrice(params: {
474
+ token: string;
475
+ chain?: string;
476
+ quote?: string;
477
+ }): Promise<MCPToolCallResponse> {
478
+ return this.callTool({
479
+ name: 'get_token_price',
480
+ arguments: params
481
+ });
482
+ }
483
+
484
+ async getTokenVolume(params: {
485
+ token: string;
486
+ chain?: string;
487
+ interval?: string;
488
+ tokenFormat?: string;
489
+ }): Promise<MCPToolCallResponse> {
490
+ return this.callTool({
491
+ name: 'get_token_volume',
492
+ arguments: params
493
+ });
494
+ }
495
+
496
+ async getOrderbook(params: {
497
+ base: string;
498
+ quote?: string;
499
+ chain?: string;
500
+ depth?: number;
501
+ }): Promise<MCPToolCallResponse> {
502
+ return this.callTool({
503
+ name: 'get_orderbook',
504
+ arguments: params
505
+ });
506
+ }
507
+
508
+ async getEnhancedOHLCV(params: {
509
+ token: string;
510
+ chain?: string;
511
+ interval?: string;
512
+ limit?: number;
513
+ }): Promise<MCPToolCallResponse> {
514
+ return this.callTool({
515
+ name: 'get_enhanced_ohlcv',
516
+ arguments: params
517
+ });
518
+ }
519
+
520
+ async discoverTokens(params: {
521
+ chain?: string;
522
+ type?: string;
523
+ limit?: number;
524
+ includeVolume?: boolean;
525
+ sortBy?: string;
526
+ sortOrder?: string;
527
+ }): Promise<MCPToolCallResponse> {
528
+ return this.callTool({
529
+ name: 'discover_tokens',
530
+ arguments: params
531
+ });
532
+ }
533
+
534
+ async getTradingIntensity(params: {
535
+ token: string;
536
+ chain?: string;
537
+ interval?: string;
538
+ tokenFormat?: string;
539
+ }): Promise<MCPToolCallResponse> {
540
+ return this.callTool({
541
+ name: 'get_trading_intensity',
542
+ arguments: params
543
+ });
544
+ }
545
+
546
+ async resolveSymbol(params: {
547
+ symbol: string;
548
+ chain?: string;
549
+ type?: string;
550
+ }): Promise<MCPToolCallResponse> {
551
+ return this.callTool({
552
+ name: 'resolve_symbol',
553
+ arguments: params
554
+ });
555
+ }
556
+
557
+ async getPerformanceMetrics(params: {
558
+ chain?: string;
559
+ endpoint?: string;
560
+ samples?: number;
561
+ }): Promise<MCPToolCallResponse> {
562
+ return this.callTool({
563
+ name: 'get_performance_metrics',
564
+ arguments: params
565
+ });
566
+ }
567
+
568
+ // =============================================================================
569
+ // RAG MCP Tools (Convenience Methods) - Knowledge & Decision Support
570
+ // =============================================================================
571
+
572
+ async searchKnowledgeBase(params: {
573
+ query: string;
574
+ limit?: number;
575
+ threshold?: number;
576
+ }): Promise<MCPToolCallResponse> {
577
+ return this.callTool({
578
+ name: 'search_knowledge_base',
579
+ arguments: params
580
+ });
581
+ }
582
+
583
+ async retrieveContextualInformation(params: {
584
+ query: string;
585
+ sources?: Array<'concept' | 'history'>;
586
+ limit?: number;
587
+ threshold?: number;
588
+ }): Promise<MCPToolCallResponse> {
589
+ return this.callTool({
590
+ name: 'retrieve_contextual_information',
591
+ arguments: params
592
+ });
593
+ }
594
+
595
+ async getHistoricalDecisions(params: {
596
+ query: string;
597
+ limit?: number;
598
+ threshold?: number;
599
+ }): Promise<MCPToolCallResponse> {
600
+ return this.callTool({
601
+ name: 'get_historical_decisions',
602
+ arguments: params
603
+ });
604
+ }
605
+
606
+ async enrichMarketContext(params: {
607
+ topic: string;
608
+ includeHistory?: boolean;
609
+ includeConcepts?: boolean;
610
+ limit?: number;
611
+ }): Promise<MCPToolCallResponse> {
612
+ return this.callTool({
613
+ name: 'enrich_market_context',
614
+ arguments: params
615
+ });
616
+ }
617
+
618
+ async comprehensiveSearch(params: {
619
+ query: string;
620
+ analysisDepth?: 'surface' | 'detailed' | 'comprehensive';
621
+ includeStatistics?: boolean;
622
+ }): Promise<MCPToolCallResponse> {
623
+ return this.callTool({
624
+ name: 'comprehensive_search',
625
+ arguments: params
626
+ });
627
+ }
628
+
629
+ async checkKnowledgeBaseStatus(params?: {
630
+ includeLayerStats?: boolean;
631
+ }): Promise<MCPToolCallResponse> {
632
+ return this.callTool({
633
+ name: 'check_knowledge_base_status',
634
+ arguments: params || {}
635
+ });
636
+ }
637
+
638
+ // =============================================================================
639
+ // APY Strategy MCP Tools (Convenience Methods) - DeFi Yield Optimization
640
+ // =============================================================================
641
+
642
+ async getApyHistory(params: {
643
+ protocol: string;
644
+ chain: string;
645
+ pool?: string;
646
+ timeframe?: '7d' | '30d' | '90d' | '180d' | '1y';
647
+ includeRiskMetrics?: boolean;
648
+ includeStatistics?: boolean;
649
+ minTvl?: number;
650
+ maxRiskScore?: number;
651
+ }): Promise<MCPToolCallResponse> {
652
+ return this.callTool({
653
+ name: 'getApyHistory',
654
+ arguments: params
655
+ });
656
+ }
657
+
658
+ async findYieldOpportunities(params: {
659
+ chains?: string[];
660
+ minApy?: number;
661
+ maxRisk?: number;
662
+ minTvl?: number;
663
+ protocols?: string[];
664
+ assets?: string[];
665
+ includeArbitrage?: boolean;
666
+ riskTolerance?: 'conservative' | 'moderate' | 'aggressive';
667
+ sortBy?: 'apy' | 'risk_adjusted_return' | 'tvl' | 'risk_score';
668
+ }): Promise<MCPToolCallResponse> {
669
+ return this.callTool({
670
+ name: 'findYieldOpportunities',
671
+ arguments: params
672
+ });
673
+ }
674
+
675
+ async analyzeArbitrageOpportunities(params: {
676
+ sourceChain: string;
677
+ targetChain: string;
678
+ token: string;
679
+ amount?: number;
680
+ includeGasCosts?: boolean;
681
+ slippageTolerance?: number;
682
+ bridgeProtocols?: string[];
683
+ }): Promise<MCPToolCallResponse> {
684
+ return this.callTool({
685
+ name: 'analyzeArbitrageOpportunities',
686
+ arguments: params
687
+ });
688
+ }
689
+
690
+ async backtestStrategy(params: {
691
+ strategy: 'yield_farming' | 'arbitrage' | 'optimization' | 'balanced';
692
+ protocols?: string[];
693
+ chains?: string[];
694
+ startDate: string;
695
+ endDate: string;
696
+ initialAmount: number;
697
+ rebalanceFrequency?: 'daily' | 'weekly' | 'monthly' | 'quarterly';
698
+ riskTolerance?: 'conservative' | 'moderate' | 'aggressive';
699
+ includeTransactionCosts?: boolean;
700
+ optimizationMethod?: 'max_sharpe' | 'risk_parity' | 'mean_variance';
701
+ }): Promise<MCPToolCallResponse> {
702
+ return this.callTool({
703
+ name: 'backtestStrategy',
704
+ arguments: params
705
+ });
706
+ }
707
+
708
+ async calculatePortfolioRisk(params: {
709
+ positions: Array<{
710
+ protocol: string;
711
+ chain?: string;
712
+ asset: string;
713
+ amount: number;
714
+ currentApy?: number;
715
+ }>;
716
+ riskMetrics?: ('var' | 'correlation' | 'concentration' | 'stress_test')[];
717
+ confidenceLevel?: 90 | 95 | 99;
718
+ timeHorizon?: number;
719
+ stressScenarios?: string[];
720
+ }): Promise<MCPToolCallResponse> {
721
+ return this.callTool({
722
+ name: 'calculatePortfolioRisk',
723
+ arguments: params
724
+ });
725
+ }
726
+
727
+ async optimizeYieldAllocation(params: {
728
+ amount: number;
729
+ riskTolerance: 'conservative' | 'moderate' | 'aggressive';
730
+ optimizationMethod: 'max_sharpe' | 'risk_parity' | 'mean_variance' | 'min_variance';
731
+ constraints?: {
732
+ maxProtocolAllocation?: number;
733
+ maxChainAllocation?: number;
734
+ maxRiskScore?: number;
735
+ minYield?: number;
736
+ };
737
+ includeProtocols?: string[];
738
+ excludeProtocols?: string[];
739
+ targetChains?: string[];
740
+ rebalanceFrequency?: 'never' | 'daily' | 'weekly' | 'monthly';
741
+ }): Promise<MCPToolCallResponse> {
742
+ return this.callTool({
743
+ name: 'optimizeYieldAllocation',
744
+ arguments: params
745
+ });
746
+ }
747
+
748
+ async assessProtocolRisk(params: {
749
+ protocol: string;
750
+ chain?: string;
751
+ includeHistoricalEvents?: boolean;
752
+ riskCategories?: ('smart_contract' | 'economic' | 'governance' | 'liquidity' | 'oracle')[];
753
+ depth?: 'basic' | 'detailed' | 'comprehensive';
754
+ }): Promise<MCPToolCallResponse> {
755
+ return this.callTool({
756
+ name: 'assessProtocolRisk',
757
+ arguments: params
758
+ });
759
+ }
760
+
761
+ async trackYieldPerformance(params: {
762
+ portfolioId: string;
763
+ timeframe?: '1d' | '7d' | '30d' | '90d' | '1y' | 'all';
764
+ includeBenchmarks?: boolean;
765
+ benchmarks?: string[];
766
+ attributionAnalysis?: boolean;
767
+ includeRealTimeData?: boolean;
768
+ alertThresholds?: {
769
+ minYield?: number;
770
+ maxDrawdown?: number;
771
+ riskScoreChange?: number;
772
+ };
773
+ granularity?: 'hourly' | 'daily' | 'weekly';
774
+ }): Promise<MCPToolCallResponse> {
775
+ return this.callTool({
776
+ name: 'trackYieldPerformance',
777
+ arguments: params
778
+ });
779
+ }
780
+ }