dero-mcp-server 0.1.2 → 0.2.2
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 +8 -8
- package/data/docs-index.json +17 -9
- package/dist/citations.d.ts +70 -0
- package/dist/citations.d.ts.map +1 -0
- package/dist/citations.js +162 -0
- package/dist/citations.js.map +1 -0
- package/dist/composites/_shared.d.ts +119 -0
- package/dist/composites/_shared.d.ts.map +1 -0
- package/dist/composites/_shared.js +152 -0
- package/dist/composites/_shared.js.map +1 -0
- package/dist/composites/diagnose-chain-health.d.ts +64 -0
- package/dist/composites/diagnose-chain-health.d.ts.map +1 -0
- package/dist/composites/diagnose-chain-health.js +144 -0
- package/dist/composites/diagnose-chain-health.js.map +1 -0
- package/dist/composites/estimate-deploy-cost.d.ts +83 -0
- package/dist/composites/estimate-deploy-cost.d.ts.map +1 -0
- package/dist/composites/estimate-deploy-cost.js +116 -0
- package/dist/composites/estimate-deploy-cost.js.map +1 -0
- package/dist/composites/explain-smart-contract.d.ts +64 -0
- package/dist/composites/explain-smart-contract.d.ts.map +1 -0
- package/dist/composites/explain-smart-contract.js +149 -0
- package/dist/composites/explain-smart-contract.js.map +1 -0
- package/dist/composites/recommend-docs-path.d.ts +97 -0
- package/dist/composites/recommend-docs-path.d.ts.map +1 -0
- package/dist/composites/recommend-docs-path.js +149 -0
- package/dist/composites/recommend-docs-path.js.map +1 -0
- package/dist/composites/trace-transaction-with-context.d.ts +107 -0
- package/dist/composites/trace-transaction-with-context.d.ts.map +1 -0
- package/dist/composites/trace-transaction-with-context.js +217 -0
- package/dist/composites/trace-transaction-with-context.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +334 -112
- package/dist/server.js.map +1 -1
- package/dist/tool-descriptions.d.ts +50 -0
- package/dist/tool-descriptions.d.ts.map +1 -0
- package/dist/tool-descriptions.js +246 -0
- package/dist/tool-descriptions.js.map +1 -0
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://github.com/DHEBP/dero-mcp-server/actions/workflows/ci.yml)
|
|
7
7
|
[](https://glama.ai/mcp/servers/DHEBP/dero-mcp-server)
|
|
8
8
|
|
|
9
|
-
**Registry listing:** `io.github.DHEBP/dero-mcp-server` · **Version:** `0.
|
|
9
|
+
**Registry listing:** `io.github.DHEBP/dero-mcp-server` · **Version:** `0.2.2` · **Transport:** `stdio` (npm package)
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
@@ -114,18 +114,18 @@ In **OpenCode MCP settings**, add a server with the same `command` / `args` / `e
|
|
|
114
114
|
| `DERO_DAEMON_URL` | `http://82.65.143.182:10102` | Daemon **base** URL (no `/json_rpc` required). Set to `http://127.0.0.1:10102` for a local daemon. |
|
|
115
115
|
| `DERO_DOCS_ROOT` | bundled index | Optional dev override: path to a local `dero-docs` clone to index live MDX instead of the shipped bundle. |
|
|
116
116
|
|
|
117
|
-
## Maintainer:
|
|
117
|
+
## Maintainer: bundled docs
|
|
118
118
|
|
|
119
|
-
|
|
119
|
+
Docs tools read from `data/docs-index.json`, committed in this repo and shipped with the npm package. Rebuild the index when [dero-docs](https://github.com/DHEBP/dero-docs) changes:
|
|
120
120
|
|
|
121
121
|
```bash
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
npm publish
|
|
125
|
-
mcp-publisher publish
|
|
122
|
+
npm run release:docs-check
|
|
123
|
+
git add data/docs-index.json && git commit -m "Refresh bundled docs index."
|
|
126
124
|
```
|
|
127
125
|
|
|
128
|
-
|
|
126
|
+
Or run **Refresh docs bundle** under [Actions](https://github.com/DHEBP/dero-mcp-server/actions/workflows/refresh-docs-bundle.yml) to open a PR. Pushes to `dero-docs` `main` can trigger that workflow via `repository_dispatch` when `MCP_DOCS_SYNC_TOKEN` is configured on the docs repo.
|
|
127
|
+
|
|
128
|
+
After merging a bundle update: bump the patch version in `package.json` and `server.json`, then `npm publish --otp=...` and `mcp-publisher publish`.
|
|
129
129
|
|
|
130
130
|
## Testing
|
|
131
131
|
|
package/data/docs-index.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 1,
|
|
3
|
-
"generated_at": "2026-05-
|
|
3
|
+
"generated_at": "2026-05-24T01:55:47.792Z",
|
|
4
4
|
"page_count": 145,
|
|
5
5
|
"pages": [
|
|
6
6
|
{
|
|
@@ -1580,30 +1580,38 @@
|
|
|
1580
1580
|
{
|
|
1581
1581
|
"product": "derod",
|
|
1582
1582
|
"slug": "tools/mcp-server",
|
|
1583
|
-
"title": "
|
|
1584
|
-
"description":
|
|
1583
|
+
"title": "DERO MCP Server | AI Assistant Integration for the DERO Blockchain",
|
|
1584
|
+
"description": "Run a read-only, agent-ready DERO MCP server locally. 20 daemon-read primitives, 5 composite tools that fuse live chain reads with the bundled DERO docs index, plus structured errors and curated citations — no middlemen, no API keys, no surveillance.",
|
|
1585
1585
|
"canonicalUrl": "https://derod.org/tools/mcp-server",
|
|
1586
1586
|
"sourcePath": "derod-main/pages/tools/mcp-server.mdx",
|
|
1587
1587
|
"headings": [
|
|
1588
1588
|
"MCP Server",
|
|
1589
|
+
"What's New in 0.2.0",
|
|
1589
1590
|
"Why This Matters",
|
|
1590
1591
|
"Install",
|
|
1591
1592
|
"Run Your Own Node",
|
|
1592
|
-
"Start your local DERO daemon with RPC enabled",
|
|
1593
1593
|
"Configure Your MCP Client",
|
|
1594
1594
|
"Claude Desktop",
|
|
1595
1595
|
"Cursor",
|
|
1596
1596
|
"OpenCode",
|
|
1597
|
-
"Continue
|
|
1597
|
+
"Continue · Cline · Zed · others",
|
|
1598
|
+
"Inspect interactively",
|
|
1598
1599
|
"What You Can Ask",
|
|
1599
|
-
"
|
|
1600
|
-
"
|
|
1600
|
+
"Composite Tools",
|
|
1601
|
+
"Primitive Tools",
|
|
1602
|
+
"Daemon RPC",
|
|
1603
|
+
"Bundled docs index",
|
|
1604
|
+
"Resources and Prompts",
|
|
1605
|
+
"Resources",
|
|
1606
|
+
"Prompts",
|
|
1607
|
+
"Structured Errors",
|
|
1608
|
+
"Read-Only by Design",
|
|
1601
1609
|
"Environment",
|
|
1602
1610
|
"Verify, Don't Trust",
|
|
1603
1611
|
"See Also"
|
|
1604
1612
|
],
|
|
1605
|
-
"plainText": "MCP Server Query the DERO blockchain from AI assistants — no middlemen, no API keys, no surveillance. The DERO MCP server implements the Model Context Protocol, an open standard for connecting AI models to external tools. Run it locally, point it at your own node, and let your AI assistant interact with DERO directly. Why This Matters AI assistants are powerful research tools, but most blockchain integrations route through centralized APIs that log your queries. This server runs on **your machine**, talks to **your node** (or a public one you choose), and communicates with your AI over **local stdio**. No accounts. No tracking. Just code you can audit. Install Requires Node.js 18+. Source code: github.com/DHEBP/dero-mcp-server Run Your Own Node The server defaults to a third-party public RPC. For real privacy, run your own daemon: Then configure the MCP server to use it (see below). Configure Your MCP Client Claude Desktop Edit claude_desktop_config.json: | OS | Path | |----|------| | macOS | ~/Library/Application Support/Claude/claude_desktop_config.json | | Windows | %APPDATA%\\Claude\\claude_desktop_config.json | | Linux | ~/.config/claude/claude_desktop_config.json | Omit env to use the default public RPC. Cursor **Settings → MCP → Add Server** - Command: dero-mcp-server - Environment: DERO_DAEMON_URL=http://127.0.0.1:10102 (optional) OpenCode Or with a local node: Continue / Cline / Zed / Others Any MCP-compatible client works. The server uses **stdio** transport: Consult your client's MCP documentation for the exact config format. What You Can Ask Once connected, talk to your AI naturally: - *\"What's the current DERO block height?\"* - *\"Show me the source code for contract [SCID]\"* - *\"What variables does this smart contract store?\"* - *\"Look up the transaction [TXID]\"* - *\"What's the network hashrate and difficulty?\"* - *\"Resolve the name dero to a wallet address\"* Available Tools | Tool | RPC Method | Description | |------|------------|-------------| | dero_daemon_ping | DERO.Ping | Check daemon connectivity | | dero_get_info | DERO.GetInfo | Network height, difficulty, version, hashrate | | dero_get_height | DERO.GetHeight | Current height, stable height, topoheight | | dero_get_block | DERO.GetBlock | Full block by hash or height | | dero_get_block_header_by_hash | DERO.GetBlockHeaderByHash | Block header by hash | | dero_get_block_header_by_topoheight | DERO.GetBlockHeaderByTopoHeight | Block header by topoheight | | dero_get_block_template | DERO.GetBlockTemplate | Mining block template | | dero_get_tx | DERO.GetTransaction | Transaction details by hash | | dero_get_sc | DERO.GetSC | Smart contract code and state variables | | dero_get_gas_estimate | DERO.GetGasEstimate | Estimate gas for a contract call | | dero_get_random_address | DERO.GetRandomAddress | Random registered wallet addresses | | dero_name_to_address | DERO.NameToAddress | Resolve registered name → address | | dero_get_encrypted_balance | DERO.GetEncryptedBalance | Encrypted balance for an address | Security Model **Read-only by design.** This server cannot: - Send transactions - Transfer funds - Invoke smart contracts - Submit blocks - Access your wallet Wallet RPC methods (transfer, scinvoke, etc.) are explicitly excluded. The server only queries public blockchain data through daemon RPC. If you need write capabilities in the future, they will be gated behind explicit flags and a separate wallet URL — never enabled by default. Environment | Variable | Default | Description | |----------|---------|-------------| | DERO_DAEMON_URL | http://82.65.143.182:10102 | Daemon base URL. Set to http://127.0.0.1:10102 for a local node. | Verify, Don't Trust - Source code on GitHub - Package on npm - MIT licensed — fork it, audit it, improve it See Also - DERO Daemon RPC API — full RPC reference - Running a DERO Node — set up your own daemon - XSWD — browser wallet integration",
|
|
1606
|
-
"lastUpdated":
|
|
1613
|
+
"plainText": "MCP Server Query the DERO blockchain — and the canonical DERO documentation — from AI assistants. No middlemen, no API keys, no surveillance. The DERO MCP server implements the Model Context Protocol, the open standard for connecting AI models to external tools. Run it locally, point it at your own daemon, and let your AI assistant interact with DERO directly over local **stdio** transport. **AI discovery files:** llms.txt and /api/openapi.json are curated subsets for agents — not a full RPC catalog. Use the Daemon RPC API and Wallet RPC API for complete method reference. Examples assume a **local daemon** at http://127.0.0.1:10102 (there is no official public node.dero.io endpoint). What's New in 0.2.0 The 0.2.0 release expands the surface from 20 primitives to **25 tools** by adding 5 **composite tools** that fuse live daemon reads with the bundled DERO docs index. Every response includes curated related_docs citations, every tool carries read-only annotations (so MCP hosts can auto-approve safely), and four new structured _meta.error codes (NO_DOCS_MATCH, INVALID_INPUT, TX_NOT_FOUND, plus existing RPC_UNREACHABLE / RPC_INVALID_PARAMS) let agents react programmatically to failures. | Surface area | 0.1.x | 0.2.0 | |---|---:|---:| | Tools | 20 | **25** (+5 composites) | | Read-only annotations | none | **25/25** | | Curated docs citations | none | **16 across 7 tools** | | Structured error codes | none | **5** | | Resources | 3 | **4** (+composite catalog) | | Prompts | 3 | **5** (refreshed composite-first, +2 new) | All 20 primitives keep their identifiers, schemas, and behavior — clients pinned to 0.1.x will continue to work. Why This Matters AI assistants are powerful research and dev tools, but most blockchain integrations route through centralized APIs that log your queries. This server runs on **your machine**, talks to **your daemon** (or a public one you choose), and communicates with your AI over **local stdio**. No accounts, no analytics, no tracking — just code you can audit. The bundled DERO documentation index (145+ pages across derod, tela, hologram, and deropay) is shipped inside the package, so the AI can quote primary sources offline without a single network round-trip beyond the daemon you pointed it at. Install Requires Node.js 18+. Source code: github.com/DHEBP/dero-mcp-server · npm: dero-mcp-server Run Your Own Node The server defaults to a third-party public RPC. For real privacy, run your own daemon: Then point the MCP server at it via DERO_DAEMON_URL (see below). Configure Your MCP Client Claude Desktop Edit claude_desktop_config.json: | OS | Path | |----|------| | macOS | ~/Library/Application Support/Claude/claude_desktop_config.json | | Windows | %APPDATA%\\Claude\\claude_desktop_config.json | | Linux | ~/.config/claude/claude_desktop_config.json | Omit env to use the default public RPC. Cursor **Settings → MCP → Add Server** - Command: dero-mcp-server - Environment: DERO_DAEMON_URL=http://127.0.0.1:10102 (optional) OpenCode Or with a local node: Continue · Cline · Zed · others Any MCP-compatible client works. The server uses **stdio** transport: Consult your client's MCP documentation for the exact config format. Inspect interactively To explore the full surface without committing to a client config, use the official MCP Inspector: It opens a local web UI that lists every tool with its schema and annotations, lets you invoke any tool with form-filled args, and shows the structured response including _meta.error blocks. What You Can Ask Once connected, talk to your AI naturally — it will pick the right composite or primitive based on your intent: - *\"Is the DERO daemon healthy and synced?\"* → diagnose_chain_health - *\"What does the contract at SCID […] do?\"* → explain_smart_contract - *\"Look up transaction [txid] and tell me what it is.\"* → trace_transaction_with_context - *\"Which DERO docs page should I read to deploy a TELA app?\"* → recommend_docs_path - *\"Estimate the gas cost to deploy this DVM contract.\"* → estimate_deploy_cost - *\"What's the current block height?\"* → dero_get_info / dero_get_height - *\"Show me the source code for contract [SCID].\"* → dero_get_sc - *\"Resolve the name dero to a wallet address.\"* → dero_name_to_address Composite Tools Each composite replaces a multi-step primitive chain with a single call, returns a plain-language narrative summary, and stitches the most relevant bundled docs pages as related_docs citations. | Composite | Replaces | When to call | |---|---|---| | diagnose_chain_health | Ping + GetInfo + GetHeight + GetTxPool | Any \"is the chain healthy / are we synced\" question | | explain_smart_contract | GetSC + manual DVM-BASIC parsing + docs lookup | \"What does this contract do\" — returns function surface + token/registry/minimal/generic classification + 1-4 curated DVM docs | | recommend_docs_path | 4× parallel dero_docs_search + manual ranking | Natural-language intent → ranked docs across all 4 DERO products; product_hint is a 1.5× score bias, not a filter | | estimate_deploy_cost | GetGasEstimate + manual surface extraction + manual gas interpretation | DVM deploy pre-flight — returns gas estimate + plain-text breakdown + parsed function surface | | trace_transaction_with_context | GetTransaction + (for SC installs) GetSC + manual classification | \"What is this tx\" — returns confirmation status, kind classification, ring stats, and parsed SC install surface inline | Each composite is fully documented in docs/composites.md (design contract, accepted/rejected designs, failure modes), and every composite ships with a green flow test in CI that runs against a live public daemon. **Why composites matter for agents.** A generic JSON-RPC client can chain primitives, but it cannot stitch the right docs context or classify failure modes for free. Composites are the wedge: they deliver agent-ready answers from the canonical DERO data sources in one call. Primitive Tools The 20 primitives map 1:1 onto daemon RPC methods plus the bundled docs index. Use them when a composite is unavailable or you need raw data. Daemon RPC | Tool | RPC Method | Purpose | |------|------------|---------| | dero_daemon_ping | DERO.Ping | Liveness check | | dero_daemon_echo | DERO.Echo | Roundtrip string echo | | dero_get_info | DERO.GetInfo | Network height, difficulty, version, hashrate, testnet flag | | dero_get_height | DERO.GetHeight | Height, stableheight, topoheight | | dero_get_block_count | DERO.GetBlockCount | Total block count | | dero_get_block | DERO.GetBlock | Full block by hash or height | | dero_get_block_header_by_hash | DERO.GetBlockHeaderByHash | Block header by hash | | dero_get_block_header_by_topo_height | DERO.GetBlockHeaderByTopoHeight | Block header by topoheight | | dero_get_last_block_header | DERO.GetLastBlockHeader | Tip block header | | dero_get_block_template | DERO.GetBlockTemplate | Mining block template | | dero_get_transaction | DERO.GetTransaction | Transaction record by hash | | dero_get_tx_pool | DERO.GetTxPool | Mempool transaction hashes | | dero_get_sc | DERO.GetSC | Smart contract code, variables, balances | | dero_get_gas_estimate | DERO.GetGasEstimate | Daemon-side gas estimate for a contract source or call | | dero_get_encrypted_balance | DERO.GetEncryptedBalance | Encrypted balance for an address | | dero_get_random_address | DERO.GetRandomAddress | Random registered wallet addresses | | dero_name_to_address | DERO.NameToAddress | Resolve a registered name to its address | Bundled docs index | Tool | Purpose | |------|---------| | dero_docs_list | Enumerate available doc pages across derod, tela, hologram, deropay | | dero_docs_search | Full-text search across the bundled docs index — in-process, no network round-trip | | dero_docs_get_page | Fetch a single doc page by slug with full plain-text content and headings | Resources and Prompts Beyond tools, the server exposes 4 **resources** and 5 **prompts** so MCP-aware clients can surface them in their UI: Resources | URI | Content | |-----|---------| | dero://mcp/server-info | Server metadata, tool list, resource list, prompt names, daemon endpoint | | dero://mcp/safety-boundary | Read-only posture and excluded method list (transfer, scinvoke, etc.) | | dero://mcp/example-flows | Composite-first agent flow recipes for common DERO investigations | | dero://mcp/composites | Structured catalog of all 5 composites — what each replaces, when to call it, what it returns, and which _meta.error codes it can emit | Prompts | Prompt | What it scripts | |--------|----------------| | network_health_check | Drives diagnose_chain_health with optional reference_topoheight | | inspect_smart_contract | Drives explain_smart_contract for any SCID | | trace_transaction | Drives trace_transaction_with_context for any tx hash | | find_dero_docs_for_intent | Drives recommend_docs_path with a natural-language intent + optional product_hint | | estimate_deploy_for_contract | Drives estimate_deploy_cost with DVM-BASIC source | Structured Errors Every tool wraps failures in a structured _meta.error block so agents can react programmatically instead of parsing error strings: | Code | Emitted by | Meaning | Retryable | |------|------------|---------|:---------:| | RPC_UNREACHABLE | All tools | Daemon not reachable on DERO_DAEMON_URL | yes | | RPC_INVALID_PARAMS | Most tools | Daemon rejected the request shape | no | | NO_DOCS_MATCH | recommend_docs_path | Intent matched zero pages across all 4 products | no — rephrase first | | INVALID_INPUT | estimate_deploy_cost | DVM compile error (wraps daemon -32098); raw message preserved in _meta.error.raw | no | | TX_NOT_FOUND | trace_transaction_with_context | Daemon returned an empty record for the hash | yes — verify hash + network first | Every error code carries a hint string with actionable next steps so the agent can recover or explain the failure cleanly to the user. Read-Only by Design Every one of the 25 tools carries the MCP read-only annotation block: This lets MCP hosts safely auto-approve any tool call from this server without prompting on every read. The server **cannot**: - Send transactions - Transfer funds - Invoke smart contracts (only **estimate** deploy cost via estimate_deploy_cost — nothing is submitted to chain) - Submit blocks - Hold wallet keys or talk to wallet RPC Wallet RPC methods (transfer, scinvoke, DERO.SendRawTransaction, DERO.SubmitBlock) are explicitly excluded. The full read-only posture, the six AND-gated conditions that would be required to expand the boundary, and the rationale for each are documented in docs/decision-boundary.md. If you need write capabilities in the future, they will be gated behind explicit flags **and** a separate wallet URL **and** a distinct annotation block (readOnlyHint: false) **and** documented escalation — never enabled by default. Environment | Variable | Default | Description | |----------|---------|-------------| | DERO_DAEMON_URL | http://82.65.143.182:10102 | Daemon base URL. Set to http://127.0.0.1:10102 for a local node. | | DERO_DOCS_ROOT | _(unset; uses bundled index)_ | Optional dev override pointing at a local docs source tree. Production deployments should leave this unset to use the bundled index. | Verify, Don't Trust - Source code on GitHub — composite design contract in docs/composites.md, read-only posture in docs/decision-boundary.md, agent-ready evidence in docs/mcp-agent-ready-evidence.md - Package on npm - Listed in the official MCP registry as io.github.DHEBP/dero-mcp-server - CI runs full smoke probes, composite flow tests, primitive flow tests, and description / citation drift guards on every push - MIT licensed — fork it, audit it, improve it See Also - DERO Daemon RPC API — full RPC reference for the methods the primitives wrap - Running a DERO Node — set up your own daemon - Smart Contract Fundamentals — DVM concepts the composites cite - XSWD — browser wallet integration (for write flows the MCP server intentionally excludes)",
|
|
1614
|
+
"lastUpdated": "2026-05-23"
|
|
1607
1615
|
},
|
|
1608
1616
|
{
|
|
1609
1617
|
"product": "derod",
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Citation helper for DERO MCP tool responses.
|
|
3
|
+
*
|
|
4
|
+
* The wedge for this server is the combination of live chain reads and the
|
|
5
|
+
* in-process bundled docs index (145+ pages across derod, tela, hologram,
|
|
6
|
+
* deropay). Citations let agents link their responses back to authoritative
|
|
7
|
+
* docs without a second tool call, and they give downstream composite tools
|
|
8
|
+
* a uniform shape to compose.
|
|
9
|
+
*
|
|
10
|
+
* Design contract:
|
|
11
|
+
* - One shape, used by primitives and composites alike.
|
|
12
|
+
* - URLs are produced by the same builder used by `dero_docs_*` so the
|
|
13
|
+
* citation always points at the same canonical page the agent would
|
|
14
|
+
* reach via dero_docs_get_page.
|
|
15
|
+
* - The slug is duplicated as `page_id` to give composites a stable join
|
|
16
|
+
* key across tools (mirrors the FoodNearMe COMPOSITES.md citation pattern).
|
|
17
|
+
* - The map of related docs per tool is hand-maintained and validated by
|
|
18
|
+
* `scripts/check-citations.ts` (added alongside this helper) so a docs
|
|
19
|
+
* reorganization cannot silently produce 404 citations in production.
|
|
20
|
+
*/
|
|
21
|
+
import { type DeroDocProduct } from './docs-parse.js';
|
|
22
|
+
export type DeroCitation = {
|
|
23
|
+
/** Always `'dero_docs'` for now; future sources (e.g. `'dero_chain'`) can extend this. */
|
|
24
|
+
source: 'dero_docs';
|
|
25
|
+
product: DeroDocProduct;
|
|
26
|
+
slug: string;
|
|
27
|
+
title: string;
|
|
28
|
+
canonical_url: string;
|
|
29
|
+
/** Alias of `slug` so composites can use a single join key across tools. */
|
|
30
|
+
page_id: string;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Build a DeroCitation pointing at one bundled docs page.
|
|
34
|
+
*
|
|
35
|
+
* The title is required (not derived from the bundled index) so this helper
|
|
36
|
+
* stays synchronous and zero-IO. It must match the docs page title; the
|
|
37
|
+
* citation guard validates this against the bundled index in CI.
|
|
38
|
+
*/
|
|
39
|
+
export declare function buildDeroCitation(product: DeroDocProduct, slug: string, title: string): DeroCitation;
|
|
40
|
+
/**
|
|
41
|
+
* Map of MCP tool name → hand-curated related docs pages.
|
|
42
|
+
*
|
|
43
|
+
* Keep this list tight — only add entries when a tool's response is
|
|
44
|
+
* meaningfully improved by linking the agent at a specific page. The CI
|
|
45
|
+
* guard verifies every slug resolves against the bundled docs index, so any
|
|
46
|
+
* docs reorganization will fail the build before it ships.
|
|
47
|
+
*
|
|
48
|
+
* Adding a tool here:
|
|
49
|
+
* 1. Use `dero_docs_search` to find the right slug(s).
|
|
50
|
+
* 2. Add an entry with product + slug + exact page title.
|
|
51
|
+
* 3. Run `npm run check:citations` to confirm slugs resolve.
|
|
52
|
+
*/
|
|
53
|
+
type RelatedDocsEntry = {
|
|
54
|
+
product: DeroDocProduct;
|
|
55
|
+
slug: string;
|
|
56
|
+
title: string;
|
|
57
|
+
};
|
|
58
|
+
export declare const RELATED_DOCS_BY_TOOL: Record<string, readonly RelatedDocsEntry[]>;
|
|
59
|
+
/**
|
|
60
|
+
* Resolve the hand-curated related docs list for a tool name and return it
|
|
61
|
+
* as fully-built `DeroCitation` objects. Returns `undefined` when the tool
|
|
62
|
+
* has no related docs configured.
|
|
63
|
+
*
|
|
64
|
+
* Use in tool handlers like:
|
|
65
|
+
* const related_docs = relatedDocsFor('dero_get_sc')
|
|
66
|
+
* return { ...rpcResult, ...(related_docs ? { related_docs } : {}) }
|
|
67
|
+
*/
|
|
68
|
+
export declare function relatedDocsFor(toolName: string): DeroCitation[] | undefined;
|
|
69
|
+
export {};
|
|
70
|
+
//# sourceMappingURL=citations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"citations.d.ts","sourceRoot":"","sources":["../src/citations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEpE,MAAM,MAAM,YAAY,GAAG;IACzB,0FAA0F;IAC1F,MAAM,EAAE,WAAW,CAAA;IACnB,OAAO,EAAE,cAAc,CAAA;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,MAAM,CAAA;IACrB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAQD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ,YAAY,CASd;AAED;;;;;;;;;;;;GAYG;AACH,KAAK,gBAAgB,GAAG;IAAE,OAAO,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAEhF,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAqGnE,CAAA;AAEV;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE,GAAG,SAAS,CAI3E"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Citation helper for DERO MCP tool responses.
|
|
3
|
+
*
|
|
4
|
+
* The wedge for this server is the combination of live chain reads and the
|
|
5
|
+
* in-process bundled docs index (145+ pages across derod, tela, hologram,
|
|
6
|
+
* deropay). Citations let agents link their responses back to authoritative
|
|
7
|
+
* docs without a second tool call, and they give downstream composite tools
|
|
8
|
+
* a uniform shape to compose.
|
|
9
|
+
*
|
|
10
|
+
* Design contract:
|
|
11
|
+
* - One shape, used by primitives and composites alike.
|
|
12
|
+
* - URLs are produced by the same builder used by `dero_docs_*` so the
|
|
13
|
+
* citation always points at the same canonical page the agent would
|
|
14
|
+
* reach via dero_docs_get_page.
|
|
15
|
+
* - The slug is duplicated as `page_id` to give composites a stable join
|
|
16
|
+
* key across tools (mirrors the FoodNearMe COMPOSITES.md citation pattern).
|
|
17
|
+
* - The map of related docs per tool is hand-maintained and validated by
|
|
18
|
+
* `scripts/check-citations.ts` (added alongside this helper) so a docs
|
|
19
|
+
* reorganization cannot silently produce 404 citations in production.
|
|
20
|
+
*/
|
|
21
|
+
import { DOC_BASE_URLS } from './docs-parse.js';
|
|
22
|
+
function buildCanonicalUrl(product, slug) {
|
|
23
|
+
const trimmed = slug.replace(/^\/+|\/+$/g, '');
|
|
24
|
+
if (!trimmed)
|
|
25
|
+
return `${DOC_BASE_URLS[product]}/`;
|
|
26
|
+
return `${DOC_BASE_URLS[product]}/${trimmed}`;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Build a DeroCitation pointing at one bundled docs page.
|
|
30
|
+
*
|
|
31
|
+
* The title is required (not derived from the bundled index) so this helper
|
|
32
|
+
* stays synchronous and zero-IO. It must match the docs page title; the
|
|
33
|
+
* citation guard validates this against the bundled index in CI.
|
|
34
|
+
*/
|
|
35
|
+
export function buildDeroCitation(product, slug, title) {
|
|
36
|
+
return {
|
|
37
|
+
source: 'dero_docs',
|
|
38
|
+
product,
|
|
39
|
+
slug,
|
|
40
|
+
title,
|
|
41
|
+
canonical_url: buildCanonicalUrl(product, slug),
|
|
42
|
+
page_id: slug,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export const RELATED_DOCS_BY_TOOL = {
|
|
46
|
+
dero_get_info: [
|
|
47
|
+
{
|
|
48
|
+
product: 'derod',
|
|
49
|
+
slug: 'rpc-api/daemon-rpc-api',
|
|
50
|
+
title: 'DERO Daemon RPC API: Complete Reference Guide | DERO Blockchain',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
product: 'derod',
|
|
54
|
+
slug: 'basics/daemon',
|
|
55
|
+
title: 'DERO Daemon: Backbone of the Privacy Blockchain | DERO Blockchain',
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
dero_get_sc: [
|
|
59
|
+
{
|
|
60
|
+
product: 'derod',
|
|
61
|
+
slug: 'dvm/smart-contract-fundamentals',
|
|
62
|
+
title: 'Smart Contract Fundamentals: Understanding DERO Contracts | DERO Blockchain',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
product: 'derod',
|
|
66
|
+
slug: 'dvm/dero-virtual-machine',
|
|
67
|
+
title: 'DERO Virtual Machine (DVM): Private Smart Contract Platform | DERO Blockchain',
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
dero_get_gas_estimate: [
|
|
71
|
+
{
|
|
72
|
+
product: 'derod',
|
|
73
|
+
slug: 'rpc-api/daemon-rpc-api',
|
|
74
|
+
title: 'DERO Daemon RPC API: Complete Reference Guide | DERO Blockchain',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
product: 'derod',
|
|
78
|
+
slug: 'dvm/create-deploy-use-smart-contract',
|
|
79
|
+
title: 'Create, Deploy & Use a Smart Contract on DERO | Step-by-Step Tutorial',
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
diagnose_chain_health: [
|
|
83
|
+
{
|
|
84
|
+
product: 'derod',
|
|
85
|
+
slug: 'basics/daemon',
|
|
86
|
+
title: 'DERO Daemon: Backbone of the Privacy Blockchain | DERO Blockchain',
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
product: 'derod',
|
|
90
|
+
slug: 'rpc-api/daemon-rpc-api',
|
|
91
|
+
title: 'DERO Daemon RPC API: Complete Reference Guide | DERO Blockchain',
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
trace_transaction_with_context: [
|
|
95
|
+
{
|
|
96
|
+
product: 'derod',
|
|
97
|
+
slug: 'rpc-api/daemon-rpc-api',
|
|
98
|
+
title: 'DERO Daemon RPC API: Complete Reference Guide | DERO Blockchain',
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
product: 'derod',
|
|
102
|
+
slug: 'dvm/smart-contract-fundamentals',
|
|
103
|
+
title: 'Smart Contract Fundamentals: Understanding DERO Contracts | DERO Blockchain',
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
estimate_deploy_cost: [
|
|
107
|
+
{
|
|
108
|
+
product: 'derod',
|
|
109
|
+
slug: 'dvm/create-deploy-use-smart-contract',
|
|
110
|
+
title: 'Create, Deploy & Use a Smart Contract on DERO | Step-by-Step Tutorial',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
product: 'derod',
|
|
114
|
+
slug: 'dvm/dvm-basic',
|
|
115
|
+
title: "DVM-BASIC: DERO's Smart Contract Language Guide | DERO Blockchain",
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
// Composite #2 (`explain_smart_contract`) curates all four DVM docs so its
|
|
119
|
+
// heuristic can elevate whichever page best matches the detected surface
|
|
120
|
+
// (token / registry / minimal / generic). The composite re-orders this
|
|
121
|
+
// array at runtime; the static ordering here is the fallback when the
|
|
122
|
+
// heuristic returns the same slug already at index 0 (the universal
|
|
123
|
+
// "fundamentals" default).
|
|
124
|
+
explain_smart_contract: [
|
|
125
|
+
{
|
|
126
|
+
product: 'derod',
|
|
127
|
+
slug: 'dvm/smart-contract-fundamentals',
|
|
128
|
+
title: 'Smart Contract Fundamentals: Understanding DERO Contracts | DERO Blockchain',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
product: 'derod',
|
|
132
|
+
slug: 'dvm/dvm-basic',
|
|
133
|
+
title: "DVM-BASIC: DERO's Smart Contract Language Guide | DERO Blockchain",
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
product: 'derod',
|
|
137
|
+
slug: 'dvm/dero-virtual-machine',
|
|
138
|
+
title: 'DERO Virtual Machine (DVM): Private Smart Contract Platform | DERO Blockchain',
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
product: 'derod',
|
|
142
|
+
slug: 'dvm/create-deploy-use-smart-contract',
|
|
143
|
+
title: 'Create, Deploy & Use a Smart Contract on DERO | Step-by-Step Tutorial',
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Resolve the hand-curated related docs list for a tool name and return it
|
|
149
|
+
* as fully-built `DeroCitation` objects. Returns `undefined` when the tool
|
|
150
|
+
* has no related docs configured.
|
|
151
|
+
*
|
|
152
|
+
* Use in tool handlers like:
|
|
153
|
+
* const related_docs = relatedDocsFor('dero_get_sc')
|
|
154
|
+
* return { ...rpcResult, ...(related_docs ? { related_docs } : {}) }
|
|
155
|
+
*/
|
|
156
|
+
export function relatedDocsFor(toolName) {
|
|
157
|
+
const entries = RELATED_DOCS_BY_TOOL[toolName];
|
|
158
|
+
if (!entries || entries.length === 0)
|
|
159
|
+
return undefined;
|
|
160
|
+
return entries.map((entry) => buildDeroCitation(entry.product, entry.slug, entry.title));
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=citations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"citations.js","sourceRoot":"","sources":["../src/citations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for DERO MCP composite tools.
|
|
3
|
+
*
|
|
4
|
+
* A composite tool stitches several primitives (daemon RPC reads + bundled
|
|
5
|
+
* docs lookups) into one intent-shaped response. These utilities exist so
|
|
6
|
+
* every composite handles failures, latency tracking, and citation
|
|
7
|
+
* attachment the same way.
|
|
8
|
+
*
|
|
9
|
+
* Anything reused by more than one composite belongs here. Composite-local
|
|
10
|
+
* helpers (e.g. narrative builders specific to one composite's response
|
|
11
|
+
* shape) should live next to that composite, not in this file.
|
|
12
|
+
*
|
|
13
|
+
* See `docs/composites.md` for the design contract that governs which
|
|
14
|
+
* utilities live here and the gate every composite must satisfy before it
|
|
15
|
+
* lands on main.
|
|
16
|
+
*/
|
|
17
|
+
import { type DeroCitation } from '../citations.js';
|
|
18
|
+
/**
|
|
19
|
+
* One step in a composite's internal chain.
|
|
20
|
+
*
|
|
21
|
+
* `required: true` aborts the chain if the step throws (use for liveness
|
|
22
|
+
* gates like `DERO.Ping`). `required: false` lets the chain continue with
|
|
23
|
+
* a degraded payload (use for enrichments like a mempool snapshot).
|
|
24
|
+
*/
|
|
25
|
+
export type ChainStep<T = unknown> = {
|
|
26
|
+
name: string;
|
|
27
|
+
required?: boolean;
|
|
28
|
+
fn: () => Promise<T>;
|
|
29
|
+
};
|
|
30
|
+
export type ChainStepResult = {
|
|
31
|
+
name: string;
|
|
32
|
+
ok: boolean;
|
|
33
|
+
value?: unknown;
|
|
34
|
+
error?: {
|
|
35
|
+
message: string;
|
|
36
|
+
};
|
|
37
|
+
latencyMs: number;
|
|
38
|
+
};
|
|
39
|
+
export type ChainResult = {
|
|
40
|
+
results: ChainStepResult[];
|
|
41
|
+
haltedAt: string | null;
|
|
42
|
+
totalMs: number;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Run a chain of named primitive calls sequentially. Required-step
|
|
46
|
+
* failures halt the chain and record `haltedAt`; non-required failures
|
|
47
|
+
* are recorded and the chain continues. Step latencies are captured so
|
|
48
|
+
* composites can attach diagnostics to a degraded response.
|
|
49
|
+
*/
|
|
50
|
+
export declare function runChain(steps: readonly ChainStep[]): Promise<ChainResult>;
|
|
51
|
+
/**
|
|
52
|
+
* Extract a single step's successful return value from a ChainResult.
|
|
53
|
+
* Returns null when the step was skipped (chain halted earlier), failed,
|
|
54
|
+
* or simply was not part of the chain.
|
|
55
|
+
*/
|
|
56
|
+
export declare function stepValue<T = unknown>(chain: ChainResult, name: string): T | null;
|
|
57
|
+
/**
|
|
58
|
+
* Per-step latency map suitable for embedding in a composite's response
|
|
59
|
+
* under a `_diagnostics` field. Lets agents and operators see which step
|
|
60
|
+
* was slow without needing to instrument the host.
|
|
61
|
+
*/
|
|
62
|
+
export declare function stepLatencies(chain: ChainResult): Record<string, number>;
|
|
63
|
+
/**
|
|
64
|
+
* Attach curated `related_docs` citations to a composite's payload.
|
|
65
|
+
* Mirrors how primitives attach citations so the response shape stays
|
|
66
|
+
* uniform across primitives and composites. Returns the payload
|
|
67
|
+
* unchanged when no curated docs are configured for the tool name.
|
|
68
|
+
*/
|
|
69
|
+
export declare function attachCitations<T extends Record<string, unknown>>(payload: T, toolName: string): T & {
|
|
70
|
+
related_docs?: DeroCitation[];
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Shape used by the JSON-RPC `rpc` closure created in `src/server.ts`.
|
|
74
|
+
* Re-declared here so composites can take it as a dependency without
|
|
75
|
+
* importing from the server module (keeps the composite layer free of
|
|
76
|
+
* `McpServer` coupling).
|
|
77
|
+
*/
|
|
78
|
+
export type DeroDaemonRpc = <T = unknown>(method: string, params?: unknown) => Promise<T>;
|
|
79
|
+
/**
|
|
80
|
+
* Loose representation of a `DERO.GetSC` response. Field names match the
|
|
81
|
+
* daemon's actual JSON keys observed on the public node. `uint64keys` is
|
|
82
|
+
* frequently absent (the daemon omits empty maps), so it is optional.
|
|
83
|
+
*/
|
|
84
|
+
export type DeroGetScResult = {
|
|
85
|
+
code?: string;
|
|
86
|
+
status?: string;
|
|
87
|
+
balance?: number;
|
|
88
|
+
balances?: Record<string, number>;
|
|
89
|
+
stringkeys?: Record<string, unknown>;
|
|
90
|
+
uint64keys?: Record<string, unknown>;
|
|
91
|
+
[k: string]: unknown;
|
|
92
|
+
};
|
|
93
|
+
export type DvmFunctionSignature = {
|
|
94
|
+
name: string;
|
|
95
|
+
args: string[];
|
|
96
|
+
returns: string;
|
|
97
|
+
};
|
|
98
|
+
export type DeroScSurface = {
|
|
99
|
+
functions: DvmFunctionSignature[];
|
|
100
|
+
stringkeys: string[];
|
|
101
|
+
uint64keys: string[];
|
|
102
|
+
balances: Record<string, number | string>;
|
|
103
|
+
raw_code_length: number;
|
|
104
|
+
has_code: boolean;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Convert a raw DERO.GetSC payload into a stable, agent-friendly surface.
|
|
108
|
+
*
|
|
109
|
+
* Behavior:
|
|
110
|
+
* - Returns `functions: []` when `code` is missing or the regex finds
|
|
111
|
+
* no Function declarations. Never throws on malformed code.
|
|
112
|
+
* - Sorts `stringkeys` / `uint64keys` alphabetically for deterministic
|
|
113
|
+
* output across invocations.
|
|
114
|
+
* - `balances` is passed through unchanged so callers can render asset
|
|
115
|
+
* balances; native DERO balance lives under `balance` on the raw
|
|
116
|
+
* payload and is left for callers to decide whether to surface.
|
|
117
|
+
*/
|
|
118
|
+
export declare function extractScSurface(raw: DeroGetScResult | null | undefined): DeroScSurface;
|
|
119
|
+
//# sourceMappingURL=_shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_shared.d.ts","sourceRoot":"","sources":["../../src/composites/_shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAEnE;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,GAAG,OAAO,IAAI;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,OAAO,CAAA;IACX,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,KAAK,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;IAC3B,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,eAAe,EAAE,CAAA;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAkChF;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAIjF;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAIxE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/D,OAAO,EAAE,CAAC,EACV,QAAQ,EAAE,MAAM,GACf,CAAC,GAAG;IAAE,YAAY,CAAC,EAAE,YAAY,EAAE,CAAA;CAAE,CAIvC;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;AAUzF;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,oBAAoB,EAAE,CAAA;IACjC,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAA;IACzC,eAAe,EAAE,MAAM,CAAA;IACvB,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAA;AA+BD;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,GAAG,aAAa,CAqBvF"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for DERO MCP composite tools.
|
|
3
|
+
*
|
|
4
|
+
* A composite tool stitches several primitives (daemon RPC reads + bundled
|
|
5
|
+
* docs lookups) into one intent-shaped response. These utilities exist so
|
|
6
|
+
* every composite handles failures, latency tracking, and citation
|
|
7
|
+
* attachment the same way.
|
|
8
|
+
*
|
|
9
|
+
* Anything reused by more than one composite belongs here. Composite-local
|
|
10
|
+
* helpers (e.g. narrative builders specific to one composite's response
|
|
11
|
+
* shape) should live next to that composite, not in this file.
|
|
12
|
+
*
|
|
13
|
+
* See `docs/composites.md` for the design contract that governs which
|
|
14
|
+
* utilities live here and the gate every composite must satisfy before it
|
|
15
|
+
* lands on main.
|
|
16
|
+
*/
|
|
17
|
+
import { relatedDocsFor } from '../citations.js';
|
|
18
|
+
/**
|
|
19
|
+
* Run a chain of named primitive calls sequentially. Required-step
|
|
20
|
+
* failures halt the chain and record `haltedAt`; non-required failures
|
|
21
|
+
* are recorded and the chain continues. Step latencies are captured so
|
|
22
|
+
* composites can attach diagnostics to a degraded response.
|
|
23
|
+
*/
|
|
24
|
+
export async function runChain(steps) {
|
|
25
|
+
const results = [];
|
|
26
|
+
const startedAt = performance.now();
|
|
27
|
+
let haltedAt = null;
|
|
28
|
+
for (const step of steps) {
|
|
29
|
+
const stepStart = performance.now();
|
|
30
|
+
try {
|
|
31
|
+
const value = await step.fn();
|
|
32
|
+
results.push({
|
|
33
|
+
name: step.name,
|
|
34
|
+
ok: true,
|
|
35
|
+
value,
|
|
36
|
+
latencyMs: Math.round(performance.now() - stepStart),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
results.push({
|
|
41
|
+
name: step.name,
|
|
42
|
+
ok: false,
|
|
43
|
+
error: { message: error instanceof Error ? error.message : String(error) },
|
|
44
|
+
latencyMs: Math.round(performance.now() - stepStart),
|
|
45
|
+
});
|
|
46
|
+
if (step.required) {
|
|
47
|
+
haltedAt = step.name;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
results,
|
|
54
|
+
haltedAt,
|
|
55
|
+
totalMs: Math.round(performance.now() - startedAt),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Extract a single step's successful return value from a ChainResult.
|
|
60
|
+
* Returns null when the step was skipped (chain halted earlier), failed,
|
|
61
|
+
* or simply was not part of the chain.
|
|
62
|
+
*/
|
|
63
|
+
export function stepValue(chain, name) {
|
|
64
|
+
const entry = chain.results.find((r) => r.name === name);
|
|
65
|
+
if (!entry || !entry.ok)
|
|
66
|
+
return null;
|
|
67
|
+
return entry.value;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Per-step latency map suitable for embedding in a composite's response
|
|
71
|
+
* under a `_diagnostics` field. Lets agents and operators see which step
|
|
72
|
+
* was slow without needing to instrument the host.
|
|
73
|
+
*/
|
|
74
|
+
export function stepLatencies(chain) {
|
|
75
|
+
const out = {};
|
|
76
|
+
for (const r of chain.results)
|
|
77
|
+
out[r.name] = r.latencyMs;
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Attach curated `related_docs` citations to a composite's payload.
|
|
82
|
+
* Mirrors how primitives attach citations so the response shape stays
|
|
83
|
+
* uniform across primitives and composites. Returns the payload
|
|
84
|
+
* unchanged when no curated docs are configured for the tool name.
|
|
85
|
+
*/
|
|
86
|
+
export function attachCitations(payload, toolName) {
|
|
87
|
+
const related_docs = relatedDocsFor(toolName);
|
|
88
|
+
if (!related_docs || related_docs.length === 0)
|
|
89
|
+
return payload;
|
|
90
|
+
return { ...payload, related_docs };
|
|
91
|
+
}
|
|
92
|
+
// DVM-BASIC function declaration:
|
|
93
|
+
// Function Name(arg Type, ...) Uint64|String
|
|
94
|
+
//
|
|
95
|
+
// Anchored with `/m` so each line of source is examined independently.
|
|
96
|
+
// Tolerant of leading whitespace and varied spacing inside the parens.
|
|
97
|
+
const DVM_FUNCTION_REGEX = /^[ \t]*Function[ \t]+([A-Za-z_][A-Za-z0-9_]*)[ \t]*\(([^)]*)\)[ \t]*(Uint64|String)\b/gm;
|
|
98
|
+
function parseDvmFunctions(code) {
|
|
99
|
+
const out = [];
|
|
100
|
+
const seen = new Set();
|
|
101
|
+
for (const match of code.matchAll(DVM_FUNCTION_REGEX)) {
|
|
102
|
+
const name = match[1];
|
|
103
|
+
if (seen.has(name))
|
|
104
|
+
continue;
|
|
105
|
+
seen.add(name);
|
|
106
|
+
const argsRaw = (match[2] ?? '').trim();
|
|
107
|
+
const returns = match[3] ?? '';
|
|
108
|
+
const args = argsRaw.length === 0
|
|
109
|
+
? []
|
|
110
|
+
: argsRaw
|
|
111
|
+
.split(',')
|
|
112
|
+
.map((s) => s.trim())
|
|
113
|
+
.filter((s) => s.length > 0);
|
|
114
|
+
out.push({ name, args, returns });
|
|
115
|
+
}
|
|
116
|
+
return out;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Convert a raw DERO.GetSC payload into a stable, agent-friendly surface.
|
|
120
|
+
*
|
|
121
|
+
* Behavior:
|
|
122
|
+
* - Returns `functions: []` when `code` is missing or the regex finds
|
|
123
|
+
* no Function declarations. Never throws on malformed code.
|
|
124
|
+
* - Sorts `stringkeys` / `uint64keys` alphabetically for deterministic
|
|
125
|
+
* output across invocations.
|
|
126
|
+
* - `balances` is passed through unchanged so callers can render asset
|
|
127
|
+
* balances; native DERO balance lives under `balance` on the raw
|
|
128
|
+
* payload and is left for callers to decide whether to surface.
|
|
129
|
+
*/
|
|
130
|
+
export function extractScSurface(raw) {
|
|
131
|
+
const code = typeof raw?.code === 'string' ? raw.code : '';
|
|
132
|
+
const functions = code.length > 0 ? parseDvmFunctions(code) : [];
|
|
133
|
+
const stringkeys = raw?.stringkeys ? Object.keys(raw.stringkeys).sort() : [];
|
|
134
|
+
const uint64keys = raw?.uint64keys ? Object.keys(raw.uint64keys).sort() : [];
|
|
135
|
+
const balances = {};
|
|
136
|
+
if (raw?.balances && typeof raw.balances === 'object') {
|
|
137
|
+
for (const [scid, amount] of Object.entries(raw.balances)) {
|
|
138
|
+
if (typeof amount === 'number' || typeof amount === 'string') {
|
|
139
|
+
balances[scid] = amount;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
functions,
|
|
145
|
+
stringkeys,
|
|
146
|
+
uint64keys,
|
|
147
|
+
balances,
|
|
148
|
+
raw_code_length: code.length,
|
|
149
|
+
has_code: code.length > 0,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=_shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_shared.js","sourceRoot":"","sources":["../../src/composites/_shared.ts"],"names":[],"mappings":"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"}
|