@vesper85/strategy-sdk 0.1.6 → 0.1.7

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.
@@ -21,11 +21,7 @@ export declare class PolymarketClient implements PolymarketAPI {
21
21
  /**
22
22
  * Call an MCP tool with retry logic
23
23
  */
24
- private callMCPTool;
25
- /**
26
- * Execute a tool on an MCP client instance
27
- */
28
- private executeMCPTool;
24
+ private invokeMCPTool;
29
25
  /**
30
26
  * Extract content from MCP tool response (ported from sozu-tg-bot)
31
27
  */
package/dist/index.js CHANGED
@@ -3,11 +3,10 @@ import { ClobClient, Side } from '@polymarket/clob-client';
3
3
  import { ethers } from 'ethers';
4
4
  import axios from 'axios';
5
5
  import { serializeSignature, createWalletClient, http } from 'viem';
6
- import { connectMCPServer, removeConnection } from '@osiris-ai/agent-sdk';
7
6
  import { Hyperliquid } from 'hyperliquid';
8
7
  import { createClient } from 'redis';
9
8
  import superjson from 'superjson';
10
- import { TechnicalAnalysisService } from '@osiris-ai/technical-indicators';
9
+ import { TechnicalAnalysisService } from '@vesper85/technical-indicators';
11
10
  import WebSocket from 'ws';
12
11
  import { RealTimeDataClient, ConnectionStatus } from '@polymarket/real-time-data-client';
13
12
  import { privateKeyToAccount } from 'viem/accounts';
@@ -186,6 +185,117 @@ var OsirisSigner = class {
186
185
  return void 0;
187
186
  }
188
187
  };
188
+ var activeClients = /* @__PURE__ */ new Map();
189
+ var getCacheKey = (mcpUrl, accessToken) => {
190
+ if (accessToken) {
191
+ return `${mcpUrl}:${accessToken.slice(0, 10)}`;
192
+ }
193
+ return `${mcpUrl}:no-auth`;
194
+ };
195
+ var isConnectionStale = (connectedAt) => {
196
+ const tenMinutesAgo = Date.now() - 10 * 60 * 1e3;
197
+ return connectedAt.getTime() < tenMinutesAgo;
198
+ };
199
+ var createHttpClient = (mcpUrl, accessToken) => {
200
+ const headers = {
201
+ "Content-Type": "application/json"
202
+ };
203
+ if (accessToken) {
204
+ headers["Authorization"] = `Bearer ${accessToken}`;
205
+ }
206
+ return axios.create({
207
+ baseURL: mcpUrl,
208
+ headers,
209
+ timeout: 3e4
210
+ });
211
+ };
212
+ var mcpRequest = async (client, method, params) => {
213
+ const requestId = Math.random().toString(36).substring(7);
214
+ const response = await client.post("", {
215
+ jsonrpc: "2.0",
216
+ id: requestId,
217
+ method,
218
+ params: params || {}
219
+ });
220
+ if (response.data.error) {
221
+ throw new Error(response.data.error.message || "MCP request failed");
222
+ }
223
+ return response.data.result;
224
+ };
225
+ var removeConnection = (mcpUrl, accessToken) => {
226
+ const cacheKey = getCacheKey(mcpUrl, accessToken);
227
+ activeClients.delete(cacheKey);
228
+ };
229
+ var connectMCPServer = async (mcpUrl, accessToken) => {
230
+ const cacheKey = getCacheKey(mcpUrl, accessToken);
231
+ const existing = activeClients.get(cacheKey);
232
+ if (existing) {
233
+ if (isConnectionStale(existing.connectedAt)) {
234
+ console.log(`[MCP] Connection to ${mcpUrl} is stale, reconnecting...`);
235
+ removeConnection(mcpUrl, accessToken);
236
+ } else {
237
+ return existing;
238
+ }
239
+ }
240
+ const httpClient = createHttpClient(mcpUrl, accessToken);
241
+ try {
242
+ await mcpRequest(httpClient, "initialize", {
243
+ protocolVersion: "2024-11-05",
244
+ capabilities: {},
245
+ clientInfo: {
246
+ name: "strategy-sdk",
247
+ version: "0.1.0"
248
+ }
249
+ });
250
+ const toolsResponse = await mcpRequest(httpClient, "tools/list", {});
251
+ const tools = toolsResponse.tools || [];
252
+ const instance = {
253
+ url: mcpUrl,
254
+ accessToken,
255
+ connectedAt: /* @__PURE__ */ new Date(),
256
+ tools
257
+ };
258
+ activeClients.set(cacheKey, instance);
259
+ console.log(`[MCP] Connected to ${mcpUrl} (${tools.length} tools available)`);
260
+ return instance;
261
+ } catch (error) {
262
+ console.warn(`[MCP] Failed to connect to ${mcpUrl}, retrying...`);
263
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
264
+ try {
265
+ const httpClient2 = createHttpClient(mcpUrl, accessToken);
266
+ await mcpRequest(httpClient2, "initialize", {
267
+ protocolVersion: "2024-11-05",
268
+ capabilities: {},
269
+ clientInfo: {
270
+ name: "strategy-sdk",
271
+ version: "0.1.0"
272
+ }
273
+ });
274
+ const toolsResponse = await mcpRequest(httpClient2, "tools/list", {});
275
+ const tools = toolsResponse.tools || [];
276
+ const instance = {
277
+ url: mcpUrl,
278
+ accessToken,
279
+ connectedAt: /* @__PURE__ */ new Date(),
280
+ tools
281
+ };
282
+ activeClients.set(cacheKey, instance);
283
+ console.log(`[MCP] Connected to ${mcpUrl} (${tools.length} tools available)`);
284
+ return instance;
285
+ } catch (retryError) {
286
+ console.error(`[MCP] Failed to connect to ${mcpUrl} after retry`);
287
+ throw retryError;
288
+ }
289
+ }
290
+ };
291
+ var callMCPTool = async (mcpUrl, accessToken, toolName, args) => {
292
+ const httpClient = createHttpClient(mcpUrl, accessToken);
293
+ const result = await mcpRequest(httpClient, "tools/call", {
294
+ name: toolName,
295
+ arguments: args || {}
296
+ });
297
+ return result;
298
+ };
189
299
 
190
300
  // src/utils/index.ts
191
301
  function mapToGammaMarket(raw) {
@@ -331,6 +441,9 @@ var PolymarketClient = class {
331
441
  this.logger.info("Initializing MCP connection for Osiris signer...");
332
442
  const mcpUrl = this.options.mcpUrl;
333
443
  const mcpAccessToken = this.options.mcpAccessToken;
444
+ if (!mcpUrl) {
445
+ throw new Error("MCP URL is required for MCP mode. Please provide mcpUrl in options.");
446
+ }
334
447
  if (!mcpAccessToken) {
335
448
  throw new Error("MCP access token is required for MCP mode. Please provide mcpAccessToken in options.");
336
449
  }
@@ -391,45 +504,18 @@ var PolymarketClient = class {
391
504
  /**
392
505
  * Call an MCP tool with retry logic
393
506
  */
394
- async callMCPTool(toolName, args) {
507
+ async invokeMCPTool(toolName, args) {
395
508
  const instance = this.ensureMcpInstance();
396
509
  const mcpUrl = instance.url;
397
510
  const accessToken = instance.accessToken;
398
511
  try {
399
- return await this.executeMCPTool(instance, toolName, args);
512
+ return await callMCPTool(mcpUrl, accessToken, toolName, args);
400
513
  } catch (error) {
401
514
  this.logger.warning(`Tool execution failed for ${toolName}, reconnecting...`, error instanceof Error ? error.message : error);
402
515
  removeConnection(mcpUrl, accessToken);
403
516
  this.mcpInstance = await connectMCPServer(mcpUrl, accessToken);
404
- return await this.executeMCPTool(this.mcpInstance, toolName, args);
405
- }
406
- }
407
- /**
408
- * Execute a tool on an MCP client instance
409
- */
410
- async executeMCPTool(instance, toolName, args) {
411
- const client = instance.client;
412
- if (client._transport && client._transport._client) {
413
- const mcpClient = client._transport._client;
414
- const result = await mcpClient.callTool({
415
- name: toolName,
416
- arguments: args || {}
417
- });
418
- return result;
419
- }
420
- const tools = await client.tools();
421
- const tool = tools[toolName];
422
- if (!tool) {
423
- throw new Error(`Tool ${toolName} not found on MCP server ${instance.url}`);
424
- }
425
- if (typeof tool.execute === "function") {
426
- const result = await tool.execute(args || {});
427
- return result;
428
- }
429
- if (typeof tool === "function") {
430
- return await tool(args || {});
517
+ return await callMCPTool(mcpUrl, accessToken, toolName, args);
431
518
  }
432
- throw new Error(`Tool ${toolName} is not callable`);
433
519
  }
434
520
  /**
435
521
  * Extract content from MCP tool response (ported from sozu-tg-bot)
@@ -675,7 +761,7 @@ var PolymarketClient = class {
675
761
  */
676
762
  async checkAllowanceViaMCP(tokenType) {
677
763
  try {
678
- const allowanceResult = await this.callMCPTool("check_allowance", {
764
+ const allowanceResult = await this.invokeMCPTool("check_allowance", {
679
765
  token: tokenType
680
766
  });
681
767
  console.log("allowanceResult", allowanceResult);
@@ -708,7 +794,7 @@ var PolymarketClient = class {
708
794
  async approveTokensViaMCP(tokenType) {
709
795
  try {
710
796
  this.logger.info(`[MCP] Approving ${tokenType}...`);
711
- const approveResult = await this.callMCPTool("approve_polymarket_tokens", {
797
+ const approveResult = await this.invokeMCPTool("approve_polymarket_tokens", {
712
798
  token_type: tokenType === "USDC" ? "USDC" : "CONDITIONAL_TOKENS",
713
799
  amount: "100",
714
800
  // Amount doesn't matter for max_approval=true
@@ -852,7 +938,7 @@ var PolymarketClient = class {
852
938
  throw new Error("userAddress is required for MCP order placement");
853
939
  }
854
940
  this.logger.info(`Creating limit order via MCP: ${params.side} ${params.size} @ ${params.price}`);
855
- const chooseWalletResult = await this.callMCPTool("choose_wallet", {
941
+ const chooseWalletResult = await this.invokeMCPTool("choose_wallet", {
856
942
  address
857
943
  });
858
944
  const walletError = this.detectMCPError(chooseWalletResult);
@@ -870,7 +956,7 @@ var PolymarketClient = class {
870
956
  errorMsg: `Failed to approve ${params.side === "BUY" ? "USDC" : "Conditional Token"}. Please try again.`
871
957
  };
872
958
  }
873
- const orderResult = await this.callMCPTool("create_and_post_order", {
959
+ const orderResult = await this.invokeMCPTool("create_and_post_order", {
874
960
  userOrder: {
875
961
  tokenID: params.tokenId,
876
962
  side: params.side,
@@ -958,7 +1044,7 @@ var PolymarketClient = class {
958
1044
  throw new Error("userAddress is required for MCP order placement");
959
1045
  }
960
1046
  this.logger.info(`Creating market order via MCP: ${params.side} ${params.amount}`);
961
- const chooseWalletResult = await this.callMCPTool("choose_wallet", {
1047
+ const chooseWalletResult = await this.invokeMCPTool("choose_wallet", {
962
1048
  address
963
1049
  });
964
1050
  const walletError = this.detectMCPError(chooseWalletResult);
@@ -976,7 +1062,7 @@ var PolymarketClient = class {
976
1062
  errorMsg: `Failed to approve ${params.side === "BUY" ? "USDC" : "Conditional Token"}. Please try again.`
977
1063
  };
978
1064
  }
979
- const orderResult = await this.callMCPTool("create_and_post_market_order", {
1065
+ const orderResult = await this.invokeMCPTool("create_and_post_market_order", {
980
1066
  userMarketOrder: {
981
1067
  tokenID: params.tokenId,
982
1068
  side: params.side,
@@ -0,0 +1,2 @@
1
+ export { connectMCPServer, removeConnection, disconnectMCPServer, callMCPTool, getConnectedServers, type MCPClientInstance, type MCPTool, } from './mcp-client';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Lightweight MCP (Model Context Protocol) Client
3
+ *
4
+ * A simplified implementation of MCP for tool calling over HTTP.
5
+ * This replaces the @ai-sdk/mcp dependency with a minimal implementation.
6
+ */
7
+ /**
8
+ * MCP Tool Definition
9
+ */
10
+ export interface MCPTool {
11
+ name: string;
12
+ description?: string;
13
+ inputSchema?: Record<string, any>;
14
+ }
15
+ /**
16
+ * MCP Client Instance
17
+ */
18
+ export interface MCPClientInstance {
19
+ url: string;
20
+ accessToken?: string;
21
+ connectedAt: Date;
22
+ tools: MCPTool[];
23
+ }
24
+ /**
25
+ * MCP Response Content
26
+ */
27
+ interface MCPContent {
28
+ type: string;
29
+ text?: string;
30
+ }
31
+ /**
32
+ * MCP Tool Call Response
33
+ */
34
+ interface MCPToolResponse {
35
+ content?: MCPContent[];
36
+ text?: string;
37
+ result?: any;
38
+ error?: {
39
+ message: string;
40
+ };
41
+ }
42
+ /**
43
+ * Remove a connection from the cache
44
+ */
45
+ export declare const removeConnection: (mcpUrl: string, accessToken?: string) => void;
46
+ /**
47
+ * Connect to an MCP server
48
+ * Connections are cached for reuse
49
+ *
50
+ * @param mcpUrl - MCP server URL
51
+ * @param accessToken - Optional Bearer token for authenticated MCP calls
52
+ */
53
+ export declare const connectMCPServer: (mcpUrl: string, accessToken?: string) => Promise<MCPClientInstance>;
54
+ /**
55
+ * Call an MCP tool
56
+ *
57
+ * @param mcpUrl - MCP server URL
58
+ * @param accessToken - Optional Bearer token
59
+ * @param toolName - Name of the tool to call
60
+ * @param args - Tool arguments
61
+ */
62
+ export declare const callMCPTool: (mcpUrl: string, accessToken: string | undefined, toolName: string, args?: Record<string, any>) => Promise<MCPToolResponse>;
63
+ /**
64
+ * Disconnect from an MCP server
65
+ */
66
+ export declare const disconnectMCPServer: (mcpUrl: string, accessToken?: string) => void;
67
+ /**
68
+ * Get all connected MCP servers
69
+ */
70
+ export declare const getConnectedServers: () => string[];
71
+ export {};
72
+ //# sourceMappingURL=mcp-client.d.ts.map
@@ -1,4 +1,4 @@
1
- import type { OHLCV, TAParams } from "@osiris-ai/technical-indicators";
1
+ import type { OHLCV, TAParams } from "@vesper85/technical-indicators";
2
2
  import type { Event as GammaEvent, Tag, Team, Sport, Series, Comment as GammaComment, SearchResults, PaginatedResponse, MarketFilters, EventFilters, EventPaginationFilters, PaginationParams, SearchParams, GammaMarket } from "polymarket-gamma";
3
3
  import type { ClearinghouseState, SpotMeta, SpotClearinghouseState, SpotMetaAndAssetCtxs, Meta, MetaAndAssetCtxs, UserFunding, UserNonFundingLedgerUpdates, FundingHistory, PredictedFundings, PerpsAtOpenInterestCap, PerpDexLimits, AllMids, UserOpenOrders, FrontendOpenOrders, UserFills, UserRateLimit, OrderStatus, L2Book, CandleSnapshot, HistoricalOrder, TwapSliceFill, SubAccount, VaultDetails, VaultEquity, UserRole, Delegation, DelegatorSummary, DelegatorHistoryEntry, DelegatorReward, ValidatorSummary, VaultSummary, UserFees, PortfolioPeriods, PreTransferCheck, Referral, ExtraAgent, LegalCheck, TwapHistory, MultiSigSigners, BuilderFeeApproval, UserOrderHistory } from "hyperliquid";
4
4
  export interface OsirisState {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vesper85/strategy-sdk",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "type": "module",
5
5
  "description": "SDK for writing and running trading strategies with Polymarket and Hyperliquid integrations",
6
6
  "keywords": [
@@ -75,4 +75,4 @@
75
75
  "url": "https://github.com/FetcchX/legion-sdk/issues"
76
76
  },
77
77
  "homepage": "https://github.com/FetcchX/legion-sdk#readme"
78
- }
78
+ }