← Plugin catalog
Finance

Kryptos

Kryptos v1.0.1

Crypto portfolio, tax & books

Full description ↓

View on ChatGPT ↗

Save this plugin to Following and return to review observed changes. Follow up to 10 plugins free.

Description

From the marketplace listing

Kryptos brings your crypto portfolio, transaction history, tax figures and accounting ledger into ChatGPT, across 5,000+ exchanges, wallets and blockchains. Ask what you hold and what it is worth, search your transaction history by asset, wallet, label or date, review DeFi positions and NFT collections, and look at the ledger detail behind any trade. Kryptos also finds the data problems that make crypto tax wrong — missing prices, missing cost basis, sells with no matching purchase, balances that disagree with the ledger, wallets you never connected — and lets you fix them in the same conversation: recategorise a transaction, correct a price, merge a transfer that detection missed, or add a trade that never made it into an export. Finance teams can map transactions to a chart of accounts, apply categorisation rules, generate double-entry journals and push them to Xero, QuickBooks or Softledger. You sign in to Kryptos with OAuth and grant access to one workspace. Kryptos never asks for exchange API keys or wallet private keys in the conversation. It reads and records only — no tool can send, swap, withdraw, deposit or trade any asset. Requires a Kryptos account.

Language: English · Automatically detected from descriptions.

What changed

Kryptos

Oct 27, 2026 · 1 saved observations

Metadata · Oct 27, 2026 · 00:49 UTC · Compared with Oct 24, 2026 · 13:35 UTC

WHAT CHANGED

Package or technical metadata updated

Package or technical metadata updated

Observed in package metadata. These changes alone do not establish a new customer-facing feature.

Open full comparison.

Is v2 template

Before

Oct 24, 2026 · 13:35 UTC

Not present

After

Oct 27, 2026 · 00:49 UTC

false

Metadata: full comparison →

Competitor profile

From the developer’s listing and package; capabilities are not independently tested. Package observed Nov 2, 2026.

Declared capabilities

  • Portfolio and holdings
  • Transaction history
  • Data quality checks

Declared limitations

  • Moving funds is not supported
  • Exchange credentials are never accepted
  • Access outside the connected workspace

Review scenarios; not an exhaustive list.

Cost & access

Kryptos does not sell products or take payments inside ChatGPT.

Terms may have changed since this observation.

Starter prompt

What is my crypto portfolio worth right now?

View onboarding →

View package source →

Keywords

Files & skills

File archives

Plugin package9 files · 67.5 KBBrowse files →
Skill instructions
crypto-bookkeeping9.97 KB

View saved version →

---
name: crypto-bookkeeping
description: Run crypto bookkeeping for a Kryptos Enterprise workspace — connect Xero, QuickBooks or Softledger, sync the chart of accounts, map transactions to GL accounts with rules, check the generated journals and push them to the ERP. Use when the user mentions a chart of accounts, GL codes, journals, month-end close, Xero, QuickBooks or Softledger.
---

# Crypto bookkeeping (Enterprise)

Map crypto activity to the chart of accounts and send clean journals to the user's accounting system. Explicit instructions from the user take priority over this workflow. Discover everything from the tools: platform, organisation, account codes, rules, task state. Never assume them. Errors return a `code` (for example `NO_TAX_YEAR_PLAN`, `PERIOD_LOCKED`) and a `message`; use both to tell why a call failed.

## Before you start

Call `list_chart_of_accounts`. If it fails with `ENTERPRISE_REQUIRED` (the feature requires an enterprise workspace), the workspace is retail: explain that bookkeeping and ERP sync are Enterprise features, and stop. Two more gates can appear later, and the error message says which one applies:

- an ERP may be disabled for the workspace (`ERP_DISABLED`);
- pushing to an ERP needs a paid Enterprise plan (the trial doesn't include it), and is refused when the period has more transactions than the plan allows (`ENTERPRISE_PLAN_REQUIRED`, `PLAN_TRANSACTION_LIMIT_EXCEEDED`).

State the gate plainly when you hit one.

## How accounts get assigned

Every ledger leg gets a debit and a credit account:

- **Asset rules** (category `ASSET_RULES`) set the asset side. Workspaces start with catch-alls ("Digital Assets" for every token, "Cash Equivalents" for fiat) at the lowest ranks. Within a category the lowest rank that matches wins, so a rule for a specific asset needs a lower rank than the catch-alls; use `reorder_rules` if needed.
- **Custom rules** (`CUSTOM_RULES`) set the other side, for deposits, withdrawals and payments only — for example a staking-reward label to an income account. Trades and transfers use asset rules only.
- **Default rules** map capital gains, capital losses, fees and rounding ("Small Errors") to accounts. They aren't matched against legs; to move them to different accounts, use `update_rule` with a new `coa`.
- **Manual assignments** (`assign_ledger_accounts`, `bulk_assign_ledger_accounts`) are kept. Rule runs and recomputes don't overwrite them.
- Rule changes take effect when `apply_rules` runs, and also on the next workspace recompute (for example after a sync).

## Workflow

1. **Connect the ERP.** Call `list_erps` (shows `isConnected`), then `get_erp_connection_status(platform)`.
   - **Not connected, Xero or QuickBooks:** `connect_erp(platform)` returns an `authUrl` for the user to open and approve; you can't do this for them. Check the status again afterwards.
   - **Softledger** uses client credentials and is connected in the Kryptos web app. Never ask for or accept those in the chat.
   - **Xero:** if `tenantInfo` is empty, no organisation is selected, and syncing, creating accounts and pushing will all fail. Call `list_erp_tenants`, ask which organisation, then `select_erp_tenant`.
   - **QuickBooks** connects to one company; there is nothing to select. **Softledger:** `select_erp_tenant` only sets the fallback location for journals whose accounts carry none.
   - **Wrong organisation:** switching does not reset anything. After selecting the right one, run `sync_coa_from_erp`, and warn that journals already pushed went to the previous organisation.
   - **Broken connection:** the status can still say connected after a token stops refreshing; it shows up as errors or failed tasks. Run `connect_erp` again (and, for Xero with several organisations, select the organisation again).
   - **No ERP:** the chart of accounts can be imported from CSV in the web app (ERP Integrations → Custom), or created one account at a time with `create_chart_of_account` (`code`, `name`, `class` = ASSET, EQUITY, EXPENSE, LIABILITY or REVENUE). Journals then stay in Kryptos.
2. **Chart of accounts.** `sync_coa_from_erp(platform)` pulls the ERP's accounts (for Xero, active accounts that have a code). Accounts deleted in the ERP are deleted in Kryptos too. Legs tagged with them lose that account, including manual tags, and rules pointing at them stop matching, so say this before running it. (If the ERP returns no accounts, or fewer than half of those held, nothing is deleted.) Read the result with `list_chart_of_accounts`.
   - **Only accounts synced from the ERP can be pushed.** A journal that uses a Kryptos-only account — including the starter accounts the default and catch-all rules point to — is rejected by the ERP adapter. After syncing, point those rules at ERP accounts with `update_rule`, then run `apply_rules`.
   - Need a new account in the ERP: `list_erp_account_classes(platform)` for the valid classes, then `create_erp_accounts` with `accounts: [{ code, name, class }]` (up to 500; existing codes are updated). Check the result for per-account `errors`.
   - Softledger account codes are internal ids; the human account number is in the name, for example "(1000) Cash".
3. **Rules.** `list_rules` returns rules by category, then rank. `create_default_rules` only seeds a workspace that has no default rules; it won't restore one that was deleted. For a custom or asset rule, resolve every reference first, because rules match ids:
   - `assets`: `[{ id, symbol, name }]` from `search_assets` (prefer the contract address), or the string `"All Assets"`;
   - `label`: `[{ label }]` using names from `get_supported_labels`;
   - `accounts` / `counterParty`: `[{ walletId }]` from `get_integrations`, or `{ address, name }` / `{ alias, name }` where `name` is the provider name. A bare address never matches;
   - `ledgerType`: `Incoming`, `Outgoing` or `All` (fee legs count as outgoing);
   - `coa`: a code from `list_chart_of_accounts`.

   Call `create_custom_rule` with the right `category` and a deliberate `rank`, check its position with `list_rules`, then `apply_rules` (asynchronous; returns a task id — poll `get_task`).

4. **Fill the gaps.** `list_coa_ledgers(missingCoa: true)` lists legs still missing an account (add `startTime`/`endTime` to work on one period, such as the month being closed) (`meta.total` for the count, up to 500 per page). A transaction with any untagged leg gets **no journal at all**, so it won't show in `list_journals` until it's fixed.
   - Many legs following one pattern → write a rule (step 3).
   - A batch of transactions of the **same type** → `bulk_assign_ledger_accounts(trxIds, debitCoaCode, creditCoaCode)`, up to 100 ids per call; poll the returned task. Trades and transfers only take the code for their direction.
   - One leg → `assign_ledger_accounts(ledgerId, debitCoaCode, creditCoaCode)`. It rebuilds that journal immediately and marks the leg as manual; pass `null` to hand it back to the rules.
5. **Wait for journals to settle.** After `apply_rules`, a bulk assignment or `trigger_recalculation`, poll `get_recalculation_status(taskId)` or `get_task` with the returned task id. Without one, `list_tasks(operationType: "coa-pipeline", limit: 1)`: `pending` or `in_progress` means journals are still being rebuilt.
6. **Check the journals.** `list_journals(includeLines: true)` shows each journal's `syncedToERP` and `erpError`; narrow it with `startTime`/`endTime` (the transaction date) and `syncedToERP: false` to see what a period still has to push. A line whose account is missing means the code no longer exists. Small rounding differences are balanced to the "Small Errors" account automatically. Tell the user how many journals are unsynced and which have errors.
7. **Roll-ups.** If the business posts monthly roll-up journals (Roll-up Accounting in the web app; there's no tool for it here), don't push individual journals for those months. Pushing everything also sends unpushed journals inside a roll-up period, which then post twice when the roll-up is pushed. Push explicit `transactionIds` outside rolled-up periods instead. A push of ids inside a closed roll-up is refused with `COVERED_BY_ROLLUP`.
8. **Push.** Before pushing, say how many journals will go, to which organisation, and whether as drafts. Then call `sync_to_erp(platform)`:
   - `transactionIds` for a specific set (up to 1000), or omit them to push every unsynced journal. **Softledger needs explicit ids, at most 50 per push.**
   - `pushType`: `DRAFT` or `POSTED` (Xero and Softledger default to draft; QuickBooks ignores it).
   - The workspace base currency (`get_accounting_settings`) must match the ERP organisation's currency, otherwise the push fails with `CURRENCY_MISMATCH`.
   - `JOURNALS_REGENERATING` means step 5 isn't finished; wait and retry.
   - Poll the returned task. A `partial_success` result lists which journals failed; their `erpError` says why. Fix them and push those ids again.
   - Journals that were already pushed are not re-sent when rules change later. Push them again with explicit `transactionIds` if the ERP copy must be updated.
9. **Lock (optional).** `lock_period` is a tax lock on a quarter or a year (see `get_lock_boundaries`). It blocks transaction and ledger edits on or before that date. It doesn't block account tagging or ERP pushes, and it isn't the same as closing a month in the ERP.

## Boundaries

- Ask before every write, and say clearly when it goes to the ERP rather than only to Kryptos.
- Don't call `disconnect_erp` unless the user asks for exactly that. It deletes that ERP's accounts from Kryptos (legs and rules lose them, including manual tags) and clears the journals' ERP references, so reconnecting and pushing again would duplicate entries in the ERP.
- `trigger_recalculation` re-derives every rule-assigned leg and rebuilds all journals (manual assignments are kept). Pass `updateLedgerCoa: false` to rebuild journals only. Run it only when the user asks.
- Never guess an account code; take it from `list_chart_of_accounts`, or ask.
- Explain the accounting treatment Kryptos applies; don't give accounting or tax advice beyond that.
get-started4.82 KB

View saved version →

---
name: get-started
description: Set up a Kryptos workspace — connect blockchain wallets by public address, wait for the import to finish, and give a first look at the portfolio. Use when the user is new to Kryptos, has nothing connected yet, asks to add or connect a wallet, or asks how to get started.
---

# Get started with Kryptos

Help the user connect their wallets and see their portfolio for the first time. Explicit instructions from the user take priority over this workflow. Discover chains, providers and portfolios from the tools; don't assume them. Errors return a `code` (for example `NO_TAX_YEAR_PLAN`, `PERIOD_LOCKED`) and a `message`; use both to tell why a call failed.

## Workflow

1. **See what's already there.** Call `get_integrations`. If wallets are connected, summarise them (chain, alias, last sync) and ask what the user wants to add. Call `get_accounting_settings` and tell the user the country (`countryCode`), base currency and cost-basis method in force. They drive every tax figure, and they're changed in the Kryptos web app, not here.
2. **Pick the portfolio.** Every wallet belongs to a portfolio, in retail and Enterprise workspaces alike. Call `list_portfolios`:
   - Enterprise: ask which portfolio to use;
   - otherwise: use the one with `isDefault: true`;
   - if there are none: offer `create_portfolio`.

   Pass its id as `primaryPortfolioId` on every `add_wallet` call.

3. **Collect the wallet.** Ask for the public wallet address and the chain. Wallets are added by **public address only**:
   - Never ask for, accept or repeat a private key, seed phrase, API key, secret or password. If the user pastes one, tell them not to share it, don't use it, and suggest they treat it as exposed.
   - Exchange accounts (API key or OAuth) and CSV files are connected in the Kryptos web app; say so and move on.
4. **Pick the chains.**
   - **EVM address** (`0x` + 40 hex characters): call `detect_wallet_chains` and show the chains with activity. Skip any whose `isWorking` is false, and ask whether to add all of them or only some. The `id` of each result is the `providerId` to use. An empty result means no activity was found; ask the user which chain they use instead of guessing.
   - **Any other address** (Bitcoin, Solana and others): find the provider with `get_integration_metadata(search: <chain name>, type: "blockchain", isWorking: true)`. Search matches loosely ("bitcoin" also finds Bitcoin Cash and Bitcoin SV), so confirm the exact provider with the user.
5. **Add it.** After the user confirms the address, chains and portfolio, call `add_wallet` once per chain with `address`, the chain's `providerId`, `primaryPortfolioId`, and an `alias` the user will recognise, such as "Main wallet (Ethereum)".
   - Each call starts an import and returns it as `sync`. If `sync` is empty, start one with `sync_integration`.
   - If the message says the credentials are already present, that wallet is already connected on that chain; tell the user and move on. If it says the alias exists, pick another alias.
6. **Wait for the import.** Track each sync with `get_sync_job` (or `list_sync_jobs`). `pending`, `queued` and `in_progress` mean it's still running; `completed`, `partially_synced`, `failed` and `cancelled` are final. Imports usually take a few minutes; report progress briefly rather than calling in a tight loop.
   - `failed`: the job explains why; report it, and don't retry more than once without asking.
   - `partially_synced` with `limitReached: true`: the import stopped at the workspace's transaction limit, so the history is incomplete. Tell the user the limit is raised through their plan or Kryptos support.
7. **First look.** After the imports, a recalculation runs automatically. Wait until `list_tasks(operationType: "workspace-recompute", limit: 1)` is no longer `pending` or `in_progress`; cost basis and gains lag until it finishes. Then:
   - `get_dashboard_totals` for net worth, cost basis and unrealised gain (never add up a page of holdings);
   - `get_holdings(sortBy: "value", sortOrder: "desc", limit: 10)` for the largest holdings;
   - `get_transaction_summary` for how many transactions were imported.
8. **Point to the review.** Call `get_reconciliation_summary` and report the review percentage. If there are action items, explain in one sentence that some transactions need attention before the tax figures can be trusted, and offer to go through them (the `review-and-reconcile` skill).

## Boundaries

- Ask before adding each wallet; show the address, chains and portfolio you'll use.
- Don't guess a chain from an address that could belong to several; ask, or use `detect_wallet_chains` for EVM addresses.
- A freshly imported wallet often shows missing prices and balance mismatches, many of them from airdropped spam tokens. That's expected; don't present it as an error.
- Describe the user's data; don't give investment or tax advice.
prepare-tax-year6.54 KB

View saved version →

---
name: prepare-tax-year
description: Get a tax year ready to file in Kryptos — check the data is complete and the gains are up to date, summarise capital gains, income and expenses for the year, generate the tax report, and optionally lock the period once filed. Use when the user asks for their tax report, their gains or income for a year, or wants to get ready to file.
---

# Prepare a tax year

Take the user from "is my data ready?" to a generated report for one tax year. Explicit instructions from the user take priority over this workflow. Read every setting from the tools — country, fiscal year, cost-basis method, available reports. Don't assume them.

Errors return a `code` (for example `NO_TAX_YEAR_PLAN`, `PERIOD_LOCKED`) and a `message`; use both to tell why a call failed.

## Workflow

1. **Pin down the year and the rules in force.** Call `get_accounting_settings`. It returns:
   - `countryCode` (ISO-2), `method` (cost basis), `baseCurrency` and `timezone`;
   - `fiscalStart` / `fiscalEnd` as day/month;
   - `advancedTxSettings`, where `cost_basis_per_wallet` says whether cost basis is tracked per wallet or across all wallets;
   - `tagsException`, the workspace's tax treatment per label.

   **`year` is the calendar year in which the tax year starts.** Work out the exact dates from `fiscalStart` in the workspace `timezone` and confirm them with the user. Examples: a UK 2024/25 tax year (6 Apr 2024 – 5 Apr 2025) is `year: 2024`; an Australian FY2025 (1 Jul 2024 – 30 Jun 2025) is `year: 2024`; a calendar-year country's 2024 is `year: 2024`.

2. **Check the data is settled.**
   - `list_sync_jobs`: any sync still `pending`, `queued` or `in_progress` will change the figures — offer to wait. A sync that ended `partially_synced` with `limitReached: true` stopped at the workspace's transaction limit, so the history is incomplete; say so.
   - `get_reconciliation_summary` covers the whole workspace, not just one year. If it shows action items (uncategorised transactions, missing purchase history, missing prices, missing balances), say how many and that they can make the figures wrong, and offer to fix them first (the `review-and-reconcile` skill). If the user wants to carry on, continue and repeat the caveat with the figures.
3. **Make sure gains are current.** Imports and edits trigger a recalculation automatically.
   - `list_tasks(operationType: "workspace-recompute", limit: 1)`: if it is `pending` or `in_progress`, wait for it.
   - Then `get_accounting_status`. Only if `hasOutput` is false, or `lastCalculation` is older than the last import or edit, call `trigger_recompute` (it returns a `taskId`) and poll `get_task` until it finishes.
   - Don't quote figures from a stale calculation.
4. **Summarise the year.**
   - **Capital gains:** `list_tax_reports(year)` gives proceeds, cost basis, gains, the number of disposals, and a summary of gains and losses (short- and long-term where the country splits them). It also has `missingPurchaseCount` — mention it if it is above zero. A year the plan doesn't cover comes back as a stub with `locked: true` and a `lockReason` instead of figures; tell the user plainly.
   - **Income and expenses** aren't in that report. Call `get_accounting_breakdown(from, to)` with the tax year's start and end in epoch ms. It is refused, with the reason, if the range touches a tax year the plan doesn't cover, so query one tax year at a time.
   - Name the cost-basis method the figures use. Figures fetched under different methods aren't comparable; pass `method` explicitly when the user asks to compare.
   - `list_tax_report_years` only lists years that have disposals. A year with only income won't appear there, but still has figures.
5. **Drill down if asked.** `get_tax_report_disposals(year)` lists each sale with the acquisitions it was matched against (pages start at 0). It is only available for tax years the workspace's plan covers. If it's refused, the `code` says why: `NO_TAX_YEAR_PLAN` (the plan doesn't cover that tax year), `ENTERPRISE_PLAN_REQUIRED`, or `PLAN_TRANSACTION_LIMIT_EXCEEDED` (the year has more transactions than the plan allows; `data` has the counts). Tell the user plainly. `get_year_end_lots` is gated the same way.
6. **Generate the report.** `get_report_catalog(year)` lists the reports for the user's country, each with `title`, `reportKey`, `type` (pdf, csv…) and its state:
   - `locked: true` means it can't be generated for that year; `lockReason` says why (for example the plan doesn't cover the year, or the transaction count in `lockData.current` is over `lockData.limit`). Don't call `generate_report` for a locked report. Note that `available: true` alone doesn't mean it can be generated.
   - A non-null `status` or `taskId` means it was already generated or is in progress; check `list_reports(year)` before generating again.
   - `accountingDependent: true` reports need current gains (step 3).
   - If the catalog is empty, no reports are offered for that country and year; say so.

   Let the user pick an unlocked report and call `generate_report(year, reportKey)`; it returns a `taskId`. Poll `get_task` until it completes. It can also fail because there's no data for the year, or because the accounting isn't ready yet (go back to step 3). Then call `get_report_link(year, reportKey)` for the download link. The link expires after about an hour, so fetch it when the user is ready; if it says the report isn't ready, wait and try again.

7. **Lock the period (optional, only once filed).** Offer this only after the user says they have filed, every wallet for the year is imported, and gains are current. Recalculations never go back before a lock, so anything imported later for a locked period is ignored.
   - `get_lock_boundaries` returns the period ends a lock can go on (`periodEnd` in epoch ms, the inclusive end; `periodKind` `quarter` or `year`; `locked`), for the workspace's cost-basis method.
   - A lock blocks edits to every transaction dated **on or before** the latest locked period end, not only the last period.
   - Confirm the boundary with the user, then call `lock_period(periodEnd, periodKind, method)`.

## Boundaries

- Ask before recomputing, generating a report or locking a period.
- Never unlock a period, change tax settings or edit transactions as part of this workflow. If figures look wrong, go back to the review.
- `get_tax_loss_harvesting` is a simulation. If the user asks about it, present it as such, and note that wash-sale or superficial-loss rules may not all be modelled.
- Report what Kryptos calculated. Don't tell the user what they owe or how to file, and don't give personal tax advice.
review-and-reconcile13.4 KB

View saved version →

---
name: review-and-reconcile
description: Review a Kryptos workspace for data problems that make crypto tax figures wrong — uncategorised transactions, missing purchase history, missing prices, balance mismatches, high P&L transactions and unidentified addresses — and fix them with the user. Use when the user asks to review, reconcile, clean up or check their data, asks why a tax figure or balance looks wrong, or wants to get ready to file.
---

# Review and reconcile a Kryptos workspace

This mirrors the **Review** page in the Kryptos web app (retail and Enterprise): a progress score and six checks. Work through them with the user, fix what the data supports, and ask about everything else. Explicit instructions from the user take priority over this workflow.

Discover everything from the tools: counts, thresholds, labels and how this workspace taxes each label. Don't assume them. Errors return a `code` (for example `NO_TAX_YEAR_PLAN`, `PERIOD_LOCKED`) and a `message`; use both to tell why a call failed. If one says a permission or scope is missing, tell the user to reconnect Kryptos and grant it.

## The six checks

| Check                      | Kind        | How to list it                                                                                                       | Usual fix                                                                               |
| -------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| Missing Integrations       | Suggestion  | `get_missing_integrations`                                                                                           | Connect the wallet or exchange, name the address, or ignore it                          |
| Missing Balances           | Action item | `get_missing_balances`                                                                                               | Mark scam tokens as spam; find the missing deposit/withdrawal                           |
| Missing Purchase History   | Action item | `get_missing_purchases`; rows via `get_transactions(isMissingTransaction: true)`                                     | Connect the source wallet, merge an unmatched transfer, relabel, or add the acquisition |
| Missing Price              | Action item | `get_missing_prices`; rows via `get_transactions(hasMissingPrice: true, isMissingPriceIgnored: false)`               | Set a per-unit price, mark spam, or dismiss                                             |
| Uncategorised Transactions | Action item | `get_transactions(types: ["deposit","withdrawal"], labels: ["Deposit","Withdrawal"], isUncategorisedIgnored: false)` | Give each a specific label, merge, or dismiss a pure transfer                           |
| High P&L Transactions      | Suggestion  | `get_transactions(minTotalGains: <highPnlThreshold>, isHighPnLReviewed: false)`                                      | Check the legs; fix them or mark reviewed                                               |

Action items must be resolved before the figures can be trusted. Suggestions are worth checking but may be correct as they are. Don't pass `isMissingTransaction` and `hasMissingPrice` in the same call; they are combined with OR, not AND.

## Workflow

1. **Check the data is settled.** Call `list_sync_jobs`. If any sync is `pending`, `queued` or `in_progress`, the counts will change; offer to wait. A sync that ended `partially_synced` with `limitReached: true` hit the workspace's transaction limit, so its history is incomplete; say so.
2. **Learn how this workspace is taxed.** Call `get_accounting_settings`. Its `tagsException` gives the tax treatment of each label here (for example `CAPITAL_GAIN`, `INCOME`, or none), and `advancedTxSettings` switches categories on or off (crypto-to-crypto, airdrops, rewards, LP tokens…). Use these, not general assumptions, when you explain what a label change does.
3. **Summarise.** Call `get_reconciliation_summary`. Report `percentage` and a table of the six checks with their counts and kind.
   - The price, purchase, uncategorised and high-P&L counts are **transactions**; their lists return **groups** (asset + wallet), so the totals won't match.
   - The integrations and balances counts should equal their lists' `meta.totalCount`. If they don't, the data changed between calls (a sync, a recompute, or a spam change finishing); read the summary again.
   - `percentage` only moves with prices, purchases, uncategorised and high-P&L items. Fixing balances or integrations is still necessary but won't change it.
4. **Fix root causes first**, in this order, skipping checks at zero:
   1. Missing Integrations and Missing Balances — an unconnected wallet or spam tokens are the most common cause of everything else.
   2. Missing Purchase History.
   3. Missing Price.
   4. Uncategorised Transactions.
   5. High P&L Transactions.
5. **For each check:** list the items (up to 200 per page, biggest groups first), explain the likely cause in plain language, and propose specific fixes as a table. **Wait for the user to confirm** before any write; one confirmation can cover a batch the user has seen. If a write is rejected because the transaction is in a locked period, check `list_period_locks` and tell the user.
6. **Re-check.** Writes (labels, edits, merges, new transactions) trigger a recalculation automatically. Watch `list_tasks(operationType: "workspace-recompute", limit: 1)` until it is no longer `pending` or `in_progress`, then call `get_reconciliation_summary` again and report the new percentage. If `get_accounting_status` still shows a `lastCalculation` from before your fixes (or after `mark_spam`, which doesn't trigger one), call `trigger_recompute` and poll `get_task` before quoting any tax figure.

Pass the `false` review flags shown in the table so items already dismissed or marked reviewed drop out of the lists, matching the summary counts.

## How to fix each check

**Missing Integrations.** Rows are groups. When `is_exchange_address` is true the row is a whole exchange (`provider_name` set): tell the user to connect that exchange in the Kryptos web app; never ask for or accept API keys or secrets in the chat. An unrecognised `address` (listed once it has at least 100 transactions; `provider` is its chain) — ask whose it is:

- the user's own wallet → add it with `add_wallet` (public address, the `provider` as `providerId`, and a `primaryPortfolioId` from `list_portfolios`);
- a known person or company → `create_contact`, then `assign_address_to_contact` (the chain as `chainName`); this also removes the row;
- never going to be named (burn address, dust sender) → `ignore_counterparty(ignored: true)` for **each** id in the row's `counter_party_ids` (not the row `id`).

**Missing Balances.** `diff` is calculated minus reported. `missing_deposit` means the history is missing an acquisition or deposit; `missing_withdrawal` means a missing disposal or withdrawal. Only wallets whose provider reports holdings are compared, so CSV-imported and custom wallets never appear here.

- In on-chain wallets most rows are usually **airdropped scam tokens**: a URL, "claim" or "visit" in the name, no price, a very large quantity, a calculated quantity of 0. Offer `mark_spam` with `entries: [{ assetId, isSpam: true }]` (up to 500; leaving out `chainId` marks it on every chain). A scam token can copy a real ticker such as USDT, so check its `assetId` differs from the one on the user's priced transactions, and use `get_asset_transaction_counts` to show how much marking hides. `mark_spam` returns a task: poll `get_task`, then `trigger_recompute`, then read the list again. Rows without an `assetId` can't be marked.
- For the rest, check Missing Integrations first. If an integration may simply be behind, call `resync_integration` with the default incremental mode, or `startTime` to backfill. Never pass `syncMode: "resync_from_start"` unless the user explicitly asks; it deletes the integration's data first. If the user can describe the missing transaction, record it with `create_manual_transaction` (see below).

**Missing Purchase History.** A sale with no earlier acquisition. Common causes, in order of likelihood:

- the coins came from a wallet that isn't connected → connect it;
- a transfer between the user's own wallets wasn't matched → merge the two sides (see Merging below);
- an incoming gift, airdrop or reward is still a plain Deposit → relabel it (see Uncategorised);
- a purchase from before the user started tracking → `create_manual_transaction` with the user's date, quantity and cost.

Never invent a cost basis, date or quantity; ask.

**Missing Price.** Read the transaction's legs with `get_transaction_ledgers`, then set the price on the unpriced leg with `update_ledger(id, ledgerId, price, priceCurrency, priceTimestamp)`: `price` is a **per-unit** price (value is quantity × price, so a total is wrong), `priceCurrency` its currency (a price in another currency is converted onto the workspace's), and `priceTimestamp` the leg's own timestamp.

- Only use a price the user gives you, or one they accept from a source you name.
- If a major asset has no price — a chain's native coin, a large stablecoin, wrapped BTC or ETH — that's a gap in Kryptos's price data: tell the user to report it to Kryptos support rather than typing a price in.
- For an airdropped scam token, offer `mark_spam` as above.
- If the user wants to leave it, dismiss it with `update_transaction_label(isMissingPriceIgnored: true)`, one transaction at a time.

**Uncategorised Transactions.** Plain Deposit/Withdrawal labels with no specific meaning. Check `tagsException`: a plain Withdrawal is commonly a taxable disposal and a plain Deposit an acquisition at market value, so a bridge move or a transfer to the user's own exchange account left as a Withdrawal can overstate gains.

- Group the transactions by what they did: the transaction's `protocol.functionName` (for example `bridge`, `addLiquidityETH`, `execTransaction`, `buyNFT`) and the protocol or exchange in its source data. Propose one label per group, using the **exact** name from `get_supported_labels`. Labels aren't validated, so a misspelt one is stored as is.
- **Merge before you relabel** (see Merging). A merged transaction keeps cost basis and holding date across the move; two separately labelled halves don't.
- Apply a label to a group with `bulk_update_transaction_labels` (`{ ids, data: { label } }`). `data` only accepts `label`, `description`, `notes` and `tags`, and one id in a locked period rejects the whole batch.
- A genuine transfer of the user's own funds with no other activity can stay a Deposit/Withdrawal. Dismiss it with `update_transaction_label(isUncategorisedIgnored: true)`, one at a time (the bulk tool can't set this flag).
- To flag one for the user to check later, add a tag; `tags` replaces the whole list, so read the current tags first.

See `references/label-guide.md`.

**High P&L Transactions.** Pass `minTotalGains` exactly equal to `highPnlThreshold` from the summary; any other value, or sorting by gains, is refused. It matches large gains and large losses. If the threshold is very low (it defaults to a single unit of currency when no one has set it), the list can be most of the workspace: say so, and review the largest by `sortBy: "netValue"` first. Gains, cost basis and proceeds are always null on this connection, so judge each transaction by its legs (`get_transaction_ledgers`): is the price plausible for that date, is the quantity right, is an earlier acquisition missing? Fix a wrong price with `update_ledger`, and wrong assets or quantities with `edit_transaction`. If the user confirms it's correct, mark it with `update_transaction_label(isHighPnLReviewed: true)`. A large gain is often just a large gain.

**Merging.** `merge_transactions(trxsIDs)` joins at least two transactions into one. It works for Deposit/Withdrawal (and fiat deposit/withdrawal) transactions no more than a day apart, with one asset on each side, and usually one deposit with one withdrawal. Kryptos sets the result's label itself (Transfer, Bridge Transfer, Trade or Cross Chain Swaps). A transaction already relabelled (for example to Bridge Send) can no longer be merged. `split_transaction` undoes a merge.

**Recording a missing transaction.** `create_manual_transaction` needs `timestamp` (epoch ms), a `label`, and legs `{ assetId, quantity, price?, walletId? }`: incoming only for a deposit, outgoing only for a withdrawal, both for a trade. Resolve each `assetId` with `search_assets` (prefer the contract address; a bare ticker can match a counterfeit) and each `walletId` with `get_integrations`.

## Boundaries

- Ask before every write. Show what will change and on which transactions.
- Never guess prices, cost basis, dates, quantities or a counterparty's identity. If the data doesn't show it, ask the user.
- Don't delete transactions, resync from scratch or unlock periods unless the user explicitly asks for that specific action.
- `get_transactions` and the summary leave out Spam- and Ignore-labelled transactions; the missing-price and missing-purchase lists may still include them.
- Describe what the data shows and what each label means for tax in this workspace. Don't give personal tax or investment advice.

## What to tell the user at the end

The starting and new percentage, what was fixed (counts per check), what is left and why, and whether gains have been recalculated since the fixes.

Referenced files: 1 — file references are metadata, not package contents.

Release notes

First plugin package for the Kryptos MCP server: portfolio, transactions, reconciliation, tax and accounting tools, with four skills — get-started (connect wallets by address), review-and-reconcile (the six Review checks), prepare-tax-year (from clean data to a generated report) and crypto-bookkeeping (chart of accounts, rules and ERP journals). Tool annotations set on every tool; wallets are added by public address only and no tool accepts API keys or secrets.

Declared in the saved package. Remote tools may change independently.

Package details

Publisher declarations from the archived package. These are separate from our research and the live service's terms.

Package author
Kryptos
Keywords
See keywords
Getting started skill
./skills/get-started/SKILL.md
Commerce declaration
Does not support commerceThis does not establish whether access is free or paid.
Review scenarios
5 positive · 3 negativeScenario counts, not test results.

Declared capabilities

  • Portfolio and holdings
  • Transaction history
  • Data quality checks
  • Tax reports and cost basis
  • Chart of accounts and ERP journals

Package observed Nov 2, 2026.

Technical details
First seen
Oct 24, 2026 · 12:40 UTC
Last seen
Nov 3, 2026 · 12:00 UTC
Collection status
Collected

plugin_asdk_app_6abf54b5b0ac8191a6bf0bf6b0e47ae9

Download plugin data (JSON)