关于 tres-report-create
tres-report-create 是通过 tres-mcp 为 TRES Finance 生成报告的技能,适用于需要导出账本、余额、账户等数据的用户。它要求先确认报告范围,再触发导出、验证记录并轮询至完成,可选下载分析文件。
主要功能
- 01根据报告类型触发导出
- 02轮询报告直至完成
- 03验证报告记录是否创建
- 04支持多种报告与输出格式
- 05可选下载并分析文件
适用场景
- 01导出指定日期范围的交易账本
- 02生成资产余额或成本基础报告
- 03下载 CSV 或 XLSX 文件进行分析
MCP 相关
通过 tres-mcp MCP 服务执行 GraphQL 查询以触发和查询报告,并获取生成文件的链接。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ anthropics/ claude-plugins-community --skill tres-report-create安装后在 Claude Code 中输入/tres-report-create确认已加载。
附带文件tests/run_report_matrix.py
详细介绍
TRES 报告生成
你可以通过 tres-mcp MCP 服务(针对 BFF 的 GraphQL)以编程方式生成 TRES Finance 报告。流程始终如下:选择报告 → 触发导出 → 轮询直至状态为 DONE → 返回预签名的 link。之后也可以下载并分析文件。
如果你不确定用户需要哪种报告,请先使用 tres-report-advisor 技能,然后再回到这里生成报告。
工作流
- [ ] Step 0: Clarify report type + date range + currency
- [ ] Step 1: Trigger the export (GraphQL via MCP `execute`)
- [ ] Step 1b: If the report isn't in the tables below, derive it from the schema
- [ ] Step 1c: VERIFY a report row was actually created (poll by exact name) — catches silent failures
- [ ] Step 2: Poll the report query until status == DONE
- [ ] Step 3 (optional): Download + analyze the file
步骤 0 — 明确范围(触发前必须完成)
开始操作前,先确认以下内容:
- 报告类型(必填)。 根据用户的描述匹配下表。如果不确定,请查询可用报告:
query { availableReportTypes { name exportType entitiesType llmDescription } } - 日期范围(如适用)。 LEDGER / AUDIT_LOG 报告使用 ISO 8601 格式的
timestamp_Gte/timestamp_Lte:- “2025 年第一季度” → Gte
2025-01-01T00:00:00Z,Lte2025-03-31T23:59:59Z - “2025 年” → Gte
2025-01-01T00:00:00Z,Lte2025-12-31T23:59:59Z - 如果需要日期范围但用户未提供,请询问。
- “2025 年第一季度” → Gte
- 货币。 默认使用
"usd",除非用户另有说明。 - 分析目标(仅当用户希望分析数据,而不只是获取文件时)。 用户希望通过数据了解什么?默认提供一般性摘要(总计、主要项目、趋势)。这将影响步骤 3。
简短确认,例如 “我将生成 2025 年第一季度的交易分类账 CSV。现在开始。”
步骤 1 — 触发导出
调用与报告的 entitiesType 匹配的 GraphQL 查询,并传入导出参数。使用 MCP execute 工具运行(如不确定,先用 validate_query 验证)。
entitiesType → 要调用的查询
| entitiesType | 查询 |
|---|---|
| LEDGER | transaction |
| ASSETS | organizationBalance |
| BALANCE | organizationBalance |
| HISTORICAL_BALANCE | organizationBalance |
| ACCOUNTS | internalAccount |
| GENERAL | internalAccount |
| STAKING_DATA | stakingYieldRecord |
| AUDIT_LOG | auditLog |
| LOGIN_HISTORY | loginHistoryExport |
报告目录(exportFormat 值 — 已根据生产环境验证)
| 报告名称 | exportFormat | entitiesType |
|---|---|---|
| 交易分类账 | BASIC_RAW_TRANSACTIONS | LEDGER |
| 已实现收益与损失 | EXTENDED_RAW_TRANSACTIONS | LEDGER |
| 成本明细原始交易 | COST_BREAKDOWN_RAW_TRANSACTIONS | LEDGER |
| 汇总明细 † | ROLLUP_BREAKDOWN | LEDGER |
| 分类账对账 | RECONCILIATION | LEDGER |
| 成本基础结转 | COST_BASIS_ROLL_FORWARD | LEDGER |
| 资产结转 | ASSET_ROLL_FORWARD | LEDGER |
| ERP 同步前 | PRE_SYNC_JOURNAL | LEDGER |
| ERP 同步后 | POST_SYNC_JOURNAL | LEDGER |
| MT940 对账单 | MT940 | LEDGER |
| 资产余额 | RAW_BALANCES | ASSETS |
| 资产余额 V2 | RAW_BALANCES_V2 | ASSETS |
| 资产余额 - 存档 † | ARCHIVED_BALANCES | ASSETS |
| 余额趋势 | BALANCE_TRENDS | ASSETS |
| 钱包余额 | INTERNAL_ACCOUNTS_BALANCES | ASSETS |
| 按资产划分的成本基础堆栈 | COST_BASIS_STACK_PER_ASSET | ASSETS |
| 资产法币价值 | DAILY_ASSET_PRICING | ASSETS |
| 重估报告 | REEVALUATION | ASSETS |
| 历史余额格式 | HISTORICAL_BALANCE | HISTORICAL_BALANCE |
| 成本基础库存 † | COST_BASIS_INVENTORY | BALANCE |
| 组织钱包 | INTERNAL_ACCOUNTS | ACCOUNTS |
| 联系人 | CONTACTS | ACCOUNTS |
| 第三方地址 | THIRD_PARTY_ADDRESSES | ACCOUNTS |
| 会计科目表 | CHART_OF_ACCOUNT | GENERAL |
| ERP 规则 | ERP_RULES | GENERAL |
| 已连接的托管方 | CONNECTED_CUSTODIANS | GENERAL |
| 质押奖励与持仓 | STAKING_DATA | STAKING_DATA |
| 审计跟踪 / 日志 | AUDIT_LOG | AUDIT_LOG |
| 登录历史 | LOGIN_HISTORY | LOGIN_HISTORY |
† = 需要特殊处理(请参阅下文“需要额外参数的报告”)。组织报告目录会不断更新 — availableReportTypes 是权威来源。如果用户请求的报告不在此表中,请转到步骤 1b,根据架构推导,而不要猜测。
导出参数(始终包含):
exportFormat— 上表中的值(UPPER_CASE)exportName— 描述性且唯一的名称(例如"Transaction Ledger Q1 2025")——你将在步骤 2 中通过此名称进行匹配currency— 除非另有说明,否则为"usd"outputFormat— 用于下游分析时为"CSV",用户需要电子表格时为"XLSX"
对于按日期范围生成的报告(LEDGER、AUDIT_LOG),添加 timestamp_Gte / timestamp_Lte。
⚠️ GraphQL 变量类型——务必准确(确保首次运行正确)
BFF 会严格验证变量类型。类型错误会返回 HTTP 400,且不会创建报告;
execute工具会在error/error_type字段中显示此错误,而不是 GraphQLerrors数组,因此很容易忽略。请使用以下准确类型声明变量:
变量 GraphQL 类型 说明 exportFormatStringUPPER_CASE 值 exportNameString唯一名称 currencyString例如 "usd"outputFormatReportOutputFormat不能是 String。值为"CSV"/"XLSX"timestamp_Gte/timestamp_LteDateTime不能是 String。ISO 8601 值identifier_In、children_Asset_AssetClass_In、children_BelongsTo_In[String]不能是 [ID]参数必须作为名称完全一致的变量传递,例如
exportName、exportFormat等——BFF 会按名称从info.variable_values中读取这些变量。内联字面值或重命名的变量($ef)会悄无声息地导致不创建报告。
示例——触发 Transaction Ledger 导出(已验证可用的形式):
query($limit: Int, $offset: Int, $timestamp_Gte: DateTime, $timestamp_Lte: DateTime,
$exportFormat: String, $exportName: String, $currency: String, $outputFormat: ReportOutputFormat) {
transaction(limit: $limit, offset: $offset, timestamp_Gte: $timestamp_Gte,
timestamp_Lte: $timestamp_Lte, exportFormat: $exportFormat,
exportName: $exportName, currency: $currency, outputFormat: $outputFormat) {
results { id }
totalCount
}
}
{
"limit": 1,
"offset": 0,
"timestamp_Gte": "2025-01-01T00:00:00Z",
"timestamp_Lte": "2025-03-31T23:59:59Z",
"exportFormat": "BASIC_RAW_TRANSACTIONS",
"exportName": "Transaction Ledger Q1 2025",
"currency": "usd",
"outputFormat": "CSV"
}
随后,导出任务会在后台异步生成。返回 200 且只有 totalCount,只能确认查询已运行——不代表报告已创建(请在步骤 1c 中验证),也不代表文件已就绪(请在步骤 2 中轮询)。
需要额外参数的报告(省略这些参数会导致报告出错或结果为空)
报告(exportFormat) | 通过以下方式触发 | 所需的额外参数 |
|---|---|---|
ROLLUP_BREAKDOWN | transaction | identifier_In: [String]——要分解的汇总父级哈希。缺少此参数时,报告将为空。 |
COST_BASIS_INVENTORY | transaction(不能用 organizationBalance) | 必须恰好提供一个 children_Asset_AssetClass_In: [String](资产类别 ID)。可选:最多一个 children_BelongsTo_In: [String]。缺失/多个参数 → 报告完成时会显示 status: ERROR(“必须恰好选择一个资产类别”)。请通过 query { assetClass(limit: N) { results { id name symbol } } } 获取资产类别 ID。 |
ARCHIVED_BALANCES | organizationBalance | 目标日期必须存在提交快照。如果没有,任务将一直处于待处理状态——任意日期的报告建议使用 HISTORICAL_BALANCE(Time Capsule)。 |
指定时间点的余额。 对于截至过去某个日期的余额报告,organizationBalance 还接受 balanceDate: DateTime(重建该日期的余额——这是 Time Capsule 路径;传入 RAW_BALANCES + balanceDate 时会升级为 HISTORICAL_BALANCE)和 commitId: UUID(从特定提交快照中提取)。查询当前余额时,两者都可以省略。
LOGIN_HISTORY 的参数格式不同
loginHistoryExport 仅接受 exportFormat: String!、exportName: String!、outputFormat: ReportOutputFormat(不接受 currency/limit/时间戳),并返回 { success reportId }:
query($exportFormat: String!, $exportName: String!, $outputFormat: ReportOutputFormat) {
loginHistoryExport(exportFormat: $exportFormat, exportName: $exportName, outputFormat: $outputFormat) {
success
reportId
}
}
步骤 1b — 未知或新添加的报告?根据架构推导(自助服务)
availableReportTypes 是唯一可信来源——其中列出了该组织支持的所有报告,包括上方表格中未列出的报告。如果请求的报告在这里没有对应行,请勿猜测:使用 MCP 内省工具,根据实时架构查找触发方式。
- [ ] 1. availableReportTypes -> get this report's exportType + entitiesType + llmDescription
- [ ] 2. Pick the trigger query from entitiesType (Step 1 table). If entitiesType is new/unclear,
default: transaction (tx / ledger / cost-basis), organizationBalance (balances / assets),
internalAccount (accounts / metadata).
- [ ] 3. introspect(<query>) -> read the EXACT arg names AND types
- [ ] 4. build_query(<query>) -> canonical variables-as-args template (optional, handy)
- [ ] 5. validate_query(<assembled query>) BEFORE executing
- [ ] 6. Trigger with the 4 export params (+ timestamps only if the query exposes them)
- [ ] 7. Poll; if it errors, apply the error->fix table, then re-trigger
- [ ] 8. On DONE: return the link AND record the working recipe
确保首次就能成功的原则:
- 读取格式,绝不臆造。 将
availableReportTypes中的exportType原样用作exportFormat。 - 根据
introspect推导变量类型,不要凭记忆。 按架构报告的精确类型声明每个变量。仅这一点就能避免 400 错误“used in position expecting type X”。检查常见类型:outputFormat→ReportOutputFormat,currency→String,timestamp_*→DateTime,列表筛选器 →[String]。 - 执行前先验证。
validate_query可捕获参数、类型和选择错误,避免创建无用报告。 - 先从最简请求开始,再仅根据错误提示添加内容。 首先只使用导出参数触发;根据错误消息判断生成器需要哪些额外筛选器。
错误 → 修复对照表(涵盖在生产环境中遇到的所有故障模式):
| 错误 | 含义 | 修复方法 |
|---|---|---|
Variable '$X' of type 'A' used in position expecting type 'B' | 声明的类型错误 | 将 $X 重新声明为 B,然后重新验证 |
Unknown argument 'X' on field 'Y' | 此查询不支持该筛选器 | 切换到提供该筛选器的查询(通常是 transaction),或移除该筛选器 |
Variable '$X' is never used | 声明了变量,但没有对应参数 | 将其作为实际参数加入查询,或移除该变量 |
触发返回 200,但报告的 status: ERROR(“must select exactly one …” / “required …”) | 生成器需要额外的必需筛选器 | 使用 introspect 查找对应的参数名称,从其列表查询中获取有效值(例如 assetClass、internalAccount),按要求添加,然后重新触发 |
报告一直处于 IN_PROGRESS 状态 | 缺少数据前提条件(例如没有 commit 快照) | 告知用户缺少的内容,并建议使用其他报告 |
保存所学内容。 新报告成功触发并达到 DONE 后:
- 短期:通过 MCP
memory工具保存配方——触发查询、exportFormat、有效的变量类型以及任何必需筛选器。 - 长期:建议在此技能的表格中新增一行(报告名称、
exportFormat、触发查询、必需参数),并告知用户,确保技能内容保持最新。
步骤 1c — 确认已创建报告行(强制执行的防静默失败检查)
每次触发后立即执行此操作,再告知用户任何成功消息。 触发查询会产生副作用:如果请求存在任何细微错误(使用内联字面值而非变量、变量被重命名为 $ef、缺少必需参数),BFF 会返回 200 且 errors: null,却不会提示地不创建报告。确认成功的唯一可靠方法是按名称查找该行。
使用触发时的确切 exportName 查询该行:
query($name: String, $ordering: String, $limit: Int) {
report(name: $name, ordering: $ordering, limit: $limit) {
results { id name status }
}
}
{ "name": "<the exact exportName from Step 1>", "ordering": "-created_at", "limit": 1 }
results为空(没有行) → 这是静默失败,并非“进行中”。不要报告成功。根据上方规则重新检查触发请求——参数是否作为变量传入(而非内联字面值),变量是否恰好命名为exportName/exportFormat/currency/outputFormat/timestamp_*,类型是否正确——然后重新触发一次。如果仍未创建行,请停止并告知用户创建失败且系统未返回错误(不要无限重试)。- 存在一行 → 很好,报告已创建。继续执行步骤 2,轮询至
DONE。
每次运行都应让
exportName保持唯一(例如追加日期或时间戳),这样查询结果才会匹配本次创建的行,而非名称相同的旧报告。
步骤 2 — 轮询直至完成
使用步骤 1 中的确切 exportName 查找报告(这是最可靠的匹配方式):
query($name: String, $ordering: String, $limit: Int) {
report(name: $name, ordering: $ordering, limit: $limit) {
results { id name status link reportSize exportFormat createdAt }
}
}
{ "name": "<the exportName from Step 1>", "ordering": "-created_at", "limit": 1 }
字段/参数注意事项(这些错误不会显式报出——请务必正确填写):
- 排序参数是
ordering,不是orderBy。 - 下载字段是
link(一个预签名 S3 URL),不是downloadUrl。 - 报告类型字段是
exportFormat,不是exportType。 - 查找报告时不要按
exportFormat筛选:存储的值是小写(例如rollup_breakdown),而你触发时用的是大写格式,因此精确筛选会匹配不到任何结果。请按name筛选。
轮询循环:
- 按名称查询最新报告。
- 检查
status:IN_PROGRESS→ 等待约 60 秒(例如在 shell 中执行sleep 60),然后再次查询。DONE→link中包含预签名下载 URL。继续后续操作。ERROR→ 生成器拒绝了输入(例如缺少必需的筛选条件)。阅读失败消息,修正参数,然后重新触发。不要在不说明的情况下重试相同的调用。
- 最多重复 10 次,每次尝试之间等待约 60 秒。
检查两个错误渠道。 报告可能以两种方式失败:(1)触发操作返回 HTTP 400,问题包含在
error/error_type中,且 GraphQLerrors为空或不存在——将任何非空的error视为严重失败,不要报告成功;(2)触发操作返回 200,但报告稍后以status: ERROR结束。切勿仅凭 200 就认定成功。
小型报告会在几秒内完成;大型报告(资产较多、日期范围较宽或组织规模较大)可能需要几分钟到几小时——请尽早说明预期。status == DONE 后,将 link 分享给用户。
呈现下载链接。 切勿在聊天中粘贴原始预签名 URL——它很长、不美观,还包含凭据。始终将其呈现为简洁、可点击的Markdown 链接,使用友好的锚文本,并将完整 URL 放在链接目标中:
[Click here to download your report](<the full presigned link>)
你可以根据报告调整锚文本,例如 [下载你的 ERP 预同步报告(CSV)](<link>)。锚文本应简短、易读;URL 本身应隐藏在其后。请说明该链接经过预签名,且会在有限时间(约 24 小时)后过期。
步骤 3 — 下载并分析(可选)
如果用户希望分析数据(而不仅仅是获取链接),请通过预签名 URL 下载,并使用 pandas 在本地检查:
import pandas as pd, requests
from io import BytesIO
resp = requests.get("<presigned_url>")
resp.raise_for_status()
df = pd.read_csv(BytesIO(resp.content))
print(df.shape, list(df.columns))
print(df.head())
print(df.dtypes)
始终先运行 df.head() 和 df.dtypes,然后执行用户要求的分析(groupby、value_counts、describe、pivot_table)。将金额格式化为 f"${value:,.2f}",并概述大型数据框,而不是倾倒所有行。有关各类报告的深入分析指南,请使用 tres-report-analyzer 技能。
规则
- 务必在触发前确认报告类型(以及必要时确认日期范围)。
- 将查询与上表中的报告
entitiesType匹配——但上述特殊情况报告除外(COST_BASIS_INVENTORY通过transaction触发)。 - 对于表中没有的报告,请遵循步骤 1b:对查询执行
introspect以获取精确的参数类型,执行validate_query,使用最少参数触发,根据错误→修复表进行修正,然后保存该方案。对于未知报告,绝不要凭猜测设置类型或筛选条件。 - 变量类型严格区分:
outputFormat的类型是ReportOutputFormat,timestamp_*的类型是DateTime,列表筛选条件的类型是[String]。类型错误 = HTTP 400 = 不会生成报告。传递参数时,变量名必须准确使用exportName/exportFormat等。 - 触发后务必执行步骤 1c。通过完全匹配的
exportName确认报告行存在后,才能声称操作成功。查询结果为空表示静默失败(200 +errors: null+ 没有报告行),并非“正在处理中”——未经确认报告行,绝不要报告成功。每次运行使用唯一的exportName,确保查询匹配到对应的报告行。 - 对于
ROLLUP_BREAKDOWN,必须传递identifier_In;对于COST_BASIS_INVENTORY,必须且只能传递一个children_Asset_AssetClass_In——否则报告为空或返回错误。 - 触发后,请通过两个渠道验证成功:触发时没有
error/error_type,且status达到DONE(而非ERROR)。 - 按
name查询report,不要按exportFormat查询;使用ordering(而非orderBy)和link(而非downloadUrl)。 - 将下载链接显示为可点击的 Markdown 链接(例如
[点击此处下载报告](<link>)),绝不要直接显示预签名 URL。请说明链接已预签名,且会在一段时间后过期。 - 除非用户另有指定,否则
currency默认为"usd",outputFormat默认为"CSV"。 - 绝不要截断或缩短交易哈希、地址、报告 ID 或
identifier_In值——始终完整显示或传递。 - 这是只读/导出技能——绝不要执行会修改平台数据的变更操作。