@keyban/agent-wallet-mcp 0.2.1 → 0.2.2
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 +34 -3
- package/dist/index.mjs +224 -145
- package/dist/index.mjs.map +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,8 +11,29 @@ of a FROST threshold key in your OS keyring; Keyban holds the other. No single
|
|
|
11
11
|
side can move funds alone, and the model never sees either share or your API
|
|
12
12
|
key.
|
|
13
13
|
|
|
14
|
+
## You need a Keyban wallet first
|
|
15
|
+
|
|
16
|
+
**This server drives a wallet Keyban provisions. It does not create one, and it
|
|
17
|
+
has nothing to drive without one** — installing the package on its own gets you
|
|
18
|
+
a server offering a single `setup_instructions` tool, which points back here. The
|
|
19
|
+
threshold key is the reason: one share lives here, the other lives with us, so
|
|
20
|
+
there is a Keyban side to every wallet by construction and no configuration can
|
|
21
|
+
replace it.
|
|
22
|
+
|
|
23
|
+
So the order is:
|
|
24
|
+
|
|
25
|
+
1. **Get a Keyban account** at <https://keyban.io>.
|
|
26
|
+
2. **Create an agent wallet** in the admin app. It provisions the wallet, its
|
|
27
|
+
API key, and a one-shot invite key that authorises this client as a signer.
|
|
28
|
+
3. **Take the configuration it hands you** — either the environment block for
|
|
29
|
+
the table below, or a ready-to-install `.mcpb` bundle with the values already
|
|
30
|
+
in it.
|
|
31
|
+
4. **Then** install, with those values in the environment.
|
|
32
|
+
|
|
14
33
|
## Install
|
|
15
34
|
|
|
35
|
+
Once you have the credentials from step 3:
|
|
36
|
+
|
|
16
37
|
```bash
|
|
17
38
|
npx -y @keyban/agent-wallet-mcp
|
|
18
39
|
```
|
|
@@ -20,14 +41,24 @@ npx -y @keyban/agent-wallet-mcp
|
|
|
20
41
|
With Claude Code:
|
|
21
42
|
|
|
22
43
|
```bash
|
|
23
|
-
claude mcp add agent-wallet
|
|
44
|
+
claude mcp add agent-wallet \
|
|
45
|
+
-e KEYBAN_API_KEY=… \
|
|
46
|
+
-e KEYBAN_APP_ID=… \
|
|
47
|
+
-e KEYBAN_INVITE_KEY=0x… \
|
|
48
|
+
-e KEYBAN_WALLET_ADDRESS=0x… \
|
|
49
|
+
-e KEYBAN_NETWORK=… \
|
|
50
|
+
-- npx -y @keyban/agent-wallet-mcp
|
|
24
51
|
```
|
|
25
52
|
|
|
26
|
-
|
|
27
|
-
|
|
53
|
+
On first boot the server runs a key generation, keeps its share in your OS
|
|
54
|
+
keyring, and registers itself on chain as a signer of that wallet using the
|
|
55
|
+
invite key. That happens once per machine; the invite key is spent by it.
|
|
28
56
|
|
|
29
57
|
## Configuration
|
|
30
58
|
|
|
59
|
+
The five required values all come from step 2 — none of them is something you
|
|
60
|
+
can pick yourself.
|
|
61
|
+
|
|
31
62
|
| Variable | Required | What it is |
|
|
32
63
|
|---|---|---|
|
|
33
64
|
| `KEYBAN_API_KEY` | yes | API key of the application the wallet belongs to. Never exposed to the model. |
|
package/dist/index.mjs
CHANGED
|
@@ -79491,78 +79491,78 @@ ${errors.map((e) => ` - ${e.message}`).join("\n")}`;
|
|
|
79491
79491
|
return 0;
|
|
79492
79492
|
}
|
|
79493
79493
|
};
|
|
79494
|
-
var
|
|
79494
|
+
var import_zod17 = require_zod();
|
|
79495
79495
|
var import_zod22 = require_zod();
|
|
79496
|
-
var NonEmptyString2 =
|
|
79497
|
-
var Any2 =
|
|
79498
|
-
var OptionalAny2 =
|
|
79496
|
+
var NonEmptyString2 = import_zod17.z.string().min(1);
|
|
79497
|
+
var Any2 = import_zod17.z.record(import_zod17.z.unknown());
|
|
79498
|
+
var OptionalAny2 = import_zod17.z.record(import_zod17.z.unknown()).optional().nullable();
|
|
79499
79499
|
var NetworkSchemaV12 = NonEmptyString2;
|
|
79500
|
-
var NetworkSchemaV22 =
|
|
79500
|
+
var NetworkSchemaV22 = import_zod17.z.string().min(3).refine((val) => val.includes(":"), {
|
|
79501
79501
|
message: "Network must be in CAIP-2 format (e.g., 'eip155:84532')"
|
|
79502
79502
|
});
|
|
79503
|
-
var NetworkSchema2 =
|
|
79504
|
-
var ResourceInfoSchema2 =
|
|
79503
|
+
var NetworkSchema2 = import_zod17.z.union([NetworkSchemaV12, NetworkSchemaV22]);
|
|
79504
|
+
var ResourceInfoSchema2 = import_zod17.z.object({
|
|
79505
79505
|
url: NonEmptyString2,
|
|
79506
|
-
description:
|
|
79507
|
-
mimeType:
|
|
79506
|
+
description: import_zod17.z.string().optional(),
|
|
79507
|
+
mimeType: import_zod17.z.string().optional()
|
|
79508
79508
|
});
|
|
79509
|
-
var PaymentRequirementsV1Schema2 =
|
|
79509
|
+
var PaymentRequirementsV1Schema2 = import_zod17.z.object({
|
|
79510
79510
|
scheme: NonEmptyString2,
|
|
79511
79511
|
network: NetworkSchemaV12,
|
|
79512
79512
|
maxAmountRequired: NonEmptyString2,
|
|
79513
79513
|
resource: NonEmptyString2,
|
|
79514
79514
|
// URL string in V1
|
|
79515
|
-
description:
|
|
79516
|
-
mimeType:
|
|
79515
|
+
description: import_zod17.z.string(),
|
|
79516
|
+
mimeType: import_zod17.z.string().optional(),
|
|
79517
79517
|
outputSchema: Any2.optional().nullable(),
|
|
79518
79518
|
payTo: NonEmptyString2,
|
|
79519
|
-
maxTimeoutSeconds:
|
|
79519
|
+
maxTimeoutSeconds: import_zod17.z.number().positive(),
|
|
79520
79520
|
asset: NonEmptyString2,
|
|
79521
79521
|
extra: OptionalAny2
|
|
79522
79522
|
});
|
|
79523
|
-
var PaymentRequiredV1Schema2 =
|
|
79524
|
-
x402Version:
|
|
79525
|
-
error:
|
|
79526
|
-
accepts:
|
|
79523
|
+
var PaymentRequiredV1Schema2 = import_zod17.z.object({
|
|
79524
|
+
x402Version: import_zod17.z.literal(1),
|
|
79525
|
+
error: import_zod17.z.string().optional(),
|
|
79526
|
+
accepts: import_zod17.z.array(PaymentRequirementsV1Schema2).min(1)
|
|
79527
79527
|
});
|
|
79528
|
-
var PaymentPayloadV1Schema2 =
|
|
79529
|
-
x402Version:
|
|
79528
|
+
var PaymentPayloadV1Schema2 = import_zod17.z.object({
|
|
79529
|
+
x402Version: import_zod17.z.literal(1),
|
|
79530
79530
|
scheme: NonEmptyString2,
|
|
79531
79531
|
network: NetworkSchemaV12,
|
|
79532
79532
|
payload: Any2
|
|
79533
79533
|
});
|
|
79534
|
-
var PaymentRequirementsV2Schema2 =
|
|
79534
|
+
var PaymentRequirementsV2Schema2 = import_zod17.z.object({
|
|
79535
79535
|
scheme: NonEmptyString2,
|
|
79536
79536
|
network: NetworkSchemaV22,
|
|
79537
79537
|
amount: NonEmptyString2,
|
|
79538
79538
|
asset: NonEmptyString2,
|
|
79539
79539
|
payTo: NonEmptyString2,
|
|
79540
|
-
maxTimeoutSeconds:
|
|
79540
|
+
maxTimeoutSeconds: import_zod17.z.number().positive(),
|
|
79541
79541
|
extra: OptionalAny2
|
|
79542
79542
|
});
|
|
79543
|
-
var PaymentRequiredV2Schema2 =
|
|
79544
|
-
x402Version:
|
|
79545
|
-
error:
|
|
79543
|
+
var PaymentRequiredV2Schema2 = import_zod17.z.object({
|
|
79544
|
+
x402Version: import_zod17.z.literal(2),
|
|
79545
|
+
error: import_zod17.z.string().optional(),
|
|
79546
79546
|
resource: ResourceInfoSchema2,
|
|
79547
|
-
accepts:
|
|
79547
|
+
accepts: import_zod17.z.array(PaymentRequirementsV2Schema2).min(1),
|
|
79548
79548
|
extensions: OptionalAny2
|
|
79549
79549
|
});
|
|
79550
|
-
var PaymentPayloadV2Schema2 =
|
|
79551
|
-
x402Version:
|
|
79550
|
+
var PaymentPayloadV2Schema2 = import_zod17.z.object({
|
|
79551
|
+
x402Version: import_zod17.z.literal(2),
|
|
79552
79552
|
resource: ResourceInfoSchema2.optional(),
|
|
79553
79553
|
accepted: PaymentRequirementsV2Schema2,
|
|
79554
79554
|
payload: Any2,
|
|
79555
79555
|
extensions: OptionalAny2
|
|
79556
79556
|
});
|
|
79557
|
-
var PaymentRequirementsSchema2 =
|
|
79557
|
+
var PaymentRequirementsSchema2 = import_zod17.z.union([
|
|
79558
79558
|
PaymentRequirementsV1Schema2,
|
|
79559
79559
|
PaymentRequirementsV2Schema2
|
|
79560
79560
|
]);
|
|
79561
|
-
var PaymentRequiredSchema2 =
|
|
79561
|
+
var PaymentRequiredSchema2 = import_zod17.z.discriminatedUnion("x402Version", [
|
|
79562
79562
|
PaymentRequiredV1Schema2,
|
|
79563
79563
|
PaymentRequiredV2Schema2
|
|
79564
79564
|
]);
|
|
79565
|
-
var PaymentPayloadSchema2 =
|
|
79565
|
+
var PaymentPayloadSchema2 = import_zod17.z.discriminatedUnion("x402Version", [
|
|
79566
79566
|
PaymentPayloadV1Schema2,
|
|
79567
79567
|
PaymentPayloadV2Schema2
|
|
79568
79568
|
]);
|
|
@@ -79977,78 +79977,78 @@ var require_schemas = __commonJS({
|
|
|
79977
79977
|
z: () => import_zod22.z
|
|
79978
79978
|
});
|
|
79979
79979
|
module.exports = __toCommonJS2(schemas_exports2);
|
|
79980
|
-
var
|
|
79980
|
+
var import_zod17 = require_zod();
|
|
79981
79981
|
var import_zod22 = require_zod();
|
|
79982
|
-
var NonEmptyString2 =
|
|
79983
|
-
var Any2 =
|
|
79984
|
-
var OptionalAny2 =
|
|
79982
|
+
var NonEmptyString2 = import_zod17.z.string().min(1);
|
|
79983
|
+
var Any2 = import_zod17.z.record(import_zod17.z.unknown());
|
|
79984
|
+
var OptionalAny2 = import_zod17.z.record(import_zod17.z.unknown()).optional().nullable();
|
|
79985
79985
|
var NetworkSchemaV12 = NonEmptyString2;
|
|
79986
|
-
var NetworkSchemaV22 =
|
|
79986
|
+
var NetworkSchemaV22 = import_zod17.z.string().min(3).refine((val) => val.includes(":"), {
|
|
79987
79987
|
message: "Network must be in CAIP-2 format (e.g., 'eip155:84532')"
|
|
79988
79988
|
});
|
|
79989
|
-
var NetworkSchema2 =
|
|
79990
|
-
var ResourceInfoSchema2 =
|
|
79989
|
+
var NetworkSchema2 = import_zod17.z.union([NetworkSchemaV12, NetworkSchemaV22]);
|
|
79990
|
+
var ResourceInfoSchema2 = import_zod17.z.object({
|
|
79991
79991
|
url: NonEmptyString2,
|
|
79992
|
-
description:
|
|
79993
|
-
mimeType:
|
|
79992
|
+
description: import_zod17.z.string().optional(),
|
|
79993
|
+
mimeType: import_zod17.z.string().optional()
|
|
79994
79994
|
});
|
|
79995
|
-
var PaymentRequirementsV1Schema2 =
|
|
79995
|
+
var PaymentRequirementsV1Schema2 = import_zod17.z.object({
|
|
79996
79996
|
scheme: NonEmptyString2,
|
|
79997
79997
|
network: NetworkSchemaV12,
|
|
79998
79998
|
maxAmountRequired: NonEmptyString2,
|
|
79999
79999
|
resource: NonEmptyString2,
|
|
80000
80000
|
// URL string in V1
|
|
80001
|
-
description:
|
|
80002
|
-
mimeType:
|
|
80001
|
+
description: import_zod17.z.string(),
|
|
80002
|
+
mimeType: import_zod17.z.string().optional(),
|
|
80003
80003
|
outputSchema: Any2.optional().nullable(),
|
|
80004
80004
|
payTo: NonEmptyString2,
|
|
80005
|
-
maxTimeoutSeconds:
|
|
80005
|
+
maxTimeoutSeconds: import_zod17.z.number().positive(),
|
|
80006
80006
|
asset: NonEmptyString2,
|
|
80007
80007
|
extra: OptionalAny2
|
|
80008
80008
|
});
|
|
80009
|
-
var PaymentRequiredV1Schema2 =
|
|
80010
|
-
x402Version:
|
|
80011
|
-
error:
|
|
80012
|
-
accepts:
|
|
80009
|
+
var PaymentRequiredV1Schema2 = import_zod17.z.object({
|
|
80010
|
+
x402Version: import_zod17.z.literal(1),
|
|
80011
|
+
error: import_zod17.z.string().optional(),
|
|
80012
|
+
accepts: import_zod17.z.array(PaymentRequirementsV1Schema2).min(1)
|
|
80013
80013
|
});
|
|
80014
|
-
var PaymentPayloadV1Schema2 =
|
|
80015
|
-
x402Version:
|
|
80014
|
+
var PaymentPayloadV1Schema2 = import_zod17.z.object({
|
|
80015
|
+
x402Version: import_zod17.z.literal(1),
|
|
80016
80016
|
scheme: NonEmptyString2,
|
|
80017
80017
|
network: NetworkSchemaV12,
|
|
80018
80018
|
payload: Any2
|
|
80019
80019
|
});
|
|
80020
|
-
var PaymentRequirementsV2Schema2 =
|
|
80020
|
+
var PaymentRequirementsV2Schema2 = import_zod17.z.object({
|
|
80021
80021
|
scheme: NonEmptyString2,
|
|
80022
80022
|
network: NetworkSchemaV22,
|
|
80023
80023
|
amount: NonEmptyString2,
|
|
80024
80024
|
asset: NonEmptyString2,
|
|
80025
80025
|
payTo: NonEmptyString2,
|
|
80026
|
-
maxTimeoutSeconds:
|
|
80026
|
+
maxTimeoutSeconds: import_zod17.z.number().positive(),
|
|
80027
80027
|
extra: OptionalAny2
|
|
80028
80028
|
});
|
|
80029
|
-
var PaymentRequiredV2Schema2 =
|
|
80030
|
-
x402Version:
|
|
80031
|
-
error:
|
|
80029
|
+
var PaymentRequiredV2Schema2 = import_zod17.z.object({
|
|
80030
|
+
x402Version: import_zod17.z.literal(2),
|
|
80031
|
+
error: import_zod17.z.string().optional(),
|
|
80032
80032
|
resource: ResourceInfoSchema2,
|
|
80033
|
-
accepts:
|
|
80033
|
+
accepts: import_zod17.z.array(PaymentRequirementsV2Schema2).min(1),
|
|
80034
80034
|
extensions: OptionalAny2
|
|
80035
80035
|
});
|
|
80036
|
-
var PaymentPayloadV2Schema2 =
|
|
80037
|
-
x402Version:
|
|
80036
|
+
var PaymentPayloadV2Schema2 = import_zod17.z.object({
|
|
80037
|
+
x402Version: import_zod17.z.literal(2),
|
|
80038
80038
|
resource: ResourceInfoSchema2.optional(),
|
|
80039
80039
|
accepted: PaymentRequirementsV2Schema2,
|
|
80040
80040
|
payload: Any2,
|
|
80041
80041
|
extensions: OptionalAny2
|
|
80042
80042
|
});
|
|
80043
|
-
var PaymentRequirementsSchema2 =
|
|
80043
|
+
var PaymentRequirementsSchema2 = import_zod17.z.union([
|
|
80044
80044
|
PaymentRequirementsV1Schema2,
|
|
80045
80045
|
PaymentRequirementsV2Schema2
|
|
80046
80046
|
]);
|
|
80047
|
-
var PaymentRequiredSchema2 =
|
|
80047
|
+
var PaymentRequiredSchema2 = import_zod17.z.discriminatedUnion("x402Version", [
|
|
80048
80048
|
PaymentRequiredV1Schema2,
|
|
80049
80049
|
PaymentRequiredV2Schema2
|
|
80050
80050
|
]);
|
|
80051
|
-
var PaymentPayloadSchema2 =
|
|
80051
|
+
var PaymentPayloadSchema2 = import_zod17.z.discriminatedUnion("x402Version", [
|
|
80052
80052
|
PaymentPayloadV1Schema2,
|
|
80053
80053
|
PaymentPayloadV2Schema2
|
|
80054
80054
|
]);
|
|
@@ -111151,6 +111151,145 @@ function resolveURL(value) {
|
|
|
111151
111151
|
return ENV_URLS[value] ?? value;
|
|
111152
111152
|
}
|
|
111153
111153
|
|
|
111154
|
+
// src/lib/session.ts
|
|
111155
|
+
var VALID_NETWORKS = [
|
|
111156
|
+
"EthereumAnvil",
|
|
111157
|
+
"BaseSepolia",
|
|
111158
|
+
"BaseMainnet",
|
|
111159
|
+
"XdcApothem",
|
|
111160
|
+
"XdcMainnet",
|
|
111161
|
+
"StellarQuickstart",
|
|
111162
|
+
"StellarTestnet",
|
|
111163
|
+
"StellarMainnet"
|
|
111164
|
+
];
|
|
111165
|
+
function createSession() {
|
|
111166
|
+
return {
|
|
111167
|
+
baseURL: ENV_URLS.prod,
|
|
111168
|
+
apiKey: "",
|
|
111169
|
+
appId: "",
|
|
111170
|
+
network: "",
|
|
111171
|
+
inviteKey: "",
|
|
111172
|
+
walletAddress: "",
|
|
111173
|
+
seededDkgBlob: null,
|
|
111174
|
+
nodeApi: null,
|
|
111175
|
+
signer: null,
|
|
111176
|
+
account: null,
|
|
111177
|
+
frostVerifierAddress: null,
|
|
111178
|
+
initPromise: null,
|
|
111179
|
+
pendingX402: /* @__PURE__ */ new Map()
|
|
111180
|
+
};
|
|
111181
|
+
}
|
|
111182
|
+
function validateNetwork(network) {
|
|
111183
|
+
if (!network || !VALID_NETWORKS.includes(network)) {
|
|
111184
|
+
throw new Error(`Invalid or missing network "${network}". Must be one of: ${VALID_NETWORKS.join(", ")}. Set it via the KEYBAN_NETWORK env var.`);
|
|
111185
|
+
}
|
|
111186
|
+
}
|
|
111187
|
+
function requireCredentials(session) {
|
|
111188
|
+
if (!session.apiKey) {
|
|
111189
|
+
throw new Error("No API key configured. Set the KEYBAN_API_KEY environment variable.");
|
|
111190
|
+
}
|
|
111191
|
+
if (!session.appId) {
|
|
111192
|
+
throw new Error("No application ID configured. Set the KEYBAN_APP_ID environment variable.");
|
|
111193
|
+
}
|
|
111194
|
+
if (!session.inviteKey) {
|
|
111195
|
+
throw new Error(
|
|
111196
|
+
"No invite key configured. Set the KEYBAN_INVITE_KEY environment variable (admin-provisioned wallets only)."
|
|
111197
|
+
);
|
|
111198
|
+
}
|
|
111199
|
+
if (!session.walletAddress) {
|
|
111200
|
+
throw new Error(
|
|
111201
|
+
"No wallet address configured. Set the KEYBAN_WALLET_ADDRESS environment variable (admin-provisioned wallets only)."
|
|
111202
|
+
);
|
|
111203
|
+
}
|
|
111204
|
+
}
|
|
111205
|
+
function requireAccount(session) {
|
|
111206
|
+
requireCredentials(session);
|
|
111207
|
+
if (!session.account || !session.signer || !session.nodeApi || !session.frostVerifierAddress) {
|
|
111208
|
+
throw new Error("Account not initialized. Call the initialize tool first.");
|
|
111209
|
+
}
|
|
111210
|
+
}
|
|
111211
|
+
function buildApiKeyHeaders(session) {
|
|
111212
|
+
return {
|
|
111213
|
+
"X-Api-Key": session.apiKey
|
|
111214
|
+
};
|
|
111215
|
+
}
|
|
111216
|
+
|
|
111217
|
+
// src/lib/configuration.ts
|
|
111218
|
+
var HEX_64 = /^0x[a-fA-F0-9]{64}$/;
|
|
111219
|
+
var HEX_40 = /^0x[a-fA-F0-9]{40}$/;
|
|
111220
|
+
var REQUIRED_VARIABLES = [
|
|
111221
|
+
{
|
|
111222
|
+
name: "KEYBAN_API_KEY",
|
|
111223
|
+
what: "API key of the application the wallet belongs to"
|
|
111224
|
+
},
|
|
111225
|
+
{
|
|
111226
|
+
name: "KEYBAN_APP_ID",
|
|
111227
|
+
what: "identifier of the Keyban application"
|
|
111228
|
+
},
|
|
111229
|
+
{
|
|
111230
|
+
name: "KEYBAN_WALLET_ADDRESS",
|
|
111231
|
+
what: "address of the account this server drives",
|
|
111232
|
+
reject: (value) => HEX_40.test(value) ? null : "must be 0x followed by 40 hex characters"
|
|
111233
|
+
},
|
|
111234
|
+
{
|
|
111235
|
+
name: "KEYBAN_INVITE_KEY",
|
|
111236
|
+
what: "one-shot key authorizing this client as a signer, on first boot",
|
|
111237
|
+
reject: (value) => HEX_64.test(value) ? null : "must be 0x followed by 64 hex characters"
|
|
111238
|
+
},
|
|
111239
|
+
{
|
|
111240
|
+
name: "KEYBAN_NETWORK",
|
|
111241
|
+
what: "network the wallet operates on",
|
|
111242
|
+
reject: (value) => VALID_NETWORKS.includes(value) ? null : `must be one of: ${VALID_NETWORKS.join(", ")}`
|
|
111243
|
+
}
|
|
111244
|
+
];
|
|
111245
|
+
function findConfigurationProblems(env = process.env) {
|
|
111246
|
+
const problems = [];
|
|
111247
|
+
for (const { name, what, reject } of REQUIRED_VARIABLES) {
|
|
111248
|
+
const value = env[name];
|
|
111249
|
+
if (!value) {
|
|
111250
|
+
problems.push({ name, what, reason: "missing" });
|
|
111251
|
+
continue;
|
|
111252
|
+
}
|
|
111253
|
+
const rejected = reject?.(value);
|
|
111254
|
+
if (rejected) problems.push({ name, what, reason: rejected });
|
|
111255
|
+
}
|
|
111256
|
+
return problems;
|
|
111257
|
+
}
|
|
111258
|
+
var WIZARD_URL = "https://keyban.io";
|
|
111259
|
+
var README_URL = "https://www.npmjs.com/package/@keyban/agent-wallet-mcp";
|
|
111260
|
+
function describeConfigurationProblems(problems) {
|
|
111261
|
+
const list = problems.map(
|
|
111262
|
+
({ name, what, reason }) => reason === "missing" ? `- ${name} \u2014 not set. It is the ${what}.` : `- ${name} \u2014 set, but ${reason}. It is the ${what}.`
|
|
111263
|
+
).join("\n");
|
|
111264
|
+
return [
|
|
111265
|
+
"This server drives a blockchain wallet that Keyban provisions. It cannot create",
|
|
111266
|
+
"one, and it will not work until it is given the credentials of an existing one.",
|
|
111267
|
+
"",
|
|
111268
|
+
"What is wrong right now:",
|
|
111269
|
+
"",
|
|
111270
|
+
list,
|
|
111271
|
+
"",
|
|
111272
|
+
"These are not values to invent: the wallet is held by a threshold key whose other",
|
|
111273
|
+
"share stays with Keyban, so every wallet has a Keyban side and no local",
|
|
111274
|
+
"configuration can stand in for it.",
|
|
111275
|
+
"",
|
|
111276
|
+
"How to get them:",
|
|
111277
|
+
"",
|
|
111278
|
+
`1. Create a Keyban account at ${WIZARD_URL}`,
|
|
111279
|
+
"2. Create an agent wallet in the admin app. It provisions the wallet, its API",
|
|
111280
|
+
" key, and a one-shot invite key that authorizes this client as a signer.",
|
|
111281
|
+
"3. Copy the configuration it hands you \u2014 either the environment block, or a",
|
|
111282
|
+
" ready-to-install .mcpb bundle with the values already in it.",
|
|
111283
|
+
"4. Restart this server with those values in its environment.",
|
|
111284
|
+
"",
|
|
111285
|
+
`The README covers the same ground: ${README_URL}`
|
|
111286
|
+
].join("\n");
|
|
111287
|
+
}
|
|
111288
|
+
function summarizeConfigurationProblems(problems) {
|
|
111289
|
+
const names = problems.map((p) => p.name).join(", ");
|
|
111290
|
+
return `Keyban agent wallet MCP server \u2014 NOT USABLE YET. It drives a wallet that Keyban provisions, and its configuration is incomplete: ${names}. None of the wallet tools are available until that is fixed. Tell the user to create an agent wallet at ${WIZARD_URL}, and call setup_instructions for the steps.`;
|
|
111291
|
+
}
|
|
111292
|
+
|
|
111154
111293
|
// src/lib/logger.ts
|
|
111155
111294
|
import { appendFileSync } from "node:fs";
|
|
111156
111295
|
var LOG_LEVELS = {
|
|
@@ -111227,69 +111366,6 @@ function createLogger(context, minLevel) {
|
|
|
111227
111366
|
}
|
|
111228
111367
|
var logger = createLogger("agent-wallet-mcp");
|
|
111229
111368
|
|
|
111230
|
-
// src/lib/session.ts
|
|
111231
|
-
var VALID_NETWORKS = [
|
|
111232
|
-
"EthereumAnvil",
|
|
111233
|
-
"BaseSepolia",
|
|
111234
|
-
"BaseMainnet",
|
|
111235
|
-
"XdcApothem",
|
|
111236
|
-
"XdcMainnet",
|
|
111237
|
-
"StellarQuickstart",
|
|
111238
|
-
"StellarTestnet",
|
|
111239
|
-
"StellarMainnet"
|
|
111240
|
-
];
|
|
111241
|
-
function createSession() {
|
|
111242
|
-
return {
|
|
111243
|
-
baseURL: ENV_URLS.prod,
|
|
111244
|
-
apiKey: "",
|
|
111245
|
-
appId: "",
|
|
111246
|
-
network: "",
|
|
111247
|
-
inviteKey: "",
|
|
111248
|
-
walletAddress: "",
|
|
111249
|
-
seededDkgBlob: null,
|
|
111250
|
-
nodeApi: null,
|
|
111251
|
-
signer: null,
|
|
111252
|
-
account: null,
|
|
111253
|
-
frostVerifierAddress: null,
|
|
111254
|
-
initPromise: null,
|
|
111255
|
-
pendingX402: /* @__PURE__ */ new Map()
|
|
111256
|
-
};
|
|
111257
|
-
}
|
|
111258
|
-
function validateNetwork(network) {
|
|
111259
|
-
if (!network || !VALID_NETWORKS.includes(network)) {
|
|
111260
|
-
throw new Error(`Invalid or missing network "${network}". Must be one of: ${VALID_NETWORKS.join(", ")}. Set it via the KEYBAN_NETWORK env var.`);
|
|
111261
|
-
}
|
|
111262
|
-
}
|
|
111263
|
-
function requireCredentials(session) {
|
|
111264
|
-
if (!session.apiKey) {
|
|
111265
|
-
throw new Error("No API key configured. Set the KEYBAN_API_KEY environment variable.");
|
|
111266
|
-
}
|
|
111267
|
-
if (!session.appId) {
|
|
111268
|
-
throw new Error("No application ID configured. Set the KEYBAN_APP_ID environment variable.");
|
|
111269
|
-
}
|
|
111270
|
-
if (!session.inviteKey) {
|
|
111271
|
-
throw new Error(
|
|
111272
|
-
"No invite key configured. Set the KEYBAN_INVITE_KEY environment variable (admin-provisioned wallets only)."
|
|
111273
|
-
);
|
|
111274
|
-
}
|
|
111275
|
-
if (!session.walletAddress) {
|
|
111276
|
-
throw new Error(
|
|
111277
|
-
"No wallet address configured. Set the KEYBAN_WALLET_ADDRESS environment variable (admin-provisioned wallets only)."
|
|
111278
|
-
);
|
|
111279
|
-
}
|
|
111280
|
-
}
|
|
111281
|
-
function requireAccount(session) {
|
|
111282
|
-
requireCredentials(session);
|
|
111283
|
-
if (!session.account || !session.signer || !session.nodeApi || !session.frostVerifierAddress) {
|
|
111284
|
-
throw new Error("Account not initialized. Call the initialize tool first.");
|
|
111285
|
-
}
|
|
111286
|
-
}
|
|
111287
|
-
function buildApiKeyHeaders(session) {
|
|
111288
|
-
return {
|
|
111289
|
-
"X-Api-Key": session.apiKey
|
|
111290
|
-
};
|
|
111291
|
-
}
|
|
111292
|
-
|
|
111293
111369
|
// src/lib/tool-registry.ts
|
|
111294
111370
|
function registerTool(server, tool) {
|
|
111295
111371
|
server.registerTool(
|
|
@@ -124422,6 +124498,20 @@ function createListExpenseTransactionsTool(session) {
|
|
|
124422
124498
|
};
|
|
124423
124499
|
}
|
|
124424
124500
|
|
|
124501
|
+
// src/tools/setup-instructions.ts
|
|
124502
|
+
var setupInstructionsSchema = external_exports.object({});
|
|
124503
|
+
function createSetupInstructionsTool(problems) {
|
|
124504
|
+
const names = problems.map((p) => p.name).join(", ");
|
|
124505
|
+
return {
|
|
124506
|
+
name: "setup_instructions",
|
|
124507
|
+
title: "How to finish setting up this wallet",
|
|
124508
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
124509
|
+
description: `This Keyban agent wallet has no wallet to drive yet, so none of its usual tools are available. Incomplete configuration: ${names}. Call this tool for the steps to obtain those values from keyban.io.`,
|
|
124510
|
+
inputSchema: setupInstructionsSchema,
|
|
124511
|
+
handler: async (_input) => describeConfigurationProblems(problems)
|
|
124512
|
+
};
|
|
124513
|
+
}
|
|
124514
|
+
|
|
124425
124515
|
// src/index.ts
|
|
124426
124516
|
var SERVER_NAME = "agent-wallet-mcp";
|
|
124427
124517
|
var SERVER_VERSION = "0.0.0";
|
|
@@ -124436,27 +124526,16 @@ async function main() {
|
|
|
124436
124526
|
if (process.env.KEYBAN_NETWORK) session.network = process.env.KEYBAN_NETWORK;
|
|
124437
124527
|
logger.info("API key configured from environment");
|
|
124438
124528
|
}
|
|
124439
|
-
const
|
|
124440
|
-
const
|
|
124441
|
-
if (
|
|
124442
|
-
|
|
124443
|
-
|
|
124444
|
-
|
|
124445
|
-
|
|
124446
|
-
|
|
124447
|
-
|
|
124448
|
-
"KEYBAN_WALLET_ADDRESS is required (deployed SchnorrAccount address, 0x + 40 hex)."
|
|
124449
|
-
);
|
|
124450
|
-
}
|
|
124451
|
-
if (!/^0x[a-fA-F0-9]{64}$/.test(envInviteKey)) {
|
|
124452
|
-
throw new Error("KEYBAN_INVITE_KEY must be 0x followed by 64 hex characters.");
|
|
124453
|
-
}
|
|
124454
|
-
if (!/^0x[a-fA-F0-9]{40}$/.test(envWalletAddress)) {
|
|
124455
|
-
throw new Error("KEYBAN_WALLET_ADDRESS must be 0x followed by 40 hex characters.");
|
|
124529
|
+
const configurationProblems = findConfigurationProblems();
|
|
124530
|
+
const unconfigured = configurationProblems.length > 0;
|
|
124531
|
+
if (unconfigured) {
|
|
124532
|
+
const summary = configurationProblems.map((p) => `${p.name} (${p.reason})`).join(", ");
|
|
124533
|
+
logger.warn(`Incomplete configuration: ${summary}`);
|
|
124534
|
+
} else {
|
|
124535
|
+
session.inviteKey = process.env.KEYBAN_INVITE_KEY ?? "";
|
|
124536
|
+
session.walletAddress = process.env.KEYBAN_WALLET_ADDRESS ?? "";
|
|
124537
|
+
logger.info("Agent-wallet credentials configured");
|
|
124456
124538
|
}
|
|
124457
|
-
session.inviteKey = envInviteKey;
|
|
124458
|
-
session.walletAddress = envWalletAddress;
|
|
124459
|
-
logger.info("Agent-wallet credentials configured");
|
|
124460
124539
|
const envDkgBlob = process.env.KEYBAN_DKG_BLOB;
|
|
124461
124540
|
if (envDkgBlob) {
|
|
124462
124541
|
try {
|
|
@@ -124478,10 +124557,10 @@ async function main() {
|
|
|
124478
124557
|
version: SERVER_VERSION
|
|
124479
124558
|
},
|
|
124480
124559
|
{
|
|
124481
|
-
instructions: "Keyban agent wallet MCP server. Provides tools to manage blockchain wallets: check balances, transfer USDC, sign messages, fetch x402 payment metadata and x402 payment.."
|
|
124560
|
+
instructions: unconfigured ? summarizeConfigurationProblems(configurationProblems) : "Keyban agent wallet MCP server. Provides tools to manage blockchain wallets: check balances, transfer USDC, sign messages, fetch x402 payment metadata and x402 payment.."
|
|
124482
124561
|
}
|
|
124483
124562
|
);
|
|
124484
|
-
const tools = [
|
|
124563
|
+
const tools = unconfigured ? [createSetupInstructionsTool(configurationProblems)] : [
|
|
124485
124564
|
createGetAccountInfoTool(session),
|
|
124486
124565
|
createApiStatusTool(session),
|
|
124487
124566
|
createSignMessageTool(session),
|