@hasdata/glassdoor-mcp 1.0.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/LICENSE +21 -0
- package/README.md +393 -0
- package/index.mjs +24 -0
- package/package.json +41 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 HasData
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
# Glassdoor MCP Server
|
|
2
|
+
|
|
3
|
+
<!-- mcp-name: com.hasdata/glassdoor -->
|
|
4
|
+
|
|
5
|
+
A hosted Model Context Protocol (MCP) server that gives Claude, Cursor, Windsurf and any other MCP client two read-only Glassdoor tools. Search job listings by keyword and location, then read one posting in full with the employer rating, the salary figure and its provenance, both as structured JSON, with no Glassdoor partner account and nothing to host.
|
|
6
|
+
|
|
7
|
+
It reads public Glassdoor job pages that a signed-out visitor can see, on the US site and 22 regional ones.
|
|
8
|
+
|
|
9
|
+
**1,000 free credits every month, no card required**, which is 100 Glassdoor calls at the 10-credit rate.
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
https://mcp.hasdata.com/api/mcp?apis=glassdoor
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
[](https://glama.ai/mcp/servers/HasData/glassdoor-mcp)
|
|
16
|
+
[](https://github.com/HasData/glassdoor-mcp/actions/workflows/contract.yml)
|
|
17
|
+
[](https://mcp.hasdata.com/api/mcp?apis=glassdoor)
|
|
18
|
+
[](#tools)
|
|
19
|
+
[](https://www.npmjs.com/package/@hasdata/glassdoor-mcp)
|
|
20
|
+
[](https://pypi.org/project/hasdata-glassdoor-mcp/)
|
|
21
|
+
[](LICENSE)
|
|
22
|
+
|
|
23
|
+
## Contents
|
|
24
|
+
|
|
25
|
+
- [What you need](#what-you-need)
|
|
26
|
+
- [Quick start](#quick-start)
|
|
27
|
+
- [Example prompts](#example-prompts)
|
|
28
|
+
- [Tools](#tools)
|
|
29
|
+
- [Errors and failure paths](#errors-and-failure-paths)
|
|
30
|
+
- [Pricing, free tier and limits](#pricing-free-tier-and-limits)
|
|
31
|
+
- [Tool selection](#tool-selection)
|
|
32
|
+
- [How it compares](#how-it-compares)
|
|
33
|
+
- [FAQ](#faq)
|
|
34
|
+
- [HasData links](#hasdata-links)
|
|
35
|
+
- [Development](#development)
|
|
36
|
+
- [Contributing](#contributing)
|
|
37
|
+
- [License](#license)
|
|
38
|
+
|
|
39
|
+
## What you need
|
|
40
|
+
|
|
41
|
+
An MCP client and a HasData API key from the [dashboard](https://app.hasdata.com/sign-up?utm_source=github&utm_medium=syndication&utm_campaign=glassdoor-mcp), free to create with no card, and the free tier covers about 100 calls a month at the 10-credit rate. This is a remote server, so the simplest path is a URL and an `x-api-key` header, with no container to run. A client that only speaks stdio reaches it through a thin launcher, published as `@hasdata/glassdoor-mcp` on npm and `hasdata-glassdoor-mcp` on PyPI, shown below.
|
|
42
|
+
|
|
43
|
+
## Quick start
|
|
44
|
+
|
|
45
|
+
The server URL is the same for every client. We run it hands-on in Claude Code and Claude Desktop. The other blocks follow each client's own documented format for a remote server.
|
|
46
|
+
|
|
47
|
+
| Field | Value |
|
|
48
|
+
| :--- | :--- |
|
|
49
|
+
| URL | `https://mcp.hasdata.com/api/mcp?apis=glassdoor` |
|
|
50
|
+
| Transport | HTTP, streamable |
|
|
51
|
+
| Auth header | `x-api-key: HASDATA_API_KEY` |
|
|
52
|
+
|
|
53
|
+
Clients with OAuth support can add the same URL as a connector and sign in without putting a key in a config file.
|
|
54
|
+
|
|
55
|
+
<details>
|
|
56
|
+
<summary><b>Claude Code</b></summary>
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
claude mcp add --transport http glassdoor "https://mcp.hasdata.com/api/mcp?apis=glassdoor" \
|
|
60
|
+
--header "x-api-key: HASDATA_API_KEY"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
</details>
|
|
64
|
+
|
|
65
|
+
<details>
|
|
66
|
+
<summary><b>Claude Desktop</b></summary>
|
|
67
|
+
|
|
68
|
+
Settings, then Connectors, then Add custom connector, then paste `https://mcp.hasdata.com/api/mcp?apis=glassdoor` and sign in.
|
|
69
|
+
|
|
70
|
+
For the config-file route, Claude Desktop loads only local (stdio) servers, so it reaches a remote server through a stdio launcher. The `@hasdata/glassdoor-mcp` package is that launcher, and it reads the key from the environment. Add this to `claude_desktop_config.json`:
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"mcpServers": {
|
|
75
|
+
"glassdoor": {
|
|
76
|
+
"command": "npx",
|
|
77
|
+
"args": ["-y", "@hasdata/glassdoor-mcp"],
|
|
78
|
+
"env": { "HASDATA_API_KEY": "YOUR_KEY" }
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
For Python instead of Node, swap the launcher for the PyPI package, which `uvx` runs without a manual install:
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"mcpServers": {
|
|
89
|
+
"glassdoor": {
|
|
90
|
+
"command": "uvx",
|
|
91
|
+
"args": ["hasdata-glassdoor-mcp"],
|
|
92
|
+
"env": { "HASDATA_API_KEY": "YOUR_KEY" }
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
</details>
|
|
99
|
+
|
|
100
|
+
<details>
|
|
101
|
+
<summary><b>Cursor</b></summary>
|
|
102
|
+
|
|
103
|
+
`~/.cursor/mcp.json` for every project, or `.cursor/mcp.json` for one:
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"mcpServers": {
|
|
108
|
+
"glassdoor": {
|
|
109
|
+
"url": "https://mcp.hasdata.com/api/mcp?apis=glassdoor",
|
|
110
|
+
"headers": { "x-api-key": "HASDATA_API_KEY" }
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
</details>
|
|
117
|
+
|
|
118
|
+
<details>
|
|
119
|
+
<summary><b>Windsurf</b></summary>
|
|
120
|
+
|
|
121
|
+
`~/.codeium/windsurf/mcp_config.json`. Windsurf calls the field `serverUrl`, not `url`:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"mcpServers": {
|
|
126
|
+
"glassdoor": {
|
|
127
|
+
"serverUrl": "https://mcp.hasdata.com/api/mcp?apis=glassdoor",
|
|
128
|
+
"headers": { "x-api-key": "HASDATA_API_KEY" }
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
</details>
|
|
135
|
+
|
|
136
|
+
<details>
|
|
137
|
+
<summary><b>VS Code</b></summary>
|
|
138
|
+
|
|
139
|
+
`.vscode/mcp.json` in the workspace:
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{
|
|
143
|
+
"servers": {
|
|
144
|
+
"glassdoor": {
|
|
145
|
+
"type": "http",
|
|
146
|
+
"url": "https://mcp.hasdata.com/api/mcp?apis=glassdoor",
|
|
147
|
+
"headers": { "x-api-key": "HASDATA_API_KEY" }
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
</details>
|
|
154
|
+
|
|
155
|
+
## Example prompts
|
|
156
|
+
|
|
157
|
+
Each of these lands on one tool, or on two in sequence when the second needs the URL the first returns.
|
|
158
|
+
|
|
159
|
+
- Find data engineer roles in Austin, TX and show me only the ones where the employer stated the salary.
|
|
160
|
+
- What is the median posted salary for this role in Austin, and how many postings did that come from?
|
|
161
|
+
- Read this Glassdoor posting in full and list the required qualifications.
|
|
162
|
+
- Which companies hiring for this role have an employer rating above 4?
|
|
163
|
+
- Show me postings for this role added in the last week, sorted by recency.
|
|
164
|
+
- Compare posted salaries for this role on the UK and the German Glassdoor sites.
|
|
165
|
+
|
|
166
|
+
A prompt that names a role goes to the listing tool, and reading the full description takes a second call per posting. The listing already carries the salary, the employer rating and the skills, so a comparison across many roles needs one call rather than one per posting.
|
|
167
|
+
|
|
168
|
+
## Tools
|
|
169
|
+
|
|
170
|
+
Two tools, 10 credits per successful call.
|
|
171
|
+
|
|
172
|
+
### Get Glassdoor job listings
|
|
173
|
+
|
|
174
|
+
[`hasdata_glassdoor_listing_getJobListings`](https://docs.hasdata.com/apis/glassdoor/listing?utm_source=github&utm_medium=syndication&utm_campaign=glassdoor-mcp)
|
|
175
|
+
|
|
176
|
+
A page of postings for a role in a place, 30 to a page.
|
|
177
|
+
|
|
178
|
+
| Parameter | Type | Required | Notes |
|
|
179
|
+
| :--- | :--- | :--- | :--- |
|
|
180
|
+
| `keyword` | string | yes | The role to search for, such as `data engineer` |
|
|
181
|
+
| `location` | string | yes | Where to search, such as `Austin, TX` |
|
|
182
|
+
| `sort` | string | | `relevant` or `recent` |
|
|
183
|
+
| `domain` | string | | One of 22 regional Glassdoor sites |
|
|
184
|
+
| `nextPageToken` | string | | Cursor for the next page, taken from the previous response |
|
|
185
|
+
|
|
186
|
+
Returns `searchInformation` with `totalResults` and the Glassdoor URL behind the query, a `jobs` array, and `pagination`.
|
|
187
|
+
|
|
188
|
+
Each posting carries `title`, `id`, `url`, `location`, `ageInDays`, `sponsored`, a `skills` array, a `description` snippet, a `salary` object and an `employer` object with its own `rating` and `logoUrl`.
|
|
189
|
+
|
|
190
|
+
The `salary` object is the reason this tool is worth more than a job board feed. It reports `min`, `median`, `max`, `currency`, `period` and, decisively, `source`, which is either `EMPLOYER_PROVIDED` or `ESTIMATED`. The first is a figure the employer published, the second is Glassdoor's own model. In the sample below, 19 of 30 postings were employer-provided and 10 estimated.
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{
|
|
194
|
+
"title": "Data Engineer",
|
|
195
|
+
"id": 1010220057561,
|
|
196
|
+
"url": "https://www.glassdoor.com/job-listing/data-engineer-esc-region-xiii-JV_IC1139761_KO0,13_KE14,29.htm?jl=1010220057561",
|
|
197
|
+
"location": "Austin, TX",
|
|
198
|
+
"ageInDays": 36,
|
|
199
|
+
"sponsored": false,
|
|
200
|
+
"skills": ["Azure", "Customer service", "System design"],
|
|
201
|
+
"salary": {
|
|
202
|
+
"currency": "USD",
|
|
203
|
+
"period": "ANNUAL",
|
|
204
|
+
"min": 82572,
|
|
205
|
+
"median": 82572,
|
|
206
|
+
"max": 82572,
|
|
207
|
+
"source": "EMPLOYER_PROVIDED"
|
|
208
|
+
},
|
|
209
|
+
"employer": {
|
|
210
|
+
"id": 477452,
|
|
211
|
+
"name": "Education Service Center Region XIII",
|
|
212
|
+
"shortName": "ESC Region XIII",
|
|
213
|
+
"rating": 4.2,
|
|
214
|
+
"sponsored": false
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Get Glassdoor job details
|
|
220
|
+
|
|
221
|
+
[`hasdata_glassdoor_job_getJobDetails`](https://docs.hasdata.com/apis/glassdoor/job?utm_source=github&utm_medium=syndication&utm_campaign=glassdoor-mcp)
|
|
222
|
+
|
|
223
|
+
One posting in full, by its Glassdoor URL.
|
|
224
|
+
|
|
225
|
+
| Parameter | Type | Required | Notes |
|
|
226
|
+
| :--- | :--- | :--- | :--- |
|
|
227
|
+
| `url` | string | yes | The posting URL, as the listing tool returns it |
|
|
228
|
+
|
|
229
|
+
Returns a `job` object. On top of the title, salary and employer the listing already gave you, it adds the full `description` as plain text, the same text as `descriptionHtml`, a `requirements` object holding `educationRequirements` and an `experienceRequirements` array, an `address` object with coordinates, `datePosted`, and an `expired` flag.
|
|
230
|
+
|
|
231
|
+
```json
|
|
232
|
+
{
|
|
233
|
+
"title": "Data Engineer",
|
|
234
|
+
"employer": {
|
|
235
|
+
"name": "ESC Region XIII",
|
|
236
|
+
"url": "https://www.glassdoor.com/Overview/Working-at-ESC-Region-XIII-EI_IE477452.11,26.htm"
|
|
237
|
+
},
|
|
238
|
+
"address": {
|
|
239
|
+
"country": "United States",
|
|
240
|
+
"region": "Texas",
|
|
241
|
+
"city": "Austin, TX",
|
|
242
|
+
"latitude": 30.26694,
|
|
243
|
+
"longitude": -97.74278
|
|
244
|
+
},
|
|
245
|
+
"requirements": {
|
|
246
|
+
"educationRequirements": "Bachelor's degree",
|
|
247
|
+
"experienceRequirements": ["Azure", "Customer service", "System design", "Windows", "SQL", "AWS"]
|
|
248
|
+
},
|
|
249
|
+
"salary": {
|
|
250
|
+
"payCurrency": "USD",
|
|
251
|
+
"period": "ANNUAL",
|
|
252
|
+
"min": 82572,
|
|
253
|
+
"median": 82572,
|
|
254
|
+
"max": 82572,
|
|
255
|
+
"source": "EMPLOYER_PROVIDED"
|
|
256
|
+
},
|
|
257
|
+
"datePosted": "2026-09-03T00:00:00",
|
|
258
|
+
"ageInDays": 36,
|
|
259
|
+
"expired": false
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Errors and failure paths
|
|
264
|
+
|
|
265
|
+
Plan for these rather than assuming a happy path.
|
|
266
|
+
|
|
267
|
+
**`salary.source` decides whether the figure is a fact or a model output.** `EMPLOYER_PROVIDED` came from the posting. `ESTIMATED` is Glassdoor's own estimate for the role and market, and mixing the two into one median produces a number that describes neither. Filter on `source` before you aggregate, and say which set a published figure came from.
|
|
268
|
+
|
|
269
|
+
**A single stated salary arrives as `min`, `median` and `max` all equal.** Three of the 30 postings in the sample looked like that. A range of zero is a point figure, not a missing range.
|
|
270
|
+
|
|
271
|
+
**`salary` can be absent, and `period` can be `HOURLY` rather than `ANNUAL`.** One posting in the sample carried no salary at all. Converting hourly to annual is your assumption to make, not something the response does.
|
|
272
|
+
|
|
273
|
+
**The listing `description` is a truncated snippet.** Eighteen of the 30 samples ended mid-sentence with an ellipsis. The full text is only on the detail tool, so a prompt that reads descriptions costs one call per posting.
|
|
274
|
+
|
|
275
|
+
**Pagination is token-based, and `otherPages` holds tokens rather than page URLs.** `pagination.otherPages` maps a page number to an opaque base64 token, and that token is what goes into `nextPageToken`. Keep the other parameters unchanged while paging.
|
|
276
|
+
|
|
277
|
+
**`www.glassdoor.com` is the default and is not a value you can pass.** The `domain` enum lists the 22 regional sites, so the US site is what you get when you leave `domain` off. There is nothing to send for it.
|
|
278
|
+
|
|
279
|
+
**`expired` is on the detail tool only.** A listing page can still show a posting the employer has closed, and only the detail call reports it. Check the flag before you act on an old `ageInDays`.
|
|
280
|
+
|
|
281
|
+
**A salary figure and an employer rating are Glassdoor's numbers.** They come from Glassdoor's own data and models, so attribute them rather than presenting them as market truth.
|
|
282
|
+
|
|
283
|
+
Results that carry data also carry a `requestMetadata.id` worth quoting in support.
|
|
284
|
+
|
|
285
|
+
## Pricing, free tier and limits
|
|
286
|
+
|
|
287
|
+
Each Glassdoor tool costs **10 credits per successful call**. Response size does not change the price, so a 30-posting page costs the same as a single detail call, which makes the listing tool the cheap way to cover a market and the detail tool the expensive way.
|
|
288
|
+
|
|
289
|
+
The free tier is **1,000 credits every month with no card**, which is 100 Glassdoor calls at the base rate. It renews with the billing cycle, so a low-volume agent runs on the free tier indefinitely.
|
|
290
|
+
|
|
291
|
+
Paid plans start at **$49 a month** for 200,000 credits, which is 20,000 calls. The unit price falls with volume, from **$2.45 per 1,000 calls** on the entry plan to **$1.00** on Business, **$0.84** on Growth and **$0.74** on the largest [high-volume plans](https://hasdata.com/prices?utm_source=github&utm_medium=syndication&utm_campaign=glassdoor-mcp).
|
|
292
|
+
|
|
293
|
+
Your plan also sets concurrency. The free tier allows 1 request at a time, Startup 15, Business 30, Growth 50, and the high-volume plans run from 200 to 1,500. Retry on the 429 with a backoff in anything unattended, because an agent that walks a page of postings will reach the ceiling before you do.
|
|
294
|
+
|
|
295
|
+
A request that comes back non-200 is not billed. A successful call that finds nothing is still a call.
|
|
296
|
+
|
|
297
|
+
A note on cost per answer. Thirty postings arrive for 10 credits, and reading all thirty in full costs 300 more. Most comp and hiring questions are answerable from the listing alone, so reach for the detail tool per posting rather than per page.
|
|
298
|
+
|
|
299
|
+
## Tool selection
|
|
300
|
+
|
|
301
|
+
Start from what the prompt gives you. A role and a place go to the listing tool, and a Glassdoor URL goes straight to the detail tool.
|
|
302
|
+
|
|
303
|
+
Then ask what the answer needs. Salary, employer rating, skills, location and age all arrive with the listing, which covers comp benchmarking, hiring-trend monitoring and sourcing shortlists in one call. The detail tool exists for the full description and the stated qualifications, which is what a matching or resume-tailoring pipeline needs and what a market summary does not.
|
|
304
|
+
|
|
305
|
+
## How it compares
|
|
306
|
+
|
|
307
|
+
Glassdoor has no public jobs API, so the honest comparison is against a job board feed and against Glassdoor's own site.
|
|
308
|
+
|
|
309
|
+
| | A job board feed | Glassdoor on the site | This server |
|
|
310
|
+
| :--- | :--- | :--- | :--- |
|
|
311
|
+
| Eligibility | A partner agreement per board | A browser and a login prompt | An API key |
|
|
312
|
+
| Employer rating | Not included | Shown | On every posting |
|
|
313
|
+
| Salary provenance | Rarely stated | Shown | `source` on every figure |
|
|
314
|
+
| Skills tags | Board-dependent | Shown | An array per posting |
|
|
315
|
+
| Regional sites | Separate integrations | Separate sites | A parameter |
|
|
316
|
+
| Structured output | Feed-dependent | None | JSON |
|
|
317
|
+
|
|
318
|
+
The row that decides it is salary provenance. Comp work falls apart when an employer figure and a modelled estimate land in the same column, and this is the field that keeps them apart.
|
|
319
|
+
|
|
320
|
+
## FAQ
|
|
321
|
+
|
|
322
|
+
### Is there an official Glassdoor MCP server?
|
|
323
|
+
|
|
324
|
+
Glassdoor does not publish one, and it does not publish a public jobs API either. This one is maintained by HasData and reads public Glassdoor pages.
|
|
325
|
+
|
|
326
|
+
### What is a Glassdoor MCP server?
|
|
327
|
+
|
|
328
|
+
An MCP server exposes tools an AI client can call. This one turns Glassdoor job searches and postings into JSON an agent can reason over, without a browser or a scraping library in your stack.
|
|
329
|
+
|
|
330
|
+
### Do I need a Glassdoor account?
|
|
331
|
+
|
|
332
|
+
No. The only credential is your HasData key.
|
|
333
|
+
|
|
334
|
+
### Are the salaries real or estimated?
|
|
335
|
+
|
|
336
|
+
Both, and the response says which. `salary.source` is `EMPLOYER_PROVIDED` for a figure the employer published and `ESTIMATED` for Glassdoor's own model. Read that field before you average anything.
|
|
337
|
+
|
|
338
|
+
### Does it return company reviews?
|
|
339
|
+
|
|
340
|
+
No. These two tools cover job listings and postings. The employer object carries the aggregate `rating` Glassdoor shows next to a company name, and review text is not part of the response.
|
|
341
|
+
|
|
342
|
+
### Which countries are covered?
|
|
343
|
+
|
|
344
|
+
The US site by default, plus 22 regional ones from `www.glassdoor.co.uk` through `www.glassdoor.co.in`, `www.glassdoor.com.au` and the language-split Belgian, Canadian and Swiss sites. Pass `domain` to switch.
|
|
345
|
+
|
|
346
|
+
### How do I page through results?
|
|
347
|
+
|
|
348
|
+
Take the token for the page you want from `pagination.otherPages` and send it as `nextPageToken`, leaving `keyword`, `location` and `sort` unchanged.
|
|
349
|
+
|
|
350
|
+
### Can I use this together with other HasData APIs?
|
|
351
|
+
|
|
352
|
+
Yes. One key covers everything, and one endpoint serves them all through the `apis` parameter. Point a client at `?apis=glassdoor,indeed` to get both tool sets in one connection, or at [`mcp.hasdata.com/api/mcp`](https://docs.hasdata.com/mcp-server?utm_source=github&utm_medium=syndication&utm_campaign=glassdoor-mcp) for the full catalogue.
|
|
353
|
+
|
|
354
|
+
### Is HasData affiliated with Glassdoor?
|
|
355
|
+
|
|
356
|
+
No. HasData is an independent service and is not affiliated with, endorsed by, or sponsored by Glassdoor. Glassdoor is a trademark of its respective owner. The tools work with publicly available data only, and you are responsible for using the results in line with Glassdoor's terms and the law that applies to you.
|
|
357
|
+
|
|
358
|
+
### Compliance and personal data
|
|
359
|
+
|
|
360
|
+
Job postings are business records, and these tools return no candidate or reviewer data. Two things still need care. Employer ratings and salary estimates are Glassdoor's own aggregates, so republishing them without attribution misrepresents whose numbers they are. And a posting at a very small employer can name a person as the contact, which is the one place personal data appears.
|
|
361
|
+
|
|
362
|
+
## HasData links
|
|
363
|
+
|
|
364
|
+
- [Glassdoor Scraper API](https://hasdata.com/apis/glassdoor-api?utm_source=github&utm_medium=syndication&utm_campaign=glassdoor-mcp), the REST endpoints behind these tools
|
|
365
|
+
- [API documentation](https://docs.hasdata.com/apis/glassdoor/listing?utm_source=github&utm_medium=syndication&utm_campaign=glassdoor-mcp)
|
|
366
|
+
- [MCP server documentation](https://docs.hasdata.com/mcp-server?utm_source=github&utm_medium=syndication&utm_campaign=glassdoor-mcp)
|
|
367
|
+
- [Pricing](https://hasdata.com/prices?utm_source=github&utm_medium=syndication&utm_campaign=glassdoor-mcp)
|
|
368
|
+
- [Dashboard](https://app.hasdata.com/sign-up?utm_source=github&utm_medium=syndication&utm_campaign=glassdoor-mcp)
|
|
369
|
+
|
|
370
|
+
Other HasData MCP servers: [Indeed](https://github.com/HasData/indeed-mcp), [Google Search](https://github.com/HasData/google-search-mcp), [Google Maps](https://github.com/HasData/google-maps-mcp), [Google Trends](https://github.com/HasData/google-trends-mcp), [Google Flights](https://github.com/HasData/google-flights-mcp), [DuckDuckGo](https://github.com/HasData/duckduckgo-mcp), [YouTube](https://github.com/HasData/youtube-mcp), [TikTok](https://github.com/HasData/tiktok-mcp), [Instagram](https://github.com/HasData/instagram-mcp), [Amazon](https://github.com/HasData/amazon-mcp), [Walmart](https://github.com/HasData/walmart-mcp), [Shopify](https://github.com/HasData/shopify-mcp), [Yelp](https://github.com/HasData/yelp-mcp), [Zillow](https://github.com/HasData/zillow-mcp), [Redfin](https://github.com/HasData/redfin-mcp), [Airbnb](https://github.com/HasData/airbnb-mcp), [Booking.com](https://github.com/HasData/booking-mcp).
|
|
371
|
+
|
|
372
|
+
## Development
|
|
373
|
+
|
|
374
|
+
The launcher is a thin stdio bridge to the remote server, so there is nothing to build.
|
|
375
|
+
|
|
376
|
+
```bash
|
|
377
|
+
npm install
|
|
378
|
+
HASDATA_API_KEY=your_key_here npm test
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
The tests in `test/` assert the tool contract, the part that can break without a commit here. They check that `?apis=glassdoor` returns the expected tool count, that no name changed, that every tool still declares its required parameters and carries a description, that `sort` still offers both orders, and that the key in use is actually accepted. That last check calls a tool for real and costs 10 credits, which is the price of a canary that can fail for the right reason.
|
|
382
|
+
|
|
383
|
+
One test asserts that a live posting still carries `salary.source`. The README leans on that field to keep employer figures apart from estimates, and a response that quietly dropped it would leave the advice standing with nothing behind it.
|
|
384
|
+
|
|
385
|
+
The contract suite also runs weekly on a schedule, because the upstream tool list can change without anyone touching this repository.
|
|
386
|
+
|
|
387
|
+
## Contributing
|
|
388
|
+
|
|
389
|
+
A tool table, a response sample or a documented behaviour that does not match reality is worth an issue. There is a template for exactly that. Pull requests are welcome for the same, and for anything in the launcher.
|
|
390
|
+
|
|
391
|
+
## License
|
|
392
|
+
|
|
393
|
+
MIT, see [LICENSE](LICENSE).
|
package/index.mjs
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Thin launcher: connects an MCP client to HasData's hosted Glassdoor MCP server
|
|
3
|
+
// (streamable HTTP) through the mcp-remote stdio bridge. The server runs remotely.
|
|
4
|
+
// This package only proxies, so nothing here scrapes anything.
|
|
5
|
+
import { spawn } from 'node:child_process';
|
|
6
|
+
import { createRequire } from 'node:module';
|
|
7
|
+
import { dirname, join } from 'node:path';
|
|
8
|
+
|
|
9
|
+
const URL = 'https://mcp.hasdata.com/api/mcp?apis=glassdoor';
|
|
10
|
+
const key = process.env.HASDATA_API_KEY;
|
|
11
|
+
if (!key) {
|
|
12
|
+
process.stderr.write('HASDATA_API_KEY is not set. Create a free key at https://app.hasdata.com and set HASDATA_API_KEY.\n');
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
// Resolve mcp-remote's CLI from its own package.json bin, so a future layout change
|
|
16
|
+
// or an exports map does not break a hardcoded deep path.
|
|
17
|
+
const require = createRequire(import.meta.url);
|
|
18
|
+
const pkg = require('mcp-remote/package.json');
|
|
19
|
+
const proxy = join(dirname(require.resolve('mcp-remote/package.json')), pkg.bin['mcp-remote']);
|
|
20
|
+
const child = spawn(process.execPath, [proxy, URL, '--header', `x-api-key:${key}`], { stdio: 'inherit' });
|
|
21
|
+
child.on('exit', (code, signal) => {
|
|
22
|
+
if (signal) process.kill(process.pid, signal);
|
|
23
|
+
else process.exit(code ?? 0);
|
|
24
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hasdata/glassdoor-mcp",
|
|
3
|
+
"mcpName": "com.hasdata/glassdoor",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "MCP server for Glassdoor through HasData's hosted API: search job listings by keyword and location, and read one posting in full with the company rating and salary estimate. No Glassdoor partner account. 1,000 free credits every month.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"hasdata-glassdoor-mcp": "index.mjs"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"index.mjs",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"test": "node --test"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"mcp-remote": "^0.1.43"
|
|
20
|
+
},
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=18"
|
|
23
|
+
},
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/HasData/glassdoor-mcp.git"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://hasdata.com/apis/glassdoor-api",
|
|
30
|
+
"keywords": [
|
|
31
|
+
"mcp",
|
|
32
|
+
"glassdoor",
|
|
33
|
+
"glassdoor-mcp",
|
|
34
|
+
"jobs",
|
|
35
|
+
"job-search",
|
|
36
|
+
"recruiting",
|
|
37
|
+
"model-context-protocol",
|
|
38
|
+
"hasdata",
|
|
39
|
+
"scraper"
|
|
40
|
+
]
|
|
41
|
+
}
|