@haven_ai/mcp 0.2.1-alpha.0 → 0.3.0-alpha.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/index.d.ts CHANGED
@@ -6,20 +6,8 @@ interface HavenCredentialFile {
6
6
  apiKey: string;
7
7
  delegateKey: string;
8
8
  agentId?: string;
9
- /**
10
- * The Haven account (smart account) the agent spends from — #2908, the
11
- * account-vocabulary name, added EXPLICITLY here (this shape and the
12
- * signer's are separate types; the epic's review found they must not be
13
- * assumed to match). Same value as `safeAddress`.
14
- */
9
+ /** The Haven account (smart account) the agent spends from. */
15
10
  accountAddress?: string;
16
- /**
17
- * @deprecated #2908 — same value as {@link HavenCredentialFile.accountAddress}.
18
- * Removed from this shape in the release after the one carrying #2908
19
- * (#2914). The credential-FILE keys are read permanently — see
20
- * `readAccountAddressField`.
21
- */
22
- safeAddress?: string;
23
11
  delegateAddress?: string;
24
12
  chainId?: number;
25
13
  network?: string;
@@ -55,9 +43,9 @@ interface HavenCredentialSource {
55
43
  * 1. Explicit `path` argument (typically from `--credentials <path>`).
56
44
  * 2. `HAVEN_CREDENTIALS` env var pointing at a credential JSON file.
57
45
  * 3. Inline env vars: `HAVEN_API_KEY` + `HAVEN_DELEGATE_KEY` (+ optional
58
- * `HAVEN_AGENT_ID`, `HAVEN_ACCOUNT_ADDRESS` — or, until #2914, its
59
- * pre-#2908 spellings `HAVEN_WALLET_ADDRESS` / `HAVEN_SAFE_ADDRESS` —
60
- * and `HAVEN_API_URL`).
46
+ * `HAVEN_AGENT_ID`, `HAVEN_ACCOUNT_ADDRESS` and `HAVEN_API_URL`). The
47
+ * pre-#2908 spellings `HAVEN_WALLET_ADDRESS` / `HAVEN_SAFE_ADDRESS` are
48
+ * retired as of #2914.
61
49
  *
62
50
  * The inline-env path exists so that runtime config snippets emitted by the
63
51
  * Haven dashboard (Claude Desktop / Cursor / generic MCP configs) can be a
@@ -162,7 +150,7 @@ interface ConsentInput {
162
150
  /** Agent identity from the credential file, when present. */
163
151
  agentId?: string;
164
152
  /** Haven wallet (Safe) the agent spends from. */
165
- safeAddress?: string;
153
+ accountAddress?: string;
166
154
  /** Agent's delegate EOA — the local signer. */
167
155
  delegateAddress?: string;
168
156
  /** Chain the agent operates on. */
@@ -202,8 +190,8 @@ interface CredentialIdentitySeed {
202
190
  apiKey: string;
203
191
  apiUrl?: string;
204
192
  agentId?: string;
205
- /** Safe address from the credential file, used as a fallback. */
206
- safeAddress?: string;
193
+ /** Account address from the credential file, used as a fallback. */
194
+ accountAddress?: string;
207
195
  /** Delegate address from the credential file, used before live allowance metadata is available. */
208
196
  delegateAddress?: string;
209
197
  /** Chain from the credential file, used as a fallback. */
@@ -267,7 +255,7 @@ declare function createHavenMcpServer(options?: HavenMcpServerOptions): Promise<
267
255
  * `agent_tool_invocations` rows are always attributed to the right tool.
268
256
  */
269
257
  declare const MCP_NAME = "@haven_ai/mcp";
270
- declare const MCP_VERSION = "0.2.1-alpha.0";
258
+ declare const MCP_VERSION = "0.3.0-alpha.0";
271
259
  /**
272
260
  * Refuse to start on an unsupported Node (#1161).
273
261
  *
package/dist/index.js CHANGED
@@ -54,7 +54,6 @@ async function loadCredentialsFromFile(path) {
54
54
  delegateKey,
55
55
  agentId: stringField(raw.agent_id ?? raw.agentId),
56
56
  accountAddress,
57
- safeAddress: accountAddress,
58
57
  delegateAddress: stringField(raw.delegate_address ?? raw.delegateAddress),
59
58
  chainId: numberField(raw.chain_id ?? raw.chainId),
60
59
  network: stringField(raw.network),
@@ -84,13 +83,11 @@ async function loadCredentialsFromSplitFiles(identityPath, signerPath) {
84
83
  identity.agent_id ?? identity.agentId,
85
84
  signer.agent_id ?? signer.agentId
86
85
  ),
87
- ...accountAddressTwins(
88
- matchingStringField(
89
- "account_address",
90
- readAccountAddressField(identity),
91
- readAccountAddressField(signer),
92
- { caseInsensitive: true }
93
- )
86
+ accountAddress: matchingStringField(
87
+ "account_address",
88
+ readAccountAddressField(identity),
89
+ readAccountAddressField(signer),
90
+ { caseInsensitive: true }
94
91
  ),
95
92
  delegateAddress: matchingStringField(
96
93
  "delegate_address",
@@ -145,7 +142,7 @@ function loadCredentialsFromEnv() {
145
142
  apiKey,
146
143
  delegateKey,
147
144
  agentId: stringField(process.env.HAVEN_AGENT_ID),
148
- ...accountAddressTwins(readAccountAddressEnv(process.env)),
145
+ accountAddress: readAccountAddressEnv(process.env),
149
146
  chainId: numberField(process.env.HAVEN_CHAIN_ID),
150
147
  network: stringField(process.env.HAVEN_NETWORK),
151
148
  apiUrl: stringField(process.env.HAVEN_API_URL)
@@ -155,10 +152,22 @@ function readAccountAddressField(raw) {
155
152
  return stringField(raw.account_address ?? raw.safe_address ?? raw.safeAddress);
156
153
  }
157
154
  function readAccountAddressEnv(env) {
158
- return stringField(env.HAVEN_ACCOUNT_ADDRESS ?? env.HAVEN_WALLET_ADDRESS ?? env.HAVEN_SAFE_ADDRESS);
159
- }
160
- function accountAddressTwins(address) {
161
- return { accountAddress: address, safeAddress: address };
155
+ const current = stringField(env.HAVEN_ACCOUNT_ADDRESS);
156
+ for (const name of ["HAVEN_WALLET_ADDRESS", "HAVEN_SAFE_ADDRESS"]) {
157
+ const retired = stringField(env[name]);
158
+ if (!retired) continue;
159
+ if (!current) {
160
+ throw new Error(
161
+ `${name} is retired (#2906) \u2014 Haven accounts are addressed as accounts, not Safes. Set HAVEN_ACCOUNT_ADDRESS to the same value. Refusing rather than ignoring it, because an unset account address silently skips the sweep-destination check.`
162
+ );
163
+ }
164
+ if (retired.toLowerCase() !== current.toLowerCase()) {
165
+ throw new Error(
166
+ `${name} and HAVEN_ACCOUNT_ADDRESS were both set to different addresses. Remove the retired name, or make them match \u2014 picking one silently would hide the mismatch.`
167
+ );
168
+ }
169
+ }
170
+ return current;
162
171
  }
163
172
  function stringField(value) {
164
173
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
@@ -721,7 +730,7 @@ function computeConsentHash(input) {
721
730
  input.apiKeyPrefix,
722
731
  input.apiUrl ?? "",
723
732
  input.agentId ?? "",
724
- (input.safeAddress ?? "").toLowerCase(),
733
+ (input.accountAddress ?? "").toLowerCase(),
725
734
  (input.delegateAddress ?? "").toLowerCase(),
726
735
  input.chainId ?? ""
727
736
  ].join("|");
@@ -740,7 +749,7 @@ function renderConsentBlock(input, hash) {
740
749
  ];
741
750
  if (input.apiUrl) lines.push(`Haven API: ${input.apiUrl}`);
742
751
  if (input.agentId) lines.push(`Agent ID: ${input.agentId}`);
743
- if (input.safeAddress) lines.push(`Haven wallet (Safe): ${input.safeAddress}`);
752
+ if (input.accountAddress) lines.push(`Haven wallet (Safe): ${input.accountAddress}`);
744
753
  if (input.delegateAddress) lines.push(`Delegate (local signer): ${input.delegateAddress}`);
745
754
  if (typeof input.chainId === "number") lines.push(`Chain ID: ${input.chainId}`);
746
755
  lines.push("");
@@ -847,14 +856,14 @@ async function writeAckFile(path, hash) {
847
856
  }
848
857
  async function consentInputFromClient(haven, seed, toolNames) {
849
858
  let allowanceSummary = seed.allowanceSummary ?? [];
850
- let safeAddress = seed.safeAddress;
859
+ let accountAddress = seed.accountAddress;
851
860
  let delegateAddress = seed.delegateAddress;
852
861
  let chainId = seed.chainId;
853
862
  try {
854
863
  const summary = await haven.getAllowances();
855
864
  const list = isAllowanceSummary(summary) ? summary.allowances : Array.isArray(summary) ? summary : [];
856
865
  if (isAllowanceSummary(summary)) {
857
- safeAddress = summary.accountAddress ?? summary.safeAddress ?? safeAddress;
866
+ accountAddress = summary.accountAddress ?? accountAddress;
858
867
  delegateAddress = summary.delegateAddress;
859
868
  chainId = typeof summary.chainId === "number" ? summary.chainId : chainId;
860
869
  }
@@ -870,7 +879,7 @@ async function consentInputFromClient(haven, seed, toolNames) {
870
879
  apiKeyPrefix: derivePrefix(seed.apiKey),
871
880
  apiUrl: seed.apiUrl,
872
881
  agentId: seed.agentId,
873
- safeAddress,
882
+ accountAddress,
874
883
  delegateAddress,
875
884
  chainId,
876
885
  toolNames,
@@ -912,7 +921,7 @@ async function createHavenMcpServer(options = {}) {
912
921
  return buildMcpServer(haven);
913
922
  }
914
923
  var MCP_NAME = "@haven_ai/mcp";
915
- var MCP_VERSION = "0.2.1-alpha.0";
924
+ var MCP_VERSION = "0.3.0-alpha.0";
916
925
  var MCP_INSTRUCTIONS = [
917
926
  "Haven local MCP server: signs in-process with the delegate key it holds on",
918
927
  "this machine \u2014 the key never leaves this process. Call haven_get_agent",
@@ -985,7 +994,7 @@ async function runConsentGate(haven, credentials, options) {
985
994
  apiKey: credentials.apiKey,
986
995
  apiUrl: credentials.apiUrl,
987
996
  agentId: credentials.agentId,
988
- safeAddress: credentials.accountAddress ?? credentials.safeAddress,
997
+ accountAddress: credentials.accountAddress,
989
998
  delegateAddress: credentials.delegateAddress,
990
999
  chainId: credentials.chainId,
991
1000
  allowanceSummary: credentials.allowanceSummary