@lemonbeijing/lemonclaw-mcp-service 0.1.2 → 0.1.3

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
@@ -1,10 +1,12 @@
1
1
  # LemonClaw MCP Service
2
2
 
3
- Local STDIO MCP service for the LemonClaw portable Runtime. The MCP package embeds the shared Runtime manager and starts Runtime Python directly; it does not install, resolve, or execute the WorkBuddy Launcher package.
3
+ 面向柠檬云的本地 STDIO MCP 服务,支持 ACC 财务、SCM 进销存、ERP 业财和独立开票。可查询客户、供应商、商品、仓库等基础资料,以及采购、销售、库存、收付款、往来、凭证、账簿、发票和经营或财务报表;对于 Action 文档明确支持的写操作,会在用户确认后执行。
4
+
5
+ MCP 包内嵌共享 Runtime 管理组件并直接启动 Runtime Python,不安装、解析或执行 WorkBuddy Launcher 包。要求 Node.js 20 或更高版本;首次相关 Tool 调用时安装 Runtime,之后按策略检查更新。MCP 服务与 WorkBuddy Launcher 共用 `~/.lemonclaw-cli` 中的 Runtime 指针、安装锁、认证、账套上下文、文档、下载和开票文件。
6
+
7
+ 必须在 MCP 服务环境中配置 `LEMONCLAW_API_KEY`,该凭据不会作为 Tool 参数暴露。每次 Tool 执行前,MCP 会先解析或安装 Runtime,再通过 Runtime 认证模块同步发生变化的 API Key,最后调用目标业务操作;API Key 未变化时不会重复写入。
4
8
 
5
- Requires Node.js 20 or newer. Runtime is installed or periodically updated on the first relevant tool call. The MCP service and WorkBuddy Launcher share `~/.lemonclaw-cli`, including the runtime pointer, installation lock, authentication, account context, documents, downloads, and invoice files.
6
-
7
- ## Run from this repository
9
+ ## 从仓库运行
8
10
 
9
11
  ```text
10
12
  npm install
@@ -12,27 +14,31 @@ npm run build
12
14
  node dist/lemonclaw-mcp.cjs
13
15
  ```
14
16
 
15
- Example MCP host configuration:
17
+ MCP Host 配置示例:
16
18
 
17
19
  ```json
18
20
  {
19
21
  "mcpServers": {
20
22
  "lemonclaw": {
21
- "type": "stdio",
22
- "command": "node",
23
- "args": ["D:/VSProject/lemonscmskills/mcp-service/dist/lemonclaw-mcp.cjs"]
23
+ "type": "stdio",
24
+ "command": "node",
25
+ "args": ["D:/VSProject/lemonscmskills/mcp-service/dist/lemonclaw-mcp.cjs"],
26
+ "env": {
27
+ "LEMONCLAW_API_KEY": "<在 MCP Host 中配置为密钥>"
28
+ }
24
29
  }
25
30
  }
26
31
  }
27
32
  ```
28
33
 
29
- After publication, use `npx --yes --prefer-online @lemonbeijing/lemonclaw-mcp-service@latest`. `npx` refreshes the MCP service when the host reconnects or restarts it; Runtime updates remain independent.
30
-
31
- ## Tool groups
32
-
33
- - Authentication: `lemon_auth_status`, `lemon_auth_save_api_key`, `lemon_auth_clear`
34
- - Account context: `lemon_account_current`, `lemon_account_list`, `lemon_account_switch`, `lemon_account_select`, `lemon_account_clear`
35
- - ACC/SCM/ERP actions: `lemon_action_search`, `lemon_action_show`, `lemon_action_read_doc`, `lemon_action_run`
36
- - Independent invoicing: `lemon_invoice_read_doc`, `lemon_invoice_api`, `lemon_invoice_run_helper`
37
-
38
- `stdout` is reserved for MCP JSON-RPC. CLI and Runtime output is captured and returned as MCP Tool content; service diagnostics use `stderr` only.
34
+ 发布后可使用 `npx --yes --prefer-online @lemonbeijing/lemonclaw-mcp-service@latest`。MCP Host 重连或重启服务时,`npx` 会刷新 MCP 包;Runtime 更新与 MCP 包更新相互独立。
35
+
36
+ ## Tool 分组
37
+
38
+ - 账套上下文:`lemon_account_current`、`lemon_account_list`、`lemon_account_switch`、`lemon_account_select`、`lemon_account_clear`
39
+ - ACC/SCM/ERP 业务:`lemon_action_search`、`lemon_action_show`、`lemon_action_read_doc`、`lemon_action_run`
40
+ - 独立开票:`lemon_invoice_read_doc`、`lemon_invoice_api`、`lemon_invoice_run_helper`
41
+
42
+ `stdout` 仅用于 MCP JSON-RPC。CLI 和 Runtime 输出会被捕获并作为 MCP Tool 内容返回;服务诊断只使用 `stderr`。
43
+
44
+ 认证是 Tool 的内部前置条件。不要通过提示词或 Tool 输入发送 API Key;需要更换凭据时,应更新 MCP Host 中的 `LEMONCLAW_API_KEY` 并重新连接。
@@ -3279,8 +3279,8 @@ var require_package = __commonJS({
3279
3279
  "package.json"(exports2, module2) {
3280
3280
  module2.exports = {
3281
3281
  name: "@lemonbeijing/lemonclaw-mcp-service",
3282
- version: "0.1.2",
3283
- description: "Local stdio MCP service for LemonClaw portable Runtime.",
3282
+ version: "0.1.3",
3283
+ description: "\u7528\u4E8E\u67E5\u8BE2\u548C\u64CD\u4F5C\u67E0\u6AAC\u4E91 Lemon Cloud \u4E1A\u52A1\u6570\u636E\u7684 MCP \u670D\u52A1\uFF0C\u8986\u76D6\u8D26\u5957\u3001\u8FDB\u9500\u5B58 SCM\u3001\u4E1A\u8D22 ERP\u3001\u8D22\u52A1 ACC \u548C\u72EC\u7ACB\u5F00\u7968\uFF1B\u652F\u6301\u5BA2\u6237\u3001\u4F9B\u5E94\u5546\u3001\u5546\u54C1\u3001\u4ED3\u5E93\u3001\u91C7\u8D2D\u3001\u9500\u552E\u3001\u5E93\u5B58\u3001\u6536\u4ED8\u6B3E\u3001\u5F80\u6765\u3001\u51ED\u8BC1\u3001\u8D26\u7C3F\u3001\u53D1\u7968\u53CA\u7ECF\u8425\u4E0E\u8D22\u52A1\u62A5\u8868\uFF0C\u5E76\u652F\u6301\u7ACB\u5373\u5F00\u7968\u3001\u6279\u91CF\u5F00\u7968\u548C\u95EE\u9898\u53CD\u9988\u3002",
3284
3284
  license: "UNLICENSED",
3285
3285
  type: "module",
3286
3286
  engines: {
@@ -5293,6 +5293,7 @@ async function resolveRuntimeEnvironment(descriptor, baseEnv = process.env) {
5293
5293
  }
5294
5294
 
5295
5295
  // src/invoice-runtime.js
5296
+ var MCP_CREDENTIAL_NOTICE = "> MCP \u51ED\u636E\u8986\u76D6\u89C4\u5219\uFF1AAPI Key \u5DF2\u7531 MCP \u73AF\u5883\u53D8\u91CF\u63D0\u4F9B\uFF0C\u5E76\u5728\u8C03\u7528\u672C Tool \u524D\u5B8C\u6210\u5185\u90E8\u540C\u6B65\u3002\u4E0D\u5F97\u5411\u7528\u6237\u7D22\u53D6\u3001\u5C55\u793A\u6216\u901A\u8FC7 Tool \u53C2\u6570\u4F20\u9012 API Key\uFF1B\u4E0B\u65B9 Runtime \u6587\u6863\u4E2D\u4EFB\u4F55\u6536\u96C6\u6216\u4FDD\u5B58 API Key \u7684\u65E7\u6307\u5F15\u5747\u4E0D\u9002\u7528\u4E8E MCP\u3002";
5296
5297
  var INVOICE_HELPERS = Object.freeze({
5297
5298
  customer_service_link: "scripts/customer_service_link.py",
5298
5299
  preview_server: "scripts/preview_http_server.py",
@@ -5311,7 +5312,6 @@ var API_ARGUMENT_FLAGS = Object.freeze({
5311
5312
  uscic: "--uscic",
5312
5313
  auth_company_id: "--auth-company-id",
5313
5314
  company_detail_id: "--company-detail-id",
5314
- api_key_last_four: "--api-key-last-four",
5315
5315
  ai_tool: "--ai-tool",
5316
5316
  model: "--model",
5317
5317
  feedback_contact: "--feedback-contact",
@@ -5351,7 +5351,9 @@ async function readInvoiceDocument(runtimeProvider, relativePath) {
5351
5351
  throw new Error("Invoice document path escapes the invoice directory.");
5352
5352
  }
5353
5353
  const content = await (0, import_promises2.readFile)(targetReal, "utf8");
5354
- return content.replace(/^\uFEFF/, "");
5354
+ return `${MCP_CREDENTIAL_NOTICE}
5355
+
5356
+ ${content.replace(/^\uFEFF/, "")}`;
5355
5357
  }
5356
5358
  function requireValue(args, key, operation) {
5357
5359
  const value = args[key];
@@ -5390,9 +5392,12 @@ async function runInvoiceApi(runtimeProvider, args) {
5390
5392
  if (args.user_confirmed !== true) {
5391
5393
  throw new Error("SkillInvoiceIssue requires explicit user confirmation.");
5392
5394
  }
5393
- for (const key of ["eiscid", "api_key_last_four", "ai_tool", "model"]) {
5395
+ for (const key of ["eiscid", "ai_tool", "model"]) {
5394
5396
  requireValue(args, key, operation);
5395
5397
  }
5398
+ if (!String(runtime.apiKeyLastFour || "").trim()) {
5399
+ throw new Error("SkillInvoiceIssue requires the configured MCP API Key.");
5400
+ }
5396
5401
  if (args.payload === void 0 && !args.payload_path) {
5397
5402
  throw new Error("SkillInvoiceIssue requires payload or payload_path.");
5398
5403
  }
@@ -5401,7 +5406,9 @@ async function runInvoiceApi(runtimeProvider, args) {
5401
5406
  const command = [script, "--action", operation];
5402
5407
  appendApiArguments(command, args);
5403
5408
  if (payloadPath) command.push("--payload-path", String(payloadPath));
5404
- if (operation === "SkillInvoiceIssue") command.push("--issue-confirm", "1");
5409
+ if (operation === "SkillInvoiceIssue") {
5410
+ command.push("--api-key-last-four", runtime.apiKeyLastFour, "--issue-confirm", "1");
5411
+ }
5405
5412
  return runProcess(runtime.python, command, {
5406
5413
  cwd: runtime.runtimeRoot,
5407
5414
  env: runtime.env,
@@ -5427,6 +5434,155 @@ var invoiceHelperNames = Object.freeze(Object.keys(INVOICE_HELPERS));
5427
5434
 
5428
5435
  // src/runtime-manager.js
5429
5436
  var import_runtime_core2 = __toESM(require_runtime_core(), 1);
5437
+
5438
+ // src/runtime-auth.js
5439
+ var API_KEY_ENVIRONMENT_VARIABLE = "LEMONCLAW_API_KEY";
5440
+ var ENSURE_API_KEY_PROGRAM = String.raw`
5441
+ import base64
5442
+ import ctypes
5443
+ import hmac
5444
+ import json
5445
+ import os
5446
+ import sys
5447
+ from pathlib import Path
5448
+
5449
+ skill_root = sys.argv[1]
5450
+ sys.path.insert(0, skill_root)
5451
+ from auth import auth as lemon_auth
5452
+
5453
+
5454
+ def credential_path():
5455
+ if os.name == "nt":
5456
+ appdata = os.environ.get("APPDATA")
5457
+ return Path(appdata) / "LemonAuthAgent" / "api-key.dat" if appdata else None
5458
+ config_root = os.environ.get("XDG_CONFIG_HOME")
5459
+ root = Path(config_root) if config_root else Path.home() / ".config"
5460
+ return root / "lemon-auth-agent" / "api-key.dat"
5461
+
5462
+
5463
+ def unprotect_windows(value):
5464
+ try:
5465
+ from ctypes import wintypes
5466
+
5467
+ encrypted = base64.b64decode(value.strip(), validate=True)
5468
+ if not encrypted:
5469
+ return None
5470
+
5471
+ class DataBlob(ctypes.Structure):
5472
+ _fields_ = [
5473
+ ("cbData", wintypes.DWORD),
5474
+ ("pbData", ctypes.POINTER(ctypes.c_ubyte)),
5475
+ ]
5476
+
5477
+ source_buffer = (ctypes.c_ubyte * len(encrypted)).from_buffer_copy(encrypted)
5478
+ source = DataBlob(
5479
+ len(encrypted), ctypes.cast(source_buffer, ctypes.POINTER(ctypes.c_ubyte))
5480
+ )
5481
+ target = DataBlob()
5482
+ crypt32 = ctypes.WinDLL("crypt32", use_last_error=True)
5483
+ crypt32.CryptUnprotectData.argtypes = [
5484
+ ctypes.POINTER(DataBlob),
5485
+ ctypes.c_void_p,
5486
+ ctypes.c_void_p,
5487
+ ctypes.c_void_p,
5488
+ ctypes.c_void_p,
5489
+ wintypes.DWORD,
5490
+ ctypes.POINTER(DataBlob),
5491
+ ]
5492
+ crypt32.CryptUnprotectData.restype = wintypes.BOOL
5493
+ if not crypt32.CryptUnprotectData(
5494
+ ctypes.byref(source), None, None, None, None, 1, ctypes.byref(target)
5495
+ ):
5496
+ return None
5497
+ try:
5498
+ return ctypes.string_at(target.pbData, target.cbData).decode("utf-8")
5499
+ finally:
5500
+ kernel32 = ctypes.WinDLL("kernel32", use_last_error=True)
5501
+ kernel32.LocalFree.argtypes = [ctypes.c_void_p]
5502
+ kernel32.LocalFree.restype = ctypes.c_void_p
5503
+ kernel32.LocalFree(ctypes.cast(target.pbData, ctypes.c_void_p))
5504
+ except Exception:
5505
+ return None
5506
+
5507
+
5508
+ def current_api_key():
5509
+ path = credential_path()
5510
+ if path is None or not path.is_file():
5511
+ return None
5512
+ try:
5513
+ stored = path.read_text(encoding="utf-8").strip()
5514
+ except (OSError, UnicodeError):
5515
+ return None
5516
+ if not stored:
5517
+ return None
5518
+ return unprotect_windows(stored) if os.name == "nt" else stored
5519
+
5520
+
5521
+ api_key = sys.stdin.read().strip()
5522
+ if not api_key:
5523
+ print(json.dumps({"ok": False, "error": "missing_api_key", "message": "Missing LEMONCLAW_API_KEY."}))
5524
+ raise SystemExit(2)
5525
+
5526
+ existing = current_api_key()
5527
+ if existing is not None and hmac.compare_digest(existing, api_key):
5528
+ result = {"ok": True, "data": {"saved": False, "unchanged": True}}
5529
+ else:
5530
+ result = lemon_auth.save_api_key(api_key)
5531
+
5532
+ print(json.dumps(result, ensure_ascii=False, separators=(",", ":")))
5533
+ `;
5534
+ function withoutApiKey(environment = {}) {
5535
+ const sanitized = { ...environment };
5536
+ delete sanitized[API_KEY_ENVIRONMENT_VARIABLE];
5537
+ return sanitized;
5538
+ }
5539
+ function authenticationFailure(result) {
5540
+ if (result.timedOut) return "LemonClaw API Key setup timed out.";
5541
+ if (result.outputLimitExceeded) return "LemonClaw API Key setup returned too much output.";
5542
+ if (result.spawnError) return `Unable to start LemonClaw authentication: ${result.spawnError.message}`;
5543
+ return String(result.stderr || result.stdout || "LemonClaw API Key setup failed.").trim().slice(0, 2e3);
5544
+ }
5545
+ async function ensureRuntimeApiKey(runtime, options = {}) {
5546
+ if (!runtime?.python || !runtime?.runtimeRoot || !runtime?.skillRoot) {
5547
+ throw new Error("Resolved Runtime environment is incomplete.");
5548
+ }
5549
+ const sourceEnvironment = options.env || process.env;
5550
+ const apiKey = String(sourceEnvironment[API_KEY_ENVIRONMENT_VARIABLE] || "").trim();
5551
+ if (!apiKey) {
5552
+ throw new Error(
5553
+ `Missing ${API_KEY_ENVIRONMENT_VARIABLE}. Configure it in the LemonClaw MCP environment and reconnect.`
5554
+ );
5555
+ }
5556
+ const run = options.run || runProcess;
5557
+ const result = await run(runtime.python, ["-c", ENSURE_API_KEY_PROGRAM, runtime.skillRoot], {
5558
+ cwd: runtime.runtimeRoot,
5559
+ env: withoutApiKey(runtime.env),
5560
+ stdin: apiKey,
5561
+ timeoutMs: Math.max(1, Number(options.timeoutMs || 6e4))
5562
+ });
5563
+ if (result.code !== 0 || result.timedOut || result.outputLimitExceeded || result.spawnError) {
5564
+ throw new Error(authenticationFailure(result));
5565
+ }
5566
+ let payload;
5567
+ try {
5568
+ payload = JSON.parse(String(result.stdout || "").trim());
5569
+ } catch {
5570
+ throw new Error("LemonClaw authentication returned an invalid response.");
5571
+ }
5572
+ if (payload?.ok !== true) {
5573
+ throw new Error(String(payload?.message || payload?.error || "LemonClaw API Key setup failed."));
5574
+ }
5575
+ return {
5576
+ apiKeyLastFour: apiKey.slice(-4),
5577
+ saved: payload?.data?.saved === true,
5578
+ unchanged: payload?.data?.unchanged === true
5579
+ };
5580
+ }
5581
+ function removeApiKeyFromEnvironment(environment) {
5582
+ return withoutApiKey(environment);
5583
+ }
5584
+
5585
+ // src/runtime-manager.js
5430
5586
  var { publicError } = import_runtime_core2.default.errors;
5431
5587
  var {
5432
5588
  bootstrapRuntime,
@@ -5464,6 +5620,8 @@ function createRuntimeManager(options = {}) {
5464
5620
  };
5465
5621
  const run = options.runProcess || runProcess;
5466
5622
  const makeEnvironment = options.resolveRuntimeEnvironment || resolveRuntimeEnvironment;
5623
+ const ensureApiKey = options.ensureRuntimeApiKey || ensureRuntimeApiKey;
5624
+ let authenticationQueue = Promise.resolve();
5467
5625
  install.cleanupAbandonedInstallLock({ env });
5468
5626
  async function resolveDescriptor(mode = "current-or-install") {
5469
5627
  if (mode === "auto") return install.maybeAutoUpdate({ env });
@@ -5472,7 +5630,18 @@ function createRuntimeManager(options = {}) {
5472
5630
  return install.bootstrapRuntime({ env, waitForPeer: true });
5473
5631
  }
5474
5632
  async function resolveEnvironment(mode = "current-or-install") {
5475
- return makeEnvironment(await resolveDescriptor(mode), env);
5633
+ const runtime = await makeEnvironment(await resolveDescriptor(mode), env);
5634
+ const authenticationTask = authenticationQueue.then(() => ensureApiKey(runtime, { env, run }));
5635
+ authenticationQueue = authenticationTask.then(
5636
+ () => void 0,
5637
+ () => void 0
5638
+ );
5639
+ const authentication = await authenticationTask;
5640
+ return {
5641
+ ...runtime,
5642
+ apiKeyLastFour: authentication.apiKeyLastFour,
5643
+ env: removeApiKeyFromEnvironment(runtime.env)
5644
+ };
5476
5645
  }
5477
5646
  async function runCli(args, runOptions = {}) {
5478
5647
  try {
@@ -5491,47 +5660,6 @@ function createRuntimeManager(options = {}) {
5491
5660
  return { resolveDescriptor, resolveEnvironment, runCli };
5492
5661
  }
5493
5662
 
5494
- // src/runtime-auth.js
5495
- var AUTH_PROGRAM = String.raw`
5496
- import json
5497
- import sys
5498
-
5499
- operation = sys.argv[1]
5500
- skill_root = sys.argv[2]
5501
- sys.path.insert(0, skill_root)
5502
- from auth import auth as lemon_auth
5503
-
5504
- if operation == "status":
5505
- result = lemon_auth.auth_status()
5506
- elif operation == "save_api_key":
5507
- result = lemon_auth.save_api_key(sys.stdin.read())
5508
- elif operation == "clear":
5509
- result = lemon_auth.clear_auth()
5510
- else:
5511
- raise SystemExit("unsupported auth operation")
5512
-
5513
- print(json.dumps(result, ensure_ascii=False, separators=(",", ":")))
5514
- `;
5515
- async function runRuntimeAuth(runtimeProvider, args, options = {}) {
5516
- const resolveRuntime = options.resolveRuntime || runtimeProvider;
5517
- const run = options.run || runProcess;
5518
- if (typeof resolveRuntime !== "function") throw new Error("Runtime provider is required.");
5519
- const runtime = await resolveRuntime("current-or-install");
5520
- const operation = String(args.operation || "");
5521
- if (!["status", "save_api_key", "clear"].includes(operation)) {
5522
- throw new Error("Unsupported Runtime authentication operation.");
5523
- }
5524
- if (operation === "save_api_key" && !String(args.api_key || "").trim()) {
5525
- throw new Error("API Key is required.");
5526
- }
5527
- return run(runtime.python, ["-c", AUTH_PROGRAM, operation, runtime.skillRoot], {
5528
- cwd: runtime.runtimeRoot,
5529
- env: runtime.env,
5530
- stdin: operation === "save_api_key" ? String(args.api_key) : void 0,
5531
- timeoutMs: Math.max(1, Number(args.timeout_seconds || 60)) * 1e3
5532
- });
5533
- }
5534
-
5535
5663
  // src/tool-result.js
5536
5664
  function publicFailure(result) {
5537
5665
  if (result.timedOut) return "LemonClaw command timed out.";
@@ -5566,8 +5694,8 @@ function toolError(error) {
5566
5694
  }
5567
5695
 
5568
5696
  // src/server.js
5569
- var productSchema = z.enum(["acc", "scm", "erp"]);
5570
- var timeoutSchema = z.number().int().min(1).max(600).default(120);
5697
+ var productSchema = z.enum(["acc", "scm", "erp"]).describe("\u4E1A\u52A1\u4EA7\u54C1\uFF1Aacc=\u8D22\u52A1\uFF0Cscm=\u8FDB\u9500\u5B58\uFF0Cerp=\u4E1A\u8D22\uFF1B\u5FC5\u987B\u4E0E\u5F53\u524D\u6240\u9009\u8D26\u5957\u4EA7\u54C1\u4E00\u81F4\u3002");
5698
+ var timeoutSchema = z.number().int().min(1).max(600).default(120).describe("\u672C\u6B21\u64CD\u4F5C\u7684\u8D85\u65F6\u65F6\u95F4\uFF0C\u5355\u4F4D\u4E3A\u79D2\uFF0C\u53D6\u503C\u8303\u56F4 1 \u81F3 600\u3002");
5571
5699
  var optionalText = z.string().min(1).optional();
5572
5700
  var readOnlyAnnotations = {
5573
5701
  readOnlyHint: true,
@@ -5602,76 +5730,9 @@ function createLemonClawServer(options = {}) {
5602
5730
  const runCli = options.runCli || runtimeManager.runCli;
5603
5731
  const resolveRuntime = options.resolveRuntime || runtimeManager.resolveEnvironment;
5604
5732
  const server = new import_server.McpServer(
5605
- { name: "lemonclaw", version: "0.1.2" },
5733
+ { name: "lemonclaw", version: "0.1.3" },
5606
5734
  {
5607
- instructions: "Use standard API Key authentication: check lemon_auth_status and, when unavailable, request the user's API Key and pass it only to lemon_auth_save_api_key. Never use browser or device-flow authentication. For ACC, SCM, and ERP, determine the product and account first, then use lemon_action_search, lemon_action_show, read every document exposed by show with lemon_action_read_doc, and only then call lemon_action_run. Never guess action parameters. Independent invoicing uses only the lemon_invoice_* tools and requires its Runtime documents."
5608
- }
5609
- );
5610
- server.registerTool(
5611
- "lemon_auth_status",
5612
- {
5613
- title: "Check LemonClaw API Key authentication",
5614
- description: "Check whether the current user's standard LemonClaw API Key can provide a token. This uses the Runtime authentication helper and never returns the API Key or token.",
5615
- inputSchema: z.object({
5616
- timeout_seconds: z.number().int().min(1).max(120).default(60)
5617
- }),
5618
- annotations: readOnlyAnnotations
5619
- },
5620
- async (args) => {
5621
- try {
5622
- return cliToolResult(await runRuntimeAuth(resolveRuntime, { ...args, operation: "status" }));
5623
- } catch (error) {
5624
- return toolError(error);
5625
- }
5626
- }
5627
- );
5628
- server.registerTool(
5629
- "lemon_auth_save_api_key",
5630
- {
5631
- title: "Save LemonClaw API Key",
5632
- description: "Save an API Key with the standard Runtime authentication helper for the current operating-system user. The key is sent to Runtime through stdin, is not placed in process arguments, and is never returned.",
5633
- inputSchema: z.object({
5634
- api_key: z.string().min(1),
5635
- timeout_seconds: z.number().int().min(1).max(120).default(60)
5636
- }),
5637
- annotations: {
5638
- readOnlyHint: false,
5639
- destructiveHint: false,
5640
- idempotentHint: false,
5641
- openWorldHint: false
5642
- }
5643
- },
5644
- async (args) => {
5645
- try {
5646
- return cliToolResult(
5647
- await runRuntimeAuth(resolveRuntime, { ...args, operation: "save_api_key" })
5648
- );
5649
- } catch (error) {
5650
- return toolError(error);
5651
- }
5652
- }
5653
- );
5654
- server.registerTool(
5655
- "lemon_auth_clear",
5656
- {
5657
- title: "Clear LemonClaw API Key authentication",
5658
- description: "Clear the current user's standard LemonClaw API Key and token cache without clearing account context. Use only when the user explicitly requests it.",
5659
- inputSchema: z.object({
5660
- timeout_seconds: z.number().int().min(1).max(120).default(60)
5661
- }),
5662
- annotations: {
5663
- readOnlyHint: false,
5664
- destructiveHint: true,
5665
- idempotentHint: true,
5666
- openWorldHint: false
5667
- }
5668
- },
5669
- async (args) => {
5670
- try {
5671
- return cliToolResult(await runRuntimeAuth(resolveRuntime, { ...args, operation: "clear" }));
5672
- } catch (error) {
5673
- return toolError(error);
5674
- }
5735
+ instructions: "LemonClaw \u7684 API Key \u4EC5\u7531 MCP \u670D\u52A1\u73AF\u5883\u53D8\u91CF\u63D0\u4F9B\uFF0C\u4E0D\u5F97\u5728\u5BF9\u8BDD\u6216 Tool \u53C2\u6570\u4E2D\u7D22\u53D6\u3001\u63A5\u6536\u3001\u5C55\u793A\u6216\u4F20\u9012\u3002\u5904\u7406 ACC\u3001SCM\u3001ERP \u4E1A\u52A1\u524D\uFF0C\u5148\u786E\u5B9A\u4EA7\u54C1\u5E76\u83B7\u53D6\u6216\u5207\u6362\u8D26\u5957\uFF1B\u968F\u540E\u4F9D\u6B21\u8C03\u7528 lemon_action_search\u3001lemon_action_show\u3001lemon_action_read_doc \u8BFB\u53D6 show \u8FD4\u56DE\u7684\u5168\u90E8\u5B9E\u9645\u6587\u6863\uFF0C\u6700\u540E\u624D\u53EF\u8C03\u7528 lemon_action_run\uFF0C\u4E25\u7981\u731C\u6D4B Action \u548C\u53C2\u6570\u3002\u72EC\u7ACB\u5F00\u7968\u53EA\u4F7F\u7528 lemon_invoice_* Tools\uFF0C\u5E76\u5148\u8BFB\u53D6 Runtime \u5F00\u7968\u6587\u6863\uFF1BRuntime \u6587\u6863\u4E2D\u4EFB\u4F55\u8981\u6C42\u6536\u96C6\u6216\u4FDD\u5B58 API Key \u7684\u65E7\u6307\u5F15\u5747\u4E0D\u9002\u7528\u4E8E MCP\uFF0C\u56E0\u4E3A\u6BCF\u6B21 Tool \u8C03\u7528\u524D\u90FD\u5DF2\u5728\u5185\u90E8\u5B8C\u6210\u8BA4\u8BC1\u3002"
5675
5736
  }
5676
5737
  );
5677
5738
  registerCliTool(
@@ -5679,8 +5740,8 @@ function createLemonClawServer(options = {}) {
5679
5740
  runCli,
5680
5741
  "lemon_account_current",
5681
5742
  {
5682
- title: "Get current Lemon account context",
5683
- description: "Read the current product and selected account set from the existing local account context. Call this before ACC, SCM, or ERP business actions.",
5743
+ title: "\u83B7\u53D6\u5F53\u524D\u67E0\u6AAC\u4E91\u8D26\u5957",
5744
+ description: "\u83B7\u53D6\u5F53\u524D\u9009\u4E2D\u7684\u67E0\u6AAC\u4E91\u4EA7\u54C1\u548C\u8D26\u5957\u4FE1\u606F\u3002\u6267\u884C ACC \u8D22\u52A1\u3001SCM \u8FDB\u9500\u5B58\u6216 ERP \u4E1A\u8D22\u4E1A\u52A1\u524D\u5E94\u5148\u8C03\u7528\u672C\u5DE5\u5177\uFF0C\u4EE5\u786E\u8BA4\u540E\u7EED Action \u4F7F\u7528\u7684 product \u4E0E\u5F53\u524D\u8D26\u5957\u4E00\u81F4\uFF1B\u672C\u5DE5\u5177\u4E0D\u4F1A\u5207\u6362\u6216\u4FEE\u6539\u8D26\u5957\u3002",
5684
5745
  inputSchema: z.object({ timeout_seconds: timeoutSchema }),
5685
5746
  annotations: readOnlyAnnotations
5686
5747
  },
@@ -5694,10 +5755,10 @@ function createLemonClawServer(options = {}) {
5694
5755
  runCli,
5695
5756
  "lemon_account_list",
5696
5757
  {
5697
- title: "List Lemon account sets",
5698
- description: "List account-set candidates and cache their returned indexes for a later lemon_account_select call. Use only when switch has no usable candidates or the user asks to list accounts.",
5758
+ title: "\u5217\u51FA\u67E0\u6AAC\u4E91\u8D26\u5957",
5759
+ description: "\u5217\u51FA\u5F53\u524D\u7528\u6237\u53EF\u7528\u7684\u67E0\u6AAC\u4E91\u8D26\u5957\uFF0C\u5E76\u7F13\u5B58\u8FD4\u56DE\u7684\u5019\u9009\u5E8F\u53F7\u4F9B lemon_account_select \u4F7F\u7528\u3002\u4EC5\u5F53 lemon_account_switch \u6CA1\u6709\u8FD4\u56DE\u53EF\u7528\u5019\u9009\uFF0C\u6216\u7528\u6237\u660E\u786E\u8981\u6C42\u67E5\u770B\u8D26\u5957\u5217\u8868\u65F6\u8C03\u7528\uFF1B\u4E0D\u8981\u4E3A\u4E86\u9009\u62E9\u5DF2\u6709\u5019\u9009\u800C\u91CD\u590D\u5237\u65B0\u5217\u8868\u3002",
5699
5760
  inputSchema: z.object({
5700
- dry_run: z.boolean().default(false),
5761
+ dry_run: z.boolean().default(false).describe("\u662F\u5426\u4EC5\u68C0\u67E5\u6D41\u7A0B\u800C\u4E0D\u5B9E\u9645\u66F4\u65B0\u672C\u5730\u5019\u9009\u7F13\u5B58\u3002"),
5701
5762
  timeout_seconds: timeoutSchema
5702
5763
  }),
5703
5764
  annotations: readOnlyAnnotations
@@ -5713,16 +5774,16 @@ function createLemonClawServer(options = {}) {
5713
5774
  runCli,
5714
5775
  "lemon_account_switch",
5715
5776
  {
5716
- title: "Switch Lemon account context",
5717
- description: "Match a product or account clue and switch when unique. If candidates are returned, present them to the user and select from that same candidate set; do not refresh it with account list.",
5777
+ title: "\u5339\u914D\u5E76\u5207\u6362\u67E0\u6AAC\u4E91\u8D26\u5957",
5778
+ description: "\u6839\u636E\u4EA7\u54C1\u3001\u8D26\u5957\u540D\u79F0\u3001\u7F16\u53F7\u6216\u7248\u672C\u7B49\u7EBF\u7D22\u5339\u914D\u5E76\u5207\u6362\u67E0\u6AAC\u4E91\u8D26\u5957\u3002\u552F\u4E00\u5339\u914D\u65F6\u53EF\u76F4\u63A5\u5207\u6362\uFF1B\u8FD4\u56DE\u591A\u4E2A\u5019\u9009\u65F6\uFF0C\u5E94\u5411\u7528\u6237\u5C55\u793A\u5E76\u901A\u8FC7 lemon_account_select \u4ECE\u540C\u4E00\u6279\u5019\u9009\u4E2D\u9009\u62E9\uFF0C\u4E0D\u8981\u8C03\u7528 lemon_account_list \u5237\u65B0\u5019\u9009\u3002",
5718
5779
  inputSchema: z.object({
5719
- query: optionalText,
5780
+ query: optionalText.describe("\u7528\u4E8E\u5339\u914D\u4EA7\u54C1\u3001\u8D26\u5957\u540D\u79F0\u3001\u7F16\u53F7\u6216\u7248\u672C\u7684\u7528\u6237\u7EBF\u7D22\u3002"),
5720
5781
  product: productSchema.optional(),
5721
5782
  asid: optionalText,
5722
5783
  serviceid: optionalText,
5723
5784
  name: optionalText,
5724
5785
  edition: optionalText,
5725
- dry_run: z.boolean().default(false),
5786
+ dry_run: z.boolean().default(false).describe("\u662F\u5426\u53EA\u9884\u89C8\u5339\u914D\u7ED3\u679C\u800C\u4E0D\u5B9E\u9645\u5207\u6362\u8D26\u5957\u3002"),
5726
5787
  timeout_seconds: timeoutSchema
5727
5788
  }),
5728
5789
  annotations: {
@@ -5750,10 +5811,10 @@ function createLemonClawServer(options = {}) {
5750
5811
  runCli,
5751
5812
  "lemon_account_select",
5752
5813
  {
5753
- title: "Select a Lemon account set",
5754
- description: "Select from the candidates cached by the most recent account switch or list. Prefer the returned index. Never invent an index or silently choose between duplicate names.",
5814
+ title: "\u9009\u62E9\u67E0\u6AAC\u4E91\u8D26\u5957\u5019\u9009",
5815
+ description: "\u4ECE\u6700\u8FD1\u4E00\u6B21 lemon_account_switch \u6216 lemon_account_list \u7F13\u5B58\u7684\u5019\u9009\u4E2D\u9009\u62E9\u8D26\u5957\u3002\u4F18\u5148\u4F7F\u7528\u5019\u9009\u8FD4\u56DE\u7684 index\uFF0C\u5E76\u4FDD\u6301\u5019\u9009\u4E2D\u7684 product \u548C\u6807\u8BC6\u4E0D\u53D8\uFF1B\u4E0D\u5F97\u7F16\u9020\u5E8F\u53F7\uFF0C\u4E5F\u4E0D\u5F97\u5728\u91CD\u540D\u8D26\u5957\u4E4B\u95F4\u9759\u9ED8\u9009\u62E9\u3002",
5755
5816
  inputSchema: z.object({
5756
- index: z.number().int().positive().optional(),
5817
+ index: z.number().int().positive().optional().describe("\u6700\u8FD1\u4E00\u6B21\u5019\u9009\u5217\u8868\u8FD4\u56DE\u7684\u5E8F\u53F7\u3002"),
5757
5818
  product: productSchema.optional(),
5758
5819
  asid: optionalText,
5759
5820
  serviceid: optionalText,
@@ -5761,7 +5822,7 @@ function createLemonClawServer(options = {}) {
5761
5822
  timeout_seconds: timeoutSchema
5762
5823
  }).refine(
5763
5824
  (value) => value.index !== void 0 || value.asid || value.serviceid || value.name,
5764
- "Provide index, asid, serviceid, or name from the latest candidate set."
5825
+ "\u5FC5\u987B\u63D0\u4F9B\u6700\u8FD1\u4E00\u6B21\u5019\u9009\u5217\u8868\u4E2D\u7684 index\u3001asid\u3001serviceid \u6216 name\u3002"
5765
5826
  ),
5766
5827
  annotations: {
5767
5828
  readOnlyHint: false,
@@ -5786,11 +5847,11 @@ function createLemonClawServer(options = {}) {
5786
5847
  runCli,
5787
5848
  "lemon_account_clear",
5788
5849
  {
5789
- title: "Clear Lemon account context",
5790
- description: "Clear saved account context without clearing authentication. Use all_products only when the user explicitly requests clearing every product context.",
5850
+ title: "\u6E05\u9664\u67E0\u6AAC\u4E91\u8D26\u5957\u4E0A\u4E0B\u6587",
5851
+ description: "\u6E05\u9664\u5DF2\u4FDD\u5B58\u7684\u67E0\u6AAC\u4E91\u8D26\u5957\u4E0A\u4E0B\u6587\uFF0C\u4F46\u4E0D\u4F1A\u6E05\u9664 API Key \u6216\u8BA4\u8BC1\u4FE1\u606F\u3002\u9ED8\u8BA4\u4EC5\u6E05\u9664\u6307\u5B9A\u6216\u5F53\u524D\u4EA7\u54C1\uFF1B\u53EA\u6709\u7528\u6237\u660E\u786E\u8981\u6C42\u6E05\u9664\u5168\u90E8\u4EA7\u54C1\u8D26\u5957\u65F6\uFF0C\u624D\u53EF\u5C06 all_products \u8BBE\u4E3A true\u3002",
5791
5852
  inputSchema: z.object({
5792
5853
  product: productSchema.optional(),
5793
- all_products: z.boolean().default(false),
5854
+ all_products: z.boolean().default(false).describe("\u662F\u5426\u6E05\u9664 ACC\u3001SCM\u3001ERP \u7684\u5168\u90E8\u8D26\u5957\u4E0A\u4E0B\u6587\u3002"),
5794
5855
  timeout_seconds: timeoutSchema
5795
5856
  }),
5796
5857
  annotations: {
@@ -5813,12 +5874,12 @@ function createLemonClawServer(options = {}) {
5813
5874
  runCli,
5814
5875
  "lemon_action_search",
5815
5876
  {
5816
- title: "Search Lemon business actions",
5817
- description: "Search for ACC, SCM, or ERP action candidates in one explicit product. Search does not select an action, create parameters, or execute business requests.",
5877
+ title: "\u641C\u7D22\u67E0\u6AAC\u4E91\u4E1A\u52A1\u80FD\u529B",
5878
+ description: "\u5728\u6307\u5B9A\u7684\u67E0\u6AAC\u4E91 ACC\u3001SCM \u6216 ERP \u4EA7\u54C1\u4E2D\u641C\u7D22\u4E0E\u7528\u6237\u9700\u6C42\u5339\u914D\u7684\u4E1A\u52A1\u80FD\u529B\u3002\u53EF\u641C\u7D22\u5BA2\u6237\u3001\u4F9B\u5E94\u5546\u3001\u5546\u54C1\u3001\u4ED3\u5E93\u7B49\u57FA\u7840\u8D44\u6599\uFF0C\u4EE5\u53CA\u91C7\u8D2D\u8BA2\u5355\u3001\u9500\u552E\u8BA2\u5355\u3001\u5E93\u5B58\u3001\u6536\u4ED8\u6B3E\u3001\u5F80\u6765\u3001\u51ED\u8BC1\u3001\u8D26\u7C3F\u3001\u53D1\u7968\u548C\u7ECF\u8425\u6216\u8D22\u52A1\u62A5\u8868\u7B49\u80FD\u529B\uFF1BERP \u8FD8\u8986\u76D6\u9500\u552E\u62A5\u4EF7\u3001\u4EF7\u683C\u8D44\u6599\u3001\u8BA2\u5355\u6C47\u603B\u3001\u5E93\u5B58\u8D26\u9F84\u3001\u6682\u4F30\u8C03\u6574\u548C\u5E94\u6536\u5E94\u4ED8\u9884\u8B66\u3002\u672C\u5DE5\u5177\u53EA\u8FD4\u56DE\u5F53\u524D\u4EA7\u54C1\u7684 Action \u5019\u9009\uFF0C\u4E0D\u9009\u62E9 Action\u3001\u4E0D\u751F\u6210\u4E1A\u52A1\u53C2\u6570\uFF0C\u4E5F\u4E0D\u6267\u884C\u67E5\u8BE2\u6216\u5199\u64CD\u4F5C\u3002",
5818
5879
  inputSchema: z.object({
5819
5880
  product: productSchema,
5820
- query: z.string().min(1),
5821
- limit: z.number().int().min(1).max(20).default(5)
5881
+ query: z.string().min(1).describe("\u7528\u6237\u7684\u81EA\u7136\u8BED\u8A00\u4E1A\u52A1\u9700\u6C42\uFF0C\u4F8B\u5982\u201C\u67E5\u8BE2\u672C\u6708\u91C7\u8D2D\u8BA2\u5355\u201D\u3002"),
5882
+ limit: z.number().int().min(1).max(20).default(5).describe("\u6700\u591A\u8FD4\u56DE\u7684\u5019\u9009\u6570\u91CF\u3002")
5822
5883
  }),
5823
5884
  annotations: readOnlyAnnotations
5824
5885
  },
@@ -5840,11 +5901,11 @@ function createLemonClawServer(options = {}) {
5840
5901
  runCli,
5841
5902
  "lemon_action_show",
5842
5903
  {
5843
- title: "Show a Lemon business action",
5844
- description: "Show one action's public contract and the documents that actually exist. A successful show does not prove the action is the unique semantic match.",
5904
+ title: "\u67E5\u770B\u67E0\u6AAC\u4E91\u4E1A\u52A1\u80FD\u529B\u5951\u7EA6",
5905
+ description: "\u67E5\u770B\u6307\u5B9A\u67E0\u6AAC\u4E91\u4E1A\u52A1 Action \u7684\u516C\u5F00\u8C03\u7528\u5951\u7EA6\u3001\u53C2\u6570\u7ED3\u6784\u53CA\u5B9E\u9645\u5B58\u5728\u7684\u8BF4\u660E\u6587\u6863\u3002\u67E5\u770B\u6210\u529F\u4E0D\u4EE3\u8868\u8BE5 Action \u5DF2\u7ECF\u662F\u7528\u6237\u9700\u6C42\u7684\u552F\u4E00\u5339\u914D\uFF1B\u5B58\u5728\u591A\u4E2A\u5408\u7406\u5019\u9009\u65F6\u4ECD\u9700\u7EE7\u7EED\u6BD4\u8F83\uFF0C\u5FC5\u8981\u65F6\u8BF7\u7528\u6237\u786E\u8BA4\u3002",
5845
5906
  inputSchema: z.object({
5846
5907
  product: productSchema,
5847
- action: z.string().min(1)
5908
+ action: z.string().min(1).describe("lemon_action_search \u5019\u9009\u8FD4\u56DE\u7684\u7CBE\u786E Action \u540D\u79F0\u3002")
5848
5909
  }),
5849
5910
  annotations: readOnlyAnnotations
5850
5911
  },
@@ -5858,12 +5919,12 @@ function createLemonClawServer(options = {}) {
5858
5919
  runCli,
5859
5920
  "lemon_action_read_doc",
5860
5921
  {
5861
- title: "Read a Lemon business action document",
5862
- description: "Read one registered ACTION, input, or output Markdown document. Read every document exposed by lemon_action_show for the final selected action before run.",
5922
+ title: "\u8BFB\u53D6\u67E0\u6AAC\u4E91\u4E1A\u52A1\u80FD\u529B\u6587\u6863",
5923
+ description: "\u8BFB\u53D6\u6307\u5B9A\u4E1A\u52A1 Action \u5DF2\u6CE8\u518C\u7684\u529F\u80FD\u8BF4\u660E\u3001\u8F93\u5165\u53C2\u6570\u6216\u8F93\u51FA\u7ED3\u679C\u6587\u6863\u3002\u6700\u7EC8\u9009\u62E9 Action \u540E\uFF0C\u5FC5\u987B\u5728\u6267\u884C\u524D\u8BFB\u53D6 lemon_action_show \u5B9E\u9645\u8FD4\u56DE\u7684\u5168\u90E8\u6587\u6863\uFF0C\u5E76\u4EE5\u6587\u6863\u5B9A\u4E49\u4E3A\u51C6\u6784\u9020\u53C2\u6570\u548C\u5C55\u793A\u7ED3\u679C\uFF1B\u4E0D\u5F97\u731C\u6D4B\u4E0D\u5B58\u5728\u7684\u6587\u6863\u6216\u5B57\u6BB5\u3002",
5863
5924
  inputSchema: z.object({
5864
5925
  product: productSchema,
5865
- action: z.string().min(1),
5866
- document: z.enum(["action", "input", "output"])
5926
+ action: z.string().min(1).describe("\u5DF2\u7ECF\u6838\u9A8C\u7684\u7CBE\u786E Action \u540D\u79F0\u3002"),
5927
+ document: z.enum(["action", "input", "output"]).describe("\u8981\u8BFB\u53D6\u7684\u6587\u6863\u7C7B\u578B\uFF1B\u53EA\u80FD\u9009\u62E9 lemon_action_show \u8FD4\u56DE\u4E3A\u5B9E\u9645\u5B58\u5728\u7684\u7C7B\u578B\u3002")
5867
5928
  }),
5868
5929
  annotations: readOnlyAnnotations
5869
5930
  },
@@ -5884,19 +5945,19 @@ function createLemonClawServer(options = {}) {
5884
5945
  runCli,
5885
5946
  "lemon_action_run",
5886
5947
  {
5887
- title: "Run a Lemon business action",
5888
- description: "Run one already-selected ACC, SCM, or ERP action with its documented nested query/body envelope. This tool never searches, guesses parameters, or executes independent invoicing. Set user_confirmed only after explicit confirmation of a documented write action.",
5948
+ title: "\u67E5\u8BE2\u6216\u6267\u884C\u67E0\u6AAC\u4E91\u4E1A\u52A1\u64CD\u4F5C",
5949
+ description: "\u6267\u884C\u5DF2\u901A\u8FC7\u68C0\u7D22\u548C\u6587\u6863\u6838\u9A8C\u7684\u67E0\u6AAC\u4E91 ACC\u3001SCM \u6216 ERP \u4E1A\u52A1\u64CD\u4F5C\u3002\u652F\u6301\u67E5\u8BE2\u5BA2\u6237\u3001\u4F9B\u5E94\u5546\u3001\u5546\u54C1\u3001\u4ED3\u5E93\u7B49\u57FA\u7840\u8D44\u6599\uFF0C\u4EE5\u53CA\u91C7\u8D2D\u8BA2\u5355\u3001\u9500\u552E\u8BA2\u5355\u3001\u5E93\u5B58\u3001\u6536\u4ED8\u6B3E\u3001\u5F80\u6765\u3001\u51ED\u8BC1\u3001\u8D26\u7C3F\u3001\u53D1\u7968\u548C\u7ECF\u8425\u6216\u8D22\u52A1\u62A5\u8868\uFF1BERP \u8FD8\u652F\u6301\u9500\u552E\u62A5\u4EF7\u3001\u4EF7\u683C\u8D44\u6599\u3001\u8BA2\u5355\u6C47\u603B\u3001\u5E93\u5B58\u8D26\u9F84\u3001\u6682\u4F30\u8C03\u6574\u548C\u5E94\u6536\u5E94\u4ED8\u9884\u8B66\u3002\u5BF9\u4E8E Action \u6587\u6863\u660E\u786E\u652F\u6301\u7684\u65B0\u589E\u3001\u4FEE\u6539\u3001\u63D0\u4EA4\u7B49\u5199\u64CD\u4F5C\uFF0C\u4EC5\u5728\u7528\u6237\u660E\u786E\u786E\u8BA4\u540E\u6267\u884C\u3002\u8C03\u7528\u524D\u5FC5\u987B\u5B8C\u6210 search\u3001show \u548C\u5168\u90E8\u6587\u6863\u8BFB\u53D6\uFF0C\u4E0D\u5F97\u731C\u6D4B\u53C2\u6570\uFF1B\u672C\u5DE5\u5177\u4E0D\u7528\u4E8E\u72EC\u7ACB\u5F00\u7968\u3002",
5889
5950
  inputSchema: z.object({
5890
5951
  product: productSchema,
5891
- action: z.string().min(1),
5952
+ action: z.string().min(1).describe("\u5DF2\u901A\u8FC7 search\u3001show \u548C\u6587\u6863\u6838\u9A8C\u7684\u7CBE\u786E Action \u540D\u79F0\u3002"),
5892
5953
  payload: z.object({
5893
- query: z.record(z.string(), z.unknown()).optional(),
5894
- body: z.union([z.record(z.string(), z.unknown()), z.array(z.unknown())]).optional(),
5895
- _outputMode: z.enum(["basic", "full"]).optional(),
5896
- _extraDisplayFields: z.array(z.string().min(1)).min(1).optional()
5897
- }).strict(),
5898
- user_confirmed: z.boolean().default(false),
5899
- dry_run: z.boolean().default(false),
5954
+ query: z.record(z.string(), z.unknown()).optional().describe("Action \u6587\u6863\u5B9A\u4E49\u7684 URL \u67E5\u8BE2\u53C2\u6570\uFF1B\u65E0\u53C2\u6570\u65F6\u6309\u6587\u6863\u8981\u6C42\u7701\u7565\u6216\u4F20\u7A7A\u5BF9\u8C61\u3002"),
5955
+ body: z.union([z.record(z.string(), z.unknown()), z.array(z.unknown())]).optional().describe("Action \u6587\u6863\u5B9A\u4E49\u7684\u8BF7\u6C42\u4F53\uFF0C\u5FC5\u987B\u4FDD\u6301\u6587\u6863\u89C4\u5B9A\u7684\u5BF9\u8C61\u6216\u6570\u7EC4\u7ED3\u6784\u3002"),
5956
+ _outputMode: z.enum(["basic", "full"]).optional().describe("\u6587\u6863\u5141\u8BB8\u65F6\u9009\u62E9\u57FA\u7840\u7ED3\u679C basic \u6216\u5B8C\u6574\u7ED3\u679C full\u3002"),
5957
+ _extraDisplayFields: z.array(z.string().min(1)).min(1).optional().describe("\u7528\u6237\u660E\u786E\u8981\u6C42\u989D\u5916\u5C55\u793A\u4E14 Action \u6587\u6863\u652F\u6301\u7684\u5B57\u6BB5\u540D\u79F0\u3002")
5958
+ }).strict().describe("\u4E25\u683C\u6309\u7167 Action \u6587\u6863\u6784\u9020\u7684\u5D4C\u5957 query/body \u8BF7\u6C42\u5305\u3002"),
5959
+ user_confirmed: z.boolean().default(false).describe("\u53EA\u6709\u7528\u6237\u660E\u786E\u786E\u8BA4\u8BE5 Action \u6587\u6863\u6807\u6CE8\u7684\u5199\u64CD\u4F5C\u65F6\u624D\u80FD\u8BBE\u4E3A true\u3002"),
5960
+ dry_run: z.boolean().default(false).describe("\u662F\u5426\u4EC5\u6821\u9A8C\u5E76\u9884\u6F14\uFF0C\u800C\u4E0D\u5B9E\u9645\u6267\u884C\u4E1A\u52A1\u8BF7\u6C42\u3002"),
5900
5961
  timeout_seconds: timeoutSchema
5901
5962
  }),
5902
5963
  annotations: {
@@ -5928,10 +5989,10 @@ function createLemonClawServer(options = {}) {
5928
5989
  server.registerTool(
5929
5990
  "lemon_invoice_read_doc",
5930
5991
  {
5931
- title: "Read Lemon independent-invoicing documentation",
5932
- description: "Read a Runtime document relative to the invoice directory. Start with SKILL.md, then read only the immediate, batch, or feedback flow and shared documents it directs you to.",
5992
+ title: "\u8BFB\u53D6\u67E0\u6AAC\u4E91\u72EC\u7ACB\u5F00\u7968\u6587\u6863",
5993
+ description: "\u8BFB\u53D6 LemonClaw Runtime \u72EC\u7ACB\u5F00\u7968\u76EE\u5F55\u5185\u7684\u56FA\u5B9A\u6D41\u7A0B\u6587\u6863\uFF0C\u53EA\u5141\u8BB8\u8BBF\u95EE\u8BE5\u76EE\u5F55\u4E2D\u7684 Markdown\u3001JSON \u6216\u6587\u672C\u6587\u4EF6\uFF0C\u4E0D\u80FD\u8BFB\u53D6\u4EFB\u610F\u672C\u5730\u6587\u4EF6\u3002\u5E94\u5148\u8BFB\u53D6 SKILL.md\uFF0C\u518D\u6309\u5176\u6307\u5F15\u8BFB\u53D6\u7ACB\u5373\u5F00\u7968\u3001\u6279\u91CF\u5F00\u7968\u3001\u95EE\u9898\u53CD\u9988\u53CA\u5171\u4EAB\u89C4\u5219\u6587\u6863\u3002",
5933
5994
  inputSchema: z.object({
5934
- path: z.string().min(1).describe("For example SKILL.md or references/immediate/flow.md")
5995
+ path: z.string().min(1).describe("\u5F00\u7968\u76EE\u5F55\u5185\u7684\u76F8\u5BF9\u6587\u6863\u8DEF\u5F84\uFF0C\u4F8B\u5982 SKILL.md \u6216 references/immediate/flow.md\u3002")
5935
5996
  }),
5936
5997
  annotations: readOnlyAnnotations
5937
5998
  },
@@ -5947,8 +6008,8 @@ function createLemonClawServer(options = {}) {
5947
6008
  server.registerTool(
5948
6009
  "lemon_invoice_api",
5949
6010
  {
5950
- title: "Call the Lemon independent-invoicing API adapter",
5951
- description: "Execute one documented independent-invoicing operation with Runtime Python. Read and follow the invoice documents first. SkillInvoiceIssue is blocked unless user_confirmed is true and required context is supplied.",
6011
+ title: "\u8C03\u7528\u67E0\u6AAC\u4E91\u72EC\u7ACB\u5F00\u7968\u63A5\u53E3",
6012
+ description: "\u6309\u7167\u72EC\u7ACB\u5F00\u7968\u6D41\u7A0B\u6587\u6863\u8C03\u7528\u56FA\u5B9A\u7684\u5F00\u7968\u63A5\u53E3\uFF0C\u652F\u6301\u516C\u53F8\u548C\u5BA2\u6237\u67E5\u8BE2\u3001\u767B\u5F55\u4EFB\u52A1\u72B6\u6001\u3001\u7A0E\u5C40\u8BA4\u8BC1\u72B6\u6001\u3001\u5269\u4F59\u989D\u5EA6\u3001\u7A0E\u76EE\u89E3\u6790\u3001\u7A0E\u5C40\u8BA4\u8BC1\u94FE\u3001\u6B63\u5F0F\u5F00\u7968\u53CA\u95EE\u9898\u53CD\u9988\u3002\u8C03\u7528\u524D\u5FC5\u987B\u8BFB\u53D6\u5BF9\u5E94\u6D41\u7A0B\u6587\u6863\u3002\u6B63\u5F0F\u5F00\u7968\u4EC5\u5728\u7528\u6237\u660E\u786E\u786E\u8BA4\u4E14\u5FC5\u9700\u4E0A\u4E0B\u6587\u5B8C\u6574\u65F6\u6267\u884C\uFF1B\u4E0D\u5F97\u901A\u8FC7\u53C2\u6570\u4F20\u9012 API Key\u3001Token \u6216\u5176\u4ED6\u8BA4\u8BC1\u51ED\u636E\u3002",
5952
6013
  inputSchema: z.object({
5953
6014
  operation: z.enum([
5954
6015
  "CompanyFullList",
@@ -5962,7 +6023,7 @@ function createLemonClawServer(options = {}) {
5962
6023
  "TaxBureauAuthChain",
5963
6024
  "SkillInvoiceIssue",
5964
6025
  "FeedbackSubmit"
5965
- ]),
6026
+ ]).describe("\u8981\u6267\u884C\u7684\u56FA\u5B9A\u5F00\u7968\u64CD\u4F5C\uFF0C\u5FC5\u987B\u6765\u81EA\u5DF2\u8BFB\u53D6\u7684\u5BF9\u5E94\u6D41\u7A0B\u6587\u6863\u3002"),
5966
6027
  eiscid: optionalText,
5967
6028
  filter_word: optionalText,
5968
6029
  company_name: optionalText,
@@ -5971,9 +6032,8 @@ function createLemonClawServer(options = {}) {
5971
6032
  uscic: optionalText,
5972
6033
  auth_company_id: optionalText,
5973
6034
  company_detail_id: optionalText,
5974
- payload: z.record(z.string(), z.unknown()).optional(),
5975
- payload_path: optionalText,
5976
- api_key_last_four: optionalText,
6035
+ payload: z.record(z.string(), z.unknown()).optional().describe("\u5BF9\u5E94\u64CD\u4F5C\u6587\u6863\u5B9A\u4E49\u7684\u8BF7\u6C42\u6570\u636E\uFF0C\u4E0D\u5F97\u6DFB\u52A0\u8BA4\u8BC1\u51ED\u636E\u3002"),
6036
+ payload_path: optionalText.describe("\u5BF9\u5E94\u6D41\u7A0B\u6587\u6863\u5141\u8BB8\u8BFB\u53D6\u7684\u672C\u5730\u8BF7\u6C42\u6570\u636E\u6587\u4EF6\u8DEF\u5F84\u3002"),
5977
6037
  ai_tool: optionalText,
5978
6038
  model: optionalText,
5979
6039
  feedback_contact: optionalText,
@@ -5984,7 +6044,7 @@ function createLemonClawServer(options = {}) {
5984
6044
  message_id: optionalText,
5985
6045
  context: optionalText,
5986
6046
  upload_file_path: optionalText,
5987
- user_confirmed: z.boolean().default(false),
6047
+ user_confirmed: z.boolean().default(false).describe("\u4EC5\u5728\u7528\u6237\u660E\u786E\u786E\u8BA4\u6B63\u5F0F\u5F00\u7968\u6216\u6587\u6863\u6807\u6CE8\u7684\u5199\u64CD\u4F5C\u540E\u8BBE\u4E3A true\u3002"),
5988
6048
  timeout_seconds: timeoutSchema
5989
6049
  }),
5990
6050
  annotations: {
@@ -6005,12 +6065,12 @@ function createLemonClawServer(options = {}) {
6005
6065
  server.registerTool(
6006
6066
  "lemon_invoice_run_helper",
6007
6067
  {
6008
- title: "Run a Lemon independent-invoicing helper",
6009
- description: "Run one whitelisted Runtime helper for invoice file parsing, validation, preview generation, preview serving, customer lookup, or customer-service output. Arguments must come from the invoice documents.",
6068
+ title: "\u8FD0\u884C\u67E0\u6AAC\u4E91\u72EC\u7ACB\u5F00\u7968\u8F85\u52A9\u7A0B\u5E8F",
6069
+ description: "\u8FD0\u884C\u72EC\u7ACB\u5F00\u7968\u6D41\u7A0B\u5185\u7F6E\u7684\u56FA\u5B9A\u767D\u540D\u5355\u8F85\u52A9\u7A0B\u5E8F\uFF0C\u7528\u4E8E Excel \u6216\u6570\u636E\u6587\u4EF6\u89E3\u6790\u3001JSON \u6821\u9A8C\u3001\u53D1\u7968\u9884\u89C8\u751F\u6210\u3001\u9884\u89C8\u670D\u52A1\u3001\u5BA2\u6237\u67E5\u8BE2\u53CA\u5BA2\u670D\u4FE1\u606F\u8F93\u51FA\u3002\u672C\u5DE5\u5177\u4E0D\u80FD\u6267\u884C\u4EFB\u610F\u7CFB\u7EDF\u547D\u4EE4\u3001\u4EFB\u610F Python \u811A\u672C\u6216\u767D\u540D\u5355\u4E4B\u5916\u7684\u7A0B\u5E8F\uFF1Boperation \u548C\u53C2\u6570\u5FC5\u987B\u6765\u81EA\u5DF2\u8BFB\u53D6\u7684\u5F00\u7968\u6D41\u7A0B\u6587\u6863\u3002",
6010
6070
  inputSchema: z.object({
6011
- operation: z.enum(invoiceHelperNames),
6012
- arguments: z.array(z.string()).max(30).default([]),
6013
- stdin: z.string().optional(),
6071
+ operation: z.enum(invoiceHelperNames).describe("\u8981\u8FD0\u884C\u7684\u767D\u540D\u5355\u8F85\u52A9\u64CD\u4F5C\uFF0C\u5FC5\u987B\u6765\u81EA\u5DF2\u8BFB\u53D6\u7684\u5F00\u7968\u6D41\u7A0B\u6587\u6863\u3002"),
6072
+ arguments: z.array(z.string()).max(30).default([]).describe("\u6309\u5BF9\u5E94\u6D41\u7A0B\u6587\u6863\u987A\u5E8F\u63D0\u4F9B\u7684\u8F85\u52A9\u7A0B\u5E8F\u53C2\u6570\uFF0C\u6700\u591A 30 \u9879\u3002"),
6073
+ stdin: z.string().optional().describe("\u4EC5\u5728\u5BF9\u5E94\u6D41\u7A0B\u6587\u6863\u8981\u6C42\u65F6\u4F20\u5165\u7684\u6807\u51C6\u8F93\u5165\u6587\u672C\u3002"),
6014
6074
  timeout_seconds: timeoutSchema
6015
6075
  }),
6016
6076
  annotations: {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lemonbeijing/lemonclaw-mcp-service",
3
- "version": "0.1.2",
4
- "description": "Local stdio MCP service for LemonClaw portable Runtime.",
3
+ "version": "0.1.3",
4
+ "description": "用于查询和操作柠檬云 Lemon Cloud 业务数据的 MCP 服务,覆盖账套、进销存 SCM、业财 ERP、财务 ACC 和独立开票;支持客户、供应商、商品、仓库、采购、销售、库存、收付款、往来、凭证、账簿、发票及经营与财务报表,并支持立即开票、批量开票和问题反馈。",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
7
7
  "engines": {