mcp104 0.1.0__tar.gz
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.
- mcp104-0.1.0/LICENSE +21 -0
- mcp104-0.1.0/PKG-INFO +226 -0
- mcp104-0.1.0/README.md +171 -0
- mcp104-0.1.0/pyproject.toml +68 -0
- mcp104-0.1.0/setup.cfg +4 -0
- mcp104-0.1.0/src/mcp104/__init__.py +0 -0
- mcp104-0.1.0/src/mcp104/assets/104-categories/Abroad.json +1 -0
- mcp104-0.1.0/src/mcp104/assets/104-categories/Area.json +1 -0
- mcp104-0.1.0/src/mcp104/assets/104-categories/AreaWork.json +1 -0
- mcp104-0.1.0/src/mcp104/assets/104-categories/Indust.json +1 -0
- mcp104-0.1.0/src/mcp104/assets/104-categories/JobCat.json +1 -0
- mcp104-0.1.0/src/mcp104/assets/104-categories/Major.json +1 -0
- mcp104-0.1.0/src/mcp104/assets/104-categories/README.md +84 -0
- mcp104-0.1.0/src/mcp104/assets/104-categories/Skill.json +1 -0
- mcp104-0.1.0/src/mcp104/assets/104-categories/Tool.json +1 -0
- mcp104-0.1.0/src/mcp104/assets/certification/README.md +45 -0
- mcp104-0.1.0/src/mcp104/assets/certification/certify_conditions_results.json +552 -0
- mcp104-0.1.0/src/mcp104/browser/__init__.py +0 -0
- mcp104-0.1.0/src/mcp104/browser/api_client.py +914 -0
- mcp104-0.1.0/src/mcp104/browser/cdp_stream.py +548 -0
- mcp104-0.1.0/src/mcp104/browser/fingerprint.py +28 -0
- mcp104-0.1.0/src/mcp104/browser/session.py +176 -0
- mcp104-0.1.0/src/mcp104/browser/stealth.py +182 -0
- mcp104-0.1.0/src/mcp104/browser/throttle.py +669 -0
- mcp104-0.1.0/src/mcp104/config.py +179 -0
- mcp104-0.1.0/src/mcp104/db/__init__.py +0 -0
- mcp104-0.1.0/src/mcp104/db/database.py +287 -0
- mcp104-0.1.0/src/mcp104/main.py +286 -0
- mcp104-0.1.0/src/mcp104/tools/__init__.py +0 -0
- mcp104-0.1.0/src/mcp104/tools/auth.py +823 -0
- mcp104-0.1.0/src/mcp104/tools/categories.py +624 -0
- mcp104-0.1.0/src/mcp104/tools/discovery.py +753 -0
- mcp104-0.1.0/src/mcp104/tools/drop_detection.py +307 -0
- mcp104-0.1.0/src/mcp104/tools/filters.py +1254 -0
- mcp104-0.1.0/src/mcp104/tools/helpers.py +780 -0
- mcp104-0.1.0/src/mcp104/tools/messaging.py +986 -0
- mcp104-0.1.0/src/mcp104/tools/search.py +867 -0
- mcp104-0.1.0/src/mcp104/tools/status.py +60 -0
- mcp104-0.1.0/src/mcp104/web/__init__.py +0 -0
- mcp104-0.1.0/src/mcp104/web/auth_server.py +362 -0
- mcp104-0.1.0/src/mcp104.egg-info/PKG-INFO +226 -0
- mcp104-0.1.0/src/mcp104.egg-info/SOURCES.txt +67 -0
- mcp104-0.1.0/src/mcp104.egg-info/dependency_links.txt +1 -0
- mcp104-0.1.0/src/mcp104.egg-info/entry_points.txt +2 -0
- mcp104-0.1.0/src/mcp104.egg-info/requires.txt +11 -0
- mcp104-0.1.0/src/mcp104.egg-info/top_level.txt +1 -0
- mcp104-0.1.0/tests/test_api_client.py +1027 -0
- mcp104-0.1.0/tests/test_auth.py +181 -0
- mcp104-0.1.0/tests/test_auth_server.py +512 -0
- mcp104-0.1.0/tests/test_auth_tools.py +2352 -0
- mcp104-0.1.0/tests/test_categories.py +939 -0
- mcp104-0.1.0/tests/test_cdp_stream.py +896 -0
- mcp104-0.1.0/tests/test_config.py +224 -0
- mcp104-0.1.0/tests/test_contract_docs.py +590 -0
- mcp104-0.1.0/tests/test_database.py +490 -0
- mcp104-0.1.0/tests/test_discovery.py +827 -0
- mcp104-0.1.0/tests/test_filters.py +785 -0
- mcp104-0.1.0/tests/test_guard_endpoints.py +336 -0
- mcp104-0.1.0/tests/test_helpers.py +513 -0
- mcp104-0.1.0/tests/test_ignore_files.py +118 -0
- mcp104-0.1.0/tests/test_login_ux.py +482 -0
- mcp104-0.1.0/tests/test_main.py +742 -0
- mcp104-0.1.0/tests/test_messaging.py +2028 -0
- mcp104-0.1.0/tests/test_packaging.py +236 -0
- mcp104-0.1.0/tests/test_search.py +1452 -0
- mcp104-0.1.0/tests/test_session.py +83 -0
- mcp104-0.1.0/tests/test_session_login_state.py +221 -0
- mcp104-0.1.0/tests/test_stealth.py +208 -0
- mcp104-0.1.0/tests/test_throttle.py +900 -0
mcp104-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jason Chueh
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
mcp104-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mcp104
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server that lets an AI agent operate a 104人力銀行 enterprise recruiting account — résumé search, job listings, messaging and 詢問意願 events, with a device-flow login that keeps credentials out of the LLM
|
|
5
|
+
Author-email: Jason Chueh <jasoncychueh@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Jason Chueh
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/jasoncychueh/104mcp
|
|
29
|
+
Project-URL: Repository, https://github.com/jasoncychueh/104mcp.git
|
|
30
|
+
Project-URL: Issues, https://github.com/jasoncychueh/104mcp/issues
|
|
31
|
+
Keywords: 104,mcp,model-context-protocol,recruiting,playwright,claude
|
|
32
|
+
Classifier: Development Status :: 3 - Alpha
|
|
33
|
+
Classifier: Intended Audience :: Developers
|
|
34
|
+
Classifier: Programming Language :: Python :: 3
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
39
|
+
Classifier: Operating System :: OS Independent
|
|
40
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
41
|
+
Requires-Python: >=3.10
|
|
42
|
+
Description-Content-Type: text/markdown
|
|
43
|
+
License-File: LICENSE
|
|
44
|
+
Requires-Dist: mcp[cli]<2,>=1.12
|
|
45
|
+
Requires-Dist: patchright>=1.0.0
|
|
46
|
+
Requires-Dist: aiosqlite>=0.20.0
|
|
47
|
+
Requires-Dist: aiohttp>=3.9.0
|
|
48
|
+
Requires-Dist: tzdata>=2024.1
|
|
49
|
+
Provides-Extra: dev
|
|
50
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
51
|
+
Requires-Dist: pytest-asyncio>=0.24.0; extra == "dev"
|
|
52
|
+
Requires-Dist: ruff>=0.14; extra == "dev"
|
|
53
|
+
Requires-Dist: pyflakes>=3.2; extra == "dev"
|
|
54
|
+
Dynamic: license-file
|
|
55
|
+
|
|
56
|
+
# 104-mcp
|
|
57
|
+
|
|
58
|
+
[](https://pypi.org/project/mcp104/)
|
|
59
|
+
[](https://pypi.org/project/mcp104/)
|
|
60
|
+
[](LICENSE)
|
|
61
|
+
[](https://github.com/jasoncychueh/104mcp)
|
|
62
|
+
|
|
63
|
+
讓 AI Agent(Claude Code 或任何 MCP client)操作 **104 人力銀行企業徵才帳號**
|
|
64
|
+
的 MCP server:搜尋履歷、列出職缺、讀取與發送站內信、送出「詢問意願」邀約、
|
|
65
|
+
記錄候選人聯繫狀態。
|
|
66
|
+
|
|
67
|
+
帳號密碼**不會經過 AI 的對話內容**。登入時 Agent 只拿到一個網址,由你本人在
|
|
68
|
+
一個只綁定本機(`127.0.0.1`)的頁面裡完成登入,包含 104 每次都會要求的手機
|
|
69
|
+
驗證碼(MFA)。登入之外的所有操作都直接呼叫 104 的 JSON API,不需要開瀏覽器。
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 安裝
|
|
74
|
+
|
|
75
|
+
只要三步,照著做即可。以 Claude Code 為例,其他 MCP client 的設定檔格式不同,
|
|
76
|
+
但欄位相同。
|
|
77
|
+
|
|
78
|
+
1. 安裝 [uv](https://docs.astral.sh/uv/)。
|
|
79
|
+
|
|
80
|
+
Windows(PowerShell):
|
|
81
|
+
|
|
82
|
+
```powershell
|
|
83
|
+
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
macOS/Linux:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
2. 在專案根目錄的 `.mcp.json` 加入:
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"mcpServers": {
|
|
97
|
+
"104-mcp": {
|
|
98
|
+
"command": "uvx",
|
|
99
|
+
"args": ["--from", "git+https://github.com/jasoncychueh/104mcp.git", "mcp104"],
|
|
100
|
+
"env": {
|
|
101
|
+
"MCP104_ACCOUNT": "<你的 104 帳號識別,例如公司信箱或帳號名>"
|
|
102
|
+
},
|
|
103
|
+
"timeout": 120000
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
`MCP104_ACCOUNT` 是必填的,用來分開不同 104 帳號各自的資料(候選人狀態、
|
|
110
|
+
每日發送計數)。`timeout` 是單一工具呼叫的上限(毫秒),120 秒是本專案建議
|
|
111
|
+
的值,請照抄。
|
|
112
|
+
|
|
113
|
+
套件發布到 PyPI 之後,`args` 可以簡化成 `["mcp104"]`。
|
|
114
|
+
|
|
115
|
+
3. 啟動 Claude Code,請 Agent 呼叫 `login()`,在跳出的瀏覽器視窗完成 104 登入。
|
|
116
|
+
第一次登入會自動下載一份專用的 Chromium(約 300 MB),不需要自己安裝任何東西。
|
|
117
|
+
|
|
118
|
+
### 常見狀況
|
|
119
|
+
|
|
120
|
+
- **第一次連線逾時**:Claude Code 給 MCP server 30 秒啟動時間,`uvx` 第一次要
|
|
121
|
+
下載並建置套件,可能超過 30 秒。用 `/mcp` 重新連線一次即可,之後約 1 秒就能啟動。
|
|
122
|
+
- **更新到新版**:`uvx` 會用快取,不會自動抓新版。跑一次
|
|
123
|
+
`uvx --refresh --from git+https://github.com/jasoncychueh/104mcp.git mcp104`(PyPI 版是 `uvx --refresh mcp104`)。
|
|
124
|
+
- **換帳號**:`MCP104_ACCOUNT` 綁定在資料目錄上,同一個目錄只能有一個值。要用第二個
|
|
125
|
+
104 帳號,請另外設 `MCP104_DATA_DIR` 指向一個新目錄。
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 登入流程
|
|
130
|
+
|
|
131
|
+
104 的登入每次都會觸發手機驗證碼(因為每次都是全新的瀏覽器),所以沒有辦法
|
|
132
|
+
自動登入,一定要你本人操作一次。流程如下:
|
|
133
|
+
|
|
134
|
+
1. Agent 呼叫 `login()`。伺服器會用你的預設瀏覽器打開登入頁(同一台機器時),
|
|
135
|
+
Agent 也會告訴你網址。
|
|
136
|
+
2. 你在那個頁面裡輸入帳密、手機驗證碼。畫面是即時串流的 104 登入頁,滑鼠鍵盤
|
|
137
|
+
都照常用。
|
|
138
|
+
3. 有兩個地方需要你手動點一下,Agent 看不出差別:
|
|
139
|
+
- **產品選擇頁**:帳號底下有多個 104 產品時,請點「招募管理」。
|
|
140
|
+
- **「此帳號已登入」對話框**:同一帳號已在別處登入時,請選「將目前帳號登出,
|
|
141
|
+
立即登入」。
|
|
142
|
+
4. 登入完成後頁面會顯示「登入已完成」並嘗試自動關閉(瀏覽器不允許的話請自行關掉)。
|
|
143
|
+
Agent 會自己等到這一刻,不需要你回頭告訴它「登入了」。
|
|
144
|
+
|
|
145
|
+
完整走完一次(含驗證碼與上面兩個分支)實測約 4–5 分鐘。登入憑證會存在本機資料
|
|
146
|
+
目錄,之後重開 Claude Code 不需要再登入,直到 104 那邊的登入過期為止。
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## 工具一覽
|
|
151
|
+
|
|
152
|
+
完整參數與回傳格式請看各工具自己的說明;這裡只列一句話用途。
|
|
153
|
+
|
|
154
|
+
**登入**
|
|
155
|
+
- `login()` — 開始一次登入,或在憑證仍有效時直接回報已登入
|
|
156
|
+
- `check_login(token, wait_seconds)` — 等待一次登入完成(Agent 用,一般不需自己呼叫)
|
|
157
|
+
- `logout()` — 清除本機登入憑證
|
|
158
|
+
|
|
159
|
+
**履歷與職缺**
|
|
160
|
+
- `search_resumes(keyword, filters, page)` — 依關鍵字與篩選條件搜尋履歷
|
|
161
|
+
- `list_recommended_resumes(jobno, page)` — 列出 104 推薦給某職缺的履歷
|
|
162
|
+
- `list_matched_resumes(jobno, page, update_date_type)` — 列出配對到某職缺的履歷;`update_date_type="2"` 只看當日配對
|
|
163
|
+
- `get_resume_detail(candidate_id)` — 取得單一候選人的完整履歷
|
|
164
|
+
- `list_jobs(page)` — 列出這個帳號底下的職缺
|
|
165
|
+
|
|
166
|
+
**篩選與欄位說明(純本機資料,不呼叫 104)**
|
|
167
|
+
- `browse_filter_values(key, code)` — 查 `search_resumes` 某個篩選鍵接受哪些值
|
|
168
|
+
- `describe_result_fields(row_type)` — 說明各工具回傳的每個欄位是什麼意思
|
|
169
|
+
|
|
170
|
+
**訊息**
|
|
171
|
+
- `read_messages(page, job_nos, candidate_name)` — 讀取收件匣
|
|
172
|
+
- `get_conversation(job_id, candidate_id, page)` — 讀取一段對話
|
|
173
|
+
- `send_message(job_id, candidate_id, message)` — 發送一則純文字站內信
|
|
174
|
+
- `send_inquiry(job_id, candidate_id, message, template_id)` — 送出「詢問意願」邀約
|
|
175
|
+
- `list_templates(type_id, page)` — 列出帳號裡存好的罐頭信範本
|
|
176
|
+
|
|
177
|
+
**候選人狀態(存在本機,與 104 無關)**
|
|
178
|
+
- `check_already_contacted(candidate_id, id_source)` — 查是否已聯繫過
|
|
179
|
+
- `update_candidate_status(candidate_id, id_source, status)` — 更新狀態標記
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## 環境變數
|
|
184
|
+
|
|
185
|
+
| 變數 | 必填/預設 | 說明 |
|
|
186
|
+
|---|---|---|
|
|
187
|
+
| `MCP104_ACCOUNT` | **必填** | 識別這次執行對應哪一個 104 帳號。不要填主機名或作業系統帳號 |
|
|
188
|
+
| `MCP104_DATA_DIR` | 選填,預設依平台慣例放在使用者目錄下 | 資料庫、登入憑證、節流狀態都存在這裡 |
|
|
189
|
+
| `MCP104_AUTH_BASE_URL` | 選填,須與 `MCP104_AUTH_BIND_PORT` 成對設定 | 登入頁的對外網址,你和伺服器不在同一台機器時才需要 |
|
|
190
|
+
| `MCP104_AUTH_BIND_PORT` | 選填,須與 `MCP104_AUTH_BASE_URL` 成對設定 | 登入頁監聽的埠 |
|
|
191
|
+
| `MAX_DAILY_MESSAGES` | `50` | 每個帳號每天最多發幾則訊息(`send_message` 與 `send_inquiry` 合計) |
|
|
192
|
+
| `LOGIN_TIMEOUT_SECONDS` | `900` | 等你完成登入的上限秒數 |
|
|
193
|
+
| `MAX_REQUESTS_PER_HOUR` | `300` | 每小時對 104 的請求上限 |
|
|
194
|
+
| `MAX_INLINE_WAIT_SECONDS` | `20` | 節流等待超過這個秒數就改回覆「稍後再試」 |
|
|
195
|
+
| `ACTIVITY_STREAK_LIMIT_MINUTES` | `20` | 連續操作多久後強制休息 |
|
|
196
|
+
| `REST_DURATION_MINUTES` | `3` | 強制休息的長度 |
|
|
197
|
+
| `MIN_CALL_INTERVAL_SECONDS` | `5` | 兩次呼叫之間的最小間隔 |
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## 安全與節流
|
|
202
|
+
|
|
203
|
+
- **每一次發送都會真的送到一位求職者手上**,無法撤回、沒有試發模式。請要求 Agent
|
|
204
|
+
先把收件人與完整內文給你看過再發。
|
|
205
|
+
- **每日發送上限 50 則**,`send_message` 與 `send_inquiry` 共用計數。
|
|
206
|
+
- **請求節流**:兩次呼叫至少間隔 5 秒、每小時最多 300 次、連續操作 20 分鐘後休息
|
|
207
|
+
3 分鐘,模擬真人節奏,降低被 104 判定為機器人的風險。
|
|
208
|
+
- **104 自己的履歷瀏覽上限**:每天 300 份,由 104 執行;接近上限時工具會提醒。
|
|
209
|
+
- **遇到 Cloudflare 機器人驗證**:工具會回傳明確錯誤並要求暫停至少 1 小時。這不是
|
|
210
|
+
「查無資料」,換關鍵字重試只會讓封鎖更嚴重。
|
|
211
|
+
- **不送已讀回報**:Agent 讀訊息不會讓對方看到「已讀」,這是刻意的。
|
|
212
|
+
- **登入憑證存在本機資料目錄**,請不要把那個目錄下的檔案交給任何人或提交進版本控制。
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## 免責聲明
|
|
217
|
+
|
|
218
|
+
這是非官方專案,與 104 人力銀行沒有任何關係,未經其授權或背書。請只在你有權操作的
|
|
219
|
+
帳號上使用,並遵守 104 的服務條款;透過本工具送出的每一則訊息、每一次邀約,後果由
|
|
220
|
+
操作者自行負責。
|
|
221
|
+
|
|
222
|
+
回報問題請到 [GitHub Issues](https://github.com/jasoncychueh/104mcp/issues)。
|
|
223
|
+
|
|
224
|
+
## 授權
|
|
225
|
+
|
|
226
|
+
MIT,見 [LICENSE](LICENSE)。
|
mcp104-0.1.0/README.md
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# 104-mcp
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/mcp104/)
|
|
4
|
+
[](https://pypi.org/project/mcp104/)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://github.com/jasoncychueh/104mcp)
|
|
7
|
+
|
|
8
|
+
讓 AI Agent(Claude Code 或任何 MCP client)操作 **104 人力銀行企業徵才帳號**
|
|
9
|
+
的 MCP server:搜尋履歷、列出職缺、讀取與發送站內信、送出「詢問意願」邀約、
|
|
10
|
+
記錄候選人聯繫狀態。
|
|
11
|
+
|
|
12
|
+
帳號密碼**不會經過 AI 的對話內容**。登入時 Agent 只拿到一個網址,由你本人在
|
|
13
|
+
一個只綁定本機(`127.0.0.1`)的頁面裡完成登入,包含 104 每次都會要求的手機
|
|
14
|
+
驗證碼(MFA)。登入之外的所有操作都直接呼叫 104 的 JSON API,不需要開瀏覽器。
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 安裝
|
|
19
|
+
|
|
20
|
+
只要三步,照著做即可。以 Claude Code 為例,其他 MCP client 的設定檔格式不同,
|
|
21
|
+
但欄位相同。
|
|
22
|
+
|
|
23
|
+
1. 安裝 [uv](https://docs.astral.sh/uv/)。
|
|
24
|
+
|
|
25
|
+
Windows(PowerShell):
|
|
26
|
+
|
|
27
|
+
```powershell
|
|
28
|
+
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
macOS/Linux:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
2. 在專案根目錄的 `.mcp.json` 加入:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"mcpServers": {
|
|
42
|
+
"104-mcp": {
|
|
43
|
+
"command": "uvx",
|
|
44
|
+
"args": ["--from", "git+https://github.com/jasoncychueh/104mcp.git", "mcp104"],
|
|
45
|
+
"env": {
|
|
46
|
+
"MCP104_ACCOUNT": "<你的 104 帳號識別,例如公司信箱或帳號名>"
|
|
47
|
+
},
|
|
48
|
+
"timeout": 120000
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`MCP104_ACCOUNT` 是必填的,用來分開不同 104 帳號各自的資料(候選人狀態、
|
|
55
|
+
每日發送計數)。`timeout` 是單一工具呼叫的上限(毫秒),120 秒是本專案建議
|
|
56
|
+
的值,請照抄。
|
|
57
|
+
|
|
58
|
+
套件發布到 PyPI 之後,`args` 可以簡化成 `["mcp104"]`。
|
|
59
|
+
|
|
60
|
+
3. 啟動 Claude Code,請 Agent 呼叫 `login()`,在跳出的瀏覽器視窗完成 104 登入。
|
|
61
|
+
第一次登入會自動下載一份專用的 Chromium(約 300 MB),不需要自己安裝任何東西。
|
|
62
|
+
|
|
63
|
+
### 常見狀況
|
|
64
|
+
|
|
65
|
+
- **第一次連線逾時**:Claude Code 給 MCP server 30 秒啟動時間,`uvx` 第一次要
|
|
66
|
+
下載並建置套件,可能超過 30 秒。用 `/mcp` 重新連線一次即可,之後約 1 秒就能啟動。
|
|
67
|
+
- **更新到新版**:`uvx` 會用快取,不會自動抓新版。跑一次
|
|
68
|
+
`uvx --refresh --from git+https://github.com/jasoncychueh/104mcp.git mcp104`(PyPI 版是 `uvx --refresh mcp104`)。
|
|
69
|
+
- **換帳號**:`MCP104_ACCOUNT` 綁定在資料目錄上,同一個目錄只能有一個值。要用第二個
|
|
70
|
+
104 帳號,請另外設 `MCP104_DATA_DIR` 指向一個新目錄。
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 登入流程
|
|
75
|
+
|
|
76
|
+
104 的登入每次都會觸發手機驗證碼(因為每次都是全新的瀏覽器),所以沒有辦法
|
|
77
|
+
自動登入,一定要你本人操作一次。流程如下:
|
|
78
|
+
|
|
79
|
+
1. Agent 呼叫 `login()`。伺服器會用你的預設瀏覽器打開登入頁(同一台機器時),
|
|
80
|
+
Agent 也會告訴你網址。
|
|
81
|
+
2. 你在那個頁面裡輸入帳密、手機驗證碼。畫面是即時串流的 104 登入頁,滑鼠鍵盤
|
|
82
|
+
都照常用。
|
|
83
|
+
3. 有兩個地方需要你手動點一下,Agent 看不出差別:
|
|
84
|
+
- **產品選擇頁**:帳號底下有多個 104 產品時,請點「招募管理」。
|
|
85
|
+
- **「此帳號已登入」對話框**:同一帳號已在別處登入時,請選「將目前帳號登出,
|
|
86
|
+
立即登入」。
|
|
87
|
+
4. 登入完成後頁面會顯示「登入已完成」並嘗試自動關閉(瀏覽器不允許的話請自行關掉)。
|
|
88
|
+
Agent 會自己等到這一刻,不需要你回頭告訴它「登入了」。
|
|
89
|
+
|
|
90
|
+
完整走完一次(含驗證碼與上面兩個分支)實測約 4–5 分鐘。登入憑證會存在本機資料
|
|
91
|
+
目錄,之後重開 Claude Code 不需要再登入,直到 104 那邊的登入過期為止。
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 工具一覽
|
|
96
|
+
|
|
97
|
+
完整參數與回傳格式請看各工具自己的說明;這裡只列一句話用途。
|
|
98
|
+
|
|
99
|
+
**登入**
|
|
100
|
+
- `login()` — 開始一次登入,或在憑證仍有效時直接回報已登入
|
|
101
|
+
- `check_login(token, wait_seconds)` — 等待一次登入完成(Agent 用,一般不需自己呼叫)
|
|
102
|
+
- `logout()` — 清除本機登入憑證
|
|
103
|
+
|
|
104
|
+
**履歷與職缺**
|
|
105
|
+
- `search_resumes(keyword, filters, page)` — 依關鍵字與篩選條件搜尋履歷
|
|
106
|
+
- `list_recommended_resumes(jobno, page)` — 列出 104 推薦給某職缺的履歷
|
|
107
|
+
- `list_matched_resumes(jobno, page, update_date_type)` — 列出配對到某職缺的履歷;`update_date_type="2"` 只看當日配對
|
|
108
|
+
- `get_resume_detail(candidate_id)` — 取得單一候選人的完整履歷
|
|
109
|
+
- `list_jobs(page)` — 列出這個帳號底下的職缺
|
|
110
|
+
|
|
111
|
+
**篩選與欄位說明(純本機資料,不呼叫 104)**
|
|
112
|
+
- `browse_filter_values(key, code)` — 查 `search_resumes` 某個篩選鍵接受哪些值
|
|
113
|
+
- `describe_result_fields(row_type)` — 說明各工具回傳的每個欄位是什麼意思
|
|
114
|
+
|
|
115
|
+
**訊息**
|
|
116
|
+
- `read_messages(page, job_nos, candidate_name)` — 讀取收件匣
|
|
117
|
+
- `get_conversation(job_id, candidate_id, page)` — 讀取一段對話
|
|
118
|
+
- `send_message(job_id, candidate_id, message)` — 發送一則純文字站內信
|
|
119
|
+
- `send_inquiry(job_id, candidate_id, message, template_id)` — 送出「詢問意願」邀約
|
|
120
|
+
- `list_templates(type_id, page)` — 列出帳號裡存好的罐頭信範本
|
|
121
|
+
|
|
122
|
+
**候選人狀態(存在本機,與 104 無關)**
|
|
123
|
+
- `check_already_contacted(candidate_id, id_source)` — 查是否已聯繫過
|
|
124
|
+
- `update_candidate_status(candidate_id, id_source, status)` — 更新狀態標記
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## 環境變數
|
|
129
|
+
|
|
130
|
+
| 變數 | 必填/預設 | 說明 |
|
|
131
|
+
|---|---|---|
|
|
132
|
+
| `MCP104_ACCOUNT` | **必填** | 識別這次執行對應哪一個 104 帳號。不要填主機名或作業系統帳號 |
|
|
133
|
+
| `MCP104_DATA_DIR` | 選填,預設依平台慣例放在使用者目錄下 | 資料庫、登入憑證、節流狀態都存在這裡 |
|
|
134
|
+
| `MCP104_AUTH_BASE_URL` | 選填,須與 `MCP104_AUTH_BIND_PORT` 成對設定 | 登入頁的對外網址,你和伺服器不在同一台機器時才需要 |
|
|
135
|
+
| `MCP104_AUTH_BIND_PORT` | 選填,須與 `MCP104_AUTH_BASE_URL` 成對設定 | 登入頁監聽的埠 |
|
|
136
|
+
| `MAX_DAILY_MESSAGES` | `50` | 每個帳號每天最多發幾則訊息(`send_message` 與 `send_inquiry` 合計) |
|
|
137
|
+
| `LOGIN_TIMEOUT_SECONDS` | `900` | 等你完成登入的上限秒數 |
|
|
138
|
+
| `MAX_REQUESTS_PER_HOUR` | `300` | 每小時對 104 的請求上限 |
|
|
139
|
+
| `MAX_INLINE_WAIT_SECONDS` | `20` | 節流等待超過這個秒數就改回覆「稍後再試」 |
|
|
140
|
+
| `ACTIVITY_STREAK_LIMIT_MINUTES` | `20` | 連續操作多久後強制休息 |
|
|
141
|
+
| `REST_DURATION_MINUTES` | `3` | 強制休息的長度 |
|
|
142
|
+
| `MIN_CALL_INTERVAL_SECONDS` | `5` | 兩次呼叫之間的最小間隔 |
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## 安全與節流
|
|
147
|
+
|
|
148
|
+
- **每一次發送都會真的送到一位求職者手上**,無法撤回、沒有試發模式。請要求 Agent
|
|
149
|
+
先把收件人與完整內文給你看過再發。
|
|
150
|
+
- **每日發送上限 50 則**,`send_message` 與 `send_inquiry` 共用計數。
|
|
151
|
+
- **請求節流**:兩次呼叫至少間隔 5 秒、每小時最多 300 次、連續操作 20 分鐘後休息
|
|
152
|
+
3 分鐘,模擬真人節奏,降低被 104 判定為機器人的風險。
|
|
153
|
+
- **104 自己的履歷瀏覽上限**:每天 300 份,由 104 執行;接近上限時工具會提醒。
|
|
154
|
+
- **遇到 Cloudflare 機器人驗證**:工具會回傳明確錯誤並要求暫停至少 1 小時。這不是
|
|
155
|
+
「查無資料」,換關鍵字重試只會讓封鎖更嚴重。
|
|
156
|
+
- **不送已讀回報**:Agent 讀訊息不會讓對方看到「已讀」,這是刻意的。
|
|
157
|
+
- **登入憑證存在本機資料目錄**,請不要把那個目錄下的檔案交給任何人或提交進版本控制。
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## 免責聲明
|
|
162
|
+
|
|
163
|
+
這是非官方專案,與 104 人力銀行沒有任何關係,未經其授權或背書。請只在你有權操作的
|
|
164
|
+
帳號上使用,並遵守 104 的服務條款;透過本工具送出的每一則訊息、每一次邀約,後果由
|
|
165
|
+
操作者自行負責。
|
|
166
|
+
|
|
167
|
+
回報問題請到 [GitHub Issues](https://github.com/jasoncychueh/104mcp/issues)。
|
|
168
|
+
|
|
169
|
+
## 授權
|
|
170
|
+
|
|
171
|
+
MIT,見 [LICENSE](LICENSE)。
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"] # no upper bound: a bad backend fails the build loudly
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "mcp104"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "MCP server that lets an AI agent operate a 104人力銀行 enterprise recruiting account — résumé search, job listings, messaging and 詢問意願 events, with a device-flow login that keeps credentials out of the LLM"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {file = "LICENSE"} # PEP 639 string form (`license = "MIT"`) needs
|
|
11
|
+
# setuptools>=69.3 for SPDX-expression support;
|
|
12
|
+
# build-system below pins setuptools>=68 with no
|
|
13
|
+
# upper bound, so an older resolved setuptools could
|
|
14
|
+
# fail on the string form. The file form is valid
|
|
15
|
+
# under both old (PEP 621 table) and current
|
|
16
|
+
# setuptools, so it's the safe choice here.
|
|
17
|
+
authors = [{name = "Jason Chueh", email = "jasoncychueh@gmail.com"}]
|
|
18
|
+
keywords = ["104", "mcp", "model-context-protocol", "recruiting", "playwright", "claude"]
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Development Status :: 3 - Alpha",
|
|
21
|
+
"Intended Audience :: Developers",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Programming Language :: Python :: 3.13",
|
|
27
|
+
"Operating System :: OS Independent",
|
|
28
|
+
"Topic :: Software Development :: Libraries",
|
|
29
|
+
]
|
|
30
|
+
requires-python = ">=3.10" # Floor is undecided, not measured against any
|
|
31
|
+
# runtime this project still targets: the container
|
|
32
|
+
# that used to explain this value (Python 3.10.12 on
|
|
33
|
+
# mcr.microsoft.com/playwright/python:v1.44.0-jammy)
|
|
34
|
+
# is gone (stdio rearchitecture); the dev machine
|
|
35
|
+
# measures 3.13.5. Whether to support 3.10 is a
|
|
36
|
+
# separate, undecided call — see backlog e5b3a2 — this
|
|
37
|
+
# value is carried forward unchanged, not re-validated.
|
|
38
|
+
dependencies = [
|
|
39
|
+
"mcp[cli]>=1.12,<2", # <2 is load-bearing: 2.0 moves mcp.server.fastmcp
|
|
40
|
+
"patchright>=1.0.0", # and renames FastMCP; unpinned fails at import
|
|
41
|
+
"aiosqlite>=0.20.0",
|
|
42
|
+
"aiohttp>=3.9.0",
|
|
43
|
+
"tzdata>=2024.1",
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
[project.optional-dependencies]
|
|
47
|
+
# The ruff / pyflakes floors below are conservative floors BELOW the versions actually
|
|
48
|
+
# measured on the dev machine (ruff 0.14.7, pyflakes 3.2.0) — not tested minima. Say so
|
|
49
|
+
# here rather than implying either was measured as a working lower bound.
|
|
50
|
+
dev = ["pytest>=8.0.0", "pytest-asyncio>=0.24.0", "ruff>=0.14", "pyflakes>=3.2"]
|
|
51
|
+
|
|
52
|
+
[project.urls]
|
|
53
|
+
Homepage = "https://github.com/jasoncychueh/104mcp"
|
|
54
|
+
Repository = "https://github.com/jasoncychueh/104mcp.git"
|
|
55
|
+
Issues = "https://github.com/jasoncychueh/104mcp/issues"
|
|
56
|
+
|
|
57
|
+
[project.scripts]
|
|
58
|
+
mcp104 = "mcp104.main:run"
|
|
59
|
+
|
|
60
|
+
[tool.setuptools.packages.find]
|
|
61
|
+
where = ["src"]
|
|
62
|
+
|
|
63
|
+
[tool.setuptools.package-data]
|
|
64
|
+
mcp104 = ["assets/**/*.json", "assets/**/*.md"] # .md required: both READMEs are cited
|
|
65
|
+
# from module docstrings
|
|
66
|
+
|
|
67
|
+
[tool.ruff]
|
|
68
|
+
target-version = "py310"
|
mcp104-0.1.0/setup.cfg
ADDED
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[{"no":"7001000000","des":"亞洲","n":[{"no":"7001053000","des":"台灣","eng":"Taiwan"},{"no":"7001001000","des":"中國","eng":"China"},{"no":"7001002000","des":"香港/澳門特別行政區","eng":"Hong Kong/Macau SAR"},{"no":"7001003000","des":"日本","eng":"Japan"},{"no":"7001004000","des":"北韓","eng":"North Korea"},{"no":"7001005000","des":"南韓","eng":"South Korea"},{"no":"7001006000","des":"越南","eng":"Vietnam"},{"no":"7001007000","des":"寮國","eng":"Laos"},{"no":"7001008000","des":"柬埔寨","eng":"Cambodia"},{"no":"7001009000","des":"緬甸","eng":"Myanmar"},{"no":"7001010000","des":"泰國","eng":"Thailand"},{"no":"7001011000","des":"馬來西亞","eng":"Malaysia"},{"no":"7001012000","des":"新加坡","eng":"Singapore"},{"no":"7001013000","des":"菲律賓","eng":"Philippines"},{"no":"7001014000","des":"汶萊","eng":"Brunei"},{"no":"7001015000","des":"印尼","eng":"Indonesia"},{"no":"7001016000","des":"阿富汗","eng":"Afghanistan"},{"no":"7001017000","des":"巴林","eng":"Bahrain"},{"no":"7001018000","des":"伊朗","eng":"Iran"},{"no":"7001019000","des":"伊拉克","eng":"Iraq"},{"no":"7001020000","des":"以色列","eng":"Israel"},{"no":"7001021000","des":"約旦","eng":"Jordan"},{"no":"7001022000","des":"科威特","eng":"Kuwait"},{"no":"7001023000","des":"黎巴嫩","eng":"Lebanon"},{"no":"7001024000","des":"阿曼","eng":"Oman"},{"no":"7001025000","des":"卡達","eng":"Qatar"},{"no":"7001026000","des":"沙烏地阿拉伯","eng":"Saudi Arabia"},{"no":"7001027000","des":"敘利亞","eng":"Syria"},{"no":"7001028000","des":"土耳其","eng":"Turkey"},{"no":"7001029000","des":"阿拉伯大公國","eng":"United Arab Emirates"},{"no":"7001030000","des":"葉門","eng":"Yemen"},{"no":"7001031000","des":"孟加拉","eng":"Bangladesh"},{"no":"7001032000","des":"不丹","eng":"Bhutan"},{"no":"7001033000","des":"印度","eng":"India"},{"no":"7001034000","des":"馬爾地夫","eng":"Maldives"},{"no":"7001035000","des":"尼泊爾","eng":"Nepal"},{"no":"7001036000","des":"巴基斯坦","eng":"Pakistan"},{"no":"7001037000","des":"斯里蘭卡","eng":"Sri Lanka"},{"no":"7001038000","des":"蒙古","eng":"Mongolia"},{"no":"7001040000","des":"亞美尼亞","eng":"Armenia"},{"no":"7001041000","des":"亞塞拜然","eng":"Azerbaijan"},{"no":"7001044000","des":"喬治亞","eng":"Georgia"},{"no":"7001047000","des":"東帝汶","eng":"East Timor"},{"no":"7001048000","des":"哈薩克","eng":"Kazakhstan"},{"no":"7001049000","des":"吉爾吉斯","eng":"Kyrgyzstan"},{"no":"7001050000","des":"塔吉克","eng":"Tajikistan"},{"no":"7001051000","des":"土庫曼","eng":"Turkmenistan"},{"no":"7001052000","des":"烏茲別克","eng":"Uzbekistan"},{"no":"7001054000","des":"巴勒斯坦","eng":"Palestine"}],"eng":"Asia"},{"no":"7002000000","des":"大洋洲","n":[{"no":"7002001000","des":"澳洲","eng":"Australia"},{"no":"7002002000","des":"紐西蘭","eng":"New Zealand"},{"no":"7002003000","des":"巴布亞紐幾內亞","eng":"Papua New Guinea"},{"no":"7002004000","des":"庫克群島","eng":"Cook Islands"},{"no":"7002005000","des":"斐濟","eng":"Fiji"},{"no":"7002006000","des":"吉里巴斯","eng":"Kiribati"},{"no":"7002008000","des":"馬紹爾群島","eng":"Marshall Islands"},{"no":"7002009000","des":"密克羅尼西亞","eng":"Micronesia"},{"no":"7002010000","des":"諾魯","eng":"Nauru"},{"no":"7002011000","des":"紐埃","eng":"Niue"},{"no":"7002012000","des":"帛琉","eng":"Palau"},{"no":"7002013000","des":"薩摩亞","eng":"Samoa"},{"no":"7002014000","des":"索羅門群島","eng":"Solomon Islands"},{"no":"7002015000","des":"東加","eng":"Tonga"},{"no":"7002016000","des":"吐瓦魯","eng":"Tuvalu"},{"no":"7002017000","des":"萬那杜","eng":"Vanuatu"}],"eng":"Oceania"},{"no":"7003000000","des":"美洲","n":[{"no":"7003001000","des":"加拿大","eng":"Canada"},{"no":"7003002000","des":"美國","eng":"United States"},{"no":"7003003000","des":"貝里斯","eng":"Belize"},{"no":"7003004000","des":"哥斯大黎加","eng":"Costa Rica"},{"no":"7003005000","des":"薩爾瓦多","eng":"El Salvador"},{"no":"7003006000","des":"瓜地馬拉","eng":"Guatemala"},{"no":"7003007000","des":"宏都拉斯","eng":"Honduras"},{"no":"7003008000","des":"尼加拉瓜","eng":"Nicaragua"},{"no":"7003009000","des":"巴拿馬","eng":"Panama"},{"no":"7003010000","des":"烏拉圭","eng":"Uruguay"},{"no":"7003011000","des":"厄瓜多","eng":"Ecuador"},{"no":"7003012000","des":"哥倫比亞","eng":"Colombia"},{"no":"7003013000","des":"巴拉圭","eng":"Paraguay"},{"no":"7003014000","des":"巴西","eng":"Brazil"},{"no":"7003015000","des":"智利","eng":"Chile"},{"no":"7003016000","des":"玻利維亞","eng":"Bolivia"},{"no":"7003017000","des":"秘魯","eng":"Peru"},{"no":"7003018000","des":"蘇利南","eng":"Suriname"},{"no":"7003019000","des":"阿根廷","eng":"Argentina"},{"no":"7003021000","des":"墨西哥","eng":"Mexico"},{"no":"7003020000","des":"多明尼加","eng":"Dominican Republic"},{"no":"7003022000","des":"委內瑞拉","eng":"Venezuela"},{"no":"7003023000","des":"古巴","eng":"Cuba"},{"no":"7003024000","des":"牙買加","eng":"Jamaica"},{"no":"7003025000","des":"蓋亞那合作共和國","eng":"Cooperative Republic of Guyana"},{"no":"7003026000","des":"聖克里斯多福及尼維斯","eng":"Saint Kitts and Nevis"},{"no":"7003027000","des":"波多黎各自由邦","eng":"Commonwealth of Puerto Rico"},{"no":"7003028000","des":"多米尼克","eng":"Commonwealth of Dominica"},{"no":"7003029000","des":"巴哈馬","eng":"Commonwealth of The Bahamas"},{"no":"7003030000","des":"巴貝多","eng":"Barbados"},{"no":"7003031000","des":"千里達及托巴哥共和國","eng":"Republic of Trinidad and Tobago"},{"no":"7003032000","des":"阿魯巴","eng":"Aruba"},{"no":"7003033000","des":"海地共和國","eng":"Republic of Haiti"},{"no":"7003034000","des":"安地卡及巴布達","eng":"Antigua and Barbuda"},{"no":"7003035000","des":"聖露西亞","eng":"Saint Lucia"}],"eng":"Americas"},{"no":"7004000000","des":"歐洲","n":[{"no":"7004001000","des":"挪威","eng":"Norway"},{"no":"7004002000","des":"瑞典","eng":"Sweden"},{"no":"7004003000","des":"芬蘭","eng":"Finland"},{"no":"7004004000","des":"丹麥","eng":"Denmark"},{"no":"7004005000","des":"冰島","eng":"Iceland"},{"no":"7004006000","des":"阿爾巴尼亞","eng":"Albania"},{"no":"7004007000","des":"安道爾","eng":"Andorra"},{"no":"7004008000","des":"波士尼亞赫塞哥維納","eng":"Bosnia and Herzegovina"},{"no":"7004009000","des":"保加利亞","eng":"Bulgaria"},{"no":"7004010000","des":"克羅埃西亞","eng":"Croatia"},{"no":"7004011000","des":"賽普勒斯","eng":"Cyprus"},{"no":"7004012000","des":"希臘","eng":"Greece"},{"no":"7004013000","des":"義大利","eng":"Italy"},{"no":"7004014000","des":"馬其頓","eng":"North Macedonia"},{"no":"7004015000","des":"馬爾他","eng":"Malta"},{"no":"7004016000","des":"葡萄牙","eng":"Portugal"},{"no":"7004017000","des":"羅馬尼亞","eng":"Romania"},{"no":"7004018000","des":"聖馬利諾","eng":"San Marino"},{"no":"7004019000","des":"塞爾維亞和黑山","eng":"Serbia and Montenegro"},{"no":"7004020000","des":"斯洛維尼亞","eng":"Slovenia"},{"no":"7004021000","des":"西班牙","eng":"Spain"},{"no":"7004022000","des":"白俄羅斯","eng":"Belarus"},{"no":"7004023000","des":"愛沙尼亞","eng":"Estonia"},{"no":"7004024000","des":"拉脫維亞","eng":"Latvia"},{"no":"7004025000","des":"立陶宛","eng":"Lithuania"},{"no":"7004026000","des":"摩爾多瓦","eng":"Moldova"},{"no":"7004027000","des":"俄羅斯","eng":"Russia"},{"no":"7004028000","des":"烏克蘭","eng":"Ukraine"},{"no":"7004029000","des":"比利時","eng":"Belgium"},{"no":"7004030000","des":"法國","eng":"France"},{"no":"7004031000","des":"愛爾蘭","eng":"Ireland"},{"no":"7004032000","des":"盧森堡","eng":"Luxembourg"},{"no":"7004033000","des":"摩納哥","eng":"Monaco"},{"no":"7004034000","des":"荷蘭","eng":"Netherlands"},{"no":"7004035000","des":"英國","eng":"United Kingdom"},{"no":"7004036000","des":"奧地利","eng":"Austria"},{"no":"7004037000","des":"捷克","eng":"Czech Republic"},{"no":"7004038000","des":"德國","eng":"Germany"},{"no":"7004039000","des":"匈牙利","eng":"Hungary"},{"no":"7004040000","des":"列支敦斯登","eng":"Liechtenstein"},{"no":"7004041000","des":"波蘭","eng":"Poland"},{"no":"7004042000","des":"斯洛伐克","eng":"Slovakia"},{"no":"7004043000","des":"瑞士","eng":"Switzerland"},{"no":"7004044000","des":"梵蒂岡","eng":"Vatican City"}],"eng":"Europe"},{"no":"7005000000","des":"非洲","n":[{"no":"7005001000","des":"阿爾及利亞","eng":"Algeria"},{"no":"7005002000","des":"埃及","eng":"Egypt"},{"no":"7005003000","des":"利比亞","eng":"Libya"},{"no":"7005004000","des":"蘇丹","eng":"Sudan"},{"no":"7005005000","des":"突尼西亞","eng":"Tunisia"},{"no":"7005006000","des":"西撒哈拉","eng":"Western Sahara"},{"no":"7005007000","des":"摩洛哥","eng":"Morocco"},{"no":"7005008000","des":"中非","eng":"Central African Republic"},{"no":"7005009000","des":"喀麥隆","eng":"Cameroon"},{"no":"7005010000","des":"赤道幾內亞","eng":"Equatorial Guinea"},{"no":"7005011000","des":"加彭","eng":"Gabon"},{"no":"7005012000","des":"剛果","eng":"Congo"},{"no":"7005013000","des":"剛果(金)","eng":"Congo (DRC)"},{"no":"7005014000","des":"聖多美和普林西比","eng":"Sao Tome and Principe"},{"no":"7005015000","des":"安哥拉","eng":"Angola"},{"no":"7005016000","des":"波札那","eng":"Botswana"},{"no":"7005017000","des":"賴索托","eng":"Lesotho"},{"no":"7005018000","des":"馬達加斯加","eng":"Madagascar"},{"no":"7005019000","des":"馬拉威","eng":"Malawi"},{"no":"7005020000","des":"模里西斯","eng":"Mauritius"},{"no":"7005021000","des":"莫三比克","eng":"Mozambique"},{"no":"7005022000","des":"納米比亞","eng":"Namibia"},{"no":"7005023000","des":"史瓦濟蘭","eng":"Eswatini"},{"no":"7005024000","des":"南非","eng":"South Africa"},{"no":"7005025000","des":"坦尚尼亞","eng":"Tanzania"},{"no":"7005026000","des":"尚比亞","eng":"Zambia"},{"no":"7005027000","des":"辛巴威","eng":"Zimbabwe"},{"no":"7005028000","des":"留尼旺","eng":"Reunion"},{"no":"7005029000","des":"聖赫倫那","eng":"Saint Helena"},{"no":"7005030000","des":"衣索比亞","eng":"Ethiopia"},{"no":"7005031000","des":"蒲隆地","eng":"Burundi"},{"no":"7005032000","des":"厄利垂亞","eng":"Eritrea"},{"no":"7005033000","des":"吉布地","eng":"Djibouti"},{"no":"7005034000","des":"葛摩","eng":"Comoros"},{"no":"7005035000","des":"肯亞","eng":"Kenya"},{"no":"7005036000","des":"盧安達","eng":"Rwanda"},{"no":"7005037000","des":"塞席爾","eng":"Seychelles"},{"no":"7005038000","des":"索馬利亞","eng":"Somalia"},{"no":"7005039000","des":"坦尚尼亞","eng":"Tanzania"},{"no":"7005040000","des":"烏干達","eng":"Uganda"},{"no":"7005041000","des":"貝南","eng":"Benin"},{"no":"7005042000","des":"布吉納法索","eng":"Burkina Faso"},{"no":"7005043000","des":"查德","eng":"Chad"},{"no":"7005044000","des":"赤道幾內亞","eng":"Equatorial Guinea"},{"no":"7005045000","des":"多哥","eng":"Togo"},{"no":"7005046000","des":"維德角","eng":"Cape Verde"},{"no":"7005047000","des":"甘比亞","eng":"Gambia"},{"no":"7005048000","des":"幾內亞","eng":"Guinea"},{"no":"7005049000","des":"幾內亞比索","eng":"Guinea-Bissau"},{"no":"7005050000","des":"迦納","eng":"Ghana"},{"no":"7005051000","des":"加彭","eng":"Gabon"},{"no":"7005052000","des":"喀麥隆","eng":"Cameroon"},{"no":"7005053000","des":"象牙海岸","eng":"Ivory Coast"},{"no":"7005054000","des":"賴比瑞亞","eng":"Liberia"},{"no":"7005055000","des":"馬利","eng":"Mali"},{"no":"7005056000","des":"尼日","eng":"Niger"},{"no":"7005057000","des":"奈及利亞","eng":"Nigeria"},{"no":"7005058000","des":"獅子山","eng":"Sierra Leone"},{"no":"7005059000","des":"塞內加爾","eng":"Senegal"},{"no":"7005060000","des":"聖多美和普林西比","eng":"Sao Tome and Principe"},{"no":"7005061000","des":"南蘇丹共和國","eng":"Republic of South Sudan"},{"no":"7005062000","des":"茅利塔尼亞伊斯蘭共和國","eng":"Islamic Republic of Mauritania"}],"eng":"Africa"}]
|