dero-mcp-server 0.1.1 → 0.1.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.
@@ -0,0 +1,30 @@
1
+ export declare const DERO_DOC_PRODUCTS: readonly ["derod", "tela", "hologram", "deropay"];
2
+ export type DeroDocProduct = (typeof DERO_DOC_PRODUCTS)[number];
3
+ export declare const DOC_SITE_DIRS: Record<DeroDocProduct, string>;
4
+ export declare const DOC_BASE_URLS: Record<DeroDocProduct, string>;
5
+ export type DeroDocsPage = {
6
+ product: DeroDocProduct;
7
+ slug: string;
8
+ title: string;
9
+ description: string | null;
10
+ canonicalUrl: string;
11
+ sourcePath: string;
12
+ headings: string[];
13
+ plainText: string;
14
+ lastUpdated: string | null;
15
+ };
16
+ export type DocsIndexFile = {
17
+ version: 1;
18
+ generated_at: string;
19
+ page_count: number;
20
+ pages: DeroDocsPage[];
21
+ };
22
+ export declare function normalizeSlug(input: string): string;
23
+ export declare function pathExists(targetPath: string): Promise<boolean>;
24
+ export declare function parseFrontmatter(raw: string): Record<string, string>;
25
+ export declare function stripFrontmatter(raw: string): string;
26
+ export declare function extractHeadings(markdown: string): string[];
27
+ export declare function mdxToPlainText(raw: string): string;
28
+ export declare function indexDocsFromRoot(root: string): Promise<DeroDocsPage[]>;
29
+ export declare function resolveDeroDocsRoot(customRoot?: string): Promise<string | null>;
30
+ //# sourceMappingURL=docs-parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs-parse.d.ts","sourceRoot":"","sources":["../src/docs-parse.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB,mDAAoD,CAAA;AAClF,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAA;AAE/D,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAKxD,CAAA;AAED,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAKxD,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,cAAc,CAAA;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,CAAC,CAAA;IACV,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,YAAY,EAAE,CAAA;CACtB,CAAA;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD;AAYD,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOrE;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWpE;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ1D;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAWlD;AAyBD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAqC7E;AAED,wBAAsB,mBAAmB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAkBrF"}
@@ -0,0 +1,147 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import path from 'node:path';
3
+ export const DERO_DOC_PRODUCTS = ['derod', 'tela', 'hologram', 'deropay'];
4
+ export const DOC_SITE_DIRS = {
5
+ derod: 'derod-main',
6
+ tela: 'tela-main',
7
+ hologram: 'hologram-main',
8
+ deropay: 'deropay-main',
9
+ };
10
+ export const DOC_BASE_URLS = {
11
+ derod: 'https://derod.org',
12
+ tela: 'https://tela.derod.org',
13
+ hologram: 'https://hologram.derod.org',
14
+ deropay: 'https://pay.derod.org',
15
+ };
16
+ export function normalizeSlug(input) {
17
+ return input.trim().replace(/^\/+/, '').replace(/\/+$/, '');
18
+ }
19
+ function safeTitleFromSlug(slug) {
20
+ if (!slug)
21
+ return 'Home';
22
+ return slug
23
+ .split('/')
24
+ .at(-1)
25
+ .split('-')
26
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
27
+ .join(' ');
28
+ }
29
+ export async function pathExists(targetPath) {
30
+ try {
31
+ await fs.access(targetPath);
32
+ return true;
33
+ }
34
+ catch {
35
+ return false;
36
+ }
37
+ }
38
+ export function parseFrontmatter(raw) {
39
+ const match = raw.match(/^---\n([\s\S]*?)\n---\n?/);
40
+ if (!match)
41
+ return {};
42
+ const frontmatter = {};
43
+ for (const line of match[1].split('\n')) {
44
+ const keyValue = line.match(/^([A-Za-z0-9_]+):\s*(.+)$/);
45
+ if (!keyValue)
46
+ continue;
47
+ frontmatter[keyValue[1]] = keyValue[2].trim().replace(/^['"]|['"]$/g, '');
48
+ }
49
+ return frontmatter;
50
+ }
51
+ export function stripFrontmatter(raw) {
52
+ return raw.replace(/^---\n[\s\S]*?\n---\n?/, '');
53
+ }
54
+ export function extractHeadings(markdown) {
55
+ const headings = [];
56
+ const headingRegex = /^#{1,3}\s+(.+)$/gm;
57
+ let match = null;
58
+ while ((match = headingRegex.exec(markdown)) !== null) {
59
+ headings.push(match[1].trim());
60
+ }
61
+ return headings;
62
+ }
63
+ export function mdxToPlainText(raw) {
64
+ return raw
65
+ .replace(/```[\s\S]*?```/g, ' ')
66
+ .replace(/^import\s+.*$/gm, ' ')
67
+ .replace(/<[^>\n]+>/g, ' ')
68
+ .replace(/!\[([^\]]*)\]\([^)]+\)/g, '$1')
69
+ .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
70
+ .replace(/^#{1,6}\s+/gm, '')
71
+ .replace(/`([^`]+)`/g, '$1')
72
+ .replace(/\s+/g, ' ')
73
+ .trim();
74
+ }
75
+ async function walkMdxFiles(dir) {
76
+ const entries = await fs.readdir(dir, { withFileTypes: true });
77
+ const files = [];
78
+ for (const entry of entries) {
79
+ const fullPath = path.join(dir, entry.name);
80
+ if (entry.isDirectory()) {
81
+ files.push(...(await walkMdxFiles(fullPath)));
82
+ continue;
83
+ }
84
+ if (entry.isFile() && entry.name.endsWith('.mdx')) {
85
+ files.push(fullPath);
86
+ }
87
+ }
88
+ return files;
89
+ }
90
+ function buildCanonicalUrl(product, slug) {
91
+ if (!slug)
92
+ return `${DOC_BASE_URLS[product]}/`;
93
+ return `${DOC_BASE_URLS[product]}/${slug}`;
94
+ }
95
+ export async function indexDocsFromRoot(root) {
96
+ const pages = [];
97
+ for (const product of DERO_DOC_PRODUCTS) {
98
+ const siteDir = DOC_SITE_DIRS[product];
99
+ const pagesDir = path.join(root, siteDir, 'pages');
100
+ if (!(await pathExists(pagesDir)))
101
+ continue;
102
+ const files = await walkMdxFiles(pagesDir);
103
+ for (const filePath of files) {
104
+ const raw = await fs.readFile(filePath, 'utf8');
105
+ const frontmatter = parseFrontmatter(raw);
106
+ const content = stripFrontmatter(raw);
107
+ const rel = path.relative(pagesDir, filePath).replace(/\\/g, '/');
108
+ const slug = normalizeSlug(rel.replace(/\.mdx$/, '').replace(/\/index$/, '').replace(/^index$/, ''));
109
+ const headings = extractHeadings(content);
110
+ pages.push({
111
+ product,
112
+ slug,
113
+ title: frontmatter.title || safeTitleFromSlug(slug),
114
+ description: frontmatter.description || null,
115
+ canonicalUrl: frontmatter.canonicalUrl || buildCanonicalUrl(product, slug),
116
+ sourcePath: path.relative(root, filePath).replace(/\\/g, '/'),
117
+ headings,
118
+ plainText: mdxToPlainText(content),
119
+ lastUpdated: frontmatter.lastUpdated || frontmatter.date || null,
120
+ });
121
+ }
122
+ }
123
+ pages.sort((a, b) => {
124
+ if (a.product !== b.product)
125
+ return a.product.localeCompare(b.product);
126
+ return a.slug.localeCompare(b.slug);
127
+ });
128
+ return pages;
129
+ }
130
+ export async function resolveDeroDocsRoot(customRoot) {
131
+ const explicit = customRoot ?? process.env.DERO_DOCS_ROOT;
132
+ if (explicit) {
133
+ const derodPages = path.join(explicit, DOC_SITE_DIRS.derod, 'pages');
134
+ return (await pathExists(derodPages)) ? explicit : null;
135
+ }
136
+ const autoCandidates = [
137
+ path.resolve(process.cwd(), '../dero-docs'),
138
+ path.resolve(process.cwd(), '../../dero-docs'),
139
+ ];
140
+ for (const candidate of autoCandidates) {
141
+ const derodPages = path.join(candidate, DOC_SITE_DIRS.derod, 'pages');
142
+ if (await pathExists(derodPages))
143
+ return candidate;
144
+ }
145
+ return null;
146
+ }
147
+ //# sourceMappingURL=docs-parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs-parse.js","sourceRoot":"","sources":["../src/docs-parse.ts"],"names":[],"mappings":"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"}
package/dist/docs.d.ts ADDED
@@ -0,0 +1,101 @@
1
+ import { type DeroDocProduct } from './docs-parse.js';
2
+ export { DERO_DOC_PRODUCTS, type DeroDocProduct, resolveDeroDocsRoot } from './docs-parse.js';
3
+ type SearchArgs = {
4
+ query: string;
5
+ product?: DeroDocProduct;
6
+ section?: string;
7
+ limit?: number;
8
+ };
9
+ export declare function listDeroDocs(product?: DeroDocProduct): Promise<{
10
+ total: number;
11
+ products: readonly ["derod", "tela", "hologram", "deropay"];
12
+ pages: {
13
+ product: "derod" | "tela" | "hologram" | "deropay";
14
+ slug: string;
15
+ title: string;
16
+ canonical_url: string;
17
+ last_updated: string | null;
18
+ }[];
19
+ docs_source: "bundled";
20
+ bundled_index: string;
21
+ docs_root?: undefined;
22
+ } | {
23
+ total: number;
24
+ products: readonly ["derod", "tela", "hologram", "deropay"];
25
+ pages: {
26
+ product: "derod" | "tela" | "hologram" | "deropay";
27
+ slug: string;
28
+ title: string;
29
+ canonical_url: string;
30
+ last_updated: string | null;
31
+ }[];
32
+ docs_source: "filesystem";
33
+ docs_root: string;
34
+ bundled_index?: undefined;
35
+ }>;
36
+ export declare function searchDeroDocs(args: SearchArgs): Promise<{
37
+ query: string;
38
+ total_matches: number;
39
+ returned: number;
40
+ results: {
41
+ product: "derod" | "tela" | "hologram" | "deropay";
42
+ slug: string;
43
+ title: string;
44
+ description: string | null;
45
+ canonical_url: string;
46
+ headings: string[];
47
+ excerpt: string;
48
+ score: number;
49
+ }[];
50
+ docs_source: "bundled";
51
+ bundled_index: string;
52
+ docs_root?: undefined;
53
+ } | {
54
+ query: string;
55
+ total_matches: number;
56
+ returned: number;
57
+ results: {
58
+ product: "derod" | "tela" | "hologram" | "deropay";
59
+ slug: string;
60
+ title: string;
61
+ description: string | null;
62
+ canonical_url: string;
63
+ headings: string[];
64
+ excerpt: string;
65
+ score: number;
66
+ }[];
67
+ docs_source: "filesystem";
68
+ docs_root: string;
69
+ bundled_index?: undefined;
70
+ }>;
71
+ export declare function getDeroDocPage(params: {
72
+ product?: DeroDocProduct;
73
+ slug: string;
74
+ }): Promise<{
75
+ product: "derod" | "tela" | "hologram" | "deropay";
76
+ slug: string;
77
+ title: string;
78
+ description: string | null;
79
+ canonical_url: string;
80
+ last_updated: string | null;
81
+ headings: string[];
82
+ content: string;
83
+ source_path: string;
84
+ docs_source: "bundled";
85
+ bundled_index: string;
86
+ docs_root?: undefined;
87
+ } | {
88
+ product: "derod" | "tela" | "hologram" | "deropay";
89
+ slug: string;
90
+ title: string;
91
+ description: string | null;
92
+ canonical_url: string;
93
+ last_updated: string | null;
94
+ headings: string[];
95
+ content: string;
96
+ source_path: string;
97
+ docs_source: "filesystem";
98
+ docs_root: string;
99
+ bundled_index?: undefined;
100
+ }>;
101
+ //# sourceMappingURL=docs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../src/docs.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EAOpB,MAAM,iBAAiB,CAAA;AAExB,OAAO,EAAE,iBAAiB,EAAE,KAAK,cAAc,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAkF7F,KAAK,UAAU,GAAG;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,cAAc,CAAA;IACxB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAmBD,wBAAsB,YAAY,CAAC,OAAO,CAAC,EAAE,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;GAgB1D;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CpD;AAED,wBAAsB,cAAc,CAAC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BtF"}
package/dist/docs.js ADDED
@@ -0,0 +1,172 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { DERO_DOC_PRODUCTS, indexDocsFromRoot, normalizeSlug, pathExists, } from './docs-parse.js';
5
+ export { DERO_DOC_PRODUCTS, resolveDeroDocsRoot } from './docs-parse.js';
6
+ const CACHE_TTL_MS = 15000;
7
+ let pageCache = null;
8
+ function bundledIndexPath() {
9
+ const here = path.dirname(fileURLToPath(import.meta.url));
10
+ // dist/docs.js -> ../data/docs-index.json
11
+ return path.resolve(here, '../data/docs-index.json');
12
+ }
13
+ async function loadBundledPages(indexPath) {
14
+ if (!(await pathExists(indexPath)))
15
+ return null;
16
+ const raw = await fs.readFile(indexPath, 'utf8');
17
+ const parsed = JSON.parse(raw);
18
+ if (!parsed?.pages?.length)
19
+ return null;
20
+ return parsed.pages;
21
+ }
22
+ async function resolveDocsSource() {
23
+ const overrideRoot = process.env.DERO_DOCS_ROOT?.trim();
24
+ if (overrideRoot) {
25
+ const derodPages = path.join(overrideRoot, 'derod-main', 'pages');
26
+ if (await pathExists(derodPages)) {
27
+ return { kind: 'filesystem', root: overrideRoot };
28
+ }
29
+ }
30
+ const bundledPath = bundledIndexPath();
31
+ if (await pathExists(bundledPath)) {
32
+ return { kind: 'bundled', indexPath: bundledPath };
33
+ }
34
+ return null;
35
+ }
36
+ async function loadPages() {
37
+ const source = await resolveDocsSource();
38
+ if (!source) {
39
+ throw new Error('DERO docs unavailable. Bundled docs index missing and DERO_DOCS_ROOT is unset or invalid.');
40
+ }
41
+ const cacheKey = source.kind === 'bundled' ? `bundled:${source.indexPath}` : `fs:${source.root}`;
42
+ if (pageCache && pageCache.key === cacheKey && Date.now() - pageCache.loadedAt < CACHE_TTL_MS) {
43
+ return pageCache.data;
44
+ }
45
+ let pages;
46
+ if (source.kind === 'bundled') {
47
+ const bundled = await loadBundledPages(source.indexPath);
48
+ if (!bundled) {
49
+ throw new Error('DERO bundled docs index is missing or empty.');
50
+ }
51
+ pages = bundled;
52
+ }
53
+ else {
54
+ pages = await indexDocsFromRoot(source.root);
55
+ }
56
+ const data = { source, pages };
57
+ pageCache = { key: cacheKey, loadedAt: Date.now(), data };
58
+ return data;
59
+ }
60
+ function sourceMeta(source) {
61
+ if (source.kind === 'bundled') {
62
+ return { docs_source: 'bundled', bundled_index: path.basename(source.indexPath) };
63
+ }
64
+ return { docs_source: 'filesystem', docs_root: source.root };
65
+ }
66
+ function scorePage(page, terms) {
67
+ const title = page.title.toLowerCase();
68
+ const slug = page.slug.toLowerCase();
69
+ const headingBlob = page.headings.join(' ').toLowerCase();
70
+ const body = page.plainText.toLowerCase();
71
+ let score = 0;
72
+ for (const term of terms) {
73
+ if (title.includes(term))
74
+ score += 6;
75
+ if (slug.includes(term))
76
+ score += 4;
77
+ if (headingBlob.includes(term))
78
+ score += 2;
79
+ if (body.includes(term))
80
+ score += 1;
81
+ }
82
+ return score;
83
+ }
84
+ export async function listDeroDocs(product) {
85
+ const { source, pages } = await loadPages();
86
+ const filtered = product ? pages.filter((page) => page.product === product) : pages;
87
+ return {
88
+ ...sourceMeta(source),
89
+ total: filtered.length,
90
+ products: DERO_DOC_PRODUCTS,
91
+ pages: filtered.map((page) => ({
92
+ product: page.product,
93
+ slug: page.slug,
94
+ title: page.title,
95
+ canonical_url: page.canonicalUrl,
96
+ last_updated: page.lastUpdated,
97
+ })),
98
+ };
99
+ }
100
+ export async function searchDeroDocs(args) {
101
+ const query = args.query.trim();
102
+ if (!query)
103
+ throw new Error('DERO docs search requires a non-empty query');
104
+ const { source, pages } = await loadPages();
105
+ let filtered = pages;
106
+ if (args.product) {
107
+ filtered = filtered.filter((page) => page.product === args.product);
108
+ }
109
+ if (args.section) {
110
+ const normalizedSection = normalizeSlug(args.section).toLowerCase();
111
+ filtered = filtered.filter((page) => {
112
+ const slug = page.slug.toLowerCase();
113
+ return slug === normalizedSection || slug.startsWith(`${normalizedSection}/`);
114
+ });
115
+ }
116
+ const terms = query
117
+ .toLowerCase()
118
+ .split(/\s+/)
119
+ .map((term) => term.trim())
120
+ .filter(Boolean);
121
+ const scored = filtered
122
+ .map((page) => ({ page, score: scorePage(page, terms) }))
123
+ .filter((entry) => entry.score > 0)
124
+ .sort((a, b) => b.score - a.score);
125
+ const limit = Math.max(1, Math.min(args.limit ?? 8, 25));
126
+ const results = scored.slice(0, limit).map(({ page, score }) => ({
127
+ product: page.product,
128
+ slug: page.slug,
129
+ title: page.title,
130
+ description: page.description,
131
+ canonical_url: page.canonicalUrl,
132
+ headings: page.headings.slice(0, 5),
133
+ excerpt: page.plainText.slice(0, 420),
134
+ score,
135
+ }));
136
+ return {
137
+ ...sourceMeta(source),
138
+ query,
139
+ total_matches: scored.length,
140
+ returned: results.length,
141
+ results,
142
+ };
143
+ }
144
+ export async function getDeroDocPage(params) {
145
+ const slug = normalizeSlug(params.slug);
146
+ if (!slug)
147
+ throw new Error('DERO docs get page requires a non-empty slug');
148
+ const { source, pages } = await loadPages();
149
+ const target = pages.find((page) => {
150
+ if (params.product && page.product !== params.product)
151
+ return false;
152
+ return normalizeSlug(page.slug).toLowerCase() === slug.toLowerCase();
153
+ });
154
+ if (!target) {
155
+ throw new Error(params.product
156
+ ? `Doc page not found for product=${params.product} slug=${slug}`
157
+ : `Doc page not found for slug=${slug}`);
158
+ }
159
+ return {
160
+ ...sourceMeta(source),
161
+ product: target.product,
162
+ slug: target.slug,
163
+ title: target.title,
164
+ description: target.description,
165
+ canonical_url: target.canonicalUrl,
166
+ last_updated: target.lastUpdated,
167
+ headings: target.headings,
168
+ content: target.plainText.slice(0, 20000),
169
+ source_path: target.sourcePath,
170
+ };
171
+ }
172
+ //# sourceMappingURL=docs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.js","sourceRoot":"","sources":["../src/docs.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAqKnE,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAsdpE"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAmNnE,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAwiBpE"}
package/dist/server.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import { z } from 'zod';
3
3
  import { deroJsonRpc, jsonRpcEndpoint } from './rpc.js';
4
+ import { DERO_DOC_PRODUCTS, getDeroDocPage, listDeroDocs, searchDeroDocs, } from './docs.js';
4
5
  const scRpcArgSchema = z.object({
5
6
  name: z.string(),
6
7
  datatype: z.enum(['S', 'U', 'H']),
@@ -31,6 +32,9 @@ const DERO_TOOL_NAMES = [
31
32
  'dero_get_gas_estimate',
32
33
  'dero_name_to_address',
33
34
  'dero_get_block_template',
35
+ 'dero_docs_search',
36
+ 'dero_docs_get_page',
37
+ 'dero_docs_list',
34
38
  ];
35
39
  const DERO_RESOURCE_URIS = [
36
40
  'dero://mcp/server-info',
@@ -42,6 +46,7 @@ const DERO_PROMPT_NAMES = [
42
46
  'inspect_smart_contract',
43
47
  'trace_transaction',
44
48
  ];
49
+ const deroDocProductSchema = z.enum(DERO_DOC_PRODUCTS);
45
50
  function toolText(data) {
46
51
  return {
47
52
  content: [
@@ -61,6 +66,35 @@ function classifyToolError(error) {
61
66
  retryable: false,
62
67
  };
63
68
  }
69
+ if (message.includes('DERO docs unavailable') ||
70
+ message.includes('bundled docs index is missing')) {
71
+ return {
72
+ code: 'DOCS_UNAVAILABLE',
73
+ hint: 'Bundled docs index is missing from this install. Reinstall dero-mcp-server or set DERO_DOCS_ROOT for local dev override.',
74
+ retryable: false,
75
+ };
76
+ }
77
+ if (message.includes('DERO docs search requires a non-empty query')) {
78
+ return {
79
+ code: 'INVALID_INPUT',
80
+ hint: 'Pass a non-empty "query" string for dero_docs_search.',
81
+ retryable: false,
82
+ };
83
+ }
84
+ if (message.includes('DERO docs get page requires a non-empty slug')) {
85
+ return {
86
+ code: 'INVALID_INPUT',
87
+ hint: 'Pass a non-empty "slug" for dero_docs_get_page.',
88
+ retryable: false,
89
+ };
90
+ }
91
+ if (message.includes('Doc page not found')) {
92
+ return {
93
+ code: 'DOC_NOT_FOUND',
94
+ hint: 'Use dero_docs_search or dero_docs_list to discover valid slugs, then retry.',
95
+ retryable: false,
96
+ };
97
+ }
64
98
  if (message.includes('RPC error -32601')) {
65
99
  return {
66
100
  code: 'RPC_METHOD_NOT_FOUND',
@@ -138,7 +172,7 @@ export function createDeroMcpServer(daemonBaseUrl) {
138
172
  const rpc = async (method, params) => deroJsonRpc(endpoint, method, params);
139
173
  const server = new McpServer({
140
174
  name: 'dero-daemon-mcp',
141
- version: '0.1.0',
175
+ version: '0.1.2',
142
176
  });
143
177
  server.registerTool('dero_daemon_ping', {
144
178
  description: 'DERO daemon connectivity check. Calls DERO.Ping. No parameters.',
@@ -332,6 +366,64 @@ export function createDeroMcpServer(daemonBaseUrl) {
332
366
  params.miner = miner;
333
367
  return rpc('DERO.GetBlockTemplate', params);
334
368
  }));
369
+ server.registerTool('dero_docs_search', {
370
+ description: 'Search bundled DERO documentation (derod/tela/hologram/deropay). Ships with npm package; optional DERO_DOCS_ROOT overrides for local dev.',
371
+ inputSchema: {
372
+ query: z
373
+ .string()
374
+ .min(1)
375
+ .describe('Search text (e.g., "wallet rpc", "tela deployment", "deropay webhooks")'),
376
+ product: deroDocProductSchema
377
+ .optional()
378
+ .describe('Optional docs product filter: derod | tela | hologram | deropay'),
379
+ section: z
380
+ .string()
381
+ .optional()
382
+ .describe('Optional section slug prefix (e.g., "rpc-api", "guides", "dero-pay")'),
383
+ limit: z
384
+ .number()
385
+ .int()
386
+ .min(1)
387
+ .max(25)
388
+ .optional()
389
+ .describe('Max matches (default 8, max 25)'),
390
+ },
391
+ }, withStructuredErrors('dero_docs_search', async ({ query, product, section, limit }) => searchDeroDocs({ query, product, section, limit })));
392
+ server.registerTool('dero_docs_get_page', {
393
+ description: 'Get one docs page by slug (optionally scoped by product). Returns headings and normalized plain-text content.',
394
+ inputSchema: {
395
+ slug: z
396
+ .string()
397
+ .min(1)
398
+ .describe('Doc slug relative to pages/ (e.g., "rpc-api/daemon-rpc-api", "tutorials/first-app", "dero-pay/quick-start")'),
399
+ product: deroDocProductSchema
400
+ .optional()
401
+ .describe('Optional product scope to disambiguate duplicate slugs'),
402
+ },
403
+ }, withStructuredErrors('dero_docs_get_page', async ({ slug, product }) => getDeroDocPage({ slug, product })));
404
+ server.registerTool('dero_docs_list', {
405
+ description: 'List indexed docs pages across derod/tela/hologram/deropay with slugs and canonical URLs.',
406
+ inputSchema: {
407
+ product: deroDocProductSchema
408
+ .optional()
409
+ .describe('Optional docs product filter: derod | tela | hologram | deropay'),
410
+ limit: z
411
+ .number()
412
+ .int()
413
+ .min(1)
414
+ .max(500)
415
+ .optional()
416
+ .describe('Max pages returned (default 120, max 500)'),
417
+ },
418
+ }, withStructuredErrors('dero_docs_list', async ({ product, limit }) => {
419
+ const docsIndex = await listDeroDocs(product);
420
+ const capped = Math.max(1, Math.min(limit ?? 120, 500));
421
+ return {
422
+ ...docsIndex,
423
+ returned: Math.min(capped, docsIndex.pages.length),
424
+ pages: docsIndex.pages.slice(0, capped),
425
+ };
426
+ }));
335
427
  server.registerResource('dero_mcp_server_info', 'dero://mcp/server-info', {
336
428
  description: 'Server metadata, tool list, resource list, and prompt names.',
337
429
  mimeType: 'application/json',
@@ -342,9 +434,12 @@ export function createDeroMcpServer(daemonBaseUrl) {
342
434
  mimeType: 'application/json',
343
435
  text: JSON.stringify({
344
436
  name: 'dero-daemon-mcp',
345
- version: '0.1.0',
437
+ version: '0.1.2',
346
438
  mode: 'read-only',
347
439
  endpoint: endpoint,
440
+ docs_products: DERO_DOC_PRODUCTS,
441
+ docs_delivery: 'bundled-index',
442
+ docs_dev_override_env: 'DERO_DOCS_ROOT',
348
443
  tools: DERO_TOOL_NAMES,
349
444
  resources: DERO_RESOURCE_URIS,
350
445
  prompts: DERO_PROMPT_NAMES,