taiwan-data-mcp 0.8.0 → 0.10.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/package.json +1 -1
- package/src/server.mjs +28 -3
- package/src/sources.mjs +23 -4
package/package.json
CHANGED
package/src/server.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
|
4
4
|
import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
5
5
|
import {
|
|
6
6
|
scamCheck, companySearch, companyProfile, personCompanies, companyRisk,
|
|
7
|
-
companyRelations, companyNameCheck, companyVerify,
|
|
7
|
+
companyRelations, companyNameCheck, companyVerify, validateTaxId, findConnection,
|
|
8
8
|
realpriceSearch, realpriceLocate, realpriceArea, realpriceEstimate, realpriceRoad,
|
|
9
9
|
drugSearch, drugInfo,
|
|
10
10
|
tenderByCompany, tenderSearch,
|
|
@@ -102,6 +102,31 @@ const TOOLS = [
|
|
|
102
102
|
},
|
|
103
103
|
run: (a) => companyVerify(a.unified_business_no),
|
|
104
104
|
},
|
|
105
|
+
{
|
|
106
|
+
name: 'taiwan_validate_tax_id',
|
|
107
|
+
description:
|
|
108
|
+
'驗證台灣統一編號(8 碼)檢查碼是否正確(財政部統編邏輯,純演算法、不查資料庫)。資料清理、表單驗證、判斷一組號碼是否為有效統編格式用。回傳 valid 與說明。資料來源:inc.com.tw。',
|
|
109
|
+
inputSchema: {
|
|
110
|
+
type: 'object',
|
|
111
|
+
properties: { unified_business_no: { type: 'string', description: '8 位統一編號,例如 22099131' } },
|
|
112
|
+
required: ['unified_business_no'],
|
|
113
|
+
},
|
|
114
|
+
run: (a) => validateTaxId(a.unified_business_no),
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: 'taiwan_find_connection',
|
|
118
|
+
description:
|
|
119
|
+
'查兩家公司/兩個人之間的最短關係鏈(天眼查式盡職調查):透過共同負責人/董監事一層層串接,回傳中間的人與公司節點與相隔層數。用於「這兩家公司/這兩個人有沒有關係、怎麼牽上線」。a、b 可填公司名、8 位統編或人名。資料來源:inc.com.tw。',
|
|
120
|
+
inputSchema: {
|
|
121
|
+
type: 'object',
|
|
122
|
+
properties: {
|
|
123
|
+
a: { type: 'string', description: '起點:公司名/統編/人名,例如「鴻海精密工業」' },
|
|
124
|
+
b: { type: 'string', description: '終點:公司名/統編/人名,例如「三創數位」' },
|
|
125
|
+
},
|
|
126
|
+
required: ['a', 'b'],
|
|
127
|
+
},
|
|
128
|
+
run: (a) => findConnection(a.a, a.b),
|
|
129
|
+
},
|
|
105
130
|
{
|
|
106
131
|
name: 'taiwan_realprice_search',
|
|
107
132
|
description:
|
|
@@ -237,7 +262,7 @@ const TOOLS = [
|
|
|
237
262
|
];
|
|
238
263
|
|
|
239
264
|
const server = new Server(
|
|
240
|
-
{ name: 'taiwan-data-mcp', version: '0.
|
|
265
|
+
{ name: 'taiwan-data-mcp', version: '0.10.0' },
|
|
241
266
|
{ capabilities: { tools: {} } }
|
|
242
267
|
);
|
|
243
268
|
|
|
@@ -258,4 +283,4 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
258
283
|
|
|
259
284
|
const transport = new StdioServerTransport();
|
|
260
285
|
await server.connect(transport);
|
|
261
|
-
console.error('taiwan-data-mcp running (stdio) —
|
|
286
|
+
console.error('taiwan-data-mcp running (stdio) — 20 tools: 防詐 / 公司登記·關係·盡調 / 實價登錄 / 藥品健康 / 政府標案 / 農產行情');
|
package/src/sources.mjs
CHANGED
|
@@ -95,12 +95,13 @@ export async function companyRisk(idOrName) {
|
|
|
95
95
|
if (f.reject) redFlags.push('政府採購拒絕往來');
|
|
96
96
|
if (f.sanction) redFlags.push(`命中國際制裁名單 ${f.sanction} 筆(OFAC/UN 等)`);
|
|
97
97
|
if (f.fsc) redFlags.push(`金管會重大裁罰 ${f.fsc} 件`);
|
|
98
|
-
if (f.judicial) redFlags.push(`司法案件 ${f.judicial}
|
|
98
|
+
if (f.judicial) redFlags.push(`司法案件 ${f.judicial} 筆(以名稱比對,含一般民事/被列名,未必為違法,僅供參考)`);
|
|
99
99
|
if (f.labor) redFlags.push(`勞動法令裁罰 ${f.labor} 筆`);
|
|
100
100
|
if (f.env) redFlags.push(`環保裁罰 ${f.env} 筆`);
|
|
101
|
-
//
|
|
102
|
-
|
|
103
|
-
const
|
|
101
|
+
// 重大紅旗(解散/拒絕往來/國際制裁/金管會重大裁罰)→ high。
|
|
102
|
+
// 司法案件以名稱比對且噪訊高(大公司常被列為當事人),與勞動/環保同列 medium,不單獨拉到 high。
|
|
103
|
+
const major = f.dissolved || f.reject || f.sanction || f.fsc;
|
|
104
|
+
const level = major ? 'high' : (f.judicial || f.labor || f.env) ? 'medium' : 'low';
|
|
104
105
|
return {
|
|
105
106
|
unified_business_no: body.id,
|
|
106
107
|
name: body.name,
|
|
@@ -157,6 +158,24 @@ export async function companyVerify(id) {
|
|
|
157
158
|
source: body.src || '經濟部商工登記公示資料' };
|
|
158
159
|
}
|
|
159
160
|
|
|
161
|
+
// 統一編號檢查碼驗證(純演算法,資料清理/表單檢核用)。
|
|
162
|
+
export async function validateTaxId(id) {
|
|
163
|
+
const tin = String(id || '').replace(/\D/g, '');
|
|
164
|
+
if (tin.length !== 8) return { input: String(id || ''), valid: false, reason: '統一編號必須是 8 位數字' };
|
|
165
|
+
const { ok, body } = await fetchJson(`https://inc.com.tw/api/taxid?id=${tin}`, { timeout: 10000 });
|
|
166
|
+
if (!ok || !body) return { input: tin, valid: false, reason: '查詢失敗(inc.com.tw)' };
|
|
167
|
+
return body;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// 關係路徑:兩家公司/兩人之間透過共同負責人/董監事串接的最短關係鏈(天眼查式盡調)。
|
|
171
|
+
export async function findConnection(a, b) {
|
|
172
|
+
const qa = String(a || '').trim(), qb = String(b || '').trim();
|
|
173
|
+
if (!qa || !qb) return { error: '請提供 a 與 b(公司名/統編/人名)' };
|
|
174
|
+
const { ok, body } = await fetchJson(`https://inc.com.tw/api/path?a=${encodeURIComponent(qa)}&b=${encodeURIComponent(qb)}`, { timeout: 25000 });
|
|
175
|
+
if (!ok || !body) return { error: '查詢失敗(inc.com.tw)', a: qa, b: qb };
|
|
176
|
+
return body; // 已自帶 from/to/path/note/source
|
|
177
|
+
}
|
|
178
|
+
|
|
160
179
|
// ── 農產批發行情 MOA(農業部農產品交易行情)──────────────────────
|
|
161
180
|
function _rocToAd(s) {
|
|
162
181
|
const m = String(s || '').match(/^(\d{2,3})\.(\d{2})\.(\d{2})$/);
|