career-compass-mcp 2.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 +340 -0
- package/build/bin/cli.d.ts +9 -0
- package/build/bin/cli.d.ts.map +1 -0
- package/build/bin/cli.js +134 -0
- package/build/bin/cli.js.map +1 -0
- package/build/src/index.d.ts +3 -0
- package/build/src/index.d.ts.map +1 -0
- package/build/src/index.js +18 -0
- package/build/src/index.js.map +1 -0
- package/build/src/prompts/index.d.ts +3 -0
- package/build/src/prompts/index.d.ts.map +1 -0
- package/build/src/prompts/index.js +122 -0
- package/build/src/prompts/index.js.map +1 -0
- package/build/src/resources/career-kb.d.ts +3 -0
- package/build/src/resources/career-kb.d.ts.map +1 -0
- package/build/src/resources/career-kb.js +143 -0
- package/build/src/resources/career-kb.js.map +1 -0
- package/build/src/schemas/career-schema.d.ts +361 -0
- package/build/src/schemas/career-schema.d.ts.map +1 -0
- package/build/src/schemas/career-schema.js +146 -0
- package/build/src/schemas/career-schema.js.map +1 -0
- package/build/src/server.d.ts +3 -0
- package/build/src/server.d.ts.map +1 -0
- package/build/src/server.js +30 -0
- package/build/src/server.js.map +1 -0
- package/build/src/storage/file-store.d.ts +22 -0
- package/build/src/storage/file-store.d.ts.map +1 -0
- package/build/src/storage/file-store.js +163 -0
- package/build/src/storage/file-store.js.map +1 -0
- package/build/src/tools/career-kb.d.ts +3 -0
- package/build/src/tools/career-kb.d.ts.map +1 -0
- package/build/src/tools/career-kb.js +148 -0
- package/build/src/tools/career-kb.js.map +1 -0
- package/build/src/tools/interview.d.ts +3 -0
- package/build/src/tools/interview.d.ts.map +1 -0
- package/build/src/tools/interview.js +194 -0
- package/build/src/tools/interview.js.map +1 -0
- package/build/src/tools/opportunity.d.ts +3 -0
- package/build/src/tools/opportunity.d.ts.map +1 -0
- package/build/src/tools/opportunity.js +137 -0
- package/build/src/tools/opportunity.js.map +1 -0
- package/build/src/tools/pipeline.d.ts +11 -0
- package/build/src/tools/pipeline.d.ts.map +1 -0
- package/build/src/tools/pipeline.js +295 -0
- package/build/src/tools/pipeline.js.map +1 -0
- package/build/src/tools/resume.d.ts +3 -0
- package/build/src/tools/resume.d.ts.map +1 -0
- package/build/src/tools/resume.js +222 -0
- package/build/src/tools/resume.js.map +1 -0
- package/build/src/types/tool-args.d.ts +52 -0
- package/build/src/types/tool-args.d.ts.map +1 -0
- package/build/src/types/tool-args.js +2 -0
- package/build/src/types/tool-args.js.map +1 -0
- package/data/example/career/experience.yaml +67 -0
- package/data/example/career/profile.yaml +31 -0
- package/data/example/career/skills.yaml +71 -0
- package/data/example/career/testimonials.yaml +26 -0
- package/data/example/pipeline/applications.yaml +312 -0
- package/package.json +82 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ben Schippers
|
|
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,340 @@
|
|
|
1
|
+
# Career Compass MCP
|
|
2
|
+
|
|
3
|
+
[](LICENSE)
|
|
4
|
+
[](https://www.npmjs.com/package/career-compass-mcp)
|
|
5
|
+
[](https://nodejs.org)
|
|
6
|
+
[](https://modelcontextprotocol.io)
|
|
7
|
+
|
|
8
|
+
**Your AI-native career co-pilot, built for Claude.**
|
|
9
|
+
|
|
10
|
+
Career Compass turns Claude into a full job-search partner — one that knows your entire career history, tailors every resume and cover letter, tracks every application, and preps you for every interview. Initiate via conversation, onboard, and track multiple applications in moments.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Your data stays on your machine
|
|
15
|
+
|
|
16
|
+
Career Compass is local-first. Your career history lives in plain YAML files on your own disk, under the directory you point `CAREER_DATA_PATH` at (default `~/.career-compass`). There is no account, no cloud sync, and no telemetry — nothing phones home.
|
|
17
|
+
|
|
18
|
+
Your real data is never committed to git: the `.gitignore` excludes `data/career/` and `data/pipeline/`, so the only career data in this repo is the fictional sample under `data/example/` (meet Alex Rivera). Read it, edit it, delete it — it's all just files you own. And nothing real ever ships in the npm package — a publish-time guard (`npm-pack-leak-guard`) scans the exact tarball and fails the publish if any real-career marker appears.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## What it feels like
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
You: I have a panel interview at Veridian Health on Friday — Director of Operations role.
|
|
26
|
+
Can you prep me?
|
|
27
|
+
|
|
28
|
+
Claude: On it. Reading your career history now...
|
|
29
|
+
|
|
30
|
+
[Generates 90-second pitch, 8 STAR stories matched to likely panel questions,
|
|
31
|
+
company research brief, 10 questions to ask them, and a list of watch-outs
|
|
32
|
+
based on gaps in your background — all in one response]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
You: Here's a job posting I just found. [pastes posting]
|
|
37
|
+
How well do I fit?
|
|
38
|
+
|
|
39
|
+
Claude: Fit score: 8.1/10. Here's why — and here's what they'll probe you on...
|
|
40
|
+
|
|
41
|
+
[Returns matched strengths, honest gap analysis, talking points in their language,
|
|
42
|
+
and a "day in the life" of what the role actually looks like]
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
You: Show me what needs attention in my pipeline today.
|
|
47
|
+
|
|
48
|
+
Claude: 3 things:
|
|
49
|
+
- Meridian Logistics follow-up is overdue (8 days since you applied, referral from Marcus Chen)
|
|
50
|
+
- Veridian panel is Friday — prep above
|
|
51
|
+
- Novare rejection arrived — want me to draft a keep-the-door-open response?
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Architecture
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
┌─────────────┐ ┌──────────────────────────────────────┐
|
|
60
|
+
│ │ MCP │ MCP Server (Node.js) │
|
|
61
|
+
│ Claude │◄────────►│ │
|
|
62
|
+
│ │ stdio │ Tools ─── Resume, Pipeline, Interview│
|
|
63
|
+
│ │ │ Resources ─ Career KB, Pipeline data │
|
|
64
|
+
└─────────────┘ │ Prompts ── Power-user shortcuts │
|
|
65
|
+
│ │
|
|
66
|
+
│ ┌──────────────┐ │
|
|
67
|
+
│ │ File Store │ │
|
|
68
|
+
│ │ (YAML files) │ │
|
|
69
|
+
│ └──────┬───────┘ │
|
|
70
|
+
└────────────────┼─────────────────────┘
|
|
71
|
+
│ reads
|
|
72
|
+
┌────────────────┼─────────────────────┐
|
|
73
|
+
│ Dashboard │ (Next.js) │
|
|
74
|
+
│ ▼ │
|
|
75
|
+
│ Pipeline Kanban · Career KB Overview │
|
|
76
|
+
│ Analytics · Onboarding Wizard │
|
|
77
|
+
└──────────────────────────────────────┘
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Your data stays on your machine
|
|
83
|
+
|
|
84
|
+
Career Compass is local-first by design. Your real career data — résumé history, the
|
|
85
|
+
companies you're talking to, salary numbers, interview notes — lives in **plain YAML
|
|
86
|
+
files on your own disk** and never leaves it.
|
|
87
|
+
|
|
88
|
+
- **Where your data lives:** `~/.career-compass/` by default (override with the
|
|
89
|
+
`CAREER_DATA_PATH` environment variable). This directory is created and read on *your*
|
|
90
|
+
machine. It is **never** uploaded anywhere, and it is **not** part of this npm package.
|
|
91
|
+
- **What ships in the package:** only the MCP server code and a small set of **fictional
|
|
92
|
+
example files** (`data/example/` — the "Alex Rivera" persona). There is no real career
|
|
93
|
+
data in the published package, and none can be — the package and your data live in
|
|
94
|
+
different places, and the publish-time leak guard enforces it.
|
|
95
|
+
- **The dashboard reads your data at request time, locally.** The Next.js routes are
|
|
96
|
+
`force-dynamic`, so the dashboard server reads your YAML *when you open a page*, from a
|
|
97
|
+
server running on your own `localhost`. Your data is **never baked into a build**, never
|
|
98
|
+
prerendered into static HTML, and never sent over the network. *(There's a regression
|
|
99
|
+
test, `standalone-dynamic.test.ts`, that guards exactly this.)*
|
|
100
|
+
- **No telemetry.** Career Compass makes no analytics or phone-home calls. The only thing
|
|
101
|
+
that ever sees your career data is the Claude conversation *you* start, through the MCP
|
|
102
|
+
server *you* run.
|
|
103
|
+
|
|
104
|
+
In short: this is a tool you run, on your machine, over your files. Treat
|
|
105
|
+
`~/.career-compass/` like any private notebook — back it up, don't commit it to a public
|
|
106
|
+
repo, and it stays yours.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Quick Start
|
|
111
|
+
|
|
112
|
+
Career Compass is on npm — point Claude straight at it, no clone or build required.
|
|
113
|
+
|
|
114
|
+
### 1. Add to Claude
|
|
115
|
+
|
|
116
|
+
Add this to your `~/.claude.json` (Claude Code) or equivalent MCP config:
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
{
|
|
120
|
+
"mcpServers": {
|
|
121
|
+
"career-compass": {
|
|
122
|
+
"command": "npx",
|
|
123
|
+
"args": ["-y", "career-compass-mcp"],
|
|
124
|
+
"env": {
|
|
125
|
+
"CAREER_DATA_PATH": "/Users/you/career-data"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
`npx -y career-compass-mcp` fetches and runs the latest server on demand. Point
|
|
133
|
+
`CAREER_DATA_PATH` anywhere you like — Career Compass initializes the directory on first
|
|
134
|
+
run. Leave it unset to use the default, `~/.career-compass`.
|
|
135
|
+
|
|
136
|
+
Prefer a global install? Run `npm install -g career-compass-mcp`, then set
|
|
137
|
+
`"command": "career-compass-mcp"` with no args.
|
|
138
|
+
|
|
139
|
+
### 2. Onboard (first conversation)
|
|
140
|
+
|
|
141
|
+
Open Claude and say:
|
|
142
|
+
|
|
143
|
+
> **"Set up my Career KB. Here's my resume:"** [paste your resume]
|
|
144
|
+
|
|
145
|
+
Claude will:
|
|
146
|
+
- Extract your work history, achievements, and skills into structured YAML
|
|
147
|
+
- Ask clarifying questions about gaps or unclear metrics
|
|
148
|
+
- Save everything to your `CAREER_DATA_PATH`
|
|
149
|
+
|
|
150
|
+
That's it. From there, every tool has full context on who you are.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Data structure
|
|
155
|
+
|
|
156
|
+
Career Compass stores all data as YAML files under `CAREER_DATA_PATH` (default `~/.career-compass`):
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
~/.career-compass/
|
|
160
|
+
├── career/
|
|
161
|
+
│ ├── profile.yaml # who you are, what you're targeting
|
|
162
|
+
│ ├── experience.yaml # roles, achievements (metrics + context + impact)
|
|
163
|
+
│ ├── skills.yaml # skills with proficiency and recency
|
|
164
|
+
│ ├── education.yaml # degrees, certifications, coursework
|
|
165
|
+
│ ├── projects.yaml # portfolio projects
|
|
166
|
+
│ └── testimonials.yaml # quotes and recommendations
|
|
167
|
+
└── pipeline/
|
|
168
|
+
└── applications.yaml # all job applications
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
This is your single source of truth — built once, enriched over time, read by every tool. You never need to edit these files by hand: use `ingest_document` to add data by pasting documents, or just ask Claude to update specific sections.
|
|
172
|
+
|
|
173
|
+
See [`data/example/`](data/example/) in this repo for a fully populated sample (the fictional Alex Rivera).
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Dashboard
|
|
178
|
+
|
|
179
|
+
v2.0 includes a local web dashboard — a visual layer on top of your Career KB and pipeline data. Open it alongside Claude or use it standalone to review and manage your search.
|
|
180
|
+
|
|
181
|
+

|
|
182
|
+

|
|
183
|
+

|
|
184
|
+

|
|
185
|
+
|
|
186
|
+
Four views:
|
|
187
|
+
|
|
188
|
+
**Pipeline kanban board** — All your applications laid out by stage (Exploring → Applied → Screening → Interviewing → Offer → Closed). Drag to advance stages. See stale applications at a glance. Click any card to drill in.
|
|
189
|
+
|
|
190
|
+
**Application detail view** — Full timeline for a single application: every status change, contacts associated with the role, notes from conversations, and next action. Everything Claude knows about that opportunity in one place.
|
|
191
|
+
|
|
192
|
+
**Career KB overview** — Visual summary of your career data: skills radar (proficiency × recency), experience timeline, testimonials, and a completeness indicator showing what Claude has to work with. Useful for spotting gaps before you onboard a new role.
|
|
193
|
+
|
|
194
|
+
**Analytics** — Funnel conversion rates, response rates by source, time-in-stage averages, and source effectiveness. See which channels are actually working.
|
|
195
|
+
|
|
196
|
+
### Running the dashboard
|
|
197
|
+
|
|
198
|
+
> **The dashboard runs from a source build today.** It's a Next.js standalone server, so it
|
|
199
|
+
> isn't part of the npm package yet — a packaged-for-npm dashboard is coming in a follow-up
|
|
200
|
+
> release. For now, build it from source:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
git clone https://github.com/benskamps/career-compass-mcp.git
|
|
204
|
+
cd career-compass-mcp
|
|
205
|
+
npm install
|
|
206
|
+
npm run build
|
|
207
|
+
|
|
208
|
+
# Try it with the bundled Alex Rivera sample (no setup, ~1 minute):
|
|
209
|
+
CAREER_DATA_PATH=data/example npm run dashboard
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
This opens the dashboard at `http://localhost:3141` (or the next available port). Point
|
|
213
|
+
`CAREER_DATA_PATH` at your own data directory to use it for real. The onboarding wizard
|
|
214
|
+
walks you through job targets, salary expectations, and confirming your skills inventory —
|
|
215
|
+
the gaps a resume doesn't naturally contain.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Tools
|
|
220
|
+
|
|
221
|
+
| Tool | What it does |
|
|
222
|
+
|------|-------------|
|
|
223
|
+
| `explore_opportunity` | Analyzes a job posting against your Career KB — fit score, matched strengths, gaps, talking points, day-in-the-life, red flags |
|
|
224
|
+
| `research_company` | Builds an intelligence brief: product, culture, funding, interview process, strategic fit |
|
|
225
|
+
| `tailor_resume` | Generates an ATS-optimized, tailored resume from your KB — standard, federal, academic, or functional formats |
|
|
226
|
+
| `generate_cover_letter` | Writes a personalized cover letter with your actual achievements woven in |
|
|
227
|
+
| `format_for_ats` | Reformats resume content for specific ATS systems: Workday, Greenhouse, Lever, LinkedIn, iCIMS, Taleo |
|
|
228
|
+
| `manage_pipeline` | Tracks applications from discovery through offer — add, update, list, stats, next actions |
|
|
229
|
+
| `classify_email` | Classifies a job-search email and extracts contacts, dates, and suggested pipeline updates |
|
|
230
|
+
| `prepare_interview` | Full interview prep: opening pitch, STAR stories, likely questions, company alignment, questions to ask |
|
|
231
|
+
| `evaluate_offer` | Breaks down total comp, compares to market, builds negotiation strategy, drafts counter scripts |
|
|
232
|
+
| `ingest_document` | Extracts achievements from any document: performance review, award email, LinkedIn recommendation, project summary |
|
|
233
|
+
| `generate_rejection_response` | Drafts a graceful response that keeps the door open and maintains the relationship |
|
|
234
|
+
|
|
235
|
+
## Resources
|
|
236
|
+
|
|
237
|
+
Claude can read these directly (e.g., "read my career profile"):
|
|
238
|
+
|
|
239
|
+
| Resource | URI | Contents |
|
|
240
|
+
|----------|-----|----------|
|
|
241
|
+
| Career Profile | `career://profile` | Name, contact, summary, targets, preferences |
|
|
242
|
+
| Work Experience | `career://experience` | Full history with achievements |
|
|
243
|
+
| Skills Inventory | `career://skills` | Skills with proficiency and recency |
|
|
244
|
+
| Projects | `career://projects` | Portfolio with outcomes |
|
|
245
|
+
| Education | `career://education` | Degrees, certifications, coursework |
|
|
246
|
+
| Testimonials | `career://testimonials` | Quotes, recommendations |
|
|
247
|
+
| Full KB | `career://full` | Everything above in one read |
|
|
248
|
+
| Pipeline | `career://pipeline` | All applications with status |
|
|
249
|
+
|
|
250
|
+
## Prompts
|
|
251
|
+
|
|
252
|
+
Power-user shortcuts (appear in Claude's prompt menu):
|
|
253
|
+
|
|
254
|
+
| Prompt | What it does |
|
|
255
|
+
|--------|-------------|
|
|
256
|
+
| `resume-tailor` | Drop in a posting → get a tailored resume |
|
|
257
|
+
| `interview-coach` | Company + role + interview type → full prep package |
|
|
258
|
+
| `negotiation-coach` | Paste an offer → get analysis, strategy, and counter scripts |
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Configuration
|
|
263
|
+
|
|
264
|
+
| Env var | Default | Description |
|
|
265
|
+
|---------|---------|-------------|
|
|
266
|
+
| `CAREER_DATA_PATH` | `~/.career-compass` | Directory where your career and pipeline YAML files are stored |
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## Building from Source
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
git clone https://github.com/benskamps/career-compass-mcp
|
|
274
|
+
cd career-compass-mcp
|
|
275
|
+
npm install
|
|
276
|
+
npm run build
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
`npm run build` compiles both the MCP server (TypeScript → `build/`) and the Next.js dashboard (`dashboard/.next/`). To work on just the MCP server, use `npm run build:mcp`. For dashboard development with hot reload, use `npm run dev:dashboard`.
|
|
280
|
+
|
|
281
|
+
Then point your MCP config to `node /path/to/career-compass-mcp/build/src/index.js` (or just use the published package via `npx -y career-compass-mcp`).
|
|
282
|
+
|
|
283
|
+
Use `npm run dev` during development — TypeScript watch mode recompiles on save.
|
|
284
|
+
Use `npm run inspect` to open the MCP Inspector (web UI for testing tools interactively).
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Why Career Compass
|
|
289
|
+
|
|
290
|
+
Job searching is one of the highest-stakes, most document-intensive activities most people do — and most tools treat it as a data entry problem. Spreadsheets for tracking. Templates for resumes. Generic advice for interviews.
|
|
291
|
+
|
|
292
|
+
Career Compass treats it as a knowledge problem. Your career history is a corpus. Every application is a retrieval and synthesis task. Every interview is a pattern-matching problem against a known dataset (the posting) and a known corpus (your KB).
|
|
293
|
+
|
|
294
|
+
The Career KB is your single source of truth — built once, enriched over time, and used by every tool. A tailored resume draws from it. Interview prep draws from it. Cover letters draw from it. The pipeline tracks against it. Nothing gets lost because it's never in a tab you'll close.
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## Development
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
git clone https://github.com/benskamps/career-compass-mcp.git
|
|
302
|
+
cd career-compass-mcp
|
|
303
|
+
npm install
|
|
304
|
+
cd dashboard && npm install && cd ..
|
|
305
|
+
|
|
306
|
+
# MCP server (TypeScript watch)
|
|
307
|
+
npm run dev
|
|
308
|
+
|
|
309
|
+
# Dashboard (Next.js + Turbopack)
|
|
310
|
+
npm run dev:dashboard
|
|
311
|
+
|
|
312
|
+
# MCP Inspector (test tools interactively)
|
|
313
|
+
npm run inspect
|
|
314
|
+
|
|
315
|
+
# Tests
|
|
316
|
+
npm run test:mcp # MCP server tests
|
|
317
|
+
npm run test # Dashboard tests
|
|
318
|
+
|
|
319
|
+
# Storybook (component library)
|
|
320
|
+
npm run storybook
|
|
321
|
+
|
|
322
|
+
# Use example data for development
|
|
323
|
+
CAREER_DATA_PATH=data/example npm run dev:dashboard
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## Contributing
|
|
329
|
+
|
|
330
|
+
Issues and PRs welcome. If you add a new tool, register it in `src/server.ts` and follow the pattern in any existing tool file — each tool returns a structured prompt that Claude acts on with the full KB in context.
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## License
|
|
335
|
+
|
|
336
|
+
MIT
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
*Part of the [Brokenbranch Lab](https://www.brokenbranch.dev/lab/) — Ben Schippers' workshop of AI-native tools and research.*
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Read the package version from package.json relative to the CLI directory.
|
|
4
|
+
* Factored out so it can be unit-tested directly (the previous inline code had
|
|
5
|
+
* a `pkgVersion = pkgVersion` self-assign that always left the version as
|
|
6
|
+
* "unknown"). Returns "unknown" only when package.json is missing/unreadable.
|
|
7
|
+
*/
|
|
8
|
+
export declare function readPkgVersion(cliDir: string): string;
|
|
9
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../bin/cli.ts"],"names":[],"mappings":";AAaA;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAOrD"}
|
package/build/bin/cli.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { homedir } from "os";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync } from "fs";
|
|
5
|
+
import { createServer as createNetServer } from "net";
|
|
6
|
+
import { spawn } from "child_process";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
8
|
+
const args = process.argv.slice(2);
|
|
9
|
+
// ─── Version ─────────────────────────────────────────────────────────────────
|
|
10
|
+
const __cliDir = fileURLToPath(new URL(".", import.meta.url));
|
|
11
|
+
/**
|
|
12
|
+
* Read the package version from package.json relative to the CLI directory.
|
|
13
|
+
* Factored out so it can be unit-tested directly (the previous inline code had
|
|
14
|
+
* a `pkgVersion = pkgVersion` self-assign that always left the version as
|
|
15
|
+
* "unknown"). Returns "unknown" only when package.json is missing/unreadable.
|
|
16
|
+
*/
|
|
17
|
+
export function readPkgVersion(cliDir) {
|
|
18
|
+
try {
|
|
19
|
+
const pkgJson = JSON.parse(readFileSync(join(cliDir, "..", "..", "package.json"), "utf-8"));
|
|
20
|
+
return typeof pkgJson.version === "string" ? pkgJson.version : "unknown";
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return "unknown"; // package.json not found — version will show as "unknown"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const pkgVersion = readPkgVersion(__cliDir);
|
|
27
|
+
if (args.includes("--version") || args.includes("-v")) {
|
|
28
|
+
console.log(`career-compass-mcp v${pkgVersion}`);
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
// ─── Help ────────────────────────────────────────────────────────────────────
|
|
32
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
33
|
+
console.log(`
|
|
34
|
+
career-compass-mcp v${pkgVersion}
|
|
35
|
+
|
|
36
|
+
Usage:
|
|
37
|
+
career-compass-mcp Run MCP server (stdio)
|
|
38
|
+
career-compass-mcp dashboard Open web dashboard
|
|
39
|
+
career-compass-mcp dashboard --port 3000 Specify port (default: 3141)
|
|
40
|
+
career-compass-mcp dashboard --no-open Start without opening browser
|
|
41
|
+
|
|
42
|
+
Options:
|
|
43
|
+
-h, --help Show this help message
|
|
44
|
+
-v, --version Show version number
|
|
45
|
+
--port <number> Dashboard port (default: 3141)
|
|
46
|
+
--no-open Don't auto-open browser
|
|
47
|
+
`);
|
|
48
|
+
process.exit(0);
|
|
49
|
+
}
|
|
50
|
+
const isDashboard = args[0] === "dashboard";
|
|
51
|
+
if (!isDashboard) {
|
|
52
|
+
// Run MCP server on stdio (existing behavior)
|
|
53
|
+
await import("../src/index.js");
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// Dashboard mode
|
|
57
|
+
const portArg = args.indexOf("--port");
|
|
58
|
+
let requestedPort = 3141;
|
|
59
|
+
if (portArg >= 0) {
|
|
60
|
+
const portValue = parseInt(args[portArg + 1], 10);
|
|
61
|
+
if (isNaN(portValue) || portValue < 1 || portValue > 65535) {
|
|
62
|
+
console.error(`Error: Invalid port "${args[portArg + 1]}". Must be a number between 1 and 65535.`);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
requestedPort = portValue;
|
|
66
|
+
}
|
|
67
|
+
const noOpen = args.includes("--no-open");
|
|
68
|
+
// Resolve data path
|
|
69
|
+
const dataPath = process.env.CAREER_DATA_PATH ?? join(homedir(), ".career-compass");
|
|
70
|
+
if (!existsSync(dataPath)) {
|
|
71
|
+
mkdirSync(join(dataPath, "career"), { recursive: true });
|
|
72
|
+
mkdirSync(join(dataPath, "pipeline"), { recursive: true });
|
|
73
|
+
}
|
|
74
|
+
// Find available port
|
|
75
|
+
const port = await findPort(requestedPort);
|
|
76
|
+
// Resolve standalone server path
|
|
77
|
+
// __cliDir is build/bin/ at runtime; go up two levels to repo root
|
|
78
|
+
const standalonePath = join(__cliDir, "..", "..", "dashboard", ".next", "standalone", "dashboard", "server.js");
|
|
79
|
+
if (!existsSync(standalonePath)) {
|
|
80
|
+
console.error([
|
|
81
|
+
"The dashboard isn't available in this install.",
|
|
82
|
+
"It currently ships in the source build, not the npm package (a packaged dashboard is coming in a follow-up release).",
|
|
83
|
+
"",
|
|
84
|
+
"To run it from source:",
|
|
85
|
+
" git clone https://github.com/benskamps/career-compass-mcp",
|
|
86
|
+
" cd career-compass-mcp && npm install && npm run build",
|
|
87
|
+
" CAREER_DATA_PATH=data/example npm run dashboard",
|
|
88
|
+
"",
|
|
89
|
+
"The MCP server (all 11 tools) works in this install — just point Claude at it.",
|
|
90
|
+
].join("\n"));
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
// Start Next.js standalone server
|
|
94
|
+
const child = spawn("node", [standalonePath], {
|
|
95
|
+
env: {
|
|
96
|
+
...process.env,
|
|
97
|
+
PORT: String(port),
|
|
98
|
+
HOSTNAME: "localhost",
|
|
99
|
+
CAREER_DATA_PATH: dataPath,
|
|
100
|
+
},
|
|
101
|
+
stdio: ["pipe", "pipe", "inherit"],
|
|
102
|
+
});
|
|
103
|
+
child.stdout?.on("data", (data) => {
|
|
104
|
+
const output = data.toString();
|
|
105
|
+
if (output.includes("Ready") || output.includes("started")) {
|
|
106
|
+
console.error(`Dashboard running at http://localhost:${port}`);
|
|
107
|
+
if (!noOpen) {
|
|
108
|
+
openBrowser(`http://localhost:${port}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
const shutdown = () => { child.kill("SIGTERM"); process.exit(0); };
|
|
113
|
+
process.on("SIGINT", shutdown);
|
|
114
|
+
process.on("SIGTERM", shutdown);
|
|
115
|
+
}
|
|
116
|
+
function findPort(preferred) {
|
|
117
|
+
return new Promise((resolve) => {
|
|
118
|
+
const server = createNetServer();
|
|
119
|
+
server.listen(preferred, () => { server.close(() => resolve(preferred)); });
|
|
120
|
+
server.on("error", () => {
|
|
121
|
+
const fallback = createNetServer();
|
|
122
|
+
fallback.listen(0, () => {
|
|
123
|
+
const addr = fallback.address();
|
|
124
|
+
const port = typeof addr === "object" && addr ? addr.port : 0;
|
|
125
|
+
fallback.close(() => resolve(port));
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
function openBrowser(url) {
|
|
131
|
+
const cmd = process.platform === "win32" ? "start" : process.platform === "darwin" ? "open" : "xdg-open";
|
|
132
|
+
spawn(cmd, [url], { shell: true, stdio: "ignore", detached: true }).unref();
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../bin/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { createServer } from "./server.js";
|
|
4
|
+
import { ensureDataDirs } from "./storage/file-store.js";
|
|
5
|
+
async function main() {
|
|
6
|
+
await ensureDataDirs();
|
|
7
|
+
const server = createServer();
|
|
8
|
+
const transport = new StdioServerTransport();
|
|
9
|
+
await server.connect(transport);
|
|
10
|
+
// Silence console.log to avoid polluting STDIO transport
|
|
11
|
+
// Use console.error for any debug output
|
|
12
|
+
console.error("Career Compass MCP server running on stdio");
|
|
13
|
+
}
|
|
14
|
+
main().catch((err) => {
|
|
15
|
+
console.error("Fatal error:", err);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
});
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,KAAK,UAAU,IAAI;IACjB,MAAM,cAAc,EAAE,CAAC;IAEvB,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,yDAAyD;IACzD,yCAAyC;IACzC,OAAO,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;AAC9D,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/prompts/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAsIvD"}
|