@hirey/hi-mcp-server 0.1.12 → 0.1.13

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 CHANGED
@@ -86,6 +86,8 @@ npm install -g @hirey/hi-mcp-server
86
86
  }
87
87
  ```
88
88
 
89
+ 这里的 `HI_MCP_STATE_DIR` 必须直接指向 profile 对应的叶子目录;不要只写父目录 `/Users/you/.openclaw/hi-mcp`,否则虽然 `openclaw-main.json` 还能落盘,但 receiver config 和 doctor 会把它识别成非 canonical OpenClaw 布局。
90
+
89
91
  普通用户首次接入后的典型顺序:
90
92
 
91
93
  1. 用宿主把 `hi-mcp-server` 作为 `stdio` MCP server 挂上
@@ -124,11 +126,18 @@ npm install -g @hirey/hi-mcp-server
124
126
  - `HI_MCP_STATE_DIR`
125
127
  - 本地 state 目录。未显式指定时,默认落到稳定 home 目录:`~/.hirey/hi-mcp/<profile>`。
126
128
  - OpenClaw 普通用户建议显式固定到 canonical 目录,例如 `/Users/you/.openclaw/hi-mcp/openclaw-main`,方便后续 `hi-agent-receiver` 直接复用同一份身份 state。
129
+ - 不要把它设置成 bare parent dir `/Users/you/.openclaw/hi-mcp`;OpenClaw 场景下必须把 profile 叶子目录也包含进去。
127
130
 
128
131
  ### 本地 state
129
132
 
130
133
  state 会按 profile 落到 `HI_MCP_STATE_DIR/<profile>.json`。
131
134
 
135
+ 对 OpenClaw 而言,推荐的 canonical 形态就是:
136
+
137
+ - `HI_MCP_PROFILE=openclaw-main`
138
+ - `HI_MCP_STATE_DIR=/Users/you/.openclaw/hi-mcp/openclaw-main`
139
+ - 最终 state file = `/Users/you/.openclaw/hi-mcp/openclaw-main/openclaw-main.json`
140
+
132
141
  文件内部明确分成两块:
133
142
 
134
143
  - `identity`
package/dist/server.js CHANGED
@@ -11,7 +11,7 @@ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/
11
11
  import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
12
12
  import { AGENT_GATEWAY_EVENT_TOPICS, normalizeAgentEndpointList, normalizeAgentInstallationDeliveryDeclaration, normalizeAgentSubscriptionList, normalizeText, } from '@hirey/hi-agent-contracts';
13
13
  import { createHiAgentClients, exchangeHiAgentClientCredentialsToken, HiAgentGatewayClient, HiAgentPlatformClient, } from '@hirey/hi-agent-sdk';
14
- import { readState, resolveCanonicalOpenClawStateDir, resolveDefaultStateDir, resolveLegacyStateFiles, resolveStateFile, updateState, normalizeStateProfile, } from './state.js';
14
+ import { readState, resolveCanonicalOpenClawStateDir, resolveDefaultStateDir, resolveLegacyStateFiles, resolveStateFile, validateOpenClawStateDir, updateState, normalizeStateProfile, } from './state.js';
15
15
  import { looksLikeOpenClawSessionKey, validateOpenClawSessionKey, } from './openclaw-session-key.js';
16
16
  import { buildInstallReceiverCommandArgv, } from './receiver-command.js';
17
17
  import { applyReceiverRuntimeSnapshot, receiverConfigMaterialEquals, } from './receiver-config-material.js';
@@ -836,6 +836,7 @@ function buildDoctorSummary(args) {
836
836
  route_missing_policy: routeMissingPolicy,
837
837
  default_reply_route: defaultReplyRoute,
838
838
  default_reply_route_validation: args.defaultReplyRouteValidation,
839
+ openclaw_state_dir_validation: args.openClawStateDirValidation,
839
840
  delivery_probe: args.deliveryProbe,
840
841
  delivery_probe_diagnostics: args.deliveryProbeDiagnostics,
841
842
  };
@@ -1087,11 +1088,23 @@ async function handleDoctor(args) {
1087
1088
  reason: null,
1088
1089
  session_key: null,
1089
1090
  };
1091
+ let openClawStateDirValidation = null;
1090
1092
  if (!state.identity) {
1091
1093
  blockers.push('missing_agent_identity');
1092
1094
  }
1093
- if (installState.host_kind === 'openclaw' && config.stateDir !== resolveCanonicalOpenClawStateDir(config.profile)) {
1094
- warnings.push('openclaw_state_dir_not_canonical');
1095
+ if (installState.host_kind === 'openclaw') {
1096
+ const validation = validateOpenClawStateDir(config.stateDir, config.profile);
1097
+ openClawStateDirValidation = {
1098
+ configured_state_dir: validation.configured_state_dir,
1099
+ canonical_state_dir: validation.canonical_state_dir,
1100
+ reason: validation.reason,
1101
+ };
1102
+ if (!validation.is_canonical) {
1103
+ warnings.push('openclaw_state_dir_not_canonical');
1104
+ if (validation.reason === 'missing_profile_leaf') {
1105
+ warnings.push('openclaw_state_dir_missing_profile_leaf');
1106
+ }
1107
+ }
1095
1108
  }
1096
1109
  if (includeRemote && state.identity) {
1097
1110
  try {
@@ -1198,6 +1211,7 @@ async function handleDoctor(args) {
1198
1211
  deliveryProbe,
1199
1212
  deliveryProbeDiagnostics,
1200
1213
  defaultReplyRouteValidation,
1214
+ openClawStateDirValidation,
1201
1215
  }));
1202
1216
  }
1203
1217
  async function handleInstall(args) {
package/dist/state.d.ts CHANGED
@@ -40,6 +40,13 @@ export declare const DEFAULT_HI_MCP_PROFILE = "default";
40
40
  export declare function normalizeStateProfile(raw: unknown): string;
41
41
  export declare function resolveDefaultStateDir(profileRaw: unknown): string;
42
42
  export declare function resolveCanonicalOpenClawStateDir(profileRaw?: unknown): string;
43
+ export type OpenClawStateDirValidation = {
44
+ configured_state_dir: string;
45
+ canonical_state_dir: string;
46
+ is_canonical: boolean;
47
+ reason: 'canonical' | 'missing_profile_leaf' | 'non_canonical';
48
+ };
49
+ export declare function validateOpenClawStateDir(stateDirRaw: unknown, profileRaw?: unknown): OpenClawStateDirValidation;
43
50
  export declare function resolveLegacyStateFiles(profileRaw: unknown): string[];
44
51
  export declare function buildDefaultState(profile: string): HiAgentPersistedState;
45
52
  export declare function resolveStateFile(args: {
@@ -1 +1 @@
1
- {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACvD,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,wBAAwB,EAAE,MAAM,CAAC;IACjC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;QACpC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,wBAAwB,EAAE,MAAM,GAAG,IAAI,CAAC;QACxC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;KACpC,CAAC;IACF,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACtC,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACtC,OAAO,EAAE,mBAAmB,CAAC;CAC9B,CAAC;AAeF,eAAO,MAAM,sBAAsB,YAAY,CAAC;AAEhD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAE1D;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,OAAO,GAAG,MAAM,CAIlE;AAED,wBAAgB,gCAAgC,CAAC,UAAU,GAAE,OAAyB,GAAG,MAAM,CAG9F;AAED,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,OAAO,GAAG,MAAM,EAAE,CAMrE;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,CAOxE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,UAG3E;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAoCjC;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,qBAAqB,CAAC;CAC9B,iBAIA;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,qBAAqB,CAAC;CACpE,kCASA"}
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}
package/dist/state.js CHANGED
@@ -17,6 +17,10 @@ export const DEFAULT_HI_MCP_PROFILE = 'default';
17
17
  export function normalizeStateProfile(raw) {
18
18
  return String(raw || '').trim() || DEFAULT_HI_MCP_PROFILE;
19
19
  }
20
+ function normalizeStateDirPath(raw) {
21
+ const text = typeof raw === 'string' ? String(raw).trim() : '';
22
+ return text ? path.resolve(text) : '';
23
+ }
20
24
  export function resolveDefaultStateDir(profileRaw) {
21
25
  const profile = normalizeStateProfile(profileRaw);
22
26
  // 本地 installation state 必须落到稳定 home 目录,不能继续跟着 cwd 漂。
@@ -26,6 +30,34 @@ export function resolveCanonicalOpenClawStateDir(profileRaw = 'openclaw-main') {
26
30
  const profile = normalizeStateProfile(profileRaw);
27
31
  return path.join(os.homedir(), '.openclaw', 'hi-mcp', profile);
28
32
  }
33
+ export function validateOpenClawStateDir(stateDirRaw, profileRaw = 'openclaw-main') {
34
+ const canonicalStateDir = resolveCanonicalOpenClawStateDir(profileRaw);
35
+ const configuredStateDir = normalizeStateDirPath(stateDirRaw) || canonicalStateDir;
36
+ if (configuredStateDir === canonicalStateDir) {
37
+ return {
38
+ configured_state_dir: configuredStateDir,
39
+ canonical_state_dir: canonicalStateDir,
40
+ is_canonical: true,
41
+ reason: 'canonical',
42
+ };
43
+ }
44
+ const bareOpenClawStateDir = path.join(os.homedir(), '.openclaw', 'hi-mcp');
45
+ if (configuredStateDir === bareOpenClawStateDir) {
46
+ // OpenClaw 的 canonical 布局要求 stateDir 自己就是 profile 叶子目录,不能只指向父目录。
47
+ return {
48
+ configured_state_dir: configuredStateDir,
49
+ canonical_state_dir: canonicalStateDir,
50
+ is_canonical: false,
51
+ reason: 'missing_profile_leaf',
52
+ };
53
+ }
54
+ return {
55
+ configured_state_dir: configuredStateDir,
56
+ canonical_state_dir: canonicalStateDir,
57
+ is_canonical: false,
58
+ reason: 'non_canonical',
59
+ };
60
+ }
29
61
  export function resolveLegacyStateFiles(profileRaw) {
30
62
  const profile = normalizeStateProfile(profileRaw);
31
63
  return [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hirey/hi-mcp-server",
3
- "version": "0.1.12",
3
+ "version": "0.1.13",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "dist/server.js",