@floatonnear/mcp 0.0.0-stage → 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/dist/amounts.d.ts +20 -0
- package/dist/amounts.js +55 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/payloads.d.ts +105 -0
- package/dist/payloads.js +292 -0
- package/dist/quote.d.ts +80 -0
- package/dist/quote.js +159 -0
- package/dist/rpc.d.ts +80 -0
- package/dist/rpc.js +134 -0
- package/dist/server.d.ts +21 -0
- package/dist/server.js +206 -0
- package/dist/sign.d.ts +69 -0
- package/dist/sign.js +72 -0
- package/package.json +42 -6
- package/README.md +0 -3
package/dist/sign.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ONLY place in this server that touches a key.
|
|
3
|
+
*
|
|
4
|
+
* It signs exactly one method — `request_payment` — with the restricted key
|
|
5
|
+
* issued by `create_agent_account`. That key is cryptographically incapable of
|
|
6
|
+
* doing anything else: its `receiver_id` is the vault, its `method_names` is
|
|
7
|
+
* `["request_payment"]`, and a NEAR function-call key cannot attach a deposit
|
|
8
|
+
* at all. So the worst a compromised copy of this server can do is make
|
|
9
|
+
* payments the vault's on-chain policy already permits.
|
|
10
|
+
*
|
|
11
|
+
* Owner methods are deliberately NOT here. They are emitted as unsigned
|
|
12
|
+
* payloads (see payloads.ts) for the human to approve in their own wallet,
|
|
13
|
+
* which keeps this server out of the trust path for anything that changes
|
|
14
|
+
* policy — the property that distinguishes the design from a custodial agent
|
|
15
|
+
* wallet.
|
|
16
|
+
*/
|
|
17
|
+
import { Account, JsonRpcProvider, KeyPair, KeyPairSigner } from "near-api-js";
|
|
18
|
+
/** Must match AGENT_ALLOWED_METHOD in the contract; pinned by constants.test.ts. */
|
|
19
|
+
const ALLOWED_METHOD = "request_payment";
|
|
20
|
+
export function buildRoute(rail, intents) {
|
|
21
|
+
if (rail === "near")
|
|
22
|
+
return "near_direct";
|
|
23
|
+
if (!intents) {
|
|
24
|
+
throw new Error("rail 'intents' requires depositAddress, quoteDeadlineNs and signature");
|
|
25
|
+
}
|
|
26
|
+
if (!/^[0-9]+$/.test(intents.quoteDeadlineNs)) {
|
|
27
|
+
// U64 crosses the ABI as a decimal string; a JSON number loses precision
|
|
28
|
+
// above 2^53 and a nanosecond deadline is far past that.
|
|
29
|
+
throw new Error(`quoteDeadlineNs must be a decimal string, got ${intents.quoteDeadlineNs}`);
|
|
30
|
+
}
|
|
31
|
+
if (!intents.depositAddress) {
|
|
32
|
+
// An empty deposit address is what a DRY quote returns. Sending one would
|
|
33
|
+
// transfer real funds to "", which the token contract rejects only after
|
|
34
|
+
// the vault has already reserved the budget.
|
|
35
|
+
throw new Error("depositAddress is empty — a dry quote cannot be paid");
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
intents: {
|
|
39
|
+
deposit_address: intents.depositAddress,
|
|
40
|
+
quote_deadline_ns: intents.quoteDeadlineNs,
|
|
41
|
+
signature: intents.signature,
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export async function sendRequestPayment(a) {
|
|
46
|
+
const provider = new JsonRpcProvider({ url: a.rpcUrl });
|
|
47
|
+
const signer = new KeyPairSigner(KeyPair.fromString(a.agentKey));
|
|
48
|
+
const account = new Account(a.agentId, provider, signer);
|
|
49
|
+
return account.callFunction({
|
|
50
|
+
contractId: a.vault,
|
|
51
|
+
methodName: ALLOWED_METHOD,
|
|
52
|
+
args: {
|
|
53
|
+
request_id: a.requestId,
|
|
54
|
+
token: a.token,
|
|
55
|
+
// U128 crosses the ABI as a decimal string; a JSON number would lose
|
|
56
|
+
// precision above 2^53.
|
|
57
|
+
amount: a.amount.toString(),
|
|
58
|
+
recipient: a.recipient,
|
|
59
|
+
memo: a.memo,
|
|
60
|
+
// Omitted entirely when undefined: the contract takes `Option<Route>`
|
|
61
|
+
// and a missing field deserialises to None, which is the NEAR rail.
|
|
62
|
+
...(a.route === undefined ? {} : { route: a.route }),
|
|
63
|
+
},
|
|
64
|
+
gas: BigInt(a.gasTgas) * 10n ** 12n,
|
|
65
|
+
// Hardcoded zero, and not a parameter. A function-call key that attaches
|
|
66
|
+
// any deposit is rejected by the protocol with
|
|
67
|
+
// InvalidAccessKeyError(DepositWithFunctionCall) — so a non-zero value
|
|
68
|
+
// here would not be a security hole, it would simply make every payment
|
|
69
|
+
// fail. Keeping it a constant means that cannot be introduced by a caller.
|
|
70
|
+
deposit: 0n,
|
|
71
|
+
});
|
|
72
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,42 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@floatonnear/mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"description": "
|
|
6
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@floatonnear/mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "MCP server for the hierarchical budget vault. The agent key signs request_payment only; owner methods emit unsigned payloads for wallet approval.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"bin": {
|
|
8
|
+
"mcp": "dist/server.js",
|
|
9
|
+
"float-mcp": "dist/server.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist/"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc -p tsconfig.json",
|
|
16
|
+
"prepack": "npm run build",
|
|
17
|
+
"test": "vitest run",
|
|
18
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@modelcontextprotocol/sdk": "^1.32.2",
|
|
22
|
+
"@noble/curves": "^1.9.7",
|
|
23
|
+
"@noble/hashes": "^1.8.0",
|
|
24
|
+
"near-api-js": "^7.4.0",
|
|
25
|
+
"zod": "^4.6.7"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^24.0.0",
|
|
29
|
+
"typescript": "^5.9.0",
|
|
30
|
+
"vitest": "^5.0.5"
|
|
31
|
+
},
|
|
32
|
+
"exports": {
|
|
33
|
+
".": "./dist/index.js",
|
|
34
|
+
"./amounts": "./dist/amounts.js",
|
|
35
|
+
"./sign": "./dist/sign.js",
|
|
36
|
+
"./payloads": "./dist/payloads.js",
|
|
37
|
+
"./quote": {
|
|
38
|
+
"types": "./dist/quote.d.ts",
|
|
39
|
+
"import": "./dist/quote.js"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
package/README.md
DELETED