bsv-mcp 0.0.21 → 0.0.23
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 +17 -40
- package/index.ts +28 -28
- package/package.json +4 -4
- package/tools/bsv/explore.ts +331 -261
- package/tools/bsv/getPrice.ts +19 -10
- package/tools/bsv/index.ts +1 -1
- package/tools/index.ts +10 -10
- package/tools/mnee/getBalance.ts +53 -43
- package/tools/mnee/index.ts +7 -7
- package/tools/mnee/parseTx.ts +31 -27
- package/tools/mnee/sendMnee.ts +70 -66
- package/tools/ordinals/getTokenByIdOrTicker.ts +14 -7
- package/tools/ordinals/marketListings.ts +26 -13
- package/tools/ordinals/marketSales.ts +11 -17
- package/tools/utils/index.ts +19 -15
- package/tools/wallet/createOrdinals.ts +27 -13
- package/tools/wallet/getAddress.ts +6 -1
- package/tools/wallet/purchaseListing.ts +18 -16
- package/tools/wallet/schemas.ts +55 -32
- package/tools/wallet/sendOrdinals.ts +106 -92
- package/tools/wallet/sendToAddress.ts +1 -1
- package/tools/wallet/tools.test.ts +3 -3
- package/tools/wallet/tools.ts +51 -38
- package/tools/wallet/transferOrdToken.ts +138 -0
- package/tools/wallet/wallet.ts +3 -9
- package/tools/wallet/transferOrdToken/index.ts +0 -103
package/tools/bsv/getPrice.ts
CHANGED
|
@@ -13,7 +13,10 @@ let cachedPrice: { value: number; timestamp: number } | null = null;
|
|
|
13
13
|
*/
|
|
14
14
|
async function getBsvPriceWithCache(): Promise<number> {
|
|
15
15
|
// Return cached price if it's still valid
|
|
16
|
-
if (
|
|
16
|
+
if (
|
|
17
|
+
cachedPrice &&
|
|
18
|
+
Date.now() - cachedPrice.timestamp < PRICE_CACHE_DURATION
|
|
19
|
+
) {
|
|
17
20
|
return cachedPrice.value;
|
|
18
21
|
}
|
|
19
22
|
|
|
@@ -22,22 +25,23 @@ async function getBsvPriceWithCache(): Promise<number> {
|
|
|
22
25
|
"https://api.whatsonchain.com/v1/bsv/main/exchangerate",
|
|
23
26
|
);
|
|
24
27
|
if (!res.ok) throw new Error("Failed to fetch price");
|
|
25
|
-
|
|
28
|
+
|
|
26
29
|
const data = (await res.json()) as {
|
|
27
30
|
currency: string;
|
|
28
31
|
rate: string;
|
|
29
32
|
time: number;
|
|
30
33
|
};
|
|
31
|
-
|
|
34
|
+
|
|
32
35
|
const price = Number(data.rate);
|
|
33
|
-
if (Number.isNaN(price) || price <= 0)
|
|
34
|
-
|
|
36
|
+
if (Number.isNaN(price) || price <= 0)
|
|
37
|
+
throw new Error("Invalid price received");
|
|
38
|
+
|
|
35
39
|
// Update cache
|
|
36
|
-
cachedPrice = {
|
|
37
|
-
value: price,
|
|
38
|
-
timestamp: Date.now()
|
|
40
|
+
cachedPrice = {
|
|
41
|
+
value: price,
|
|
42
|
+
timestamp: Date.now(),
|
|
39
43
|
};
|
|
40
|
-
|
|
44
|
+
|
|
41
45
|
return price;
|
|
42
46
|
}
|
|
43
47
|
|
|
@@ -50,7 +54,12 @@ export function registerGetPriceTool(server: McpServer): void {
|
|
|
50
54
|
"bsv_getPrice",
|
|
51
55
|
"Retrieves the current price of Bitcoin SV (BSV) in USD from a reliable exchange API. This tool provides real-time market data that can be used for calculating transaction values, monitoring market conditions, or converting between BSV and fiat currencies.",
|
|
52
56
|
{
|
|
53
|
-
args: z
|
|
57
|
+
args: z
|
|
58
|
+
.object({})
|
|
59
|
+
.optional()
|
|
60
|
+
.describe(
|
|
61
|
+
"No parameters required - simply returns the current BSV price in USD",
|
|
62
|
+
),
|
|
54
63
|
},
|
|
55
64
|
async () => {
|
|
56
65
|
try {
|
package/tools/bsv/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import { registerDecodeTransactionTool } from "./decodeTransaction";
|
|
3
|
-
import { registerGetPriceTool } from "./getPrice";
|
|
4
3
|
import { registerExploreTool } from "./explore";
|
|
4
|
+
import { registerGetPriceTool } from "./getPrice";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Register all BSV tools with the MCP server
|
package/tools/index.ts
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import { registerBsvTools } from "./bsv";
|
|
3
|
+
import { registerMneeTools } from "./mnee";
|
|
3
4
|
import { registerOrdinalsTools } from "./ordinals";
|
|
4
5
|
import { registerUtilsTools } from "./utils";
|
|
5
|
-
import { registerMneeTools } from "./mnee";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Register all tools with the MCP server
|
|
9
9
|
* @param server The MCP server instance
|
|
10
10
|
*/
|
|
11
11
|
export function registerAllTools(server: McpServer): void {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
// Register BSV-related tools
|
|
13
|
+
registerBsvTools(server);
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
// Register Ordinals-related tools
|
|
16
|
+
registerOrdinalsTools(server);
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
// Register utility tools
|
|
19
|
+
registerUtilsTools(server);
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
// Register MNEE tools
|
|
22
|
+
registerMneeTools(server);
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
// Add more tool categories as needed
|
|
25
25
|
}
|
package/tools/mnee/getBalance.ts
CHANGED
|
@@ -1,56 +1,66 @@
|
|
|
1
|
+
import { PrivateKey } from "@bsv/sdk";
|
|
1
2
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
3
|
import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
4
|
+
import type {
|
|
5
|
+
ServerNotification,
|
|
6
|
+
ServerRequest,
|
|
7
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
5
8
|
import type { MneeInterface } from "mnee";
|
|
9
|
+
import { z } from "zod";
|
|
6
10
|
|
|
7
11
|
export const getBalanceArgsSchema = z.object({});
|
|
8
12
|
|
|
9
13
|
export type GetBalanceArgs = z.infer<typeof getBalanceArgsSchema>;
|
|
10
14
|
|
|
11
15
|
export function registerGetBalanceTool(
|
|
12
|
-
|
|
13
|
-
|
|
16
|
+
server: McpServer,
|
|
17
|
+
mnee: MneeInterface,
|
|
14
18
|
): void {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
19
|
+
server.tool(
|
|
20
|
+
"mnee_getBalance",
|
|
21
|
+
"Retrieves the current MNEE token balance for the wallet. Returns the balance in MNEE tokens.",
|
|
22
|
+
{
|
|
23
|
+
args: getBalanceArgsSchema,
|
|
24
|
+
},
|
|
25
|
+
async (
|
|
26
|
+
{ args }: { args: GetBalanceArgs },
|
|
27
|
+
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
28
|
+
) => {
|
|
29
|
+
try {
|
|
30
|
+
// Get private key from wallet
|
|
31
|
+
const privateKeyWif = process.env.PRIVATE_KEY_WIF;
|
|
32
|
+
if (!privateKeyWif) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
"Private key WIF not available in environment variables",
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
const privateKey = PrivateKey.fromWif(privateKeyWif);
|
|
38
|
+
if (!privateKey) {
|
|
39
|
+
throw new Error("No private key available");
|
|
40
|
+
}
|
|
31
41
|
|
|
32
|
-
|
|
33
|
-
|
|
42
|
+
const address = privateKey.toAddress().toString();
|
|
43
|
+
const balance = await mnee.balance(address);
|
|
34
44
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
45
|
+
return {
|
|
46
|
+
content: [
|
|
47
|
+
{
|
|
48
|
+
type: "text",
|
|
49
|
+
text: JSON.stringify({ balance }, null, 2),
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
};
|
|
53
|
+
} catch (error) {
|
|
54
|
+
return {
|
|
55
|
+
content: [
|
|
56
|
+
{
|
|
57
|
+
type: "text",
|
|
58
|
+
text: error instanceof Error ? error.message : String(error),
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
isError: true,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
);
|
|
56
66
|
}
|
package/tools/mnee/index.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import { registerGetBalanceTool } from "./getBalance";
|
|
3
2
|
import Mnee from "mnee";
|
|
4
|
-
import {
|
|
3
|
+
import { registerGetBalanceTool } from "./getBalance";
|
|
5
4
|
import { registerParseTxTool } from "./parseTx";
|
|
5
|
+
import { registerSendMneeTool } from "./sendMnee";
|
|
6
6
|
|
|
7
7
|
const mnee = new Mnee({
|
|
8
|
-
|
|
8
|
+
environment: "production",
|
|
9
9
|
});
|
|
10
10
|
/**
|
|
11
11
|
* Register all MNEE tools with the MCP server
|
|
12
12
|
* @param server The MCP server instance
|
|
13
13
|
*/
|
|
14
14
|
export function registerMneeTools(server: McpServer): void {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
// Register MNEE-related tools
|
|
16
|
+
registerGetBalanceTool(server, mnee);
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
registerSendMneeTool(server, mnee);
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
registerParseTxTool(server, mnee);
|
|
21
21
|
}
|
package/tools/mnee/parseTx.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
|
|
3
3
|
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
4
|
+
import type {
|
|
5
|
+
ServerNotification,
|
|
6
|
+
ServerRequest,
|
|
7
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
4
8
|
import type { MneeInterface, ParseTxResponse } from "mnee";
|
|
5
9
|
import { z } from "zod";
|
|
6
10
|
|
|
@@ -8,38 +12,38 @@ import { z } from "zod";
|
|
|
8
12
|
* Schema for the parseTx tool arguments.
|
|
9
13
|
*/
|
|
10
14
|
export const parseTxArgsSchema = z.object({
|
|
11
|
-
|
|
15
|
+
txid: z.string().describe("Transaction ID to parse"),
|
|
12
16
|
});
|
|
13
17
|
|
|
14
18
|
export type ParseTxArgs = z.infer<typeof parseTxArgsSchema>;
|
|
15
19
|
|
|
16
20
|
export function registerParseTxTool(
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
server: McpServer,
|
|
22
|
+
mnee: MneeInterface,
|
|
19
23
|
): void {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
server.tool(
|
|
25
|
+
"mnee_parseTx",
|
|
26
|
+
"Parse an MNEE transaction to get detailed information about its operations and amounts. All amounts are in atomic units with 5 decimal precision (e.g. 1000 atomic units = 0.01 MNEE).",
|
|
27
|
+
{ args: parseTxArgsSchema },
|
|
28
|
+
async (
|
|
29
|
+
{ args }: { args: ParseTxArgs },
|
|
30
|
+
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
31
|
+
): Promise<CallToolResult> => {
|
|
32
|
+
try {
|
|
33
|
+
const result: ParseTxResponse = await mnee.parseTx(args.txid);
|
|
30
34
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
35
|
+
return {
|
|
36
|
+
content: [
|
|
37
|
+
{
|
|
38
|
+
type: "text",
|
|
39
|
+
text: JSON.stringify(result, null, 2),
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
};
|
|
43
|
+
} catch (error) {
|
|
44
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
45
|
+
return { content: [{ type: "text", text: msg }], isError: true };
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
);
|
|
45
49
|
}
|
package/tools/mnee/sendMnee.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
|
|
3
3
|
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
4
|
+
import type {
|
|
5
|
+
ServerNotification,
|
|
6
|
+
ServerRequest,
|
|
7
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
4
8
|
import type Mnee from "mnee";
|
|
5
9
|
import type { SendMNEE, TransferResponse } from "mnee";
|
|
6
10
|
import { z } from "zod";
|
|
@@ -9,12 +13,12 @@ import { z } from "zod";
|
|
|
9
13
|
* Schema for the sendMnee tool arguments.
|
|
10
14
|
*/
|
|
11
15
|
export const sendMneeArgsSchema = z.object({
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
address: z.string().describe("The recipient's address"),
|
|
17
|
+
amount: z.number().describe("Amount to send"),
|
|
18
|
+
currency: z
|
|
19
|
+
.enum(["MNEE", "USD"])
|
|
20
|
+
.default("MNEE")
|
|
21
|
+
.describe("Currency of the amount (MNEE or USD)"),
|
|
18
22
|
});
|
|
19
23
|
|
|
20
24
|
export type SendMneeArgs = z.infer<typeof sendMneeArgsSchema>;
|
|
@@ -23,75 +27,75 @@ export type SendMneeArgs = z.infer<typeof sendMneeArgsSchema>;
|
|
|
23
27
|
* Format a number as USD
|
|
24
28
|
*/
|
|
25
29
|
function formatUSD(amount: number): string {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
return new Intl.NumberFormat("en-US", {
|
|
31
|
+
style: "currency",
|
|
32
|
+
currency: "USD",
|
|
33
|
+
minimumFractionDigits: 2,
|
|
34
|
+
maximumFractionDigits: 2,
|
|
35
|
+
}).format(amount);
|
|
32
36
|
}
|
|
33
37
|
|
|
34
38
|
/**
|
|
35
39
|
* Registers the mnee_sendMnee tool for sending MNEE tokens
|
|
36
40
|
*/
|
|
37
41
|
export function registerSendMneeTool(server: McpServer, mnee: Mnee): void {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
42
|
+
server.tool(
|
|
43
|
+
"mnee_sendMnee",
|
|
44
|
+
"Send MNEE tokens to a specified address",
|
|
45
|
+
{ args: sendMneeArgsSchema },
|
|
46
|
+
async (
|
|
47
|
+
{ args }: { args: SendMneeArgs },
|
|
48
|
+
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
49
|
+
): Promise<CallToolResult> => {
|
|
50
|
+
try {
|
|
51
|
+
// Since 1 MNEE = $1, the amount is the same in both currencies
|
|
52
|
+
const mneeAmount = args.amount;
|
|
49
53
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
const transferRequest: SendMNEE[] = [
|
|
55
|
+
{
|
|
56
|
+
address: args.address,
|
|
57
|
+
amount: mneeAmount,
|
|
58
|
+
},
|
|
59
|
+
];
|
|
56
60
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
// Get WIF from environment
|
|
62
|
+
const wif = process.env.PRIVATE_KEY_WIF;
|
|
63
|
+
if (!wif) {
|
|
64
|
+
throw new Error("PRIVATE_KEY_WIF environment variable is not set");
|
|
65
|
+
}
|
|
62
66
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
const result: TransferResponse = await mnee.transfer(
|
|
68
|
+
transferRequest,
|
|
69
|
+
wif,
|
|
70
|
+
);
|
|
67
71
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
72
|
+
if (result.error) {
|
|
73
|
+
throw new Error(result.error);
|
|
74
|
+
}
|
|
71
75
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
76
|
+
return {
|
|
77
|
+
content: [
|
|
78
|
+
{
|
|
79
|
+
type: "text",
|
|
80
|
+
text: JSON.stringify(
|
|
81
|
+
{
|
|
82
|
+
success: true,
|
|
83
|
+
txid: result.txid,
|
|
84
|
+
rawtx: result.rawtx,
|
|
85
|
+
mneeAmount: mneeAmount,
|
|
86
|
+
usdAmount: formatUSD(mneeAmount),
|
|
87
|
+
recipient: args.address,
|
|
88
|
+
},
|
|
89
|
+
null,
|
|
90
|
+
2,
|
|
91
|
+
),
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
};
|
|
95
|
+
} catch (error) {
|
|
96
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
97
|
+
return { content: [{ type: "text", text: msg }], isError: true };
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
);
|
|
97
101
|
}
|
|
@@ -3,14 +3,21 @@ import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/proto
|
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
|
|
5
5
|
// Schema for get token by ID or ticker arguments
|
|
6
|
-
export const getTokenByIdOrTickerArgsSchema = z
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
export const getTokenByIdOrTickerArgsSchema = z
|
|
7
|
+
.object({
|
|
8
|
+
id: z
|
|
9
|
+
.string()
|
|
10
|
+
.optional()
|
|
11
|
+
.describe("BSV20 token ID in outpoint format (txid_vout)"),
|
|
12
|
+
tick: z.string().optional().describe("BSV20 token ticker symbol"),
|
|
13
|
+
})
|
|
14
|
+
.refine((data) => data.id || data.tick, {
|
|
15
|
+
message: "Either id or tick must be provided",
|
|
16
|
+
});
|
|
12
17
|
|
|
13
|
-
export type GetTokenByIdOrTickerArgs = z.infer<
|
|
18
|
+
export type GetTokenByIdOrTickerArgs = z.infer<
|
|
19
|
+
typeof getTokenByIdOrTickerArgsSchema
|
|
20
|
+
>;
|
|
14
21
|
|
|
15
22
|
// BSV20 token response type
|
|
16
23
|
interface TokenResponse {
|
|
@@ -18,16 +18,16 @@ export const marketListingsArgsSchema = z.object({
|
|
|
18
18
|
.default("desc")
|
|
19
19
|
.describe("Sort direction (asc or desc)"),
|
|
20
20
|
address: z.string().optional().describe("Bitcoin address"),
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
// NFT-specific parameters
|
|
23
23
|
origin: z.string().optional().describe("Origin outpoint"),
|
|
24
24
|
mime: z.string().optional().describe("MIME type filter"),
|
|
25
25
|
num: z.string().optional().describe("Inscription number"),
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
// General market parameters
|
|
28
28
|
minPrice: z.number().optional().describe("Minimum price in satoshis"),
|
|
29
29
|
maxPrice: z.number().optional().describe("Maximum price in satoshis"),
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
// Token-specific parameters
|
|
32
32
|
tokenType: z
|
|
33
33
|
.enum(["nft", "bsv20", "bsv21", "all"])
|
|
@@ -39,7 +39,11 @@ export const marketListingsArgsSchema = z.object({
|
|
|
39
39
|
.describe("Sort method (recent, price, num, height, price_per_token)"),
|
|
40
40
|
id: z.string().optional().describe("Token ID in outpoint format"),
|
|
41
41
|
tick: z.string().optional().describe("Token ticker symbol"),
|
|
42
|
-
pending: z
|
|
42
|
+
pending: z
|
|
43
|
+
.boolean()
|
|
44
|
+
.default(false)
|
|
45
|
+
.optional()
|
|
46
|
+
.describe("Include pending sales"),
|
|
43
47
|
});
|
|
44
48
|
|
|
45
49
|
export type MarketListingsArgs = z.infer<typeof marketListingsArgsSchema>;
|
|
@@ -118,7 +122,7 @@ export function registerMarketListingsTool(server: McpServer): void {
|
|
|
118
122
|
// Determine the API endpoint based on tokenType
|
|
119
123
|
let baseUrl = "https://ordinals.gorillapool.io/api";
|
|
120
124
|
let useTokenParams = false;
|
|
121
|
-
|
|
125
|
+
|
|
122
126
|
if (tokenType === "bsv20" || tokenType === "bsv21") {
|
|
123
127
|
baseUrl += "/bsv20/market";
|
|
124
128
|
useTokenParams = true;
|
|
@@ -131,11 +135,15 @@ export function registerMarketListingsTool(server: McpServer): void {
|
|
|
131
135
|
url.searchParams.append("limit", limit.toString());
|
|
132
136
|
url.searchParams.append("offset", offset.toString());
|
|
133
137
|
url.searchParams.append("dir", dir);
|
|
134
|
-
|
|
138
|
+
|
|
135
139
|
// Add sort parameter based on token type
|
|
136
140
|
if (useTokenParams) {
|
|
137
141
|
// BSV20/BSV21 specific sort options
|
|
138
|
-
if (
|
|
142
|
+
if (
|
|
143
|
+
sort === "height" ||
|
|
144
|
+
sort === "price" ||
|
|
145
|
+
sort === "price_per_token"
|
|
146
|
+
) {
|
|
139
147
|
url.searchParams.append("sort", sort);
|
|
140
148
|
}
|
|
141
149
|
// Add token-specific parameters
|
|
@@ -144,10 +152,13 @@ export function registerMarketListingsTool(server: McpServer): void {
|
|
|
144
152
|
}
|
|
145
153
|
if (id) url.searchParams.append("id", id);
|
|
146
154
|
if (tick) url.searchParams.append("tick", tick);
|
|
147
|
-
if (pending !== undefined)
|
|
155
|
+
if (pending !== undefined)
|
|
156
|
+
url.searchParams.append("pending", pending.toString());
|
|
148
157
|
// For BSV20/21, min/max price parameters have slightly different names
|
|
149
|
-
if (minPrice !== undefined)
|
|
150
|
-
|
|
158
|
+
if (minPrice !== undefined)
|
|
159
|
+
url.searchParams.append("min_price", minPrice.toString());
|
|
160
|
+
if (maxPrice !== undefined)
|
|
161
|
+
url.searchParams.append("max_price", maxPrice.toString());
|
|
151
162
|
} else {
|
|
152
163
|
// NFT specific sort options
|
|
153
164
|
if (sort === "recent" || sort === "price" || sort === "num") {
|
|
@@ -158,10 +169,12 @@ export function registerMarketListingsTool(server: McpServer): void {
|
|
|
158
169
|
if (mime) url.searchParams.append("mime", mime);
|
|
159
170
|
if (num) url.searchParams.append("num", num);
|
|
160
171
|
// For NFTs, min/max price parameters use short names
|
|
161
|
-
if (minPrice !== undefined)
|
|
162
|
-
|
|
172
|
+
if (minPrice !== undefined)
|
|
173
|
+
url.searchParams.append("min", minPrice.toString());
|
|
174
|
+
if (maxPrice !== undefined)
|
|
175
|
+
url.searchParams.append("max", maxPrice.toString());
|
|
163
176
|
}
|
|
164
|
-
|
|
177
|
+
|
|
165
178
|
// Add common parameters
|
|
166
179
|
if (address) url.searchParams.append("address", address);
|
|
167
180
|
|
|
@@ -26,7 +26,11 @@ export const marketSalesArgsSchema = z.object({
|
|
|
26
26
|
.describe("Type of token to search for (bsv20, bsv21, or all)"),
|
|
27
27
|
id: z.string().optional().describe("Token ID in outpoint format"),
|
|
28
28
|
tick: z.string().optional().describe("Token ticker symbol"),
|
|
29
|
-
pending: z
|
|
29
|
+
pending: z
|
|
30
|
+
.boolean()
|
|
31
|
+
.default(false)
|
|
32
|
+
.optional()
|
|
33
|
+
.describe("Include pending sales"),
|
|
30
34
|
});
|
|
31
35
|
|
|
32
36
|
export type MarketSalesArgs = z.infer<typeof marketSalesArgsSchema>;
|
|
@@ -71,21 +75,10 @@ export function registerMarketSalesTool(server: McpServer): void {
|
|
|
71
75
|
{
|
|
72
76
|
args: marketSalesArgsSchema,
|
|
73
77
|
},
|
|
74
|
-
async (
|
|
75
|
-
{ args }: { args: MarketSalesArgs },
|
|
76
|
-
extra: RequestHandlerExtra,
|
|
77
|
-
) => {
|
|
78
|
+
async ({ args }: { args: MarketSalesArgs }, extra: RequestHandlerExtra) => {
|
|
78
79
|
try {
|
|
79
|
-
const {
|
|
80
|
-
|
|
81
|
-
offset,
|
|
82
|
-
dir,
|
|
83
|
-
tokenType,
|
|
84
|
-
id,
|
|
85
|
-
tick,
|
|
86
|
-
pending,
|
|
87
|
-
address
|
|
88
|
-
} = args;
|
|
80
|
+
const { limit, offset, dir, tokenType, id, tick, pending, address } =
|
|
81
|
+
args;
|
|
89
82
|
|
|
90
83
|
// Determine the API endpoint based on tokenType
|
|
91
84
|
let baseUrl = "https://ordinals.gorillapool.io/api";
|
|
@@ -98,7 +91,7 @@ export function registerMarketSalesTool(server: McpServer): void {
|
|
|
98
91
|
url.searchParams.append("limit", limit.toString());
|
|
99
92
|
url.searchParams.append("offset", offset.toString());
|
|
100
93
|
url.searchParams.append("dir", dir);
|
|
101
|
-
|
|
94
|
+
|
|
102
95
|
// Add type parameter for bsv21 if needed
|
|
103
96
|
if (tokenType === "bsv21") {
|
|
104
97
|
url.searchParams.append("type", "v2");
|
|
@@ -106,7 +99,8 @@ export function registerMarketSalesTool(server: McpServer): void {
|
|
|
106
99
|
|
|
107
100
|
if (id) url.searchParams.append("id", id);
|
|
108
101
|
if (tick) url.searchParams.append("tick", tick);
|
|
109
|
-
if (pending !== undefined)
|
|
102
|
+
if (pending !== undefined)
|
|
103
|
+
url.searchParams.append("pending", pending.toString());
|
|
110
104
|
if (address) url.searchParams.append("address", address);
|
|
111
105
|
|
|
112
106
|
// Fetch market sales from GorillaPool API
|