@pipeworx/mcp-greenhouse 0.1.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 +39 -0
- package/package.json +20 -0
- package/server.json +18 -0
- package/src/index.ts +153 -0
- package/tsconfig.json +14 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Pipeworx
|
|
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,39 @@
|
|
|
1
|
+
# mcp-greenhouse
|
|
2
|
+
|
|
3
|
+
Greenhouse MCP Pack — wraps the Greenhouse Harvest API v1
|
|
4
|
+
|
|
5
|
+
Part of the [Pipeworx](https://pipeworx.io) open MCP gateway.
|
|
6
|
+
|
|
7
|
+
## Tools
|
|
8
|
+
|
|
9
|
+
| Tool | Description |
|
|
10
|
+
|------|-------------|
|
|
11
|
+
| `greenhouse_list_candidates` | List candidates from Greenhouse ATS. |
|
|
12
|
+
| `greenhouse_get_candidate` | Get a single candidate by ID from Greenhouse. |
|
|
13
|
+
| `greenhouse_list_jobs` | List jobs from Greenhouse ATS. |
|
|
14
|
+
| `greenhouse_get_job` | Get a single job by ID from Greenhouse. |
|
|
15
|
+
| `greenhouse_list_applications` | List job applications from Greenhouse ATS. |
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
Add to your MCP client config:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"mcpServers": {
|
|
24
|
+
"greenhouse": {
|
|
25
|
+
"url": "https://gateway.pipeworx.io/greenhouse/mcp"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Or use the CLI:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx pipeworx use greenhouse
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## License
|
|
38
|
+
|
|
39
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pipeworx/mcp-greenhouse",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Greenhouse MCP Pack — wraps the Greenhouse Harvest API v1",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.ts",
|
|
7
|
+
"types": "src/index.ts",
|
|
8
|
+
"keywords": ["mcp", "mcp-server", "model-context-protocol", "pipeworx", "greenhouse"],
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/pipeworx-io/mcp-greenhouse"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"typecheck": "tsc --noEmit"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"typescript": "^5.7.0"
|
|
19
|
+
}
|
|
20
|
+
}
|
package/server.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
|
+
"name": "io.github.pipeworx-io/greenhouse",
|
|
4
|
+
"title": "greenhouse",
|
|
5
|
+
"description": "Greenhouse MCP Pack — wraps the Greenhouse Harvest API v1",
|
|
6
|
+
"version": "0.1.0",
|
|
7
|
+
"websiteUrl": "https://pipeworx.io/packs/greenhouse",
|
|
8
|
+
"repository": {
|
|
9
|
+
"url": "https://github.com/pipeworx-io/mcp-greenhouse",
|
|
10
|
+
"source": "github"
|
|
11
|
+
},
|
|
12
|
+
"remotes": [
|
|
13
|
+
{
|
|
14
|
+
"type": "streamable-http",
|
|
15
|
+
"url": "https://gateway.pipeworx.io/greenhouse/mcp"
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
interface McpToolDefinition {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: 'object';
|
|
6
|
+
properties: Record<string, unknown>;
|
|
7
|
+
required?: string[];
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface McpToolExport {
|
|
12
|
+
tools: McpToolDefinition[];
|
|
13
|
+
callTool: (name: string, args: Record<string, unknown>) => Promise<unknown>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Greenhouse MCP Pack — wraps the Greenhouse Harvest API v1
|
|
18
|
+
*
|
|
19
|
+
* BYO key: _apiKey = Harvest API key.
|
|
20
|
+
* Auth: Basic auth with apiKey as username, empty password.
|
|
21
|
+
* Tools: list/get candidates, list/get jobs, list applications.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
const API = 'https://harvest.greenhouse.io/v1';
|
|
26
|
+
|
|
27
|
+
async function ghFetch(apiKey: string, path: string): Promise<unknown> {
|
|
28
|
+
const credentials = btoa(`${apiKey}:`);
|
|
29
|
+
const res = await fetch(`${API}${path}`, {
|
|
30
|
+
headers: {
|
|
31
|
+
Authorization: `Basic ${credentials}`,
|
|
32
|
+
'Content-Type': 'application/json',
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
if (!res.ok) {
|
|
36
|
+
const text = await res.text();
|
|
37
|
+
throw new Error(`Greenhouse API error (${res.status}): ${text}`);
|
|
38
|
+
}
|
|
39
|
+
return res.json();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const tools: McpToolExport['tools'] = [
|
|
43
|
+
{
|
|
44
|
+
name: 'greenhouse_list_candidates',
|
|
45
|
+
description: 'List candidates from Greenhouse ATS.',
|
|
46
|
+
inputSchema: {
|
|
47
|
+
type: 'object' as const,
|
|
48
|
+
properties: {
|
|
49
|
+
_apiKey: { type: 'string', description: 'Greenhouse Harvest API key' },
|
|
50
|
+
per_page: { type: 'number', description: 'Results per page (max 500, default 50)' },
|
|
51
|
+
page: { type: 'number', description: 'Page number (default 1)' },
|
|
52
|
+
},
|
|
53
|
+
required: ['_apiKey'],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'greenhouse_get_candidate',
|
|
58
|
+
description: 'Get a single candidate by ID from Greenhouse.',
|
|
59
|
+
inputSchema: {
|
|
60
|
+
type: 'object' as const,
|
|
61
|
+
properties: {
|
|
62
|
+
_apiKey: { type: 'string', description: 'Greenhouse Harvest API key' },
|
|
63
|
+
id: { type: 'number', description: 'Candidate ID' },
|
|
64
|
+
},
|
|
65
|
+
required: ['_apiKey', 'id'],
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: 'greenhouse_list_jobs',
|
|
70
|
+
description: 'List jobs from Greenhouse ATS.',
|
|
71
|
+
inputSchema: {
|
|
72
|
+
type: 'object' as const,
|
|
73
|
+
properties: {
|
|
74
|
+
_apiKey: { type: 'string', description: 'Greenhouse Harvest API key' },
|
|
75
|
+
status: { type: 'string', description: 'Filter by status: open, closed, draft (optional)' },
|
|
76
|
+
per_page: { type: 'number', description: 'Results per page (max 500, default 50)' },
|
|
77
|
+
page: { type: 'number', description: 'Page number (default 1)' },
|
|
78
|
+
},
|
|
79
|
+
required: ['_apiKey'],
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: 'greenhouse_get_job',
|
|
84
|
+
description: 'Get a single job by ID from Greenhouse.',
|
|
85
|
+
inputSchema: {
|
|
86
|
+
type: 'object' as const,
|
|
87
|
+
properties: {
|
|
88
|
+
_apiKey: { type: 'string', description: 'Greenhouse Harvest API key' },
|
|
89
|
+
id: { type: 'number', description: 'Job ID' },
|
|
90
|
+
},
|
|
91
|
+
required: ['_apiKey', 'id'],
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: 'greenhouse_list_applications',
|
|
96
|
+
description: 'List job applications from Greenhouse ATS.',
|
|
97
|
+
inputSchema: {
|
|
98
|
+
type: 'object' as const,
|
|
99
|
+
properties: {
|
|
100
|
+
_apiKey: { type: 'string', description: 'Greenhouse Harvest API key' },
|
|
101
|
+
job_id: { type: 'number', description: 'Filter by job ID (optional)' },
|
|
102
|
+
status: { type: 'string', description: 'Filter by status: active, converted, hired, rejected (optional)' },
|
|
103
|
+
per_page: { type: 'number', description: 'Results per page (max 500, default 50)' },
|
|
104
|
+
page: { type: 'number', description: 'Page number (default 1)' },
|
|
105
|
+
},
|
|
106
|
+
required: ['_apiKey'],
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
async function callTool(name: string, args: Record<string, unknown>): Promise<unknown> {
|
|
112
|
+
const apiKey = args._apiKey as string;
|
|
113
|
+
|
|
114
|
+
switch (name) {
|
|
115
|
+
case 'greenhouse_list_candidates': {
|
|
116
|
+
const perPage = (args.per_page as number) ?? 50;
|
|
117
|
+
const page = (args.page as number) ?? 1;
|
|
118
|
+
return ghFetch(apiKey, `/candidates?per_page=${perPage}&page=${page}`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
case 'greenhouse_get_candidate': {
|
|
122
|
+
const id = args.id as number;
|
|
123
|
+
return ghFetch(apiKey, `/candidates/${id}`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
case 'greenhouse_list_jobs': {
|
|
127
|
+
const perPage = (args.per_page as number) ?? 50;
|
|
128
|
+
const page = (args.page as number) ?? 1;
|
|
129
|
+
let path = `/jobs?per_page=${perPage}&page=${page}`;
|
|
130
|
+
if (args.status) path += `&status=${args.status as string}`;
|
|
131
|
+
return ghFetch(apiKey, path);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
case 'greenhouse_get_job': {
|
|
135
|
+
const id = args.id as number;
|
|
136
|
+
return ghFetch(apiKey, `/jobs/${id}`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
case 'greenhouse_list_applications': {
|
|
140
|
+
const perPage = (args.per_page as number) ?? 50;
|
|
141
|
+
const page = (args.page as number) ?? 1;
|
|
142
|
+
let path = `/applications?per_page=${perPage}&page=${page}`;
|
|
143
|
+
if (args.job_id) path += `&job_id=${args.job_id as number}`;
|
|
144
|
+
if (args.status) path += `&status=${args.status as string}`;
|
|
145
|
+
return ghFetch(apiKey, path);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
default:
|
|
149
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export default { tools, callTool, meter: { credits: 10 } } satisfies McpToolExport;
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"outDir": "dist",
|
|
10
|
+
"rootDir": "src",
|
|
11
|
+
"declaration": true
|
|
12
|
+
},
|
|
13
|
+
"include": ["src"]
|
|
14
|
+
}
|