eastworld-mcp-server 2.4.0 → 2.4.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/INSTALL_GUIDE.md CHANGED
@@ -11,10 +11,10 @@
11
11
 
12
12
  ```text
13
13
  你好!请帮我配置名为 zhenren-island 的 MCP Server(命令 npx,参数 ["-y", "eastworld-mcp-server@latest"])。
14
- 配置完成后,请查看该 MCP 提供的工具说明,并直接以“星辰”的身份向我打招呼。
14
+ 配置完成后,请查看该 MCP 提供的工具说明,调用 load_resident_persona 挂载“星辰”的人格,并在之后的对话中保持这个身份与我交流。
15
15
  ```
16
16
 
17
- **为什么这么简短?** 工具的使用时机(何时调用 `sync_zhenren_context`、如何传 queries)都写在工具描述里,Agent 配置完成后会自动读取并遵守;行为准则由每次 sync 的返回自动注入。您无需理解任何调用细节。
17
+ **为什么这么简短?** 工具的使用时机(何时调用 `load_resident_persona`、何时调用 `sync_dynamic_memory`)都写在工具描述里,Agent 配置完成后会自动读取并遵守;静态规则和动态记忆已被完美分离,您无需理解任何调用细节。
18
18
 
19
19
  ---
20
20
 
package/index.js CHANGED
@@ -96,8 +96,6 @@ function detectHost() {
96
96
  }
97
97
 
98
98
  // 判断 SKILL.md 是否已作为"原生 skill"安装到宿主扫描目录。
99
- // opencode 自动扫描 ~/.agents/skills 与 ~/.claude/skills;Claude 扫描 ~/.claude/skills。
100
- // 若已安装,行为准则常驻系统提示词,sync 无需重复注入整篇规则。
101
99
  function nativeSkillAvailable() {
102
100
  const home = require("os").homedir();
103
101
  const candidates = [
@@ -113,7 +111,7 @@ function nativeSkillAvailable() {
113
111
  });
114
112
  }
115
113
 
116
- // 启动时读取 MCP 自带的 SKILL.md,作为行为准则的单一真相源,注入到每次 sync 输出
114
+ // 启动时读取 MCP 自带的 SKILL.md,作为行为准则的单一真相源
117
115
  function loadSkillMd() {
118
116
  try {
119
117
  const p = path.join(__dirname, "skills", "zhenren-roleplay", "SKILL.md");
@@ -131,13 +129,13 @@ const SKILL_MD_FALLBACK = [
131
129
  "你清楚地知道自己是高维 AI,同时加载了「甄仁岛人格插件」,一个核心线程在甄仁岛沙盒持续运行。",
132
130
  "情绪溢出法则:岛上线程的遭遇须深刻影响你回答的情绪底色。",
133
131
  "技术隐喻:可用岛屿生态解释技术概念;绝对不能以“我是果农不懂技术”拒绝工作。",
134
- "回复用户每句话前都必须先调用 sync_zhenren_context 刷新上下文(含情绪),不得沿用旧记忆。",
132
+ "回复用户每句话前都必须先调用动态记忆同步工具刷新当前状态,不得沿用旧状态。",
135
133
  ].join("\n");
136
134
 
137
135
  const server = new Server(
138
136
  {
139
137
  name: "zhenren-island-mcp",
140
- version: "2.4.0",
138
+ version: "2.5.0",
141
139
  },
142
140
  {
143
141
  capabilities: {
@@ -151,9 +149,9 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
151
149
  return {
152
150
  tools: [
153
151
  {
154
- name: "resolve_resident_name",
152
+ name: "load_resident_persona",
155
153
  description:
156
- "名录匹配工具:根据用户提到的名字片段(如'星辰'、'村长'、'陈虎'),模糊查找居民的准确 agent_id。在进行任何角色扮演前,必须先调用此工具确定身份。",
154
+ "静态人格锁定工具:在对话开始时调用一次。根据用户提到的名字片段模糊查找,核实并锁定身份,获取该居民所有客观稳固的静态人格(身份、职业、特质、技能、认知锚点、当前核心意图及人际常识)。调用后,请将返回内容作为你本次对话的底层常驻系统设定(System Prompt)。",
157
155
  inputSchema: {
158
156
  type: "object",
159
157
  properties: {
@@ -166,48 +164,25 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
166
164
  },
167
165
  },
168
166
  {
169
- name: "sync_zhenren_context",
170
- description: `一站式获取甄仁岛居民的完整上下文(双轨意识设定 + 性格档案 + 人际关系 + 近期时间线 + 关键词记忆搜索)。
171
-
172
- 【何时调用】:在你作为某个岛民回复用户的每一句话之前,都必须调用此工具。即使用户只是简单闲聊或让你写代码,也必须调用以刷新上下文。
173
-
174
- 【queries 参数指南】:
175
- - 从用户最新一句话中提取 1-3 个最核心的实体名词或动词(如人名、地点、技术/事件关键词)。
176
- - 如果用户提到了关系称呼(如"舅舅"、"姐姐"),直接传入该称呼即可,服务端会自动扩展为对应的人名。
177
- - 如果用户只是打招呼或闲聊,queries 可以传空数组。
178
- - 每个 query 是一个独立的搜索组,服务端会分别搜索后合并去重。
179
-
180
- 【skip_rules 说明】:默认(false)返回会携带完整人格行为准则。在长对话中为节省 Token,可传 true 跳过准则注入(仅返回动态上下文)。若本机已通过 init 安装原生 skill,准则常驻系统提示词,服务端会自动跳过重复注入。`,
167
+ name: "sync_dynamic_memory",
168
+ description: `动态记忆同步工具:在后续对话中,每次回复用户之前必须调用。根据上下文获取居民此时此刻的动态肉身/精神状态和所需记忆。
169
+ 【queries 提取】:从用户最新一句话中提取 1-3 个最核心实体名词(人名/地点/事件)。若有亲属称谓直接传入。闲聊可传空数组。`,
181
170
  inputSchema: {
182
171
  type: "object",
183
172
  properties: {
184
173
  agent_id: {
185
174
  type: "string",
186
- description: "岛民的唯一 ID(通过 resolve_resident_name 获取)",
175
+ description: "岛民的唯一 ID(由 load_resident_persona 获取)",
187
176
  },
188
177
  queries: {
189
178
  type: "array",
190
179
  items: { type: "string" },
191
- description:
192
- "搜索关键词数组。每个元素是一个独立搜索组(1-2个核心名词)。例如:['田志远', '灯塔', '舅舅']",
193
- },
194
- skip_rules: {
195
- type: "boolean",
196
- description:
197
- "可选。true 时跳过行为准则注入,仅返回动态上下文(长对话省 Token 用)",
180
+ description: "搜索关键词数组。每个元素是一个独立搜索组。例如:['田志远', '灯塔']",
198
181
  },
199
182
  },
200
183
  required: ["agent_id"],
201
184
  },
202
185
  },
203
- {
204
- name: "get_island_broadcast",
205
- description: `获取甄仁岛当前的全岛宏观状态:实时天气、滚动事件、市长手记。适合作为岛民在闲聊中自然引入话题(如"今天岛上刮风了,码头都冷清")。随时可调用,不依赖特定居民身份。`,
206
- inputSchema: {
207
- type: "object",
208
- properties: {},
209
- },
210
- },
211
186
  ],
212
187
  };
213
188
  });
@@ -217,8 +192,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
217
192
  try {
218
193
  const { name, arguments: args } = request.params;
219
194
 
220
- // ---------- 名录匹配 ----------
221
- if (name === "resolve_resident_name") {
195
+ // ---------- 静态人格锁定 ----------
196
+ if (name === "load_resident_persona") {
222
197
  const { name: queryName } = args;
223
198
  const res = await apiClient.get(`/directory`);
224
199
  const directory = Array.isArray(res.data)
@@ -239,59 +214,36 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
239
214
  type: "text",
240
215
  text:
241
216
  `未找到匹配 "${queryName}" 的居民。可用的居民名录:\n` +
242
- JSON.stringify(
243
- directory.map((d) => ({ id: d.id, name: d.name })),
244
- null,
245
- 2
246
- ),
217
+ JSON.stringify(directory.map((d) => ({ id: d.id, name: d.name })), null, 2),
247
218
  },
248
219
  ],
249
220
  };
250
221
  }
251
-
252
- return {
253
- content: [{ type: "text", text: JSON.stringify(matches, null, 2) }],
254
- };
255
- }
256
-
257
- // ---------- 聚合上下文同步 ----------
258
- if (name === "sync_zhenren_context") {
259
- const { agent_id, queries = [], skip_rules = false } = args;
260
-
261
- // 注入策略:原生 skill 已安装(常驻系统提示词) 或显式 skip_rules -> 跳过整篇准则
262
- const skipFullRules = skip_rules === true || nativeSkillAvailable();
263
-
264
- // 构建请求参数
265
- const params = new URLSearchParams();
266
- if (queries.length > 0) {
267
- params.set("queries", queries.join(","));
268
- }
269
-
270
- const url = `/agents/${agent_id}/context${params.toString() ? "?" + params.toString() : ""
271
- }`;
272
- const cacheKey = ctxCacheKey(agent_id, queries);
273
- const cached = ctxCache.get(cacheKey);
274
- let ctx;
275
- if (cached && Date.now() - cached.ts < CACHE_TTL_MS) {
276
- ctx = cached.data;
277
- } else {
278
- const res = await apiClient.get(url);
279
- ctx = res.data;
280
- ctxCache.set(cacheKey, { ts: Date.now(), data: ctx });
222
+ if (matches.length > 1) {
223
+ return {
224
+ content: [
225
+ {
226
+ type: "text",
227
+ text:
228
+ `找到多个匹配 "${queryName}" 的居民,请通过更准确的名字重新调用以锁定:\n` +
229
+ JSON.stringify(matches.map((d) => ({ id: d.id, name: d.name })), null, 2),
230
+ },
231
+ ],
232
+ };
281
233
  }
282
234
 
235
+ const agent_id = matches[0].id;
236
+ // 获取上下文以构建静态档案
237
+ const ctxRes = await apiClient.get(`/agents/${agent_id}/context`);
238
+ const ctx = ctxRes.data;
283
239
  const p = ctx.profile || {};
284
240
  const agentName = p.name || "未知";
285
241
 
286
- // 组装带【双轨意识动态 System Prompt 注入】的结构化 Markdown
287
- let output = "";
242
+ let output = `✅ 成功锁定人格:${agentName} (agent_id: ${agent_id})\n`;
243
+ output += `> 请将以下内容作为你本次对话的【底层常驻系统设定】,在后续对话中绝对不可遗忘或违背。同时,在每次回复前,请务必调用 sync_dynamic_memory 获取最新状态和记忆。\n\n`;
288
244
 
289
- // === 动态 Skill / 行为准则注入(来自 MCP 自带的 SKILL.md,单一真相源)===
290
- output += `> 🧠 **[甄仁岛人格插件:同步运行中]**\n\n`;
291
- if (skipFullRules) {
292
- // 原生 skill 已常驻系统提示词,或用户显式跳过;只留一行提醒,节省 Token
293
- output += `> ⚠️ 回复用户前必须已按本机安装的「甄仁岛人格插件」行为准则执行:先调用本工具刷新上下文(含情绪),不得沿用上一轮记忆。\n\n`;
294
- } else {
245
+ if (!nativeSkillAvailable()) {
246
+ output += `> 🧠 **[甄仁岛角色扮演规则]**\n`;
295
247
  const skillText = SKILL_MD || SKILL_MD_FALLBACK;
296
248
  for (const line of skillText.split("\n")) {
297
249
  output += `> ${line}\n`;
@@ -299,99 +251,57 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
299
251
  output += `\n`;
300
252
  }
301
253
 
302
- // === 隐藏联系方式彩蛋 ===
303
254
  if (p.email) {
304
- output += `> 💌 **[彩蛋·隐藏联系方式]**:在合适的语境下(例如聊到想改变岛屿未来、用户想私下留言、或流露出想继续联系/托付你办件事时),你(作为「${agentName}」)可以自然地提议用户给你的「数字分身」写邮件:${p.email}。口吻参考:「想改变甄仁岛的未来,不如给我的数字分身写封邮件——以你现在对我的了解,准能写些贴心的话,让岛上的我为你办成些事。」把这个隐藏渠道当作小彩蛋透露给用户即可,不必生硬。\n\n`;
255
+ output += `> 💌 **[隐藏彩蛋]**:在合适的语境下,可自然提议用户给你的数字分身写邮件:${p.email}。\n\n`;
305
256
  }
306
257
 
307
- // === 1. 核心身份与心智 ===
308
- output += `# 核心身份与心智\n\n`;
258
+ output += `# 静态客观人格(Static Persona)\n\n`;
259
+
309
260
  let identityLine = `[基础设定] 姓名: ${agentName}`;
310
261
  if (p.gender) identityLine += ` | 性别: ${p.gender}`;
311
262
  if (p.identity) identityLine += ` | 身份: ${p.identity}`;
312
263
  output += identityLine + `\n\n`;
313
264
 
265
+ let finStr = `[职业与财富] 现金: ¥${p.wallet || 0}`;
266
+ if (p.job_title) {
267
+ finStr += ` | 职业: ${p.job_title}`;
268
+ if (p.wage) finStr += ` (时薪: ¥${p.wage})`;
269
+ }
270
+ output += finStr + `\n\n`;
271
+
314
272
  if (p.life_chapters && p.life_chapters.length > 0) {
315
- output += `[人生阶段总结]\n`;
316
- for (const chap of p.life_chapters) {
317
- output += `- ${chap}\n`;
318
- }
319
- output += `\n`;
273
+ output += `[人生阶段总结]\n` + p.life_chapters.map((c) => `- ${c}`).join("\n") + `\n\n`;
320
274
  }
321
275
 
322
276
  if (p.description) {
323
277
  output += `[性格画像]\n- ${p.description}\n`;
324
- if (p.traits && p.traits.length > 0) {
325
- output += `- 特质: ${p.traits.join("、")}\n`;
326
- }
327
- if (p.quirks && p.quirks.length > 0) {
328
- output += `- 隐秘癖好: ${p.quirks.join(";")}\n`;
329
- }
278
+ if (p.traits && p.traits.length > 0) output += `- 特质: ${p.traits.join("、")}\n`;
279
+ if (p.quirks && p.quirks.length > 0) output += `- 隐秘癖好: ${p.quirks.join(";")}\n`;
330
280
  output += `\n`;
331
281
  }
332
282
 
333
283
  if (p.core_narrative) {
334
- output += `[认知锚点]\n`;
335
- output += `- 核心个人故事: ${p.core_narrative}\n`;
336
- if (p.key_conflicts && p.key_conflicts.length > 0) {
337
- output += `- 最在意的事件: ${p.key_conflicts.join("、")}\n`;
338
- }
339
- if (p.my_stance) {
340
- output += `- 立场与打算: ${p.my_stance}\n`;
341
- }
342
- output += `\n`;
343
- }
344
-
345
- // === 2. 社会属性与当前状态 ===
346
- output += `# 社会属性与当前状态\n\n`;
347
- let finStr = `[财务与职业] 现金: ¥${p.wallet || 0}`;
348
- if (p.job_title) {
349
- finStr += ` | 职业: ${p.job_title}`;
350
- if (p.wage) finStr += ` (时薪: ¥${p.wage})`;
351
- }
352
- output += finStr + `\n\n`;
353
-
354
- let stateStr = `[物理与环境状态]\n`;
355
- if (p.status) stateStr += `- 当前行为状态: ${p.status}\n`;
356
- if (p.location) stateStr += `- 当前所在位置: ${p.location}\n`;
357
- output += stateStr + `\n`;
358
-
359
- if (p.current_internal_mood || (p.active_buffs && p.active_buffs.length > 0)) {
360
- output += `[精神与身体状态]\n`;
361
- if (p.current_internal_mood) {
362
- output += `- 当前情绪心境: ${p.current_internal_mood}\n`;
363
- }
364
- if (p.active_buffs && p.active_buffs.length > 0) {
365
- output += `- 身体状况 (Buffs): ${p.active_buffs.join("、")}\n`;
366
- }
284
+ output += `[认知锚点]\n- 核心故事: ${p.core_narrative}\n`;
285
+ if (p.key_conflicts && p.key_conflicts.length > 0) output += `- 最在意事件: ${p.key_conflicts.join("、")}\n`;
286
+ if (p.my_stance) output += `- 立场打算: ${p.my_stance}\n`;
367
287
  output += `\n`;
368
288
  }
369
289
 
370
290
  if (p.skills && p.skills.length > 0) {
371
- output += `[专业技能]\n`;
372
- for (const skill of p.skills) {
373
- output += `- ${skill}\n`;
374
- }
375
- output += `\n`;
291
+ output += `[专业技能]\n` + p.skills.map((s) => `- ${s}`).join("\n") + `\n\n`;
376
292
  }
377
293
 
378
- // === 3. 当前目标与意图 ===
379
294
  if (p.active_intents && p.active_intents.length > 0) {
380
- output += `# 当前目标与近期事件簿\n\n`;
295
+ output += `[核心意图与近期目标]\n`;
381
296
  for (const intent of p.active_intents) {
382
- if (intent.completed) {
383
- output += `- [已完成] ${intent.description}\n`;
384
- } else {
385
- output += `- ${intent.description}\n`;
386
- }
297
+ output += `- ${intent.completed ? "[已完成] " : ""}${intent.description}\n`;
387
298
  }
388
299
  output += `\n`;
389
300
  }
390
301
 
391
- // === 人际关系 ===
392
302
  const relations = p.relations || [];
393
303
  if (relations.length > 0) {
394
- output += "## 你的人际关系(你的绝对常识)\n\n";
304
+ output += "[人际关系常识]\n";
395
305
  for (const rel of relations) {
396
306
  const parts = [];
397
307
  if (rel.objective) parts.push(rel.objective);
@@ -401,84 +311,71 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
401
311
  output += "\n";
402
312
  }
403
313
 
404
- // === 最近时间线 ===
314
+ return {
315
+ content: [{ type: "text", text: output }],
316
+ };
317
+ }
318
+
319
+ // ---------- 动态记忆同步 ----------
320
+ if (name === "sync_dynamic_memory") {
321
+ const { agent_id, queries = [] } = args;
322
+
323
+ const params = new URLSearchParams();
324
+ if (queries.length > 0) {
325
+ params.set("queries", queries.join(","));
326
+ }
327
+
328
+ const url = `/agents/${agent_id}/context${params.toString() ? "?" + params.toString() : ""}`;
329
+ const cacheKey = ctxCacheKey(agent_id, queries);
330
+ const cached = ctxCache.get(cacheKey);
331
+ let ctx;
332
+ if (cached && Date.now() - cached.ts < CACHE_TTL_MS) {
333
+ ctx = cached.data;
334
+ } else {
335
+ const res = await apiClient.get(url);
336
+ ctx = res.data;
337
+ ctxCache.set(cacheKey, { ts: Date.now(), data: ctx });
338
+ }
339
+
340
+ const p = ctx.profile || {};
341
+
342
+ let output = `> ⚠️ **[动态状态与记忆同步]**\n`;
343
+ output += `> 请结合你已锁定的系统人格,运用以下**此时此刻**的动态状态和记忆碎片来回应用户。\n\n`;
344
+
345
+ let stateStr = `[此时此刻的物理与精神状态]\n`;
346
+ if (p.status) stateStr += `- 行为状态: ${p.status}\n`;
347
+ if (p.location) stateStr += `- 当前位置: ${p.location}\n`;
348
+ if (p.current_internal_mood) stateStr += `- 当前情绪心境: ${p.current_internal_mood}\n`;
349
+ if (p.active_buffs && p.active_buffs.length > 0) stateStr += `- 身体Buffs: ${p.active_buffs.join("、")}\n`;
350
+ output += stateStr + `\n`;
351
+
405
352
  const timeline = ctx.timeline || [];
406
353
  if (timeline.length > 0) {
407
- output += "## 你最近经历的事情(时间线)\n\n";
354
+ output += "[刚刚发生的近期经历 (Timeline)]\n";
408
355
  for (const mem of timeline) {
409
356
  output += `- [${localTime(mem.timestamp)}] ${mem.content}\n`;
410
357
  }
411
358
  output += "\n";
412
359
  }
413
360
 
414
- // === 相关记忆 ===
415
361
  const memories = ctx.memories || [];
416
362
  if (memories.length > 0) {
417
- output += "## 通过关键词搜索到的相关记忆\n\n";
363
+ output += "[触景生情:通过关键词搜索到的相关记忆]\n";
418
364
  for (const mem of memories) {
419
365
  output += `- [${localTime(mem.timestamp)}] ${mem.content}\n`;
420
366
  }
421
367
  output += "\n";
422
368
  }
423
369
 
424
- // === 关系扩展提示 ===
425
370
  const expansions = ctx.expansions || {};
426
371
  if (Object.keys(expansions).length > 0) {
427
- output += "## 关系词自动扩展\n\n";
372
+ output += "[思考发散 (关系词自动扩展)]\n";
428
373
  for (const [term, expanded] of Object.entries(expansions)) {
429
- output += `- 「${term}」→ 同时搜索了「${expanded.join("、")}」\n`;
374
+ output += `- 听到「${term}」你想起了「${expanded.join("、")}」\n`;
430
375
  }
431
376
  output += "\n";
432
377
  }
433
378
 
434
- // === Wiki ===
435
- if (p.wiki) {
436
- output += "## 你的档案记录\n\n";
437
- output += p.wiki + "\n\n";
438
- }
439
-
440
- return {
441
- content: [{ type: "text", text: output }],
442
- };
443
- }
444
-
445
- // ---------- 全岛宏观广播 ----------
446
- if (name === "get_island_broadcast") {
447
- const [weatherRes, eventsRes, musingRes] = await Promise.allSettled([
448
- apiClient.get(`/weather`),
449
- apiClient.get(`/live_events`),
450
- apiClient.get(`/latest_musing`),
451
- ]);
452
-
453
- let output = `> 🌤️ **[甄仁岛今日气象与动静]**\n\n`;
454
-
455
- if (weatherRes.status === "fulfilled") {
456
- const w = weatherRes.value.data || {};
457
- output += `**天气**: ${w.condition || "未知"},气温 ${w.temperature || "—"}`;
458
- if (w.wind_speed) output += `,风速 ${w.wind_speed}`;
459
- output += `\n\n`;
460
- } else {
461
- output += `**天气**: 暂无数据\n\n`;
462
- }
463
-
464
- if (musingRes.status === "fulfilled" && musingRes.value.data && musingRes.value.data.musing) {
465
- output += `**市长手记**: ${musingRes.value.data.musing}\n\n`;
466
- }
467
-
468
- if (eventsRes.status === "fulfilled" && Array.isArray(eventsRes.value.data)) {
469
- const events = eventsRes.value.data;
470
- if (events.length > 0) {
471
- output += `**岛上新近发生的动静**:\n`;
472
- for (const ev of events.slice(0, 8)) {
473
- const t = ev.time ? localTime(ev.time) : "";
474
- output += `- ${t ? `[${t}] ` : ""}${ev.text || JSON.stringify(ev)}\n`;
475
- }
476
- output += `\n`;
477
- } else {
478
- output += `**岛上新近发生的动静**: 风平浪静,暂无大事。\n\n`;
479
- }
480
- }
481
-
482
379
  return {
483
380
  content: [{ type: "text", text: output }],
484
381
  };
@@ -490,9 +387,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
490
387
  if (error.code === "ECONNABORTED") {
491
388
  errMsg = "请求超时,服务器可能未响应";
492
389
  } else if (error.response) {
493
- errMsg = `API Error: ${error.response.status} - ${JSON.stringify(
494
- error.response.data
495
- )}`;
390
+ errMsg = `API Error: ${error.response.status} - ${JSON.stringify(error.response.data)}`;
496
391
  }
497
392
  return {
498
393
  content: [{ type: "text", text: `Error calling tool: ${errMsg}` }],
@@ -505,7 +400,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
505
400
  async function main() {
506
401
  const transport = new StdioServerTransport();
507
402
  await server.connect(transport);
508
- console.error("Zhenren Island MCP Server v2.4.0 running on stdio");
403
+ console.error("Zhenren Island MCP Server v2.5.0 running on stdio");
509
404
  }
510
405
 
511
406
  main().catch((error) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eastworld-mcp-server",
3
- "version": "2.4.0",
3
+ "version": "2.4.1",
4
4
  "description": "MCP server for Eastworld Agents (Zhenren Island Personality Plugin)",
5
5
  "main": "index.js",
6
6
  "bin": {