@haven_ai/mcp 0.4.0-alpha.0 → 0.5.0-alpha.1

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
@@ -1,5 +1,5 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { HavenClient } from '@haven_ai/sdk';
2
+ import { HavenClientUpdate, HavenClient } from '@haven_ai/sdk';
3
3
  import { z } from 'zod/v3';
4
4
 
5
5
  interface HavenCredentialFile {
@@ -159,6 +159,12 @@ interface ToolSuccess<T> {
159
159
  * leave, which is how `idempotencyKey` survived #2312 and #2348.
160
160
  */
161
161
  warnings?: string[];
162
+ /**
163
+ * #3303: the backend's `client_update` hint when this package is behind the
164
+ * version the deployment recommends (`required: false`) or below its
165
+ * minimum (`required: true`). Carries the exact command that updates it.
166
+ */
167
+ client_update?: HavenClientUpdate;
162
168
  }
163
169
  interface ToolFailure {
164
170
  success: false;
@@ -198,6 +204,8 @@ interface ToolFailure {
198
204
  * own wallet needs to recover first.
199
205
  */
200
206
  retry_with_new_quote?: boolean;
207
+ /** #3303: as on {@link ToolSuccess}; on a 426 `client_outdated` refusal it is always `required: true`. */
208
+ client_update?: HavenClientUpdate;
201
209
  }
202
210
  type ToolPayload<T = unknown> = ToolSuccess<T> | ToolFailure;
203
211
  declare function createToolHandlers(haven: HavenClient): Record<HavenMcpToolName, (input: unknown) => Promise<ToolPayload>>;
@@ -239,7 +247,7 @@ interface ConsentInput {
239
247
  apiUrl?: string;
240
248
  /** Agent identity from the credential file, when present. */
241
249
  agentId?: string;
242
- /** Haven wallet (Safe) the agent spends from. */
250
+ /** Haven wallet the agent spends from. */
243
251
  accountAddress?: string;
244
252
  /** Agent's delegate EOA — the local signer. */
245
253
  delegateAddress?: string;
@@ -345,7 +353,7 @@ declare function createHavenMcpServer(options?: HavenMcpServerOptions): Promise<
345
353
  * `agent_tool_invocations` rows are always attributed to the right tool.
346
354
  */
347
355
  declare const MCP_NAME = "@haven_ai/mcp";
348
- declare const MCP_VERSION = "0.4.0-alpha.0";
356
+ declare const MCP_VERSION = "0.5.0-alpha.1";
349
357
  /**
350
358
  * Refuse to start on an unsupported Node (#1161).
351
359
  *
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
- import { composeDescription, toolDescriptions as toolDescriptions$1, HavenPaymentStateError, HavenSigningError, HavenApiError, AgentPaymentNextAction, HavenError, HavenClient, isSupportedNodeVersion, unsupportedNodeVersionMessage, verifyPaymentReceipt, discoverMerchantMcpUrl, sameUrl, AgentPaymentFailureCode } from '@haven_ai/sdk';
3
+ import { composeDescription, toolDescriptions as toolDescriptions$1, HavenPaymentStateError, HavenSigningError, HavenApiError, AgentPaymentNextAction, HavenError, HavenClient, havenClientIdentity, isSupportedNodeVersion, unsupportedNodeVersionMessage, verifyPaymentReceipt, discoverMerchantMcpUrl, sameUrl, AgentPaymentFailureCode } from '@haven_ai/sdk';
4
4
  import { readFile, stat, mkdir, writeFile } from 'fs/promises';
5
5
  import { z } from 'zod/v3';
6
6
  import { createHash } from 'crypto';
@@ -730,6 +730,9 @@ function normalizeError(err) {
730
730
  phase: stringOrUndefined(body?.phase),
731
731
  nextAction: stringOrUndefined(body?.nextAction) ?? stringOrUndefined(body?.next_action) ?? AgentPaymentNextAction.StopAndTellUser,
732
732
  next_action: stringOrUndefined(body?.nextAction) ?? stringOrUndefined(body?.next_action) ?? AgentPaymentNextAction.StopAndTellUser,
733
+ // #3303: a backend refusal that already names why no tool follows (the
734
+ // 426 `client_outdated` does) keeps that reason at the top level.
735
+ ...typeof body?.next_tool_omitted_reason === "string" ? { next_tool_omitted_reason: body.next_tool_omitted_reason } : {},
733
736
  body: err.body
734
737
  };
735
738
  }
@@ -782,7 +785,7 @@ function renderConsentBlock(input, hash) {
782
785
  ];
783
786
  if (input.apiUrl) lines.push(`Haven API: ${input.apiUrl}`);
784
787
  if (input.agentId) lines.push(`Agent ID: ${input.agentId}`);
785
- if (input.accountAddress) lines.push(`Haven wallet (Safe): ${input.accountAddress}`);
788
+ if (input.accountAddress) lines.push(`Haven wallet: ${input.accountAddress}`);
786
789
  if (input.delegateAddress) lines.push(`Delegate (local signer): ${input.delegateAddress}`);
787
790
  if (typeof input.chainId === "number") lines.push(`Chain ID: ${input.chainId}`);
788
791
  lines.push("");
@@ -945,7 +948,10 @@ async function resolveHavenClient(options = {}) {
945
948
  const client = new HavenClient({
946
949
  apiKey: credentials.apiKey,
947
950
  delegateKey: credentials.delegateKey,
948
- baseUrl: credentials.apiUrl
951
+ baseUrl: credentials.apiUrl,
952
+ // #3303: name this package, not the SDK inside it, so the backend's
953
+ // update hint and refusal speak about what the user actually installed.
954
+ clientIdentity: havenClientIdentity(MCP_NAME, MCP_VERSION)
949
955
  });
950
956
  return { client, credentials };
951
957
  }
@@ -954,7 +960,7 @@ async function createHavenMcpServer(options = {}) {
954
960
  return buildMcpServer(haven);
955
961
  }
956
962
  var MCP_NAME = "@haven_ai/mcp";
957
- var MCP_VERSION = "0.4.0-alpha.0";
963
+ var MCP_VERSION = "0.5.0-alpha.1";
958
964
  var MCP_INSTRUCTIONS = [
959
965
  "Haven local MCP server: signs in-process with the delegate key it holds on",
960
966
  "this machine \u2014 the key never leaves this process. Call haven_get_agent",
@@ -991,7 +997,7 @@ function buildMcpServer(haven) {
991
997
  toolSchemas[name],
992
998
  async (args) => haven.withRequestContext(
993
999
  { "X-Haven-MCP-Tool": name },
994
- async () => toMcpResult(await handlers[name](args))
1000
+ async () => toMcpResult(withClientUpdate(await handlers[name](args), haven.clientUpdate()))
995
1001
  )
996
1002
  );
997
1003
  }
@@ -1041,6 +1047,10 @@ async function runConsentGate(haven, credentials, options) {
1041
1047
  writeAck: options.writeAck
1042
1048
  });
1043
1049
  }
1050
+ function withClientUpdate(payload, hint) {
1051
+ if (!hint || payload.client_update) return payload;
1052
+ return { ...payload, client_update: hint };
1053
+ }
1044
1054
  function toMcpResult(payload) {
1045
1055
  return {
1046
1056
  isError: !payload.success,