taiwan-data-mcp 0.4.0 → 0.5.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 CHANGED
@@ -19,7 +19,9 @@
19
19
  | `taiwan_realprice_estimate` | 自動估價:單價區間與推估總價 | housetw.com |
20
20
  | `taiwan_realprice_road` | 查某路段成交行情與逐年走勢 | housetw.com |
21
21
  | `taiwan_drug_search` | 用中文藥名搜尋核准藥品、取許可證字號 | [health-hub](https://health-hub-epx.pages.dev)(衛福部食藥署) |
22
- | `taiwan_drug_info` | 用許可證字號查藥品主要成分 | health-hub |
22
+ | `taiwan_drug_info` | 用許可證字號查藥品成分/適應症/健保價/回收/短缺 | health-hub |
23
+ | `taiwan_gov_tender_by_company` | 查某公司投標/得標的政府採購案 | 政府電子採購網(g0v PCC API) |
24
+ | `taiwan_gov_tender_search` | 用標案名稱關鍵字搜尋政府採購案 | 政府電子採購網(g0v PCC API) |
23
25
 
24
26
  跨工具串接是重點:例如「查這家公司 → 看它登記地址那區的房價 → 查它官網是不是詐騙」,一次問答內 AI 自己串起來。
25
27
 
@@ -75,6 +77,7 @@ node test/e2e.mjs # MCP 協定層測試
75
77
  - 公司登記查核 — **[inc.com.tw](https://inc.com.tw)**(台灣公司登記網)
76
78
  - 165 防詐查詢 — **[fraud.tw](https://fraud.tw)**(防詐雷達)
77
79
  - 藥品/健康查詢 — **[health-hub](https://health-hub-epx.pages.dev)**(衛福部食藥署資料)
80
+ - 政府標案查詢 — 政府電子採購網開放資料(透過 [g0v PCC API](https://pcc.g0v.ronny.tw))
78
81
 
79
82
  三站皆為聚合台灣政府開放資料的免費查詢服務。
80
83
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "taiwan-data-mcp",
3
- "version": "0.4.0",
4
- "description": "MCP server for Taiwan public data — 實價登錄行情、公司登記查核、165 防詐查詢、藥品成分查詢。Lets AI assistants (Claude, Cursor, etc.) query real Taiwan data.",
3
+ "version": "0.5.0",
4
+ "description": "MCP server for Taiwan public data — 實價登錄、公司登記查核、165 防詐、藥品查詢、政府標案。Lets AI assistants (Claude, Cursor, etc.) query real Taiwan data.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "taiwan-data-mcp": "src/server.mjs"
package/src/server.mjs CHANGED
@@ -6,6 +6,7 @@ import {
6
6
  scamCheck, companySearch, companyProfile, personCompanies, companyRisk,
7
7
  realpriceSearch, realpriceLocate, realpriceArea, realpriceEstimate, realpriceRoad,
8
8
  drugSearch, drugInfo,
9
+ tenderByCompany, tenderSearch,
9
10
  } from './sources.mjs';
10
11
 
11
12
  const TOOLS = [
@@ -149,7 +150,7 @@ const TOOLS = [
149
150
  {
150
151
  name: 'taiwan_drug_info',
151
152
  description:
152
- '用藥品許可證字號查該藥的主要成分。資料來源:衛福部食藥署藥品許可證 · health-hub。用藥請依醫師、藥師指示。',
153
+ '用藥品許可證字號查該藥詳情:主成分、適應症、用法、劑型、藥品類別/管制分級、健保價、是否被回收、供應短缺狀態。資料來源:衛福部食藥署 · health-hub。用藥請依醫師、藥師指示。',
153
154
  inputSchema: {
154
155
  type: 'object',
155
156
  properties: { license_no: { type: 'string', description: '藥品許可證字號,例如「衛署藥輸字第024600號」(可先用 taiwan_drug_search 取得)' } },
@@ -157,6 +158,31 @@ const TOOLS = [
157
158
  },
158
159
  run: (a) => drugInfo(a.license_no),
159
160
  },
161
+ {
162
+ name: 'taiwan_gov_tender_by_company',
163
+ description:
164
+ '查某公司/廠商參與投標或得標的政府採購案,回傳標案名稱、機關、公告類型、日期與相關廠商。可搭配公司查核做盡職調查(這家公司接過哪些政府標案)。資料來源:政府電子採購網開放資料(g0v PCC API)。',
165
+ inputSchema: {
166
+ type: 'object',
167
+ properties: { company: { type: 'string', description: '公司/廠商名稱,例如「大同股份有限公司」' } },
168
+ required: ['company'],
169
+ },
170
+ run: (a) => tenderByCompany(a.company),
171
+ },
172
+ {
173
+ name: 'taiwan_gov_tender_search',
174
+ description:
175
+ '用標案名稱關鍵字搜尋政府採購案,回傳標案、機關、得標廠商與日期(可翻頁)。資料來源:政府電子採購網開放資料(g0v PCC API)。',
176
+ inputSchema: {
177
+ type: 'object',
178
+ properties: {
179
+ keyword: { type: 'string', description: '標案名稱關鍵字,例如「口罩」「資訊服務」' },
180
+ page: { type: 'number', description: '頁碼(可選,預設 1)' },
181
+ },
182
+ required: ['keyword'],
183
+ },
184
+ run: (a) => tenderSearch(a.keyword, a.page),
185
+ },
160
186
  ];
161
187
 
162
188
  const server = new Server(
@@ -181,4 +207,4 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
181
207
 
182
208
  const transport = new StdioServerTransport();
183
209
  await server.connect(transport);
184
- console.error('taiwan-data-mcp running (stdio) — 12 tools: 防詐 / 公司登記 / 實價登錄 / 藥品健康');
210
+ console.error('taiwan-data-mcp running (stdio) — 14 tools: 防詐 / 公司登記 / 實價登錄 / 藥品健康 / 政府標案');
package/src/sources.mjs CHANGED
@@ -107,6 +107,58 @@ export async function companyRisk(id) {
107
107
  };
108
108
  }
109
109
 
110
+ // ── 政府標案 PCC(g0v 政府採購開放資料)─────────────────────────
111
+ const PCC_BASE = 'https://pcc-api.openfun.app';
112
+
113
+ function _fmtTenderDate(d) {
114
+ const s = String(d || '');
115
+ return s.length === 8 ? `${s.slice(0, 4)}-${s.slice(4, 6)}-${s.slice(6, 8)}` : s || null;
116
+ }
117
+ function _mapTender(r) {
118
+ const b = r.brief || {};
119
+ const names = b.companies?.names || [];
120
+ return {
121
+ date: _fmtTenderDate(r.date),
122
+ title: b.title || null,
123
+ type: b.type || null,
124
+ agency: r.unit_name || null,
125
+ companies: names,
126
+ tender_url: r.url ? `https://pcc.g0v.ronny.tw${r.url}` : null,
127
+ };
128
+ }
129
+
130
+ export async function tenderByCompany(name) {
131
+ const q = String(name || '').trim();
132
+ if (q.length < 2) return { error: '公司名稱至少 2 個字' };
133
+ const { ok, body } = await fetchJson(`${PCC_BASE}/api/searchbycompanyname?query=${encodeURIComponent(q)}`, { timeout: 20000 });
134
+ if (!ok || !body || !Array.isArray(body.records)) return { error: '查詢失敗(政府採購開放資料)', query: q };
135
+ return {
136
+ query: q,
137
+ total: body.total_records ?? body.records.length,
138
+ showing: Math.min(body.records.length, 25),
139
+ tenders: body.records.slice(0, 25).map(_mapTender),
140
+ note: '含該廠商參與投標或得標的採購案;以廠商名比對',
141
+ source: '政府電子採購網(公共工程委員會)開放資料 · 透過 g0v PCC API',
142
+ };
143
+ }
144
+
145
+ export async function tenderSearch(keyword, page = 1) {
146
+ const q = String(keyword || '').trim();
147
+ if (q.length < 2) return { error: '搜尋關鍵字至少 2 個字' };
148
+ const p = Math.max(1, Number(page) || 1);
149
+ const { ok, body } = await fetchJson(`${PCC_BASE}/api/searchbytitle?query=${encodeURIComponent(q)}&page=${p}`, { timeout: 20000 });
150
+ if (!ok || !body || !Array.isArray(body.records)) return { error: '查詢失敗(政府採購開放資料)', query: q };
151
+ return {
152
+ query: q,
153
+ page: p,
154
+ total: body.total_records ?? null,
155
+ total_pages: body.total_pages ?? null,
156
+ showing: Math.min(body.records.length, 25),
157
+ tenders: body.records.slice(0, 25).map(_mapTender),
158
+ source: '政府電子採購網(公共工程委員會)開放資料 · 透過 g0v PCC API',
159
+ };
160
+ }
161
+
110
162
  // ── 藥品/健康 health-hub ───────────────────────────────────────
111
163
  const HEALTH_BASE = 'https://health-hub-epx.pages.dev';
112
164
 
@@ -127,6 +179,11 @@ export async function drugSearch(name) {
127
179
  export async function drugInfo(licenseNo) {
128
180
  const lic = String(licenseNo || '').trim();
129
181
  if (!lic) return { error: '請提供藥品許可證字號(license_no),可先用 taiwan_drug_search 取得' };
182
+ // 優先用完整端點(含適應症/健保價/回收/短缺);未部署時自動退回成分端點
183
+ const full = await fetchJson(`${HEALTH_BASE}/api/drug.json?lic=${encodeURIComponent(lic)}`);
184
+ if (full.ok && full.body && full.body.name) return full.body;
185
+ if (full.status === 404 && full.body && full.body.error) return full.body; // 確實查無此藥
186
+
130
187
  const { ok, body } = await fetchJson(`${HEALTH_BASE}/api/drug-ingredients?lic=${encodeURIComponent(lic)}`);
131
188
  if (!ok || !body) return { error: '查詢失敗(health-hub)', license_no: lic };
132
189
  if (!body.name) return { error: `查無此許可證字號 ${lic}`, license_no: lic };