diff --git a/.github/actions/generate-mcp-tools/generate-tools.mjs b/.github/actions/generate-mcp-tools/generate-tools.mjs index 18f98c1..3ada6d3 100644 --- a/.github/actions/generate-mcp-tools/generate-tools.mjs +++ b/.github/actions/generate-mcp-tools/generate-tools.mjs @@ -440,7 +440,7 @@ function renderSchema(jsonSchema) { const type = Array.isArray(prop.type) ? prop.type.join(" | ") : (prop.type ?? "unknown"); - const requiredStr = required.has(key) ? "✅" : ""; + const requiredStr = required.has(key) ? "true" : "false"; const description = prop.description ?? ""; const defaultVal = prop.default !== undefined ? String(prop.default) : ""; diff --git a/README.md b/README.md index 92a6da7..13e0a90 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ Add the following configuration to your MCP client settings (e.g., `claude_deskt "args": ["-y", "@iqai/mcp-polymarket"], "env": { "POLYMARKET_PRIVATE_KEY": "your_private_key_here", - "POLYMARKET_RPC_URL": "https://polygon-mainnet.g.alchemy.com/v2/" + "POLYGON_RPC_URL": "https://polygon-mainnet.g.alchemy.com/v2/" } } } @@ -75,7 +75,7 @@ Add the following configuration to your MCP client settings (e.g., `claude_deskt | Variable | Required | Description | Default | | :--- | :--- | :--- | :--- | | `POLYMARKET_PRIVATE_KEY` | No | Private key for trading (enables trading tools) | - | -| `POLYMARKET_RPC_URL` | No | Polygon RPC URL for transactions | `https://polygon-rpc.com` | +| `POLYGON_RPC_URL` | No | Polygon RPC URL for transactions | `https://polygon-rpc.com` | | `CLOB_API_BASE` | No | Polymarket CLOB API base URL | `https://clob.polymarket.com` | | `CHAIN_ID` | No | Blockchain network chain ID | `137` (Polygon) | | `SIGNATURE_TYPE` | No | Signature type for signing transactions | `2` | diff --git a/package-lock.json b/package-lock.json index 5a45357..4f852c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@iqai/mcp-polymarket", - "version": "0.0.4", + "version": "0.0.16", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@iqai/mcp-polymarket", - "version": "0.0.4", + "version": "0.0.16", "license": "MIT", "dependencies": { - "@hk/polymarket": "npm:@jsr/hk__polymarket@^0.2.1", + "@jsr/hk__polymarket": "^0.2.1", "@modelcontextprotocol/sdk": "^1.20.2", "@polymarket/clob-client": "^4.22.8", "ethers": "^5.8.0", @@ -25,7 +25,8 @@ "@changesets/cli": "^2.29.7", "@types/node": "^24.9.1", "tsx": "^4.20.6", - "typescript": "^5.9.3" + "typescript": "^5.9.3", + "zod-to-json-schema": "^3.25.1" } }, "node_modules/@babel/runtime": { @@ -1704,23 +1705,6 @@ "@ethersproject/strings": "^5.8.0" } }, - "node_modules/@hk/polymarket": { - "name": "@jsr/hk__polymarket", - "version": "0.2.1", - "resolved": "https://npm.jsr.io/~/11/@jsr/hk__polymarket/0.2.1.tgz", - "integrity": "sha512-rK4IbprOl9ApPOHnai7Ajz8NYesD+PfZK54244oAXlgFvUW906MioQoMBQSpSMgc6dWOTIGgPBfKByWoUy0NoA==", - "dependencies": { - "@elysiajs/cors": "^1.3.3", - "@elysiajs/eden": "^1.3.2", - "@elysiajs/openapi": "^1.3.7", - "@elysiajs/swagger": "^1.3.1", - "@ethersproject/wallet": "^5.8.0", - "@polymarket/clob-client": "^4.21.0", - "elysia": "^1.3.8", - "lru-cache": "^11.1.0", - "undici": "^7.15.0" - } - }, "node_modules/@inquirer/external-editor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.2.tgz", @@ -1760,6 +1744,22 @@ "url": "https://opencollective.com/express" } }, + "node_modules/@jsr/hk__polymarket": { + "version": "0.2.1", + "resolved": "https://npm.jsr.io/~/11/@jsr/hk__polymarket/0.2.1.tgz", + "integrity": "sha512-rK4IbprOl9ApPOHnai7Ajz8NYesD+PfZK54244oAXlgFvUW906MioQoMBQSpSMgc6dWOTIGgPBfKByWoUy0NoA==", + "dependencies": { + "@elysiajs/cors": "^1.3.3", + "@elysiajs/eden": "^1.3.2", + "@elysiajs/openapi": "^1.3.7", + "@elysiajs/swagger": "^1.3.1", + "@ethersproject/wallet": "^5.8.0", + "@polymarket/clob-client": "^4.21.0", + "elysia": "^1.3.8", + "lru-cache": "^11.1.0", + "undici": "^7.15.0" + } + }, "node_modules/@manypkg/find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@manypkg/find-root/-/find-root-1.1.0.tgz", @@ -5280,12 +5280,12 @@ } }, "node_modules/zod-to-json-schema": { - "version": "3.24.6", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz", - "integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==", + "version": "3.25.1", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz", + "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", "license": "ISC", "peerDependencies": { - "zod": "^3.24.1" + "zod": "^3.25 || ^4" } } } diff --git a/src/index.ts b/src/index.ts index c3a41d3..dead092 100644 --- a/src/index.ts +++ b/src/index.ts @@ -42,12 +42,12 @@ async function main() { server.addTool(tools.redeemPositionsTool); server.addTool(tools.getPositionsTool); - console.log( - "✅ Trading features enabled (POLYMARKET_PRIVATE_KEY is configured)", + process.stderr.write( + "Trading features enabled (POLYMARKET_PRIVATE_KEY is configured)\n", ); } else { - console.warn( - "ℹ️ Read-only mode: Set POLYMARKET_PRIVATE_KEY environment variable to enable trading features", + process.stderr.write( + "Read-only mode: Set POLYMARKET_PRIVATE_KEY environment variable to enable trading features\n", ); } @@ -57,6 +57,6 @@ async function main() { } main().catch((error) => { - console.error("🚨 Failed to start MCP server:", error); + console.error("Failed to start MCP server:", error); process.exit(1); }); diff --git a/src/script.ts b/src/script.ts index 0a8f145..c0c1b88 100644 --- a/src/script.ts +++ b/src/script.ts @@ -10,7 +10,7 @@ import { tradeApi } from "./services/trading.js"; */ async function placeMarketOrder() { try { - console.log("🚀 Placing market order..."); + console.log("Placing market order..."); // Market order parameters const params = { @@ -20,17 +20,17 @@ async function placeMarketOrder() { amount: 1, // For BUY orders, this is the dollar amount ($USD) to spend }; - console.log("📋 Order parameters:", JSON.stringify(params, null, 2)); + console.log("Order parameters:", JSON.stringify(params, null, 2)); // Execute the market order const result = await tradeApi.placeMarketOrder(params); - console.log("✅ Market order placed successfully!"); - console.log("📊 Result:", JSON.stringify(result, null, 2)); + console.log("Market order placed successfully!"); + console.log("Result:", JSON.stringify(result, null, 2)); return result; } catch (error) { - console.error("❌ Error placing market order:", error); + console.error("Error placing market order:", error); // Check if it's an approval error if (error && typeof error === "object" && "message" in error) { @@ -44,10 +44,10 @@ async function placeMarketOrder() { // Run the script placeMarketOrder() .then(() => { - console.log("🎉 Script completed successfully"); + console.log("Script completed successfully"); process.exit(0); }) .catch((error) => { - console.error("💥 Script failed:", error); + console.error("Script failed:", error); process.exit(1); }); diff --git a/src/services/approvals.ts b/src/services/approvals.ts index 1bafe08..dc53270 100644 --- a/src/services/approvals.ts +++ b/src/services/approvals.ts @@ -187,37 +187,37 @@ export class PolymarketApprovals { { key: "USDC_ALLOWANCE_FOR_CTF", fn: () => usdc.approve(CTF_ADDRESS, constants.MaxUint256), - label: "USDC→CTF", + label: "USDC->CTF", }, { key: "USDC_ALLOWANCE_FOR_EXCHANGE", fn: () => usdc.approve(EXCHANGE_ADDRESS, constants.MaxUint256), - label: "USDC→Exchange", + label: "USDC->Exchange", }, { key: "CTF_APPROVAL_FOR_EXCHANGE", fn: () => ctf.setApprovalForAll(EXCHANGE_ADDRESS, true), - label: "CTF→Exchange", + label: "CTF->Exchange", }, { key: "USDC_ALLOWANCE_FOR_NEG_RISK_EXCHANGE", fn: () => usdc.approve(NEG_RISK_EXCHANGE_ADDRESS, constants.MaxUint256), - label: "USDC→NegRiskExchange", + label: "USDC->NegRiskExchange", }, { key: "USDC_ALLOWANCE_FOR_NEG_RISK_ADAPTER", fn: () => usdc.approve(NEG_RISK_ADAPTER_ADDRESS, constants.MaxUint256), - label: "USDC→NegRiskAdapter", + label: "USDC->NegRiskAdapter", }, { key: "CTF_APPROVAL_FOR_NEG_RISK_EXCHANGE", fn: () => ctf.setApprovalForAll(NEG_RISK_EXCHANGE_ADDRESS, true), - label: "CTF→NegRiskExchange", + label: "CTF->NegRiskExchange", }, { key: "CTF_APPROVAL_FOR_NEG_RISK_ADAPTER", fn: () => ctf.setApprovalForAll(NEG_RISK_ADAPTER_ADDRESS, true), - label: "CTF→NegRiskAdapter", + label: "CTF->NegRiskAdapter", }, ] as const; @@ -226,7 +226,7 @@ export class PolymarketApprovals { if (current.missing.includes(key)) { const hash = await this.sendTx(fn, nonce++, waitConfs); txHashes.push(hash); - console.log(`Approved ${label}: ${hash}`); + process.stderr.write(`Approved ${label}: ${hash}\n`); } } diff --git a/src/services/config.ts b/src/services/config.ts index c6672ea..565fdf0 100644 --- a/src/services/config.ts +++ b/src/services/config.ts @@ -32,7 +32,7 @@ export function getConfig(overrides: Partial = {}): BaseConfig { const rpcUrl = overrides.rpcUrl ?? - process.env.POLYMARKET_RPC_URL ?? + process.env.POLYGON_RPC_URL ?? "https://polygon-rpc.com"; const privateKey = overrides.privateKey ?? process.env.POLYMARKET_PRIVATE_KEY; diff --git a/src/services/redemption.ts b/src/services/redemption.ts index bac2138..88be854 100644 --- a/src/services/redemption.ts +++ b/src/services/redemption.ts @@ -174,7 +174,7 @@ export class PolymarketRedemption { "No CTF tokens to redeem. Balance is 0 - position may have already been redeemed.", }; } - console.log(`Token balance: ${tokenBalance.toString()}`); + process.stderr.write(`Token balance: ${tokenBalance.toString()}` + "\n"); } // Check if market is resolved @@ -220,9 +220,9 @@ export class PolymarketRedemption { amounts = [tokenBalance, 0n]; } - console.log(`Redeeming negRisk position:`); - console.log(` Condition ID: ${conditionIdBytes32}`); - console.log(` Amounts: [${amounts[0]}, ${amounts[1]}]`); + process.stderr.write(`Redeeming negRisk position:` + "\n"); + process.stderr.write(` Condition ID: ${conditionIdBytes32}` + "\n"); + process.stderr.write(` Amounts: [${amounts[0]}, ${amounts[1]}]` + "\n"); const negRiskAdapter = this.getNegRiskAdapterContract(); tx = await negRiskAdapter.redeemPositions(conditionIdBytes32, amounts, { @@ -240,9 +240,9 @@ export class PolymarketRedemption { }; } - console.log(`Redeeming CTF position:`); - console.log(` Condition ID: ${conditionIdBytes32}`); - console.log(` Winning index sets: [${winningIndexSets.join(", ")}]`); + process.stderr.write(`Redeeming CTF position:` + "\n"); + process.stderr.write(` Condition ID: ${conditionIdBytes32}` + "\n"); + process.stderr.write(` Winning index sets: [${winningIndexSets.join(", ")}]` + "\n"); const ctf = this.getCtfContract(); tx = await ctf.redeemPositions( @@ -256,7 +256,7 @@ export class PolymarketRedemption { ); } - console.log(`Transaction submitted: ${tx.hash}`); + process.stderr.write(`Transaction submitted: ${tx.hash}` + "\n"); // Wait for confirmation const receipt = await tx.wait(1); diff --git a/src/services/trading.ts b/src/services/trading.ts index a85884d..3a7b6cb 100644 --- a/src/services/trading.ts +++ b/src/services/trading.ts @@ -112,11 +112,11 @@ export class PolymarketTrading { cfg.funderAddress, ); - console.log("✓ Polymarket trading client initialized"); - console.log(` - Signer: ${await ethersSigner.getAddress()}`); - console.log(` - Signature Type: ${cfg.signatureType}`); + process.stderr.write("Polymarket trading client initialized"); + process.stderr.write(` - Signer: ${await ethersSigner.getAddress()}` + "\n"); + process.stderr.write(` - Signature Type: ${cfg.signatureType}` + "\n"); if (cfg.funderAddress) { - console.log(` - Funder/Proxy: ${cfg.funderAddress}`); + process.stderr.write(` - Funder/Proxy: ${cfg.funderAddress}` + "\n"); } } @@ -253,11 +253,11 @@ export class PolymarketTrading { const client = this.getClient(); - console.log(`📝 Placing ${args.side} order:`); - console.log(` Token: ${args.tokenId}`); - console.log(` Price: ${args.price}`); - console.log(` Size: ${args.size}`); - console.log( + process.stderr.write(`Placing ${args.side} order:` + "\n"); + process.stderr.write(` Token: ${args.tokenId}` + "\n"); + process.stderr.write(` Price: ${args.price}` + "\n"); + process.stderr.write(` Size: ${args.size}` + "\n"); + process.stderr.write( ` Market: negRisk=${marketParams.negRisk}, tickSize=${marketParams.tickSize}`, ); @@ -304,10 +304,10 @@ export class PolymarketTrading { const client = this.getClient(); - console.log(`🚀 Placing ${args.side} market order:`); - console.log(` Token: ${args.tokenId}`); - console.log(` Amount: ${args.amount}`); - console.log( + process.stderr.write(`Placing ${args.side} market order:` + "\n"); + process.stderr.write(` Token: ${args.tokenId}` + "\n"); + process.stderr.write(` Amount: ${args.amount}` + "\n"); + process.stderr.write( ` Market: negRisk=${marketParams.negRisk}, tickSize=${marketParams.tickSize}`, );