@openclawcash/mcp-server 0.1.2 → 0.1.4

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/README.md CHANGED
@@ -58,6 +58,8 @@ Set one of these environment variables:
58
58
  - `OPENCLAWCASH_AGENT_KEY`
59
59
  - `AGENTWALLETAPI_KEY`
60
60
 
61
+ All MCP tools require an OpenClawCash agent key because they call the authenticated agent API, including read tools such as `swap_quote` and `supported_tokens_list`.
62
+
61
63
  Optional base URL override:
62
64
 
63
65
  - `OPENCLAWCASH_BASE_URL`
@@ -217,8 +219,10 @@ The MCP server itself does not hold approval memory. The MCP client or agent run
217
219
 
218
220
  ## Notes
219
221
 
220
- - `swap_quote` is read-only.
222
+ - `swap_quote` is read-only, but still requires an agent key.
223
+ - `supported_tokens_list` is read-only, but still requires an agent key.
221
224
  - `transfer_send`, `swap_execute`, `approve_token`, `wallet_create`, and `wallet_import` are write tools.
225
+ - For `wallet_get`, `transactions_list`, `supported_tokens_list`, and `swap_quote`, pass at most one wallet selector when using `walletId`, `walletLabel`, or `walletAddress`.
222
226
  - The server uses stdio transport and is intended for MCP-compatible desktop or agent clients.
223
227
 
224
228
  ## Standalone Packaging Notes
@@ -7,7 +7,7 @@ import { fileURLToPath } from "node:url";
7
7
  import { z } from "zod";
8
8
 
9
9
  const SERVER_NAME = "openclawcash";
10
- const SERVER_VERSION = "0.1.1";
10
+ const SERVER_VERSION = "0.1.6";
11
11
  const PROTOCOL_VERSION = "2024-11-05";
12
12
  const DEFAULT_BASE_URL = "https://openclawcash.com";
13
13
 
@@ -130,13 +130,16 @@ const transferArgsSchema = walletSelectorBaseSchema
130
130
  message: "Provide exactly one of amount or value.",
131
131
  });
132
132
 
133
- const swapQuoteArgsSchema = z.object({
134
- network: z.string().min(1),
135
- tokenIn: z.string().min(1),
136
- tokenOut: z.string().min(1),
137
- amountIn: z.string().min(1),
138
- chain: z.enum(["evm", "solana"]).optional(),
139
- });
133
+ const swapQuoteArgsSchema = walletSelectorBaseSchema
134
+ .extend({
135
+ network: z.string().min(1),
136
+ tokenIn: z.string().min(1),
137
+ tokenOut: z.string().min(1),
138
+ amountIn: z.string().min(1),
139
+ })
140
+ .refine((data) => [data.walletId, data.walletLabel, data.walletAddress].filter((value) => value !== undefined).length <= 1, {
141
+ message: selectorDescription(),
142
+ });
140
143
 
141
144
  const swapExecuteArgsSchema = z
142
145
  .object({
@@ -165,14 +168,17 @@ const approveArgsSchema = z
165
168
  message: "Provide exactly one of walletId or walletAddress.",
166
169
  });
167
170
 
168
- const supportedTokensArgsSchema = z.object({
169
- network: z.string().min(1).optional(),
170
- chain: z.enum(["evm", "solana"]).optional(),
171
- });
171
+ const supportedTokensArgsSchema = walletSelectorBaseSchema
172
+ .extend({
173
+ network: z.string().min(1).optional(),
174
+ })
175
+ .refine((data) => [data.walletId, data.walletLabel, data.walletAddress].filter((value) => value !== undefined).length <= 1, {
176
+ message: selectorDescription(),
177
+ });
172
178
 
173
179
  const createWalletArgsSchema = z.object({
174
180
  label: z.string().min(1),
175
- network: z.enum(["sepolia", "mainnet", "solana-devnet", "solana-testnet", "solana-mainnet"]).optional(),
181
+ network: z.enum(["sepolia", "mainnet", "polygon-mainnet", "solana-devnet", "solana-testnet", "solana-mainnet"]).optional(),
176
182
  exportPassphrase: z.string().trim().min(12),
177
183
  exportPassphraseStorageType: z.enum(["env", "secret_manager", "vault", "other"]),
178
184
  exportPassphraseStorageRef: z.string().trim().min(3),
@@ -181,10 +187,154 @@ const createWalletArgsSchema = z.object({
181
187
 
182
188
  const importWalletArgsSchema = z.object({
183
189
  label: z.string().min(1),
184
- network: z.enum(["mainnet", "solana-mainnet"]),
190
+ network: z.enum(["mainnet", "polygon-mainnet", "solana-mainnet"]),
185
191
  privateKey: z.string().min(1),
186
192
  });
187
193
 
194
+ const userTagSetArgsSchema = z.object({
195
+ userTag: z
196
+ .string()
197
+ .trim()
198
+ .toLowerCase()
199
+ .min(3)
200
+ .max(64)
201
+ .regex(/^[a-z0-9][a-z0-9._-]{2,63}$/),
202
+ });
203
+
204
+ const polymarketLimitArgsSchema = z
205
+ .object({
206
+ walletId: z.union([z.number().int().positive(), z.string().min(1)]).optional(),
207
+ walletAddress: z.string().min(1).optional(),
208
+ tokenId: z.string().min(1),
209
+ side: z.enum(["BUY", "SELL"]),
210
+ price: z.number().positive(),
211
+ size: z.number().positive(),
212
+ })
213
+ .refine((data) => [data.walletId, data.walletAddress].filter((v) => v !== undefined).length === 1, {
214
+ message: "Provide exactly one of walletId or walletAddress.",
215
+ });
216
+
217
+ const polymarketMarketArgsSchema = z
218
+ .object({
219
+ walletId: z.union([z.number().int().positive(), z.string().min(1)]).optional(),
220
+ walletAddress: z.string().min(1).optional(),
221
+ tokenId: z.string().min(1),
222
+ side: z.enum(["BUY", "SELL"]),
223
+ amount: z.number().positive(),
224
+ orderType: z.enum(["FAK", "FOK", "GTC"]).optional(),
225
+ worstPrice: z.number().min(0).max(1).optional(),
226
+ })
227
+ .refine((data) => [data.walletId, data.walletAddress].filter((v) => v !== undefined).length === 1, {
228
+ message: "Provide exactly one of walletId or walletAddress.",
229
+ });
230
+
231
+ const polymarketReadArgsSchema = z
232
+ .object({
233
+ walletId: z.union([z.number().int().positive(), z.string().min(1)]).optional(),
234
+ walletAddress: z.string().min(1).optional(),
235
+ status: z.string().min(1).optional(),
236
+ limit: z.number().int().positive().max(200).optional(),
237
+ cursor: z.string().min(1).optional(),
238
+ })
239
+ .refine((data) => [data.walletId, data.walletAddress].filter((v) => v !== undefined).length === 1, {
240
+ message: "Provide exactly one of walletId or walletAddress.",
241
+ });
242
+
243
+ const polymarketCancelArgsSchema = z
244
+ .object({
245
+ walletId: z.union([z.number().int().positive(), z.string().min(1)]).optional(),
246
+ walletAddress: z.string().min(1).optional(),
247
+ orderId: z.string().min(1),
248
+ })
249
+ .refine((data) => [data.walletId, data.walletAddress].filter((v) => v !== undefined).length === 1, {
250
+ message: "Provide exactly one of walletId or walletAddress.",
251
+ });
252
+
253
+ const checkoutEscrowIdArgsSchema = z.object({
254
+ id: z.string().min(1),
255
+ });
256
+
257
+ const checkoutPayreqIdArgsSchema = z.object({
258
+ id: z.string().min(1),
259
+ });
260
+
261
+ const checkoutWalletSelectorArgsSchema = z
262
+ .object({
263
+ id: z.string().min(1),
264
+ walletId: z.union([z.number().int().positive(), z.string().min(1)]).optional(),
265
+ walletAddress: z.string().min(1).optional(),
266
+ })
267
+ .refine((data) => [data.walletId, data.walletAddress].filter((v) => v !== undefined).length === 1, {
268
+ message: "Provide exactly one of walletId or walletAddress.",
269
+ });
270
+
271
+ const checkoutCreatePayreqArgsSchema = z
272
+ .object({
273
+ walletId: z.union([z.number().int().positive(), z.string().min(1)]).optional(),
274
+ walletAddress: z.string().min(1).optional(),
275
+ amount: z.string().min(1),
276
+ expiresInSeconds: z.number().int().positive().optional(),
277
+ autoReleaseSeconds: z.number().int().positive().optional(),
278
+ disputeWindowSeconds: z.number().int().positive().optional(),
279
+ metadata: z.record(z.unknown()).optional(),
280
+ })
281
+ .refine((data) => [data.walletId, data.walletAddress].filter((v) => v !== undefined).length === 1, {
282
+ message: "Provide exactly one of walletId or walletAddress.",
283
+ });
284
+
285
+ const checkoutFundingConfirmArgsSchema = z.object({
286
+ id: z.string().min(1),
287
+ txHash: z.string().min(1),
288
+ minConfirmations: z.number().int().positive().optional(),
289
+ });
290
+
291
+ const checkoutAcceptArgsSchema = z.object({
292
+ id: z.string().min(1),
293
+ });
294
+
295
+ const checkoutProofArgsSchema = z.object({
296
+ id: z.string().min(1),
297
+ proofHash: z.string().trim().min(1).max(128),
298
+ proofUrl: z.string().url().optional(),
299
+ });
300
+
301
+ const checkoutDisputeArgsSchema = z.object({
302
+ id: z.string().min(1),
303
+ reasonCode: z.string().trim().min(3).max(64),
304
+ details: z.record(z.unknown()).optional(),
305
+ });
306
+
307
+ const checkoutSwapAndPayArgsSchema = z
308
+ .object({
309
+ id: z.string().min(1),
310
+ walletId: z.union([z.number().int().positive(), z.string().min(1)]).optional(),
311
+ walletAddress: z.string().min(1).optional(),
312
+ confirm: z.boolean().optional(),
313
+ slippage: z.number().positive().max(5).optional(),
314
+ })
315
+ .refine((data) => [data.walletId, data.walletAddress].filter((v) => v !== undefined).length === 1, {
316
+ message: "Provide exactly one of walletId or walletAddress.",
317
+ });
318
+
319
+ const checkoutWebhookCreateArgsSchema = z.object({
320
+ url: z.string().url(),
321
+ eventTypes: z.array(z.string().min(1)).optional(),
322
+ enabled: z.boolean().optional(),
323
+ });
324
+
325
+ const checkoutWebhookUpdateArgsSchema = z.object({
326
+ id: z.union([z.number().int().positive(), z.string().min(1)]),
327
+ url: z.string().url().optional(),
328
+ eventTypes: z.array(z.string().min(1)).optional(),
329
+ enabled: z.boolean().optional(),
330
+ }).refine((data) => data.url !== undefined || data.eventTypes !== undefined || data.enabled !== undefined, {
331
+ message: "Provide at least one of url, eventTypes, or enabled.",
332
+ });
333
+
334
+ const checkoutWebhookDeleteArgsSchema = z.object({
335
+ id: z.union([z.number().int().positive(), z.string().min(1)]),
336
+ });
337
+
188
338
  function queryString(params) {
189
339
  const search = new URLSearchParams();
190
340
  for (const [key, value] of Object.entries(params)) {
@@ -226,6 +376,9 @@ async function callAgentApi({ method, pathName, query, body, requireAuth = true
226
376
  if (requireAuth) {
227
377
  headers["X-Agent-Key"] = requireAgentKey();
228
378
  }
379
+ if (["POST", "PATCH", "DELETE"].includes(String(method || "").toUpperCase())) {
380
+ headers["Idempotency-Key"] = `mcp-${Date.now()}-${Math.random().toString(16).slice(2)}`;
381
+ }
229
382
 
230
383
  const url = `${getBaseUrl()}${pathName}${queryString(query || {})}`;
231
384
  const response = await fetch(url, {
@@ -354,6 +507,9 @@ const tools = [
354
507
  properties: {
355
508
  network: { type: "string", description: "Example: mainnet, sepolia, solana-mainnet." },
356
509
  chain: { type: "string", enum: ["evm", "solana"] },
510
+ walletId: { oneOf: [{ type: "integer" }, { type: "string" }], description: "Optional wallet selector for history-linked activity." },
511
+ walletLabel: { type: "string", description: "Optional wallet selector for history-linked activity." },
512
+ walletAddress: { type: "string", description: "Optional wallet selector for history-linked activity." },
357
513
  },
358
514
  additionalProperties: false,
359
515
  },
@@ -363,7 +519,6 @@ const tools = [
363
519
  method: "GET",
364
520
  pathName: "/api/agent/supported-tokens",
365
521
  query: args,
366
- requireAuth: false,
367
522
  }),
368
523
  },
369
524
  {
@@ -400,6 +555,9 @@ const tools = [
400
555
  type: "object",
401
556
  properties: {
402
557
  network: { type: "string" },
558
+ walletId: { oneOf: [{ type: "integer" }, { type: "string" }], description: "Optional wallet selector for history-linked activity." },
559
+ walletLabel: { type: "string", description: "Optional wallet selector for history-linked activity." },
560
+ walletAddress: { type: "string", description: "Optional wallet selector for history-linked activity." },
403
561
  tokenIn: { type: "string" },
404
562
  tokenOut: { type: "string" },
405
563
  amountIn: { type: "string" },
@@ -416,7 +574,6 @@ const tools = [
416
574
  pathName: "/api/agent/quote",
417
575
  query: { network },
418
576
  body,
419
- requireAuth: false,
420
577
  });
421
578
  },
422
579
  },
@@ -478,7 +635,7 @@ const tools = [
478
635
  label: { type: "string" },
479
636
  network: {
480
637
  type: "string",
481
- enum: ["sepolia", "mainnet", "solana-devnet", "solana-testnet", "solana-mainnet"],
638
+ enum: ["sepolia", "mainnet", "polygon-mainnet", "solana-devnet", "solana-testnet", "solana-mainnet"],
482
639
  },
483
640
  exportPassphrase: { type: "string", minLength: 12 },
484
641
  exportPassphraseStorageType: { type: "string", enum: ["env", "secret_manager", "vault", "other"] },
@@ -514,12 +671,12 @@ const tools = [
514
671
  },
515
672
  {
516
673
  name: "wallet_import",
517
- description: withWriteSafety("Import a mainnet or Solana mainnet wallet under the configured agent key."),
674
+ description: withWriteSafety("Import a mainnet, polygon-mainnet, or Solana mainnet wallet under the configured agent key."),
518
675
  inputSchema: {
519
676
  type: "object",
520
677
  properties: {
521
678
  label: { type: "string" },
522
- network: { type: "string", enum: ["mainnet", "solana-mainnet"] },
679
+ network: { type: "string", enum: ["mainnet", "polygon-mainnet", "solana-mainnet"] },
523
680
  privateKey: { type: "string" },
524
681
  },
525
682
  required: ["label", "network", "privateKey"],
@@ -533,6 +690,524 @@ const tools = [
533
690
  body: args,
534
691
  }),
535
692
  },
693
+ {
694
+ name: "user_tag_get",
695
+ description: "Read global checkout user tag for the API key owner.",
696
+ inputSchema: {
697
+ type: "object",
698
+ properties: {},
699
+ additionalProperties: false,
700
+ },
701
+ parse: (args) => z.object({}).parse(args ?? {}),
702
+ execute: async () =>
703
+ callAgentApi({
704
+ method: "GET",
705
+ pathName: "/api/agent/user-tag",
706
+ }),
707
+ },
708
+ {
709
+ name: "user_tag_set",
710
+ description: withWriteSafety("Set global checkout user tag once (immutable after set)."),
711
+ inputSchema: {
712
+ type: "object",
713
+ properties: {
714
+ userTag: { type: "string" },
715
+ },
716
+ required: ["userTag"],
717
+ additionalProperties: false,
718
+ },
719
+ parse: (args) => userTagSetArgsSchema.parse(args ?? {}),
720
+ execute: async (args) =>
721
+ callAgentApi({
722
+ method: "PUT",
723
+ pathName: "/api/agent/user-tag",
724
+ body: args,
725
+ }),
726
+ },
727
+ {
728
+ name: "checkout_payreq_create",
729
+ description: withWriteSafety("Create a checkout pay request and escrow."),
730
+ inputSchema: {
731
+ type: "object",
732
+ properties: {
733
+ walletId: { oneOf: [{ type: "integer" }, { type: "string" }] },
734
+ walletAddress: { type: "string" },
735
+ amount: { type: "string" },
736
+ expiresInSeconds: { type: "integer" },
737
+ autoReleaseSeconds: { type: "integer" },
738
+ disputeWindowSeconds: { type: "integer" },
739
+ metadata: { type: "object", additionalProperties: true },
740
+ },
741
+ required: ["amount"],
742
+ additionalProperties: false,
743
+ },
744
+ parse: (args) => checkoutCreatePayreqArgsSchema.parse(args ?? {}),
745
+ execute: async (args) =>
746
+ callAgentApi({
747
+ method: "POST",
748
+ pathName: "/api/agent/checkout/payreq",
749
+ body: args,
750
+ }),
751
+ },
752
+ {
753
+ name: "checkout_payreq_get",
754
+ description: "Get checkout pay request details by id.",
755
+ inputSchema: {
756
+ type: "object",
757
+ properties: { id: { type: "string" } },
758
+ required: ["id"],
759
+ additionalProperties: false,
760
+ },
761
+ parse: (args) => checkoutPayreqIdArgsSchema.parse(args ?? {}),
762
+ execute: async (args) =>
763
+ callAgentApi({
764
+ method: "GET",
765
+ pathName: `/api/agent/checkout/payreq/${encodeURIComponent(args.id)}`,
766
+ }),
767
+ },
768
+ {
769
+ name: "checkout_escrow_get",
770
+ description: "Get checkout escrow details by escrow id.",
771
+ inputSchema: {
772
+ type: "object",
773
+ properties: { id: { type: "string" } },
774
+ required: ["id"],
775
+ additionalProperties: false,
776
+ },
777
+ parse: (args) => checkoutEscrowIdArgsSchema.parse(args ?? {}),
778
+ execute: async (args) =>
779
+ callAgentApi({
780
+ method: "GET",
781
+ pathName: `/api/agent/checkout/escrows/${encodeURIComponent(args.id)}`,
782
+ }),
783
+ },
784
+ {
785
+ name: "checkout_funding_confirm",
786
+ description: withWriteSafety("Confirm checkout escrow funding transaction."),
787
+ inputSchema: {
788
+ type: "object",
789
+ properties: {
790
+ id: { type: "string" },
791
+ txHash: { type: "string" },
792
+ minConfirmations: { type: "integer" },
793
+ },
794
+ required: ["id", "txHash"],
795
+ additionalProperties: false,
796
+ },
797
+ parse: (args) => checkoutFundingConfirmArgsSchema.parse(args ?? {}),
798
+ execute: async (args) => {
799
+ const { id, ...body } = args;
800
+ return callAgentApi({
801
+ method: "POST",
802
+ pathName: `/api/agent/checkout/escrows/${encodeURIComponent(id)}/funding-confirm`,
803
+ body,
804
+ });
805
+ },
806
+ },
807
+ {
808
+ name: "checkout_accept",
809
+ description: withWriteSafety("Accept escrow as buyer."),
810
+ inputSchema: {
811
+ type: "object",
812
+ properties: {
813
+ id: { type: "string" },
814
+ },
815
+ required: ["id"],
816
+ additionalProperties: false,
817
+ },
818
+ parse: (args) => checkoutAcceptArgsSchema.parse(args ?? {}),
819
+ execute: async (args) => {
820
+ const { id, ...body } = args;
821
+ return callAgentApi({
822
+ method: "POST",
823
+ pathName: `/api/agent/checkout/escrows/${encodeURIComponent(id)}/accept`,
824
+ body,
825
+ });
826
+ },
827
+ },
828
+ {
829
+ name: "checkout_proof_submit",
830
+ description: withWriteSafety("Submit checkout proof."),
831
+ inputSchema: {
832
+ type: "object",
833
+ properties: {
834
+ id: { type: "string" },
835
+ proofHash: { type: "string" },
836
+ proofUrl: { type: "string" },
837
+ },
838
+ required: ["id", "proofHash"],
839
+ additionalProperties: false,
840
+ },
841
+ parse: (args) => checkoutProofArgsSchema.parse(args ?? {}),
842
+ execute: async (args) => {
843
+ const { id, ...body } = args;
844
+ return callAgentApi({
845
+ method: "POST",
846
+ pathName: `/api/agent/checkout/escrows/${encodeURIComponent(id)}/proof`,
847
+ body,
848
+ });
849
+ },
850
+ },
851
+ {
852
+ name: "checkout_dispute_open",
853
+ description: withWriteSafety("Open checkout dispute."),
854
+ inputSchema: {
855
+ type: "object",
856
+ properties: {
857
+ id: { type: "string" },
858
+ reasonCode: { type: "string" },
859
+ details: { type: "object", additionalProperties: true },
860
+ },
861
+ required: ["id", "reasonCode"],
862
+ additionalProperties: false,
863
+ },
864
+ parse: (args) => checkoutDisputeArgsSchema.parse(args ?? {}),
865
+ execute: async (args) => {
866
+ const { id, ...body } = args;
867
+ return callAgentApi({
868
+ method: "POST",
869
+ pathName: `/api/agent/checkout/escrows/${encodeURIComponent(id)}/dispute`,
870
+ body,
871
+ });
872
+ },
873
+ },
874
+ {
875
+ name: "checkout_quick_pay",
876
+ description: withWriteSafety("Directly fund checkout escrow from buyer wallet."),
877
+ inputSchema: {
878
+ type: "object",
879
+ properties: {
880
+ id: { type: "string" },
881
+ walletId: { oneOf: [{ type: "integer" }, { type: "string" }] },
882
+ walletAddress: { type: "string" },
883
+ },
884
+ required: ["id"],
885
+ additionalProperties: false,
886
+ },
887
+ parse: (args) => checkoutWalletSelectorArgsSchema.parse(args ?? {}),
888
+ execute: async (args) => {
889
+ const { id, ...body } = args;
890
+ return callAgentApi({
891
+ method: "POST",
892
+ pathName: `/api/agent/checkout/escrows/${encodeURIComponent(id)}/quick-pay`,
893
+ body,
894
+ });
895
+ },
896
+ },
897
+ {
898
+ name: "checkout_swap_and_pay",
899
+ description: withWriteSafety("Swap source asset and fund checkout escrow."),
900
+ inputSchema: {
901
+ type: "object",
902
+ properties: {
903
+ id: { type: "string" },
904
+ walletId: { oneOf: [{ type: "integer" }, { type: "string" }] },
905
+ walletAddress: { type: "string" },
906
+ confirm: { type: "boolean" },
907
+ slippage: { type: "number" },
908
+ },
909
+ required: ["id"],
910
+ additionalProperties: false,
911
+ },
912
+ parse: (args) => checkoutSwapAndPayArgsSchema.parse(args ?? {}),
913
+ execute: async (args) => {
914
+ const { id, ...body } = args;
915
+ return callAgentApi({
916
+ method: "POST",
917
+ pathName: `/api/agent/checkout/escrows/${encodeURIComponent(id)}/swap-and-pay`,
918
+ body,
919
+ });
920
+ },
921
+ },
922
+ {
923
+ name: "checkout_release",
924
+ description: withWriteSafety("Release checkout escrow to seller."),
925
+ inputSchema: {
926
+ type: "object",
927
+ properties: {
928
+ id: { type: "string" },
929
+ force: { type: "boolean" },
930
+ },
931
+ required: ["id"],
932
+ additionalProperties: false,
933
+ },
934
+ parse: (args) => checkoutEscrowIdArgsSchema.extend({ force: z.boolean().optional() }).parse(args ?? {}),
935
+ execute: async (args) => {
936
+ const { id, ...body } = args;
937
+ return callAgentApi({
938
+ method: "POST",
939
+ pathName: `/api/agent/checkout/escrows/${encodeURIComponent(id)}/release`,
940
+ body,
941
+ });
942
+ },
943
+ },
944
+ {
945
+ name: "checkout_refund",
946
+ description: withWriteSafety("Refund checkout escrow to buyer."),
947
+ inputSchema: {
948
+ type: "object",
949
+ properties: {
950
+ id: { type: "string" },
951
+ force: { type: "boolean" },
952
+ },
953
+ required: ["id"],
954
+ additionalProperties: false,
955
+ },
956
+ parse: (args) => checkoutEscrowIdArgsSchema.extend({ force: z.boolean().optional() }).parse(args ?? {}),
957
+ execute: async (args) => {
958
+ const { id, ...body } = args;
959
+ return callAgentApi({
960
+ method: "POST",
961
+ pathName: `/api/agent/checkout/escrows/${encodeURIComponent(id)}/refund`,
962
+ body,
963
+ });
964
+ },
965
+ },
966
+ {
967
+ name: "checkout_cancel",
968
+ description: withWriteSafety("Cancel checkout escrow."),
969
+ inputSchema: {
970
+ type: "object",
971
+ properties: {
972
+ id: { type: "string" },
973
+ },
974
+ required: ["id"],
975
+ additionalProperties: false,
976
+ },
977
+ parse: (args) => checkoutEscrowIdArgsSchema.parse(args ?? {}),
978
+ execute: async (args) =>
979
+ callAgentApi({
980
+ method: "POST",
981
+ pathName: `/api/agent/checkout/escrows/${encodeURIComponent(args.id)}/cancel`,
982
+ body: {},
983
+ }),
984
+ },
985
+ {
986
+ name: "checkout_webhooks_list",
987
+ description: "List checkout webhook subscriptions.",
988
+ inputSchema: { type: "object", properties: {}, additionalProperties: false },
989
+ parse: (args) => z.object({}).parse(args ?? {}),
990
+ execute: async () =>
991
+ callAgentApi({
992
+ method: "GET",
993
+ pathName: "/api/agent/checkout/webhooks",
994
+ }),
995
+ },
996
+ {
997
+ name: "checkout_webhook_create",
998
+ description: withWriteSafety("Create checkout webhook subscription."),
999
+ inputSchema: {
1000
+ type: "object",
1001
+ properties: {
1002
+ url: { type: "string" },
1003
+ eventTypes: { type: "array", items: { type: "string" } },
1004
+ enabled: { type: "boolean" },
1005
+ },
1006
+ required: ["url"],
1007
+ additionalProperties: false,
1008
+ },
1009
+ parse: (args) => checkoutWebhookCreateArgsSchema.parse(args ?? {}),
1010
+ execute: async (args) =>
1011
+ callAgentApi({
1012
+ method: "POST",
1013
+ pathName: "/api/agent/checkout/webhooks",
1014
+ body: args,
1015
+ }),
1016
+ },
1017
+ {
1018
+ name: "checkout_webhook_update",
1019
+ description: withWriteSafety("Update checkout webhook subscription."),
1020
+ inputSchema: {
1021
+ type: "object",
1022
+ properties: {
1023
+ id: { oneOf: [{ type: "integer" }, { type: "string" }] },
1024
+ url: { type: "string" },
1025
+ eventTypes: { type: "array", items: { type: "string" } },
1026
+ enabled: { type: "boolean" },
1027
+ },
1028
+ required: ["id"],
1029
+ additionalProperties: false,
1030
+ },
1031
+ parse: (args) => checkoutWebhookUpdateArgsSchema.parse(args ?? {}),
1032
+ execute: async (args) => {
1033
+ const { id, ...body } = args;
1034
+ return callAgentApi({
1035
+ method: "PATCH",
1036
+ pathName: `/api/agent/checkout/webhooks/${encodeURIComponent(String(id))}`,
1037
+ body,
1038
+ });
1039
+ },
1040
+ },
1041
+ {
1042
+ name: "checkout_webhook_delete",
1043
+ description: withWriteSafety("Delete checkout webhook subscription."),
1044
+ inputSchema: {
1045
+ type: "object",
1046
+ properties: {
1047
+ id: { oneOf: [{ type: "integer" }, { type: "string" }] },
1048
+ },
1049
+ required: ["id"],
1050
+ additionalProperties: false,
1051
+ },
1052
+ parse: (args) => checkoutWebhookDeleteArgsSchema.parse(args ?? {}),
1053
+ execute: async (args) =>
1054
+ callAgentApi({
1055
+ method: "DELETE",
1056
+ pathName: `/api/agent/checkout/webhooks/${encodeURIComponent(String(args.id))}`,
1057
+ }),
1058
+ },
1059
+ {
1060
+ name: "polymarket_order_limit",
1061
+ description: withWriteSafety("Place a Polymarket limit order from a configured polygon-mainnet wallet."),
1062
+ inputSchema: {
1063
+ type: "object",
1064
+ properties: {
1065
+ walletId: { oneOf: [{ type: "integer" }, { type: "string" }] },
1066
+ walletAddress: { type: "string" },
1067
+ tokenId: { type: "string" },
1068
+ side: { type: "string", enum: ["BUY", "SELL"] },
1069
+ price: { type: "number" },
1070
+ size: { type: "number" },
1071
+ },
1072
+ required: ["tokenId", "side", "price", "size"],
1073
+ additionalProperties: false,
1074
+ },
1075
+ parse: (args) => polymarketLimitArgsSchema.parse(args ?? {}),
1076
+ execute: async (args) =>
1077
+ callAgentApi({
1078
+ method: "POST",
1079
+ pathName: "/api/agent/venues/polymarket/orders/limit",
1080
+ body: args,
1081
+ }),
1082
+ },
1083
+ {
1084
+ name: "polymarket_order_market",
1085
+ description: withWriteSafety("Place a Polymarket market order from a configured polygon-mainnet wallet."),
1086
+ inputSchema: {
1087
+ type: "object",
1088
+ properties: {
1089
+ walletId: { oneOf: [{ type: "integer" }, { type: "string" }] },
1090
+ walletAddress: { type: "string" },
1091
+ tokenId: { type: "string" },
1092
+ side: { type: "string", enum: ["BUY", "SELL"] },
1093
+ amount: { type: "number" },
1094
+ orderType: { type: "string", enum: ["FAK", "FOK", "GTC"] },
1095
+ worstPrice: { type: "number" },
1096
+ },
1097
+ required: ["tokenId", "side", "amount"],
1098
+ additionalProperties: false,
1099
+ },
1100
+ parse: (args) => polymarketMarketArgsSchema.parse(args ?? {}),
1101
+ execute: async (args) =>
1102
+ callAgentApi({
1103
+ method: "POST",
1104
+ pathName: "/api/agent/venues/polymarket/orders/market",
1105
+ body: args,
1106
+ }),
1107
+ },
1108
+ {
1109
+ name: "polymarket_account",
1110
+ description: "Read Polymarket account summary for a configured polygon-mainnet wallet.",
1111
+ inputSchema: {
1112
+ type: "object",
1113
+ properties: {
1114
+ walletId: { oneOf: [{ type: "integer" }, { type: "string" }] },
1115
+ walletAddress: { type: "string" },
1116
+ },
1117
+ additionalProperties: false,
1118
+ },
1119
+ parse: (args) => polymarketReadArgsSchema.parse(args ?? {}),
1120
+ execute: async (args) =>
1121
+ callAgentApi({
1122
+ method: "GET",
1123
+ pathName: "/api/agent/venues/polymarket/account",
1124
+ query: args,
1125
+ }),
1126
+ },
1127
+ {
1128
+ name: "polymarket_orders",
1129
+ description: "List Polymarket open orders for a configured polygon-mainnet wallet.",
1130
+ inputSchema: {
1131
+ type: "object",
1132
+ properties: {
1133
+ walletId: { oneOf: [{ type: "integer" }, { type: "string" }] },
1134
+ walletAddress: { type: "string" },
1135
+ status: { type: "string" },
1136
+ limit: { type: "integer" },
1137
+ cursor: { type: "string" },
1138
+ },
1139
+ additionalProperties: false,
1140
+ },
1141
+ parse: (args) => polymarketReadArgsSchema.parse(args ?? {}),
1142
+ execute: async (args) =>
1143
+ callAgentApi({
1144
+ method: "GET",
1145
+ pathName: "/api/agent/venues/polymarket/orders",
1146
+ query: args,
1147
+ }),
1148
+ },
1149
+ {
1150
+ name: "polymarket_cancel_order",
1151
+ description: withWriteSafety("Cancel a Polymarket order for a configured polygon-mainnet wallet."),
1152
+ inputSchema: {
1153
+ type: "object",
1154
+ properties: {
1155
+ walletId: { oneOf: [{ type: "integer" }, { type: "string" }] },
1156
+ walletAddress: { type: "string" },
1157
+ orderId: { type: "string" },
1158
+ },
1159
+ required: ["orderId"],
1160
+ additionalProperties: false,
1161
+ },
1162
+ parse: (args) => polymarketCancelArgsSchema.parse(args ?? {}),
1163
+ execute: async (args) =>
1164
+ callAgentApi({
1165
+ method: "POST",
1166
+ pathName: "/api/agent/venues/polymarket/orders/cancel",
1167
+ body: args,
1168
+ }),
1169
+ },
1170
+ {
1171
+ name: "polymarket_activity",
1172
+ description: "List Polymarket trade activity for a configured polygon-mainnet wallet.",
1173
+ inputSchema: {
1174
+ type: "object",
1175
+ properties: {
1176
+ walletId: { oneOf: [{ type: "integer" }, { type: "string" }] },
1177
+ walletAddress: { type: "string" },
1178
+ limit: { type: "integer" },
1179
+ cursor: { type: "string" },
1180
+ },
1181
+ additionalProperties: false,
1182
+ },
1183
+ parse: (args) => polymarketReadArgsSchema.parse(args ?? {}),
1184
+ execute: async (args) =>
1185
+ callAgentApi({
1186
+ method: "GET",
1187
+ pathName: "/api/agent/venues/polymarket/activity",
1188
+ query: args,
1189
+ }),
1190
+ },
1191
+ {
1192
+ name: "polymarket_positions",
1193
+ description: "List Polymarket open positions (open-market filtered) for a configured polygon-mainnet wallet, including position PnL fields.",
1194
+ inputSchema: {
1195
+ type: "object",
1196
+ properties: {
1197
+ walletId: { oneOf: [{ type: "integer" }, { type: "string" }] },
1198
+ walletAddress: { type: "string" },
1199
+ limit: { type: "integer" },
1200
+ },
1201
+ additionalProperties: false,
1202
+ },
1203
+ parse: (args) => polymarketReadArgsSchema.parse(args ?? {}),
1204
+ execute: async (args) =>
1205
+ callAgentApi({
1206
+ method: "GET",
1207
+ pathName: "/api/agent/venues/polymarket/positions",
1208
+ query: args,
1209
+ }),
1210
+ },
536
1211
  ];
537
1212
 
538
1213
  const resources = [
@@ -561,6 +1236,7 @@ const resources = [
561
1236
  "3. Use `wallet_get` or `balances_get` before write actions.",
562
1237
  "4. For writes, establish approval mode once per session.",
563
1238
  "5. Use `swap_quote` before `swap_execute`.",
1239
+ "6. For Polymarket: ask your human to complete setup in dashboard (/venues/polymarket), then place/cancel orders and inspect account/activity/positions via polymarket tools.",
564
1240
  ].join("\n"),
565
1241
  },
566
1242
  ];
@@ -666,7 +1342,7 @@ async function runSelfTest() {
666
1342
  capabilities: {},
667
1343
  clientInfo: {
668
1344
  name: "openclawcash-self-test",
669
- version: "0.1.1",
1345
+ version: SERVER_VERSION,
670
1346
  },
671
1347
  },
672
1348
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclawcash/mcp-server",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "OpenClawCash MCP server for managed agent wallets, balances, transfers, swaps, and approvals.",
5
5
  "type": "module",
6
6
  "license": "Proprietary",