bps-mcp-server 0.2.0 → 0.3.0
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 +82 -3
- package/dist/client/allstats-client.d.ts +72 -0
- package/dist/client/allstats-client.d.ts.map +1 -0
- package/dist/client/allstats-client.js +247 -0
- package/dist/client/allstats-client.js.map +1 -0
- package/dist/config/defaults.d.ts +2 -0
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +2 -0
- package/dist/config/defaults.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +11 -2
- package/dist/server.js.map +1 -1
- package/dist/tools/allstats.tools.d.ts +4 -0
- package/dist/tools/allstats.tools.d.ts.map +1 -0
- package/dist/tools/allstats.tools.js +171 -0
- package/dist/tools/allstats.tools.js.map +1 -0
- package/dist/tools/search.tools.d.ts +2 -1
- package/dist/tools/search.tools.d.ts.map +1 -1
- package/dist/tools/search.tools.js +113 -7
- package/dist/tools/search.tools.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -8,7 +8,9 @@ MCP (Model Context Protocol) server untuk data statistik BPS (Badan Pusat Statis
|
|
|
8
8
|
|
|
9
9
|
## Fitur
|
|
10
10
|
|
|
11
|
-
- **
|
|
11
|
+
- **34 tools** mencakup seluruh endpoint BPS WebAPI v1 + AllStats Search
|
|
12
|
+
- **Integrasi AllStats Search** — pencarian unified + full-text PDF search (tanpa API key)
|
|
13
|
+
- **Smart fallback** — WebAPI search otomatis fallback ke AllStats jika tidak ada hasil
|
|
12
14
|
- **3 MCP Resources** — domain list, kabupaten per provinsi, subjek per domain
|
|
13
15
|
- **5 MCP Prompts** — template analisis data siap pakai
|
|
14
16
|
- **Domain resolver** dengan fuzzy matching (ketik "Jatim" → Jawa Timur)
|
|
@@ -133,7 +135,9 @@ File `~/.cursor/mcp.json` atau `.vscode/mcp.json`:
|
|
|
133
135
|
}
|
|
134
136
|
```
|
|
135
137
|
|
|
136
|
-
## Tools (
|
|
138
|
+
## Tools (34)
|
|
139
|
+
|
|
140
|
+
### WebAPI Tools (32)
|
|
137
141
|
|
|
138
142
|
| Tool | Deskripsi |
|
|
139
143
|
|------|-----------|
|
|
@@ -167,9 +171,82 @@ File `~/.cursor/mcp.json` atau `.vscode/mcp.json`:
|
|
|
167
171
|
| `list_csa_tables` | Tabel CSA per subjek |
|
|
168
172
|
| `get_csa_table` | Detail tabel CSA (HTML) |
|
|
169
173
|
| `list_glossary` | Glosarium istilah statistik |
|
|
170
|
-
| `search` | Pencarian lintas tipe |
|
|
174
|
+
| `search` | Pencarian lintas tipe (WebAPI + AllStats fallback) |
|
|
171
175
|
| `cache_clear` | Bersihkan cache |
|
|
172
176
|
|
|
177
|
+
### AllStats Search Tools (2)
|
|
178
|
+
|
|
179
|
+
| Tool | Deskripsi |
|
|
180
|
+
|------|-----------|
|
|
181
|
+
| `allstats_search` | Pencarian unified semua konten BPS (publikasi, tabel, BRS, infografis, data mikro, glosarium, klasifikasi) |
|
|
182
|
+
| `allstats_deep_search` | Full-text search di dalam isi PDF publikasi BPS — **fitur unik, tidak tersedia di WebAPI** |
|
|
183
|
+
|
|
184
|
+
## Integrasi AllStats Search
|
|
185
|
+
|
|
186
|
+
Server ini mengintegrasikan dua sumber data yang saling melengkapi:
|
|
187
|
+
|
|
188
|
+
```
|
|
189
|
+
┌─────────────────────────────────────────────────────────┐
|
|
190
|
+
│ BPS MCP Server │
|
|
191
|
+
│ │
|
|
192
|
+
│ ┌──────────────────┐ ┌────────────────────────┐ │
|
|
193
|
+
│ │ WebAPI BPS │ │ AllStats Search │ │
|
|
194
|
+
│ │ (Primary) │ │ (Supplementary) │ │
|
|
195
|
+
│ │ │ │ │ │
|
|
196
|
+
│ │ + Structured │ │ + Full-text PDF search │ │
|
|
197
|
+
│ │ data (JSON) │ │ + Unified search │ │
|
|
198
|
+
│ │ + Dynamic tables │ │ semua tipe konten │ │
|
|
199
|
+
│ │ + Ekspor/Impor │ │ + Tanpa API key │ │
|
|
200
|
+
│ │ + Sensus data │ │ + Filter wilayah 550+ │ │
|
|
201
|
+
│ │ - No PDF search │ │ - HTML scraping │ │
|
|
202
|
+
│ └──────────────────┘ └────────────────────────┘ │
|
|
203
|
+
│ │
|
|
204
|
+
│ Strategi interaksi: │
|
|
205
|
+
│ 1. search → WebAPI dulu, fallback AllStats jika kosong │
|
|
206
|
+
│ 2. allstats_search → langsung ke AllStats Search │
|
|
207
|
+
│ 3. allstats_deep_search → cari teks di dalam PDF │
|
|
208
|
+
└─────────────────────────────────────────────────────────┘
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Cara Kerja
|
|
212
|
+
|
|
213
|
+
**`search` (smart fallback)**
|
|
214
|
+
- Prioritas: WebAPI BPS (structured JSON)
|
|
215
|
+
- Jika WebAPI mengembalikan hasil kosong atau error, otomatis fallback ke AllStats Search
|
|
216
|
+
- User mendapat notifikasi sumber data yang digunakan
|
|
217
|
+
|
|
218
|
+
**`allstats_search` (unified discovery)**
|
|
219
|
+
- Langsung query ke `searchengine.web.bps.go.id`
|
|
220
|
+
- Mendukung filter: tipe konten, wilayah, rentang tahun, urutan
|
|
221
|
+
- Tidak memerlukan API key BPS
|
|
222
|
+
- Cocok untuk discovery atau pencarian broad
|
|
223
|
+
|
|
224
|
+
**`allstats_deep_search` (PDF full-text)**
|
|
225
|
+
- Cari teks di dalam isi PDF publikasi BPS
|
|
226
|
+
- Memerlukan `publication_id` (24 karakter hex) dari hasil `allstats_search`
|
|
227
|
+
- Mengembalikan halaman PDF yang cocok beserta cuplikan teks
|
|
228
|
+
- Fitur unik yang tidak tersedia di WebAPI
|
|
229
|
+
|
|
230
|
+
### Workflow Contoh
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
1. Discovery → Deep Search:
|
|
234
|
+
allstats_search("akses internet", content="publication")
|
|
235
|
+
→ dapat publication_id
|
|
236
|
+
→ allstats_deep_search("akses internet", publication_id="131385d0253c6aae7c7a59fa")
|
|
237
|
+
→ halaman PDF yang membahas "akses internet"
|
|
238
|
+
|
|
239
|
+
2. Smart fallback:
|
|
240
|
+
search(keyword="kemiskinan Papua")
|
|
241
|
+
→ WebAPI kosong → otomatis cari via AllStats
|
|
242
|
+
→ hasil dari AllStats ditampilkan dengan catatan fallback
|
|
243
|
+
|
|
244
|
+
3. Parallel enrichment (oleh AI):
|
|
245
|
+
- get_dynamic_data → data angka terstruktur
|
|
246
|
+
- allstats_search("inflasi", content="pressrelease") → BRS terbaru
|
|
247
|
+
→ AI menggabungkan data angka + konteks dari BRS
|
|
248
|
+
```
|
|
249
|
+
|
|
173
250
|
## Resources (3)
|
|
174
251
|
|
|
175
252
|
| URI | Deskripsi |
|
|
@@ -195,6 +272,8 @@ File `~/.cursor/mcp.json` atau `.vscode/mcp.json`:
|
|
|
195
272
|
"Bandingkan angka kemiskinan Jawa Timur vs Jawa Barat 2020-2023"
|
|
196
273
|
"Cari BRS terbaru tentang inflasi"
|
|
197
274
|
"Data ekspor kopi Indonesia tahun 2024"
|
|
275
|
+
"Cari publikasi tentang statistik telekomunikasi"
|
|
276
|
+
"Cari teks tentang akses internet di dalam publikasi BPS"
|
|
198
277
|
```
|
|
199
278
|
|
|
200
279
|
## Environment Variables
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { ICacheProvider } from "../services/cache.js";
|
|
2
|
+
export type AllStatsContentType = "all" | "publication" | "table" | "pressrelease" | "infographic" | "microdata" | "news" | "glosarium" | "kbli2020" | "kbli2017" | "kbli2015" | "kbli2009";
|
|
3
|
+
export type AllStatsSortOrder = "terbaru" | "relevansi";
|
|
4
|
+
export interface AllStatsSearchParams {
|
|
5
|
+
query: string;
|
|
6
|
+
content?: AllStatsContentType;
|
|
7
|
+
domain?: string;
|
|
8
|
+
page?: number;
|
|
9
|
+
titleOnly?: boolean;
|
|
10
|
+
yearFrom?: string;
|
|
11
|
+
yearTo?: string;
|
|
12
|
+
sort?: AllStatsSortOrder;
|
|
13
|
+
}
|
|
14
|
+
export interface AllStatsSearchResult {
|
|
15
|
+
url: string;
|
|
16
|
+
title: string;
|
|
17
|
+
description: string;
|
|
18
|
+
contentType: string;
|
|
19
|
+
domain: string;
|
|
20
|
+
deepSearchId?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface AllStatsSearchResponse {
|
|
23
|
+
query: string;
|
|
24
|
+
totalResults: number;
|
|
25
|
+
currentPage: number;
|
|
26
|
+
totalPages: number;
|
|
27
|
+
results: AllStatsSearchResult[];
|
|
28
|
+
}
|
|
29
|
+
export interface AllStatsDeepSearchParams {
|
|
30
|
+
query: string;
|
|
31
|
+
publicationId: string;
|
|
32
|
+
domain?: string;
|
|
33
|
+
page?: number;
|
|
34
|
+
}
|
|
35
|
+
export interface AllStatsDeepSearchMatch {
|
|
36
|
+
pageNumber: number;
|
|
37
|
+
excerpt: string;
|
|
38
|
+
highlights: string[];
|
|
39
|
+
pdfViewerUrl: string;
|
|
40
|
+
}
|
|
41
|
+
export interface AllStatsDeepSearchPublication {
|
|
42
|
+
title: string;
|
|
43
|
+
publisher: string;
|
|
44
|
+
coverUrl: string;
|
|
45
|
+
publicationUrl: string;
|
|
46
|
+
pdfDownloadBase: string;
|
|
47
|
+
}
|
|
48
|
+
export interface AllStatsDeepSearchResponse {
|
|
49
|
+
query: string;
|
|
50
|
+
publication: AllStatsDeepSearchPublication;
|
|
51
|
+
totalMatches: number;
|
|
52
|
+
currentPage: number;
|
|
53
|
+
totalPages: number;
|
|
54
|
+
matches: AllStatsDeepSearchMatch[];
|
|
55
|
+
}
|
|
56
|
+
export declare class AllStatsClient {
|
|
57
|
+
private readonly cache;
|
|
58
|
+
constructor(cache: ICacheProvider | null);
|
|
59
|
+
private fetchHtml;
|
|
60
|
+
private fetchWithRetry;
|
|
61
|
+
private doFetch;
|
|
62
|
+
search(params: AllStatsSearchParams): Promise<AllStatsSearchResponse>;
|
|
63
|
+
private parseSearchResults;
|
|
64
|
+
deepSearch(params: AllStatsDeepSearchParams): Promise<AllStatsDeepSearchResponse>;
|
|
65
|
+
private parseDeepSearchResults;
|
|
66
|
+
}
|
|
67
|
+
export declare class AllStatsError extends Error {
|
|
68
|
+
readonly statusCode?: number | undefined;
|
|
69
|
+
readonly endpoint?: string | undefined;
|
|
70
|
+
constructor(message: string, statusCode?: number | undefined, endpoint?: string | undefined);
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=allstats-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"allstats-client.d.ts","sourceRoot":"","sources":["../../src/client/allstats-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAa3D,MAAM,MAAM,mBAAmB,GAC3B,KAAK,GACL,aAAa,GACb,OAAO,GACP,cAAc,GACd,aAAa,GACb,WAAW,GACX,MAAM,GACN,WAAW,GACX,UAAU,GACV,UAAU,GACV,UAAU,GACV,UAAU,CAAC;AAEf,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,WAAW,CAAC;AAExD,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,iBAAiB,CAAC;CAC1B;AAED,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,oBAAoB,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,6BAA6B,CAAC;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,uBAAuB,EAAE,CAAC;CACpC;AAiBD,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,cAAc,GAAG,IAAI;YAI3C,SAAS;YA2BT,cAAc;YA4Bd,OAAO;IAiCf,MAAM,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAe3E,OAAO,CAAC,kBAAkB;IAoEpB,UAAU,CACd,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,0BAA0B,CAAC;IAYtC,OAAO,CAAC,sBAAsB;CAwE/B;AAID,qBAAa,aAAc,SAAQ,KAAK;aAGpB,UAAU,CAAC,EAAE,MAAM;aACnB,QAAQ,CAAC,EAAE,MAAM;gBAFjC,OAAO,EAAE,MAAM,EACC,UAAU,CAAC,EAAE,MAAM,YAAA,EACnB,QAAQ,CAAC,EAAE,MAAM,YAAA;CAKpC"}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import * as cheerio from "cheerio";
|
|
2
|
+
import { logger } from "../utils/logger.js";
|
|
3
|
+
// ========== Constants ==========
|
|
4
|
+
const ALLSTATS_BASE = "https://searchengine.web.bps.go.id";
|
|
5
|
+
const USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36";
|
|
6
|
+
const FETCH_TIMEOUT_MS = 30_000;
|
|
7
|
+
const MAX_RETRIES = 3;
|
|
8
|
+
const RETRY_BASE_DELAY_MS = 1_000;
|
|
9
|
+
// ========== OCR Cleanup ==========
|
|
10
|
+
const OCR_PATTERNS = [
|
|
11
|
+
/^Ps\s*\/\/\s*W\s*Ww\s*\.Bp\s*S\.G\s*O\.I\s*D\s*/i,
|
|
12
|
+
/^Ht\s*Tp\s*\/\/\s*.*?\.Bp\s*S\s*\.\s*Go\s*\.\s*Id\s*/i,
|
|
13
|
+
];
|
|
14
|
+
function cleanExcerpt(text) {
|
|
15
|
+
let cleaned = text;
|
|
16
|
+
for (const p of OCR_PATTERNS)
|
|
17
|
+
cleaned = cleaned.replace(p, "");
|
|
18
|
+
return cleaned.replace(/\s+/g, " ").trim();
|
|
19
|
+
}
|
|
20
|
+
// ========== Client ==========
|
|
21
|
+
export class AllStatsClient {
|
|
22
|
+
cache;
|
|
23
|
+
constructor(cache) {
|
|
24
|
+
this.cache = cache;
|
|
25
|
+
}
|
|
26
|
+
// ---------- HTTP ----------
|
|
27
|
+
async fetchHtml(path, params) {
|
|
28
|
+
const url = new URL(path, ALLSTATS_BASE);
|
|
29
|
+
for (const [k, v] of Object.entries(params)) {
|
|
30
|
+
url.searchParams.set(k, v);
|
|
31
|
+
}
|
|
32
|
+
const cacheKey = `allstats:${url.toString()}`;
|
|
33
|
+
// Check cache
|
|
34
|
+
if (this.cache) {
|
|
35
|
+
const cached = await this.cache.get(cacheKey);
|
|
36
|
+
if (cached) {
|
|
37
|
+
logger.debug(`AllStats cache hit: ${cacheKey}`);
|
|
38
|
+
return cached;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const html = await this.fetchWithRetry(url.toString());
|
|
42
|
+
// Cache for 30 minutes
|
|
43
|
+
if (this.cache) {
|
|
44
|
+
await this.cache.set(cacheKey, html, 30 * 60);
|
|
45
|
+
}
|
|
46
|
+
return html;
|
|
47
|
+
}
|
|
48
|
+
async fetchWithRetry(url) {
|
|
49
|
+
let lastError;
|
|
50
|
+
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
|
|
51
|
+
try {
|
|
52
|
+
return await this.doFetch(url);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
lastError = error;
|
|
56
|
+
// Retry on 403 (rate limit) and 5xx
|
|
57
|
+
const isRetryable = error instanceof AllStatsError &&
|
|
58
|
+
error.statusCode !== undefined &&
|
|
59
|
+
(error.statusCode === 403 || error.statusCode >= 500);
|
|
60
|
+
if (!isRetryable || attempt === MAX_RETRIES - 1) {
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
const delay = RETRY_BASE_DELAY_MS * Math.pow(2, attempt);
|
|
64
|
+
logger.warn(`AllStats retry (${attempt + 1}/${MAX_RETRIES}) after ${delay}ms: ${url}`);
|
|
65
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
throw lastError;
|
|
69
|
+
}
|
|
70
|
+
async doFetch(url) {
|
|
71
|
+
logger.debug(`AllStats fetch: ${url}`);
|
|
72
|
+
const controller = new AbortController();
|
|
73
|
+
const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
74
|
+
let res;
|
|
75
|
+
try {
|
|
76
|
+
res = await fetch(url, {
|
|
77
|
+
headers: {
|
|
78
|
+
"User-Agent": USER_AGENT,
|
|
79
|
+
Accept: "text/html,application/xhtml+xml",
|
|
80
|
+
},
|
|
81
|
+
signal: controller.signal,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
86
|
+
throw new AllStatsError(`Request timeout after ${FETCH_TIMEOUT_MS}ms`, 408, url);
|
|
87
|
+
}
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
clearTimeout(timeout);
|
|
92
|
+
}
|
|
93
|
+
if (!res.ok) {
|
|
94
|
+
throw new AllStatsError(`AllStats HTTP ${res.status} ${res.statusText}`, res.status, url);
|
|
95
|
+
}
|
|
96
|
+
return res.text();
|
|
97
|
+
}
|
|
98
|
+
// ---------- Search ----------
|
|
99
|
+
async search(params) {
|
|
100
|
+
const html = await this.fetchHtml("/search", {
|
|
101
|
+
q: params.query,
|
|
102
|
+
content: params.content || "all",
|
|
103
|
+
page: String(params.page || 1),
|
|
104
|
+
title: params.titleOnly ? "1" : "0",
|
|
105
|
+
mfd: params.domain || "0000",
|
|
106
|
+
from: params.yearFrom || "all",
|
|
107
|
+
to: params.yearTo || "all",
|
|
108
|
+
sort: params.sort || "terbaru",
|
|
109
|
+
});
|
|
110
|
+
return this.parseSearchResults(html, params.query, params.page || 1);
|
|
111
|
+
}
|
|
112
|
+
parseSearchResults(html, query, currentPage) {
|
|
113
|
+
const $ = cheerio.load(html);
|
|
114
|
+
// Total results: "Menampilkan 4.079 hasil pencarian dalam 0.367 detik"
|
|
115
|
+
const totalMatch = $("body")
|
|
116
|
+
.text()
|
|
117
|
+
.match(/Menampilkan\s+([\d.]+)\s+hasil pencarian/);
|
|
118
|
+
const totalResults = totalMatch
|
|
119
|
+
? parseInt(totalMatch[1].replace(/\./g, ""))
|
|
120
|
+
: 0;
|
|
121
|
+
// Pagination
|
|
122
|
+
const pages = [];
|
|
123
|
+
$("a[onclick*='changePage']").each((_, el) => {
|
|
124
|
+
const m = $(el).attr("onclick")?.match(/changePage\((\d+)\)/);
|
|
125
|
+
if (m)
|
|
126
|
+
pages.push(parseInt(m[1]));
|
|
127
|
+
});
|
|
128
|
+
const totalPages = pages.length > 0 ? Math.max(...pages) : 1;
|
|
129
|
+
// Results
|
|
130
|
+
const results = [];
|
|
131
|
+
$("div.card-result").each((_, el) => {
|
|
132
|
+
const $c = $(el);
|
|
133
|
+
const url = $c.find("a.stretched-link").attr("href") || "";
|
|
134
|
+
const title = $c.find("h5.fw-medium").text().trim();
|
|
135
|
+
const description = $c
|
|
136
|
+
.find("p.text-body-secondary.text-truncate")
|
|
137
|
+
.text()
|
|
138
|
+
.trim();
|
|
139
|
+
const badges = $c.find("div.badge");
|
|
140
|
+
const contentType = badges.first().text().trim();
|
|
141
|
+
const domain = $c.find("div.badge.text-bg-light").text().trim() ||
|
|
142
|
+
badges.last().text().trim();
|
|
143
|
+
let deepSearchId;
|
|
144
|
+
const deepHref = $c.find('a[href*="deep"]').attr("href");
|
|
145
|
+
if (deepHref) {
|
|
146
|
+
const m = deepHref.match(/id=([a-f0-9]{24})/);
|
|
147
|
+
if (m)
|
|
148
|
+
deepSearchId = m[1];
|
|
149
|
+
}
|
|
150
|
+
results.push({
|
|
151
|
+
url,
|
|
152
|
+
title,
|
|
153
|
+
description,
|
|
154
|
+
contentType,
|
|
155
|
+
domain,
|
|
156
|
+
deepSearchId,
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
return {
|
|
160
|
+
query,
|
|
161
|
+
totalResults,
|
|
162
|
+
currentPage,
|
|
163
|
+
totalPages,
|
|
164
|
+
results,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
// ---------- Deep Search ----------
|
|
168
|
+
async deepSearch(params) {
|
|
169
|
+
const html = await this.fetchHtml("/deep", {
|
|
170
|
+
q: params.query,
|
|
171
|
+
id: params.publicationId,
|
|
172
|
+
content: "publication",
|
|
173
|
+
mfd: params.domain || "0000",
|
|
174
|
+
page: String(params.page || 1),
|
|
175
|
+
});
|
|
176
|
+
return this.parseDeepSearchResults(html, params.query, params.page || 1);
|
|
177
|
+
}
|
|
178
|
+
parseDeepSearchResults(html, query, currentPage) {
|
|
179
|
+
const $ = cheerio.load(html);
|
|
180
|
+
// Publication metadata
|
|
181
|
+
const publication = {
|
|
182
|
+
title: $("h5.card-title.fw-semibold").first().text().trim(),
|
|
183
|
+
publisher: $("p.card-text.text-body-secondary").first().text().trim(),
|
|
184
|
+
coverUrl: $("img.foreground").attr("src") || "",
|
|
185
|
+
publicationUrl: $('a.btn-info[href*="bps.go.id/publication"]').attr("href") || "",
|
|
186
|
+
pdfDownloadBase: "",
|
|
187
|
+
};
|
|
188
|
+
// PDF download base from inline script
|
|
189
|
+
$("script").each((_, el) => {
|
|
190
|
+
const content = $(el).html() || "";
|
|
191
|
+
const m = content.match(/https:\/\/web-api\.bps\.go\.id\/download\.php\?f=[^#"]*/);
|
|
192
|
+
if (m)
|
|
193
|
+
publication.pdfDownloadBase = m[0];
|
|
194
|
+
});
|
|
195
|
+
// Total matches: "Menampilkan 11 halaman dengan kata kunci "akses internet""
|
|
196
|
+
const totalMatch = $("body")
|
|
197
|
+
.text()
|
|
198
|
+
.match(/Menampilkan\s+(\d+)\s+halaman dengan kata kunci/);
|
|
199
|
+
const totalMatches = totalMatch ? parseInt(totalMatch[1]) : 0;
|
|
200
|
+
// Pagination
|
|
201
|
+
const pages = [];
|
|
202
|
+
$("a[onclick*='changePage']").each((_, el) => {
|
|
203
|
+
const m = $(el).attr("onclick")?.match(/changePage\((\d+)\)/);
|
|
204
|
+
if (m)
|
|
205
|
+
pages.push(parseInt(m[1]));
|
|
206
|
+
});
|
|
207
|
+
const totalPages = pages.length > 0 ? Math.max(...pages) : 1;
|
|
208
|
+
// Matches
|
|
209
|
+
const matches = [];
|
|
210
|
+
$("div.card-result").each((_, el) => {
|
|
211
|
+
const $c = $(el);
|
|
212
|
+
const pageNumber = parseInt($c.find("a.linkhalaman").attr("data-page") || "0");
|
|
213
|
+
const excerptEl = $c.find('p[id^="deskripsi-"]');
|
|
214
|
+
const excerpt = cleanExcerpt(excerptEl.text());
|
|
215
|
+
const highlights = [];
|
|
216
|
+
excerptEl.find("mark").each((_, mark) => {
|
|
217
|
+
const kw = $(mark).text().trim().toLowerCase();
|
|
218
|
+
if (!highlights.includes(kw))
|
|
219
|
+
highlights.push(kw);
|
|
220
|
+
});
|
|
221
|
+
const pdfViewerUrl = publication.pdfDownloadBase
|
|
222
|
+
? `${publication.pdfDownloadBase}#page=${pageNumber}`
|
|
223
|
+
: "";
|
|
224
|
+
matches.push({ pageNumber, excerpt, highlights, pdfViewerUrl });
|
|
225
|
+
});
|
|
226
|
+
return {
|
|
227
|
+
query,
|
|
228
|
+
publication,
|
|
229
|
+
totalMatches,
|
|
230
|
+
currentPage,
|
|
231
|
+
totalPages,
|
|
232
|
+
matches,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
// ========== Error ==========
|
|
237
|
+
export class AllStatsError extends Error {
|
|
238
|
+
statusCode;
|
|
239
|
+
endpoint;
|
|
240
|
+
constructor(message, statusCode, endpoint) {
|
|
241
|
+
super(message);
|
|
242
|
+
this.statusCode = statusCode;
|
|
243
|
+
this.endpoint = endpoint;
|
|
244
|
+
this.name = "AllStatsError";
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=allstats-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"allstats-client.js","sourceRoot":"","sources":["../../src/client/allstats-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,6 +18,8 @@ export declare const CACHE_TTL: {
|
|
|
18
18
|
readonly PRESS_RELEASE: number;
|
|
19
19
|
readonly PUBLICATION: number;
|
|
20
20
|
readonly STRATEGIC_INDICATOR: number;
|
|
21
|
+
readonly ALLSTATS_SEARCH: number;
|
|
22
|
+
readonly ALLSTATS_DEEP_SEARCH: number;
|
|
21
23
|
};
|
|
22
24
|
export declare const ATTRIBUTION: string;
|
|
23
25
|
export declare const ATTRIBUTION_EN: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ;;;;;;;;;CASX,CAAC;AAEX,eAAO,MAAM,SAAS
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ;;;;;;;;;CASX,CAAC;AAEX,eAAO,MAAM,SAAS;;;;;;;;;;;;CAYZ,CAAC;AAEX,eAAO,MAAM,WAAW,QAEoC,CAAC;AAE7D,eAAO,MAAM,cAAc,QAE+B,CAAC"}
|
package/dist/config/defaults.js
CHANGED
|
@@ -18,6 +18,8 @@ export const CACHE_TTL = {
|
|
|
18
18
|
PRESS_RELEASE: 30 * 60,
|
|
19
19
|
PUBLICATION: 6 * 60 * 60,
|
|
20
20
|
STRATEGIC_INDICATOR: 1 * 60 * 60,
|
|
21
|
+
ALLSTATS_SEARCH: 30 * 60,
|
|
22
|
+
ALLSTATS_DEEP_SEARCH: 60 * 60,
|
|
21
23
|
};
|
|
22
24
|
export const ATTRIBUTION = "Sumber: Badan Pusat Statistik (BPS) — https://www.bps.go.id\n" +
|
|
23
25
|
"Layanan ini menggunakan API Badan Pusat Statistik (BPS).";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,YAAY,EAAE,6BAA6B;IAC3C,YAAY,EAAE,KAAc;IAC5B,cAAc,EAAE,MAAM;IACtB,aAAa,EAAE,IAAI;IACnB,iBAAiB,EAAE,GAAG;IACtB,SAAS,EAAE,MAAe;IAC1B,SAAS,EAAE,OAAgB;IAC3B,SAAS,EAAE,IAAI;CACP,CAAC;AAEX,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,WAAW,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE;IACzB,YAAY,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE;IAC1B,aAAa,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE;IAC3B,YAAY,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE;IACzB,YAAY,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE;IACzB,UAAU,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE;IACvB,aAAa,EAAE,EAAE,GAAG,EAAE;IACtB,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE;IACxB,mBAAmB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE;
|
|
1
|
+
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,YAAY,EAAE,6BAA6B;IAC3C,YAAY,EAAE,KAAc;IAC5B,cAAc,EAAE,MAAM;IACtB,aAAa,EAAE,IAAI;IACnB,iBAAiB,EAAE,GAAG;IACtB,SAAS,EAAE,MAAe;IAC1B,SAAS,EAAE,OAAgB;IAC3B,SAAS,EAAE,IAAI;CACP,CAAC;AAEX,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,WAAW,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE;IACzB,YAAY,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE;IAC1B,aAAa,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE;IAC3B,YAAY,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE;IACzB,YAAY,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE;IACzB,UAAU,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE;IACvB,aAAa,EAAE,EAAE,GAAG,EAAE;IACtB,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE;IACxB,mBAAmB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE;IAChC,eAAe,EAAE,EAAE,GAAG,EAAE;IACxB,oBAAoB,EAAE,EAAE,GAAG,EAAE;CACrB,CAAC;AAEX,MAAM,CAAC,MAAM,WAAW,GACtB,+DAA+D;IAC/D,0DAA0D,CAAC;AAE7D,MAAM,CAAC,MAAM,cAAc,GACzB,8DAA8D;IAC9D,wDAAwD,CAAC"}
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAkB/D,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,aAAa,EACnB,KAAK,EAAE,cAAc,GAAG,IAAI,GAC3B;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,cAAc,CAAA;CAAE,CAqCpE"}
|
package/dist/server.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import { BpsClient } from "./client/bps-client.js";
|
|
3
|
+
import { AllStatsClient } from "./client/allstats-client.js";
|
|
3
4
|
import { DomainResolver } from "./services/domain-resolver.js";
|
|
4
5
|
import { registerDomainTools } from "./tools/domain.tools.js";
|
|
5
6
|
import { registerDynamicDataTools } from "./tools/dynamic-data.tools.js";
|
|
@@ -8,6 +9,7 @@ import { registerPublicationTools } from "./tools/publication.tools.js";
|
|
|
8
9
|
import { registerReferenceTools } from "./tools/reference.tools.js";
|
|
9
10
|
import { registerTradeTools } from "./tools/trade.tools.js";
|
|
10
11
|
import { registerSearchTools } from "./tools/search.tools.js";
|
|
12
|
+
import { registerAllStatsTools } from "./tools/allstats.tools.js";
|
|
11
13
|
import { registerUtilityTools } from "./tools/utility.tools.js";
|
|
12
14
|
import { registerInfographicTools } from "./tools/infographic.tools.js";
|
|
13
15
|
import { registerCensusTools } from "./tools/census.tools.js";
|
|
@@ -19,23 +21,30 @@ import { registerPrompts } from "./prompts/analysis.prompts.js";
|
|
|
19
21
|
export function createServer(config, auth, cache) {
|
|
20
22
|
const server = new McpServer({
|
|
21
23
|
name: "bps-statistics",
|
|
22
|
-
version: "0.
|
|
24
|
+
version: "0.2.0",
|
|
23
25
|
});
|
|
24
26
|
const client = new BpsClient(auth, cache, config);
|
|
27
|
+
const allStatsClient = new AllStatsClient(cache);
|
|
25
28
|
const resolver = new DomainResolver(client);
|
|
29
|
+
// WebAPI-based tools
|
|
26
30
|
registerDomainTools(server, client, resolver);
|
|
27
31
|
registerDynamicDataTools(server, client, config);
|
|
28
32
|
registerStaticTableTools(server, client);
|
|
29
33
|
registerPublicationTools(server, client);
|
|
30
34
|
registerReferenceTools(server, client);
|
|
31
35
|
registerTradeTools(server, client);
|
|
32
|
-
registerSearchTools(server, client);
|
|
33
36
|
registerInfographicTools(server, client);
|
|
34
37
|
registerCensusTools(server, client);
|
|
35
38
|
registerCsaTools(server, client);
|
|
36
39
|
registerNewsTools(server, client);
|
|
37
40
|
registerGlossaryTools(server, client);
|
|
41
|
+
// Search tools — WebAPI with AllStats fallback
|
|
42
|
+
registerSearchTools(server, client, allStatsClient);
|
|
43
|
+
// AllStats-only tools (search engine + deep search)
|
|
44
|
+
registerAllStatsTools(server, allStatsClient);
|
|
45
|
+
// Utility
|
|
38
46
|
registerUtilityTools(server, cache);
|
|
47
|
+
// Resources & Prompts
|
|
39
48
|
registerResources(server, client, resolver);
|
|
40
49
|
registerPrompts(server);
|
|
41
50
|
return { server, client, resolver };
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,MAAM,UAAU,YAAY,CAC1B,MAAc,EACd,IAAmB,EACnB,KAA4B;IAE5B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;IAE5C,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC9C,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACjD,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,MAAM,UAAU,YAAY,CAC1B,MAAc,EACd,IAAmB,EACnB,KAA4B;IAE5B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAClD,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;IAE5C,qBAAqB;IACrB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC9C,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACjD,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEtC,+CAA+C;IAC/C,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC;IAEpD,oDAAoD;IACpD,qBAAqB,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAE9C,UAAU;IACV,oBAAoB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAEpC,sBAAsB;IACtB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC5C,eAAe,CAAC,MAAM,CAAC,CAAC;IAExB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { AllStatsClient } from "../client/allstats-client.js";
|
|
3
|
+
export declare function registerAllStatsTools(server: McpServer, allStatsClient: AllStatsClient): void;
|
|
4
|
+
//# sourceMappingURL=allstats.tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"allstats.tools.d.ts","sourceRoot":"","sources":["../../src/tools/allstats.tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EACV,cAAc,EAGf,MAAM,8BAA8B,CAAC;AAyFtC,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,cAAc,EAAE,cAAc,GAC7B,IAAI,CAuHN"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { appendAttribution } from "../services/attribution.js";
|
|
3
|
+
// ========== Formatters ==========
|
|
4
|
+
function formatSearchResults(res) {
|
|
5
|
+
const lines = [];
|
|
6
|
+
lines.push(`## Hasil AllStats Search: "${res.query}"`);
|
|
7
|
+
lines.push("");
|
|
8
|
+
lines.push(`Ditemukan **${res.totalResults.toLocaleString("id-ID")}** hasil (halaman ${res.currentPage}/${res.totalPages})`);
|
|
9
|
+
lines.push("");
|
|
10
|
+
if (res.results.length === 0) {
|
|
11
|
+
lines.push("_Tidak ada hasil ditemukan._");
|
|
12
|
+
return lines.join("\n");
|
|
13
|
+
}
|
|
14
|
+
for (let i = 0; i < res.results.length; i++) {
|
|
15
|
+
const r = res.results[i];
|
|
16
|
+
lines.push(`### ${i + 1}. ${r.title}`);
|
|
17
|
+
if (r.description)
|
|
18
|
+
lines.push(`> ${r.description}`);
|
|
19
|
+
lines.push("");
|
|
20
|
+
lines.push(`- **Tipe:** ${r.contentType}`);
|
|
21
|
+
lines.push(`- **Sumber:** ${r.domain}`);
|
|
22
|
+
if (r.url)
|
|
23
|
+
lines.push(`- **URL:** ${r.url}`);
|
|
24
|
+
if (r.deepSearchId) {
|
|
25
|
+
lines.push(`- **Deep Search ID:** \`${r.deepSearchId}\` _(gunakan allstats_deep_search untuk cari teks di dalam publikasi ini)_`);
|
|
26
|
+
}
|
|
27
|
+
lines.push("");
|
|
28
|
+
}
|
|
29
|
+
if (res.currentPage < res.totalPages) {
|
|
30
|
+
lines.push(`---\n_Halaman ${res.currentPage} dari ${res.totalPages}. Gunakan parameter \`page\` untuk melihat halaman berikutnya._`);
|
|
31
|
+
}
|
|
32
|
+
return lines.join("\n");
|
|
33
|
+
}
|
|
34
|
+
function formatDeepSearchResults(res) {
|
|
35
|
+
const lines = [];
|
|
36
|
+
const pub = res.publication;
|
|
37
|
+
lines.push(`## Deep Search: "${res.query}"`);
|
|
38
|
+
lines.push("");
|
|
39
|
+
lines.push(`### Publikasi: ${pub.title}`);
|
|
40
|
+
if (pub.publisher)
|
|
41
|
+
lines.push(`**Penerbit:** ${pub.publisher}`);
|
|
42
|
+
if (pub.publicationUrl)
|
|
43
|
+
lines.push(`**URL:** ${pub.publicationUrl}`);
|
|
44
|
+
lines.push("");
|
|
45
|
+
lines.push(`Ditemukan **${res.totalMatches}** halaman cocok (halaman hasil ${res.currentPage}/${res.totalPages})`);
|
|
46
|
+
lines.push("");
|
|
47
|
+
if (res.matches.length === 0) {
|
|
48
|
+
lines.push("_Tidak ada halaman yang cocok ditemukan._");
|
|
49
|
+
return lines.join("\n");
|
|
50
|
+
}
|
|
51
|
+
for (const match of res.matches) {
|
|
52
|
+
lines.push(`#### Halaman ${match.pageNumber}`);
|
|
53
|
+
if (match.excerpt) {
|
|
54
|
+
lines.push(`> ${match.excerpt}`);
|
|
55
|
+
}
|
|
56
|
+
if (match.highlights.length > 0) {
|
|
57
|
+
lines.push(`**Kata kunci:** ${match.highlights.join(", ")}`);
|
|
58
|
+
}
|
|
59
|
+
if (match.pdfViewerUrl) {
|
|
60
|
+
lines.push(`**PDF:** ${match.pdfViewerUrl}`);
|
|
61
|
+
}
|
|
62
|
+
lines.push("");
|
|
63
|
+
}
|
|
64
|
+
if (res.currentPage < res.totalPages) {
|
|
65
|
+
lines.push(`---\n_Halaman ${res.currentPage} dari ${res.totalPages}. Gunakan parameter \`page\` untuk melihat halaman berikutnya._`);
|
|
66
|
+
}
|
|
67
|
+
return lines.join("\n");
|
|
68
|
+
}
|
|
69
|
+
// ========== Tool Registration ==========
|
|
70
|
+
export function registerAllStatsTools(server, allStatsClient) {
|
|
71
|
+
// ---------- allstats_search ----------
|
|
72
|
+
server.tool("allstats_search", "Pencarian konten BPS melalui AllStats Search Engine (publikasi, tabel, BRS, infografis, data mikro, glosarium, klasifikasi). Berguna untuk discovery, mencari publikasi, atau sebagai alternatif/fallback dari WebAPI search. Tidak memerlukan API key.", {
|
|
73
|
+
query: z.string().describe("Kata kunci pencarian"),
|
|
74
|
+
content: z
|
|
75
|
+
.enum([
|
|
76
|
+
"all",
|
|
77
|
+
"publication",
|
|
78
|
+
"table",
|
|
79
|
+
"pressrelease",
|
|
80
|
+
"infographic",
|
|
81
|
+
"microdata",
|
|
82
|
+
"news",
|
|
83
|
+
"glosarium",
|
|
84
|
+
"kbli2020",
|
|
85
|
+
"kbli2017",
|
|
86
|
+
"kbli2015",
|
|
87
|
+
"kbli2009",
|
|
88
|
+
])
|
|
89
|
+
.default("all")
|
|
90
|
+
.describe("Filter tipe konten: all, publication, table, pressrelease, infographic, microdata, news, glosarium, kbli2020/2017/2015/2009"),
|
|
91
|
+
domain: z
|
|
92
|
+
.string()
|
|
93
|
+
.default("0000")
|
|
94
|
+
.describe("Kode wilayah MFD. 'all'=semua, '0000'=nasional, 2 digit=provinsi (cth: 3500=Jatim), 4 digit=kab/kota"),
|
|
95
|
+
page: z
|
|
96
|
+
.number()
|
|
97
|
+
.default(1)
|
|
98
|
+
.describe("Nomor halaman (10 hasil per halaman)"),
|
|
99
|
+
title_only: z
|
|
100
|
+
.boolean()
|
|
101
|
+
.default(false)
|
|
102
|
+
.describe("Cari di judul saja (true) atau semua field (false)"),
|
|
103
|
+
year_from: z
|
|
104
|
+
.string()
|
|
105
|
+
.default("all")
|
|
106
|
+
.describe("Filter tahun mulai ('all' atau tahun, cth: '2020')"),
|
|
107
|
+
year_to: z
|
|
108
|
+
.string()
|
|
109
|
+
.default("all")
|
|
110
|
+
.describe("Filter tahun sampai ('all' atau tahun, cth: '2024')"),
|
|
111
|
+
sort: z
|
|
112
|
+
.enum(["terbaru", "relevansi"])
|
|
113
|
+
.default("terbaru")
|
|
114
|
+
.describe("Urutan hasil: 'terbaru' (newest first) atau 'relevansi'"),
|
|
115
|
+
}, async ({ query, content, domain, page, title_only, year_from, year_to, sort }) => {
|
|
116
|
+
try {
|
|
117
|
+
const result = await allStatsClient.search({
|
|
118
|
+
query,
|
|
119
|
+
content,
|
|
120
|
+
domain,
|
|
121
|
+
page,
|
|
122
|
+
titleOnly: title_only,
|
|
123
|
+
yearFrom: year_from,
|
|
124
|
+
yearTo: year_to,
|
|
125
|
+
sort,
|
|
126
|
+
});
|
|
127
|
+
const text = appendAttribution(formatSearchResults(result));
|
|
128
|
+
return { content: [{ type: "text", text }] };
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
const message = error instanceof Error
|
|
132
|
+
? `Gagal melakukan pencarian AllStats: ${error.message}`
|
|
133
|
+
: "Terjadi kesalahan saat mengakses AllStats Search.";
|
|
134
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
// ---------- allstats_deep_search ----------
|
|
138
|
+
server.tool("allstats_deep_search", "Full-text search di dalam isi PDF publikasi BPS. Mengembalikan halaman yang cocok beserta cuplikan teks. Dapatkan publication_id dari hasil allstats_search (field deep_search_id). Fitur unik — tidak tersedia di WebAPI. Tidak memerlukan API key.", {
|
|
139
|
+
query: z.string().describe("Kata kunci untuk dicari di dalam publikasi"),
|
|
140
|
+
publication_id: z
|
|
141
|
+
.string()
|
|
142
|
+
.regex(/^[a-f0-9]{24}$/, "Harus berupa 24 karakter hex")
|
|
143
|
+
.describe("ID publikasi (24 karakter hex) dari URL publikasi BPS atau dari field deep_search_id di hasil allstats_search"),
|
|
144
|
+
domain: z
|
|
145
|
+
.string()
|
|
146
|
+
.default("0000")
|
|
147
|
+
.describe("Kode wilayah MFD"),
|
|
148
|
+
page: z
|
|
149
|
+
.number()
|
|
150
|
+
.default(1)
|
|
151
|
+
.describe("Halaman hasil (bukan halaman PDF)"),
|
|
152
|
+
}, async ({ query, publication_id, domain, page }) => {
|
|
153
|
+
try {
|
|
154
|
+
const result = await allStatsClient.deepSearch({
|
|
155
|
+
query,
|
|
156
|
+
publicationId: publication_id,
|
|
157
|
+
domain,
|
|
158
|
+
page,
|
|
159
|
+
});
|
|
160
|
+
const text = appendAttribution(formatDeepSearchResults(result));
|
|
161
|
+
return { content: [{ type: "text", text }] };
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
const message = error instanceof Error
|
|
165
|
+
? `Gagal melakukan deep search AllStats: ${error.message}`
|
|
166
|
+
: "Terjadi kesalahan saat mengakses AllStats Deep Search.";
|
|
167
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=allstats.tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"allstats.tools.js","sourceRoot":"","sources":["../../src/tools/allstats.tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import type { BpsClient } from "../client/bps-client.js";
|
|
3
|
-
|
|
3
|
+
import type { AllStatsClient } from "../client/allstats-client.js";
|
|
4
|
+
export declare function registerSearchTools(server: McpServer, client: BpsClient, allStatsClient?: AllStatsClient): void;
|
|
4
5
|
//# sourceMappingURL=search.tools.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.tools.d.ts","sourceRoot":"","sources":["../../src/tools/search.tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"search.tools.d.ts","sourceRoot":"","sources":["../../src/tools/search.tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAA0B,MAAM,8BAA8B,CAAC;AAuC3F,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,SAAS,EACjB,cAAc,CAAC,EAAE,cAAc,GAC9B,IAAI,CAuHN"}
|
|
@@ -1,22 +1,128 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { appendAttribution } from "../services/attribution.js";
|
|
3
3
|
import { formatErrorForUser } from "../utils/error.js";
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
import { BpsNotFoundError } from "../utils/error.js";
|
|
5
|
+
import { logger } from "../utils/logger.js";
|
|
6
|
+
/** Map WebAPI type names to AllStats content types */
|
|
7
|
+
const WEBAPI_TO_ALLSTATS_CONTENT = {
|
|
8
|
+
statictable: "table",
|
|
9
|
+
pressrelease: "pressrelease",
|
|
10
|
+
publication: "publication",
|
|
11
|
+
strategicindicator: "table",
|
|
12
|
+
};
|
|
13
|
+
function formatAllStatsFallback(res) {
|
|
14
|
+
const lines = [];
|
|
15
|
+
lines.push(`### Hasil dari AllStats Search (fallback)`);
|
|
16
|
+
lines.push(`Ditemukan **${res.totalResults.toLocaleString("id-ID")}** hasil via AllStats Search Engine`);
|
|
17
|
+
lines.push("");
|
|
18
|
+
for (let i = 0; i < res.results.length; i++) {
|
|
19
|
+
const r = res.results[i];
|
|
20
|
+
lines.push(`**${i + 1}. ${r.title}**`);
|
|
21
|
+
if (r.description)
|
|
22
|
+
lines.push(`> ${r.description}`);
|
|
23
|
+
lines.push(`- Tipe: ${r.contentType} | Sumber: ${r.domain}`);
|
|
24
|
+
if (r.url)
|
|
25
|
+
lines.push(`- URL: ${r.url}`);
|
|
26
|
+
if (r.deepSearchId) {
|
|
27
|
+
lines.push(`- Deep Search ID: \`${r.deepSearchId}\` _(gunakan allstats_deep_search untuk cari di dalam publikasi)_`);
|
|
28
|
+
}
|
|
29
|
+
lines.push("");
|
|
30
|
+
}
|
|
31
|
+
return lines.join("\n");
|
|
32
|
+
}
|
|
33
|
+
export function registerSearchTools(server, client, allStatsClient) {
|
|
34
|
+
server.tool("search", "Pencarian data lintas tipe di BPS. Mencari via WebAPI (tabel statis, publikasi, BRS, indikator). Jika WebAPI tidak menemukan hasil, otomatis fallback ke AllStats Search Engine untuk hasil yang lebih luas.", {
|
|
6
35
|
domain: z.string().default("0000").describe("Kode domain BPS"),
|
|
7
36
|
keyword: z.string().describe("Kata kunci pencarian"),
|
|
8
|
-
type: z
|
|
37
|
+
type: z
|
|
38
|
+
.string()
|
|
39
|
+
.optional()
|
|
40
|
+
.describe("Filter tipe hasil: 'statictable', 'pressrelease', 'publication', 'strategicindicator' (opsional)"),
|
|
9
41
|
page: z.number().optional().describe("Nomor halaman"),
|
|
10
42
|
}, async ({ domain, keyword, type, page }) => {
|
|
43
|
+
// --- Step 1: Try WebAPI ---
|
|
44
|
+
let webapiResult = null;
|
|
45
|
+
let webapiError = null;
|
|
11
46
|
try {
|
|
12
|
-
|
|
47
|
+
webapiResult = await client.search(domain, keyword, type, page);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
webapiError = error;
|
|
51
|
+
logger.debug(`WebAPI search failed for "${keyword}": ${error instanceof Error ? error.message : "unknown"}`);
|
|
52
|
+
}
|
|
53
|
+
// Check if WebAPI returned data
|
|
54
|
+
const webapiHasData = webapiResult !== null &&
|
|
55
|
+
Array.isArray(webapiResult.data) &&
|
|
56
|
+
webapiResult.data.length > 0;
|
|
57
|
+
if (webapiHasData) {
|
|
58
|
+
// WebAPI returned results — use them
|
|
13
59
|
const text = appendAttribution(`## Hasil Pencarian: "${keyword}"\n\n` +
|
|
14
|
-
"```json\n" +
|
|
60
|
+
"```json\n" +
|
|
61
|
+
JSON.stringify(webapiResult, null, 2) +
|
|
62
|
+
"\n```");
|
|
15
63
|
return { content: [{ type: "text", text }] };
|
|
16
64
|
}
|
|
17
|
-
|
|
18
|
-
|
|
65
|
+
// --- Step 2: Fallback to AllStats ---
|
|
66
|
+
if (allStatsClient) {
|
|
67
|
+
try {
|
|
68
|
+
const allStatsContent = type && WEBAPI_TO_ALLSTATS_CONTENT[type]
|
|
69
|
+
? WEBAPI_TO_ALLSTATS_CONTENT[type]
|
|
70
|
+
: "all";
|
|
71
|
+
const allStatsResult = await allStatsClient.search({
|
|
72
|
+
query: keyword,
|
|
73
|
+
content: allStatsContent,
|
|
74
|
+
domain,
|
|
75
|
+
page: page || 1,
|
|
76
|
+
});
|
|
77
|
+
if (allStatsResult.results.length > 0) {
|
|
78
|
+
const parts = [];
|
|
79
|
+
parts.push(`## Hasil Pencarian: "${keyword}"\n`);
|
|
80
|
+
// Indicate fallback if WebAPI was attempted
|
|
81
|
+
if (webapiError) {
|
|
82
|
+
parts.push(`> **Catatan:** WebAPI BPS tidak tersedia (${webapiError instanceof Error ? webapiError.message : "error"}). Menampilkan hasil dari AllStats Search.\n`);
|
|
83
|
+
}
|
|
84
|
+
else if (webapiResult && !webapiHasData) {
|
|
85
|
+
parts.push(`> **Catatan:** WebAPI BPS tidak menemukan hasil untuk "${keyword}". Menampilkan hasil dari AllStats Search.\n`);
|
|
86
|
+
}
|
|
87
|
+
parts.push(formatAllStatsFallback(allStatsResult));
|
|
88
|
+
const text = appendAttribution(parts.join("\n"));
|
|
89
|
+
return { content: [{ type: "text", text }] };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (allStatsError) {
|
|
93
|
+
logger.debug(`AllStats fallback also failed for "${keyword}": ${allStatsError instanceof Error ? allStatsError.message : "unknown"}`);
|
|
94
|
+
// If both fail, return the original error
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// --- Step 3: Both failed or no results ---
|
|
98
|
+
if (webapiError) {
|
|
99
|
+
// WebAPI had an error and AllStats also failed or not available
|
|
100
|
+
if (webapiError instanceof BpsNotFoundError) {
|
|
101
|
+
return {
|
|
102
|
+
content: [
|
|
103
|
+
{
|
|
104
|
+
type: "text",
|
|
105
|
+
text: `Tidak ditemukan hasil untuk "${keyword}" di WebAPI maupun AllStats Search.`,
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
isError: true,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
content: [{ type: "text", text: formatErrorForUser(webapiError) }],
|
|
113
|
+
isError: true,
|
|
114
|
+
};
|
|
19
115
|
}
|
|
116
|
+
// WebAPI returned empty
|
|
117
|
+
return {
|
|
118
|
+
content: [
|
|
119
|
+
{
|
|
120
|
+
type: "text",
|
|
121
|
+
text: `Tidak ditemukan hasil untuk "${keyword}".`,
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
isError: true,
|
|
125
|
+
};
|
|
20
126
|
});
|
|
21
127
|
}
|
|
22
128
|
//# sourceMappingURL=search.tools.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.tools.js","sourceRoot":"","sources":["../../src/tools/search.tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"search.tools.js","sourceRoot":"","sources":["../../src/tools/search.tools.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bps-mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "MCP server for BPS (Badan Pusat Statistik) Indonesia statistics data",
|
|
5
5
|
"author": "Murphi",
|
|
6
6
|
"license": "MIT",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
41
|
+
"cheerio": "^1.2.0",
|
|
41
42
|
"zod": "^3.24.4"
|
|
42
43
|
},
|
|
43
44
|
"devDependencies": {
|