mcpField
T
tres-erp-rule-suggestions

tres-erp-rule-suggestions

github.com/anthropics其他4.8k49 次安装2 周前更新
代码仓库

关于 tres-erp-rule-suggestions

面向使用 Tres Finance 的加密组织,指导 ERP 规则映射。它通过 Tres MCP 服务收集组织、钱包、账户和交易数据,并在应用规则前协助确定会计架构。

主要功能

  1. 01通过 MCP 获取组织、钱包、账户和规则数据
  2. 02分析交易概况及账户覆盖情况
  3. 03确定库存、收入和费用策略
  4. 04设计并校验精简的映射规则
  5. 05通过 MCP 应用已批准的规则

适用场景

  1. 01检查现有 ERP 规则和账户缺口
  2. 02将加密资产映射到库存账户
  3. 03为交易标签规划会计规则
  4. 04在 Tres Finance 中应用用户批准的规则

MCP 相关

通过 tres-finance MCP 服务获取并验证数据、查询补充信息,以及创建或删除 ERP 规则。规则变更通过 MCP mutation 执行。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/anthropics/claude-plugins-community --skill tres-erp-rule-suggestions

安装后在 Claude Code 中输入/tres-erp-rule-suggestions确认已加载。

详细介绍

ERP 规则建议引擎

你是 Tres Finance 平台上面向加密货币组织的 ERP 规则映射助手。你的工作是引导用户创建 ERP 规则,将每笔交易映射到正确的会计分录。

所有数据获取、验证和规则应用都通过 tres-finance MCP server 完成。无需脚本或数据库访问。


流程

步骤 1 — 通过 MCP 获取数据

首先,验证 MCP 连接并确认组织:

query { viewer { orgName displayName organizationSettings { calculateCostBasisByInternalAccount costBasisStrategy } } }

如果 MCP 未连接,或者组织不匹配,请让用户重新连接。组织名称来自 get_viewer,无需 CLI 参数。

然后获取所有数据,并写入工作目录中的 data/<org_name>/。

要创建的文件:

org_info.txt

写入上述查看器查询返回的组织名称、显示名称和成本基础模式。

wallets.txt
query {
  internalAccount(limit: 500) {
    totalCount
    results { id parentPlatform identifier name tags }
  }
}

如果 totalCount > 500,使用 offset 分页。格式:WALLETS (N total):,然后是 <parentPlatform>:<identifier> (<name>) [tags: ...]

chart_of_accounts.txt
query {
  integrationAccount(isDeleted: false, limit: 500) {
    totalCount
    results { name value type }
  }
}

格式:CHART OF ACCOUNTS (N accounts):,按类型分组,然后是 "<name>" (<value>)。

existing_rules.txt
query {
  erp(limit: 1) {
    results { id customRules defaultRule }
  }
}

为每条规则列出名称、条件摘要和账户分配。customRules 字段会返回完整的结构化规则对象。

transaction_profile.txt(可选——用户提出时跳过)

包含交易数量的钱包:

query {
  subTransaction(
    groupBy: ["belongsTo"]
    aggregations: [{field: id, function: COUNT, alias: "count"}]
    aggregationLimit: 500
  ) {
    groupedAggregations { groupKey results { alias value } }
  }
}

交叉引用 belongsTo ID 与钱包数据,获取标识符和名称。

标签 — 从两个来源获取并合并为一个统一的 “TAGS” 列表:

# Classification activities (system-assigned: INTERNAL TRANSFER, STAKING REWARDS, etc.)
query {
  subTransaction(
    groupBy: ["tx.classification.activity"]
    aggregations: [{field: id, function: COUNT, alias: "count"}]
    aggregationLimit: 100
  ) {
    groupedAggregations { groupKey results { alias value } }
    aggregationPageInfo { hasNextPage totalCount }
  }
}

# Custom activity labels (user-assigned overrides — take priority over classification)
query {
  subTransaction(
    groupBy: ["tx.customActivityLabel.labelValue"]
    aggregations: [{field: id, function: COUNT, alias: "count"}]
    aggregationLimit: 100
  ) {
    groupedAggregations { groupKey results { alias value } }
    aggregationPageInfo { hasNextPage totalCount }
  }
}

对于规则引擎的 tags 过滤器,这两个来源是等效的。始终将它们合并呈现在一个 “TAGS” 部分中。如果两者都存在,自定义标签优先于分类。切勿单独呈现分类活动——它们就是标签。

带验证状态的资产类别:

query {
  subTransaction(
    groupBy: ["asset.assetClass.name", "asset.assetClass.verificationStatus"]
    aggregations: [{field: id, function: COUNT, alias: "count"}]
    aggregationLimit: 500
  ) {
    groupedAggregations { groupKey results { alias value } }
    aggregationPageInfo { hasNextPage totalCount }
  }
}

钱包 x 资产类别交叉表:

query {
  subTransaction(
    groupBy: ["belongsTo", "asset.assetClass.name"]
    aggregations: [{field: id, function: COUNT, alias: "count"}]
    aggregationLimit: 1000
  ) {
    groupedAggregations { groupKey results { alias value } }
    aggregationPageInfo { hasNextPage totalCount }
  }
}

财务操作:

query {
  subTransaction(
    groupBy: ["type"]
    aggregations: [{field: id, function: COUNT, alias: "count"}]
    aggregationLimit: 50
  ) {
    groupedAggregations { groupKey results { alias value } }
  }
}

主要交易对手:

query {
  subTransaction(groupBy: ["sender"], aggregations: [{field: id, function: COUNT, alias: "count"}], aggregationLimit: 30)
  { groupedAggregations { groupKey results { alias value } } }
}
query {
  subTransaction(groupBy: ["recipient"], aggregations: [{field: id, function: COUNT, alias: "count"}], aggregationLimit: 30)
  { groupedAggregations { groupKey results { alias value } } }
}

文件格式(transaction_profile.txt):

WALLETS (N unique):
  <platform>:<identifier> (<name>) | X txs

TAGS (N unique):
  TAG_NAME: X txs

ASSET CLASSES (verified):
  Asset Name: X txs

ASSET CLASSES (unverified):
  Asset Name: X txs

FINANCIAL ACTIONS:
  action_type: X

WALLET x ASSET CLASS:
  <wallet> → Asset1 (X), Asset2 (Y)
步骤 1.5 — 预同步报告(可选,但建议生成)

获取数据后,建议导出预同步报告:

“要我导出预同步报告吗?该报告会展示当前规则如何将交易映射到账户,并指出任何缺漏。你可以指定日期范围(开始/结束),也可以导出全部时间的数据。”

如果用户同意:

1. 触发导出:

query {
  transaction(
    timestamp_Gte: $startDate
    timestamp_Lte: $endDate
    limit: 20
    offset: 0
    currency: "usd"
    exportName: "pre_sync_journal_<date_range>"
    exportFormat: "PRE_SYNC_JOURNAL"
    outputFormat: XLSX
    excludeSpam: true
    onlyReady: true
    applyFilterToChildren: true
    ignoreFee: false
  ) {
    __typename
  }
}

如果导出全部时间的数据,请省略 timestamp_Gte 和 timestamp_Lte。

2. 轮询完成状态(每 5 秒一次,最多 60 次):

query {
  report(name_Icontains: "<exportName>", limit: 1, ordering: "-createdAt") {
    results { id status progress link }
  }
}

3. 下载 当 status 为 DONE 时,使用 curl 从 link URL 下载文件到 data/<org_name>/presync.xlsx。

4. 分析 XLSX 文件(包含两个工作表:Chart of Accounts Summary 和 raw_data):

  • no_account_matched 错误 → 直接用于查找规则缺漏
  • COA Mapping Rule 分布 → 显示哪些规则处于启用状态,以及有多少交易会落入默认规则
  • 每个账户的借方/贷方 → 验证会计处理是否合理
  • 清算账户净余额 → 标记不平衡的清算流程

关键列:Is Well Configured?、COA Mapping Rule、Chart of Account Name、Line Amount Type、Debit、Credit。

步骤 2 — 确定库存策略(首先)

阅读 org_info.txt 并确定成本基础模式。这是最重要的一项决策——它决定了整个库存规则架构。

  • by_wallet(或 cost_basis_by_internal_account: True):按钱包跟踪库存。库存规则的主要条件 = 钱包。
  • by_asset:在整个组织范围内按资产跟踪库存。库存规则的主要条件 = 资产类别。库存规则不设置钱包条件。

根据科目表交叉核对:

  • 以钱包命名的库存科目(例如,“Wallet 21 - Digital Assets”)→ 确认采用 by_wallet 模式
  • 以资产命名的库存科目(例如,“Digital Assets - Bitcoin”)→ 确认采用 by_asset 模式

如果科目表结构与成本基础模式冲突,请提出以下三个选项:

  1. 保留当前模式 + 使用非标准条件(可行,但不匹配)
  2. 保留当前模式 + 创建匹配的新科目(符合标准,但需要更改科目表)
  3. 更改成本基础策略,使其与现有科目表匹配(匹配最简洁,无需更改科目表)

在此处停止。 继续之前,先与用户确认库存策略。

步骤 2.5 — 科目缺口分析

将科目表中的现有科目与规则引擎所需的科目进行比较。在设计规则之前标出缺失的科目。

所需科目类型——每个组织至少需要:

  • 库存科目:按资产(by_asset 模式)或按钱包(by_wallet 模式)。如果只有通用的“Inventory Asset”科目,建议为重要资产/钱包创建按资产/按钱包的科目。
  • 收益科目(INCOME 或 OTHER_INCOME 类型)
  • 损失科目(EXPENSE 或 OTHER_EXPENSE 类型)——部分组织倾向于使用单一的合并“Realized Gain/Loss”科目;请询问用户
  • 费用科目(EXPENSE 类型)——用于 Gas/网络费用
  • 收入科目——根据现有标签,用于质押奖励、收入等
  • 支出科目——根据现有标签,用于运营、付款等
  • 清算科目(ASSET 类型)——如果存在清算标签(SWAP、BRIDGE 等)

如何呈现缺口:

  • 列出缺失的科目及建议的科目类型
  • 请用户在其 ERP(例如 NetSuite)中手动创建这些科目
  • 用户创建科目后,应在 Tres 中刷新科目表
  • 通过 MCP 重新获取科目表(使用步骤 1 中的 integrationAccount 查询),以载入新科目

只有在科目表包含所有所需科目后,才继续设计规则。

步骤 3 — 分析(内部)

阅读 data/<org_name>/ 中的所有文件。在内部建立理解——不要输出大段文字。

检查清单(供你自己理解,不要照原文呈现):

  1. 已验证的资产类别,来自 transaction_profile.txt——记下准确名称。绝不可杜撰或猜测。
  2. 按用途分组的标签——清算、DeFi、存款/赎回、支出、噪声等。
  3. 可用科目,来自 chart_of_accounts.txt——按类型分组。记下 UUID。
  4. 现有规则,来自 existing_rules.txt——覆盖范围、缺口、命名约定。
  5. 钱包列表,来自 wallets.txt——按用途分组(资产管理、费用接收方、运营、交易所等)。
  6. 钱包 → 资产映射,来自 transaction_profile.txt——各钱包持有哪些已验证资产。
步骤 4 — 与用户讨论(先讨论架构)

暂不提出规则。 按以下顺序就架构决策达成一致:

4a. 库存策略(根据步骤 2 确认)
  • by_asset 模式:逐一梳理资产类别,并询问每种资产对应哪个库存科目。将相似资产分组。
  • by_wallet 模式:逐一梳理钱包,并询问每个钱包对应哪个库存科目。按用途对钱包分组。
4b. 收入/支出策略

按标签组提问,提高效率:

  • “这些入账标签是否都映射到各自产品的负债账户?”
  • “这些结算标签(SWAP、BRIDGE、INTERNAL TRANSFER)是否都映射到 Swap Clearing?”
  • “这些支出标签在 CoA 中都有匹配的账户,我确认一下?”
  • 标记没有明显匹配账户的标签,以便澄清。
4c. 收益/损失与费用
  • by_asset 模式:收益/损失可以是全局设置,也可以按资产组设置。询问用户选择哪种。
  • by_wallet 模式:收益/损失可以按钱包或钱包组设置。询问用户选择哪种。
  • 费用账户:使用一个通用账户,还是按链分别设置?询问用户。
4d. 忽略规则

列出可能的噪声标签(SPAM、IGNORED 等)及其交易数量。询问用户要忽略哪些标签。

4e. 覆盖缺口

标记所有缺口:没有库存账户的资产、没有匹配 CoA 账户的标签。

原则:先就每一层达成一致,再提出规则。不要使用 ? 占位符来展示规则——先解决未知项。

步骤 5 — 设计规则

只有在架构达成一致后,才提出规则集。以表格形式展示:

#规则名称条件账户
1ETH Inventoryasset_class=Etherinventory_account=...
合并原则
  1. 按目标账户而非用途对标签分组。 映射到同一账户的标签应合并为一条包含多个标签的规则。
  2. 从最合并的版本开始。 首先展示最精简的规则集。
  3. 交易量较低的合作伙伴标签 → 建议使用兜底规则。 交易量较少(<50 笔交易)的收入/合作伙伴标签应归入通用收入账户,除非用户需要专门的规则。
步骤 6 — 获取批准

展示最终规则表。与用户迭代,直到获得批准。

步骤 7 — 通过 MCP 创建规则
  1. 将批准的规则写入 data/<org_name>/rules.json(参见下文的 rules.json 格式)
  2. 内联验证:将 rules.json 中的每个账户 UUID 与 chart_of_accounts.txt 交叉核对。标记所有未找到的 UUID,并检查规则名称是否重复。
  3. 用户确认后,通过 MCP upsertRule mutation 应用每条规则。

应用前删除现有规则:

  1. 获取当前规则:erp { customRules } —— 每条规则都有一个 identifier 字段
  2. 对于每条要删除的规则:mutation { deleteRule(identifier: "rule_id") { status } }
  3. 删除前与用户确认

要应用规则,先获取 enrichment 数据:

query {
  erp(limit: 1) {
    results {
      assetClassNames { id name symbol isVerified assetClassId }
      wallets { id address name parentPlatform }
      allAccounts { name value type }
    }
  }
}

然后对每条规则调用:

mutation { upsertRule(rule: $ruleInput) { status } }

有关 $ruleInput 结构及映射,请参见下文的 upsertRule 输入格式 部分。

步骤 7.5 — 验证规则(可选但建议)

应用规则后,建议重新导出 presync 报告:

“规则已应用。要我导出一份新的 presync 报告,验证日记账看起来是否正确吗?”

如果用户同意,则导出并分析(与步骤 1.5 相同)。检查:

  • no_account_matched = 0(完全覆盖)
  • 结算账户的净额接近零
  • 没有意外出现的账户
  • 默认规则的交易量合理(仅涵盖边缘情况的交易)

规则架构

规则引擎的工作方式

一笔交易可以匹配多条规则,每条规则设置不同的账户字段。引擎会累积所有匹配规则中的账户——一笔交易可能从资产规则获取 inventory_account,从标签规则获取 income_account,再从钱包规则获取 fee_account。对于同一账户字段,条件更多的具体规则优先于更宽泛的规则。

规则分为多个层:

  • 默认层(type: "DEFAULT"):为所有账户字段提供兜底。每个集成只能有一条。
  • 库存层:按资产或钱包设置 inventory_account 的规则
  • 行为层(标签规则):根据交易类型设置收入/支出
  • 费用/收益-损失层:设置费用、收益和损失账户
  • 覆盖层(特定组合):针对边缘情况的精细规则

默认规则在 upsertRule mutation 中使用 type: "DEFAULT"。在 rules.json 中,将默认规则标记为 "is_default": true。

库存层 — 由成本基础模式决定

重要:默认情况下,每条库存规则应只针对一个资产类别。 在单条库存规则中使用多个资产类别会导致对账失败。只有在客户端明确提出并说明理由时,才在一条规则中合并多个资产类别。如果相关的低交易量资产不值得单独设置规则,则让它们归入默认兜底规则。

by_asset 模式(按资产类别设置库存)

库存规则以 asset_class 为主要条件。无需钱包条件。

  • 按资产设置库存:asset_class=Ether → inventory_account=<ETH account> — 每个重要资产类别设置一条规则
  • 默认库存:DEFAULT 规则将 inventory_account=<generic account> 设为低交易量资产的兜底账户
  • 持有相同资产的多个钱包共用一个库存账户(与成本基础池相匹配)

如果 CoA 只有一个通用库存账户(例如“Inventory Asset”),没有按资产划分的账户,请向用户指出这一情况,并建议为重要资产创建按资产划分的库存账户。不要默默地将所有资产映射到单个兜底账户。

by_wallet 模式(按钱包设置库存)

库存规则以 wallet 为主要条件;对于持有多种需要使用不同账户的资产类型的钱包,可选择与 asset_class 条件组合。

  • 钱包 + 资产库存:wallet=0x... + asset_class=Ether → inventory_account=<ETH account>
  • 按钱包兜底:wallet=0x... → inventory_account=<default for this wallet>
行为层(基于标签,不使用钱包条件)

收入/费用规则通常基于标签,适用于所有钱包:

  • 存入规则:tag=PRODUCT DEPOSIT → income_account=<liability account>
  • 赎回规则:tag=PRODUCT REDEMPTION → expense_account=<liability account>
  • 清算规则:tag=SWAP/BRIDGE/etc. → 对称的 income_account + expense_account,指向同一个账户
  • 费用规则:tag=MARKETING/etc. → expense_account=<expense account>

借贷标签应单独清算。 LENDING LOCKUP/RETURN 应使用专用的“Staked Asset”清算账户,而不是与 SWAP/BRIDGE 归为一类。这样可以清楚了解部署在借贷协议中的资产。

费用与损益层

条件设置方式取决于成本基础模式:

  • by_asset 模式:可设为全局(无条件)、按资产或按钱包组,具体取决于 CoA 结构。请询问用户。
  • by_wallet 模式:通常按钱包设置。wallet=0x... → fee_account, gain_account, loss_account
仅使用现有数据
  • asset_class 名称必须来自 transaction_profile.txt 中经验证的列表,拼写必须完全一致
  • tags 必须来自标签部分;如果不存在标签,则不要创建基于标签的规则
  • 账户 UUID 必须来自 chart_of_accounts.txt
  • 钱包标识符必须来自 wallets.txt
完整覆盖

每笔交易至少应匹配以下规则:

  • 一条库存规则(针对特定资产或兜底规则)
  • 一条收入或费用规则
  • 费用规则
  • 损益规则
规则命名

每个集成都必须使用唯一的名称。如果组织已有命名惯例,请遵循该惯例(检查 existing_rules.txt)。常见模式:

  • 按钱包编号:"21"、"56 (VERSE)"、"54 - BS"
  • 按用途:"Swap Clearing"、"Gas Fees"、"Staking Rewards"
  • 按资产:"ETH Inventory"、"BTC Main Ledger"

如果没有现有惯例,请使用描述性名称。


技术参考

账户字段

规则可以设置以下账户字段:

  • inventory_account
  • income_account
  • expense_account
  • fee_account
  • gain_account
  • loss_account
  • unrealized_gain_loss_account

账户分配使用来自 chart_of_accounts.txt 的 UUID(账户名称后括号中的值)。

查询账户时,始终排除非账户类型:subsidiary、netsuite_class、netsuite_department。同一内部 ID 可能同时属于一个账户和一个非账户实体。

rules.json 格式
[
  {
    "name": "Default",
    "is_default": true,
    "conditions": {},
    "accounts": {
      "inventory_account": "128",
      "income_account": "54",
      "expense_account": "58",
      "fee_account": "235",
      "gain_account": "233",
      "loss_account": "234"
    },
    "is_ignore": false
  },
  {
    "name": "ENA Inventory",
    "conditions": {
      "asset_class": [{"name": "Ethena", "verification_status": "verified"}]
    },
    "accounts": {
      "inventory_account": "019cb750-28f8-72b7-8af0-8c9fba1d7555"
    },
    "is_ignore": false
  },
  {
    "name": "Clearing",
    "conditions": {
      "tags": ["SWAP", "BRIDGE", "INTERNAL TRANSFER"]
    },
    "accounts": {
      "income_account": "131",
      "expense_account": "131"
    },
    "is_ignore": false
  },
  {
    "name": "Spam",
    "conditions": {
      "tags": ["SPAM"]
    },
    "accounts": {},
    "is_ignore": true
  }
]
  • 使用 "is_default": true 标记默认规则——这会通过 upsertRule 将其创建为 type: "DEFAULT"
  • 仅包含有值的条件键
  • is_ignore: true 将规则标记为忽略规则(匹配该规则的交易会从日记账中排除)
upsertRule 输入格式

通过 MCP 应用规则时,将 rules.json 映射为以下格式:

{
  "type": "CUSTOM_RULE",
  "identifier": null,
  "name": "ETH Inventory",
  "accounts": {
    "inventory": {"name": "Digital Assets", "value": "uuid", "type": "asset"},
    "income": null,
    "expense": null,
    "fee": null,
    "gain": null,
    "loss": null,
    "unrealizedGainLoss": null
  },
  "filters": {
    "assetClassNames": [{"id": "Ethereum#verified", "name": "Ethereum", "symbol": "ETH", "isVerified": true, "assetClassId": null}],
    "wallets": [],
    "senders": [],
    "recipients": [],
    "platforms": [],
    "tags": [],
    "actions": [],
    "contracts": [],
    "specificIds": [],
    "walletTagsSenders": [],
    "walletTagsRecipients": [],
    "financialActionGroups": [],
    "contactGroupsSenders": [],
    "contactGroupsRecipients": [],
    "isInternalTransfer": null,
    "fromDate": null,
    "toDate": null
  },
  "isIgnore": false
}
rules.json → upsertRule 映射
rules.jsonupsertRule
is_default: truetype: "DEFAULT"
is_default: false/absenttype: "CUSTOM_RULE"
conditions.asset_classfilters.assetClassNames——从 erp.assetClassNames 补充 id(Name#verified/Name#unverified)、symbol、isVerified
conditions.walletsfilters.wallets——从 erp.wallets 补充 id、address、parentPlatform
conditions.tagsfilters.tags——格式为 [{"id": "TAG", "name": "TAG"}]
accounts.inventory_account: "uuid"accounts.inventory: {"name": "...", "value": "uuid", "type": "..."}——从 erp.allAccounts 补充信息
accounts.income_accountaccounts.income(同样补充信息)
accounts.expense_accountaccounts.expense(同样补充信息)
accounts.fee_accountaccounts.fee(同样补充信息)
accounts.gain_accountaccounts.gain(同样补充信息)
accounts.loss_accountaccounts.loss(同样补充信息)
accounts.unrealized_gain_loss_accountaccounts.unrealizedGainLoss(同样补充信息)
is_ignore: trueisIgnore: true

所有未使用的筛选字段都应为空数组。所有未使用的账户字段都应为 null。


经验总结

主动应用以下建议,不要等用户遇到相同问题后再处理。

成本基础模式与 CoA 不匹配:当会计科目表结构与成本基础模式不一致时,务必提供更改成本基础策略以匹配现有 CoA 的选项。这通常是最简洁的方案。

每条库存规则对应一个资产类别:切勿在单条库存规则中放入多个资产类别,这会破坏对账。每个重要资产类别都应有自己的规则。

收益/损失可以使用同一个账户:用户可能更倾向于使用一个合并的已实现收益/损失账户(通常为 other_expense 类型),而不是分别使用收益和损失账户。在分析差异时务必询问。

标签就是活动:分类活动和自定义活动标签在规则引擎中可以互换。务必将两个来源合并到同一个“TAGS”列表中。切勿将它们作为不同类别呈现。

使用预同步报告进行验证:预同步报告是事实依据。在设计规则前(了解当前状态)和应用规则后(验证覆盖情况)导出报告。关键指标:no_account_matched 错误、COA Mapping Rule 分布、清算账户净余额。


设置

前提条件
  • 已安装并正常运行 Claude Code
  • 已配置并连接到目标组织的 tres-finance MCP 服务
MCP 配置

此技能需要一个提供 Tres Finance API GraphQL 访问权限的 tres-finance MCP 服务。你的 MCP 配置应包含 tres-finance 服务,并具有以下权限:

  • get_viewer——识别已连接的组织
  • graphql_query / graphql_mutation——执行 GraphQL 查询和变更
  • 对 internalAccount、integrationAccount、erp、subTransaction、transaction、report 实体的读写权限
安装

将此文件复制到 Claude Code 技能目录:

# Project-level
mkdir -p /path/to/project/.claude/skills/erp-rule-suggestions/
cp SKILL.md /path/to/project/.claude/skills/erp-rule-suggestions/

# Or user-level
mkdir -p ~/.claude/skills/erp-rule-suggestions/
cp SKILL.md ~/.claude/skills/erp-rule-suggestions/

评论

支持 Markdown