kaspa-simple-mcp 0.1.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/README.md +177 -0
- package/dist/conversion.d.ts +3 -0
- package/dist/conversion.d.ts.map +1 -0
- package/dist/conversion.js +8 -0
- package/dist/conversion.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -0
- package/dist/kaspa-client.d.ts +26 -0
- package/dist/kaspa-client.d.ts.map +1 -0
- package/dist/kaspa-client.js +44 -0
- package/dist/kaspa-client.js.map +1 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# kaspa-simple-mcp
|
|
2
|
+
|
|
3
|
+
A read-only [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server for the Kaspa blockchain mainnet. Lets AI agents query Kaspa data through simple, deterministic tools — no node required.
|
|
4
|
+
|
|
5
|
+
Built for use with MCP-compatible clients like [OpenCode](https://opencode.ai), Claude, Cursor, and others.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Balance lookup** — get the confirmed KAS balance for any mainnet address
|
|
10
|
+
- **Transaction lookup** — get status, timestamp, total value, and top outputs for any transaction
|
|
11
|
+
- **Fee estimation** — get the current network priority fee rate
|
|
12
|
+
|
|
13
|
+
All data comes from the public [api.kaspa.org](https://api.kaspa.org) REST API. No API key needed. Read-only. Mainnet only.
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
### Via npm (recommended)
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install -g kaspa-simple-mcp
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Via npx (no install)
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx kaspa-simple-mcp
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### From source
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
git clone https://github.com/danieliyahu1/kaspa-simple-mcp.git
|
|
33
|
+
cd kaspa-simple-mcp
|
|
34
|
+
npm install
|
|
35
|
+
npm run build
|
|
36
|
+
npm start
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
### MCP client configuration
|
|
42
|
+
|
|
43
|
+
The server communicates over **stdio**. Configure it as an MCP tool server in your client's settings.
|
|
44
|
+
|
|
45
|
+
**OpenCode (`opencode.json`):**
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"mcp": {
|
|
50
|
+
"kaspa-simple-mcp": {
|
|
51
|
+
"command": "npx",
|
|
52
|
+
"args": ["-y", "kaspa-simple-mcp"]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Claude Desktop (`claude_desktop_config.json`):**
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"mcpServers": {
|
|
63
|
+
"kaspa": {
|
|
64
|
+
"command": "npx",
|
|
65
|
+
"args": ["-y", "kaspa-simple-mcp"]
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Tools
|
|
72
|
+
|
|
73
|
+
### `get_balance`
|
|
74
|
+
|
|
75
|
+
Get the confirmed KAS balance for a Kaspa mainnet address.
|
|
76
|
+
|
|
77
|
+
**Parameters:**
|
|
78
|
+
|
|
79
|
+
| Name | Type | Description |
|
|
80
|
+
|------|------|-------------|
|
|
81
|
+
| `address` | string | Kaspa mainnet address (e.g., `kaspa:...`) |
|
|
82
|
+
|
|
83
|
+
**Example response:**
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{ "balance": "1250.50000000" }
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### `get_transaction`
|
|
90
|
+
|
|
91
|
+
Look up a transaction by its ID.
|
|
92
|
+
|
|
93
|
+
**Parameters:**
|
|
94
|
+
|
|
95
|
+
| Name | Type | Description |
|
|
96
|
+
|------|------|-------------|
|
|
97
|
+
| `txId` | string | 64-char Kaspa transaction ID (hex) |
|
|
98
|
+
|
|
99
|
+
**Example response:**
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"status": "confirmed",
|
|
104
|
+
"timestamp": 1700000000,
|
|
105
|
+
"totalKas": "500.00000000",
|
|
106
|
+
"outputs": [
|
|
107
|
+
{ "recipient": "kaspa:...", "amount": "250.00000000" },
|
|
108
|
+
{ "recipient": "kaspa:...", "amount": "250.00000000" }
|
|
109
|
+
]
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
If the transaction has more than 5 outputs, a `moreOutputs` field indicates how many were omitted.
|
|
114
|
+
|
|
115
|
+
### `get_fee_estimate`
|
|
116
|
+
|
|
117
|
+
Get the current network priority fee rate.
|
|
118
|
+
|
|
119
|
+
**Parameters:** None
|
|
120
|
+
|
|
121
|
+
**Example response:**
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{ "feerate": "0.00000100" }
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The fee rate is in KAS/KB — multiply by your estimated transaction size in KB to get the total fee.
|
|
128
|
+
|
|
129
|
+
## Examples
|
|
130
|
+
|
|
131
|
+
**Check a balance:**
|
|
132
|
+
```
|
|
133
|
+
Agent: get_balance for kaspa:qpauqsvk7yf9unexwmxsnmg547mhyga37csh0kj53q6xxgl24ydxjsgzthw5j
|
|
134
|
+
Agent: The balance is 100.00000000 KAS.
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**Look up a transaction:**
|
|
138
|
+
```
|
|
139
|
+
Agent: get_transaction for b2a4c3e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2
|
|
140
|
+
Agent: Transaction is confirmed with 500 KAS total.
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Estimate fees:**
|
|
144
|
+
```
|
|
145
|
+
Agent: What's the current fee estimate?
|
|
146
|
+
Agent: Current priority fee rate is 0.00000100 KAS/KB.
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Output characteristics
|
|
150
|
+
|
|
151
|
+
- All monetary values returned in **KAS** (not sompi), as strings with 8 decimal places
|
|
152
|
+
- Responses are **deterministic JSON** structures — easy for LLMs to parse
|
|
153
|
+
- Errors include descriptive messages
|
|
154
|
+
- No authentication or configuration required
|
|
155
|
+
|
|
156
|
+
## Development
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
# Build
|
|
160
|
+
npm run build
|
|
161
|
+
|
|
162
|
+
# Test against mainnet
|
|
163
|
+
node test_integration.mjs
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Publishing
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
npm login
|
|
170
|
+
npm publish
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Make sure you're logged into the npm registry first. The `prepublishOnly` script runs the TypeScript build automatically.
|
|
174
|
+
|
|
175
|
+
## License
|
|
176
|
+
|
|
177
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversion.d.ts","sourceRoot":"","sources":["../src/conversion.ts"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversion.js","sourceRoot":"","sources":["../src/conversion.ts"],"names":[],"mappings":"AAAA,MAAM,aAAa,GAAG,WAAW,CAAC;AAElC,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,CAAC,KAAK,GAAG,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,OAAO,KAAK,GAAG,aAAa,CAAC;AAC/B,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import z from "zod";
|
|
5
|
+
import { getBalance, getTransaction, getFeeEstimate, KaspaClientError, } from "./kaspa-client.js";
|
|
6
|
+
import { sompiToKas } from "./conversion.js";
|
|
7
|
+
const server = new McpServer({
|
|
8
|
+
name: "kaspa-simple-mcp",
|
|
9
|
+
version: "0.1.0",
|
|
10
|
+
});
|
|
11
|
+
server.tool("get_balance", {
|
|
12
|
+
address: z.string().describe("Kaspa mainnet address"),
|
|
13
|
+
}, async ({ address }) => {
|
|
14
|
+
try {
|
|
15
|
+
const data = await getBalance(address);
|
|
16
|
+
return {
|
|
17
|
+
content: [{ type: "text", text: JSON.stringify({ balance: sompiToKas(data.balance) }) }],
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
return formatError(err);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
server.tool("get_transaction", {
|
|
25
|
+
txId: z.string().describe("Kaspa transaction ID"),
|
|
26
|
+
}, async ({ txId }) => {
|
|
27
|
+
try {
|
|
28
|
+
const tx = await getTransaction(txId);
|
|
29
|
+
const totalSompi = tx.outputs.reduce((sum, o) => sum + o.amount, 0);
|
|
30
|
+
const outputs = tx.outputs.slice(0, 5).map((o) => ({
|
|
31
|
+
recipient: o.script_public_key_address,
|
|
32
|
+
amount: sompiToKas(o.amount),
|
|
33
|
+
}));
|
|
34
|
+
const result = {
|
|
35
|
+
status: tx.is_accepted ? "confirmed" : "pending",
|
|
36
|
+
timestamp: tx.block_time ?? null,
|
|
37
|
+
totalKas: sompiToKas(totalSompi),
|
|
38
|
+
outputs,
|
|
39
|
+
};
|
|
40
|
+
if (tx.outputs.length > 5) {
|
|
41
|
+
result.moreOutputs = tx.outputs.length - 5;
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
return formatError(err);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
server.tool("get_fee_estimate", {}, async () => {
|
|
52
|
+
try {
|
|
53
|
+
const data = await getFeeEstimate();
|
|
54
|
+
return {
|
|
55
|
+
content: [
|
|
56
|
+
{ type: "text", text: JSON.stringify({ feerate: sompiToKas(data.priorityBucket.feerate) }) },
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
return formatError(err);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
function formatError(err) {
|
|
65
|
+
const message = err instanceof KaspaClientError
|
|
66
|
+
? err.message
|
|
67
|
+
: err instanceof Error
|
|
68
|
+
? err.message
|
|
69
|
+
: "Unknown error";
|
|
70
|
+
return {
|
|
71
|
+
content: [{ type: "text", text: JSON.stringify({ error: message }) }],
|
|
72
|
+
isError: true,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
async function main() {
|
|
76
|
+
const transport = new StdioServerTransport();
|
|
77
|
+
await server.connect(transport);
|
|
78
|
+
}
|
|
79
|
+
main();
|
|
80
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface BalanceResponse {
|
|
2
|
+
balance: number;
|
|
3
|
+
}
|
|
4
|
+
export interface TransactionOutput {
|
|
5
|
+
amount: number;
|
|
6
|
+
script_public_key_address: string;
|
|
7
|
+
}
|
|
8
|
+
export interface TransactionResponse {
|
|
9
|
+
transaction_id: string;
|
|
10
|
+
is_accepted: boolean;
|
|
11
|
+
block_time?: number;
|
|
12
|
+
outputs: TransactionOutput[];
|
|
13
|
+
}
|
|
14
|
+
export interface FeeEstimateResponse {
|
|
15
|
+
priorityBucket: {
|
|
16
|
+
feerate: number;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export declare class KaspaClientError extends Error {
|
|
20
|
+
statusCode?: number | undefined;
|
|
21
|
+
constructor(message: string, statusCode?: number | undefined);
|
|
22
|
+
}
|
|
23
|
+
export declare function getBalance(address: string): Promise<BalanceResponse>;
|
|
24
|
+
export declare function getTransaction(txId: string): Promise<TransactionResponse>;
|
|
25
|
+
export declare function getFeeEstimate(): Promise<FeeEstimateResponse>;
|
|
26
|
+
//# sourceMappingURL=kaspa-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kaspa-client.d.ts","sourceRoot":"","sources":["../src/kaspa-client.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,yBAAyB,EAAE,MAAM,CAAC;CACnC;AAED,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE;QACd,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IAGhC,UAAU,CAAC,EAAE,MAAM;gBAD1B,OAAO,EAAE,MAAM,EACR,UAAU,CAAC,EAAE,MAAM,YAAA;CAK7B;AAgCD,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAE1E;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAI/E;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAEnE"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const BASE_URL = "https://api.kaspa.org";
|
|
2
|
+
const TIMEOUT_MS = 10_000;
|
|
3
|
+
export class KaspaClientError extends Error {
|
|
4
|
+
statusCode;
|
|
5
|
+
constructor(message, statusCode) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.statusCode = statusCode;
|
|
8
|
+
this.name = "KaspaClientError";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
async function fetchJson(path) {
|
|
12
|
+
const controller = new AbortController();
|
|
13
|
+
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
14
|
+
try {
|
|
15
|
+
const response = await fetch(`${BASE_URL}${path}`, {
|
|
16
|
+
signal: controller.signal,
|
|
17
|
+
});
|
|
18
|
+
if (!response.ok) {
|
|
19
|
+
throw new KaspaClientError(`Kaspa API error: ${response.status} ${response.statusText}`, response.status);
|
|
20
|
+
}
|
|
21
|
+
return (await response.json());
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
if (err instanceof KaspaClientError)
|
|
25
|
+
throw err;
|
|
26
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
27
|
+
throw new KaspaClientError("Kaspa API request timed out");
|
|
28
|
+
}
|
|
29
|
+
throw new KaspaClientError(err instanceof Error ? err.message : "Unknown network error");
|
|
30
|
+
}
|
|
31
|
+
finally {
|
|
32
|
+
clearTimeout(timer);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export async function getBalance(address) {
|
|
36
|
+
return fetchJson(`/addresses/${address}/balance`);
|
|
37
|
+
}
|
|
38
|
+
export async function getTransaction(txId) {
|
|
39
|
+
return fetchJson(`/transactions/${txId}?inputs=false&outputs=true`);
|
|
40
|
+
}
|
|
41
|
+
export async function getFeeEstimate() {
|
|
42
|
+
return fetchJson("/info/fee-estimate");
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=kaspa-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kaspa-client.js","sourceRoot":"","sources":["../src/kaspa-client.ts"],"names":[],"mappings":"AAAA,MAAM,QAAQ,GAAG,uBAAuB,CAAC;AACzC,MAAM,UAAU,GAAG,MAAM,CAAC;AAwB1B,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAGhC;IAFT,YACE,OAAe,EACR,UAAmB;QAE1B,KAAK,CAAC,OAAO,CAAC,CAAC;QAFR,eAAU,GAAV,UAAU,CAAS;QAG1B,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAED,KAAK,UAAU,SAAS,CAAI,IAAY;IACtC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,UAAU,CAAC,CAAC;IAE/D,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,QAAQ,GAAG,IAAI,EAAE,EAAE;YACjD,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,gBAAgB,CACxB,oBAAoB,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,EAC5D,QAAQ,CAAC,MAAM,CAChB,CAAC;QACJ,CAAC;QAED,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAM,CAAC;IACtC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,gBAAgB;YAAE,MAAM,GAAG,CAAC;QAC/C,IAAI,GAAG,YAAY,YAAY,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAC7D,MAAM,IAAI,gBAAgB,CAAC,6BAA6B,CAAC,CAAC;QAC5D,CAAC;QACD,MAAM,IAAI,gBAAgB,CACxB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAC7D,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAe;IAC9C,OAAO,SAAS,CAAkB,cAAc,OAAO,UAAU,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAY;IAC/C,OAAO,SAAS,CACd,iBAAiB,IAAI,4BAA4B,CAClD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,OAAO,SAAS,CAAsB,oBAAoB,CAAC,CAAC;AAC9D,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "kaspa-simple-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A read-only MCP server for Kaspa mainnet — balance lookup, transaction lookup, and fee estimates.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"kaspa-simple-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"start": "node dist/index.js",
|
|
16
|
+
"test": "node test_integration.mjs",
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
18
|
+
},
|
|
19
|
+
"keywords": ["kaspa", "mcp", "model-context-protocol", "crypto", "blockchain"],
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/danieliyahu1/kaspa-simple-mcp"
|
|
24
|
+
},
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/danieliyahu1/kaspa-simple-mcp/issues"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://github.com/danieliyahu1/kaspa-simple-mcp#readme",
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18.0.0"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
34
|
+
"zod": "^3.24.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^22.0.0",
|
|
38
|
+
"typescript": "^5.7.0"
|
|
39
|
+
}
|
|
40
|
+
}
|