job_ops-mcp 0.3.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/.env.example +33 -0
- package/LICENSE +21 -0
- package/README.md +400 -0
- package/config/profile.example.yml +67 -0
- package/cv.example.md +53 -0
- package/dist/cli.js +385 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.js +63 -0
- package/dist/config.js.map +1 -0
- package/dist/core/browser.js +27 -0
- package/dist/core/browser.js.map +1 -0
- package/dist/core/content_hash.js +11 -0
- package/dist/core/content_hash.js.map +1 -0
- package/dist/core/csv.js +107 -0
- package/dist/core/csv.js.map +1 -0
- package/dist/core/cv_parse.js +201 -0
- package/dist/core/cv_parse.js.map +1 -0
- package/dist/core/html.js +10 -0
- package/dist/core/html.js.map +1 -0
- package/dist/core/jd_normalize.js +99 -0
- package/dist/core/jd_normalize.js.map +1 -0
- package/dist/core/jobs.js +106 -0
- package/dist/core/jobs.js.map +1 -0
- package/dist/core/llm.js +227 -0
- package/dist/core/llm.js.map +1 -0
- package/dist/core/modes.js +55 -0
- package/dist/core/modes.js.map +1 -0
- package/dist/core/outreach_safety.js +77 -0
- package/dist/core/outreach_safety.js.map +1 -0
- package/dist/core/profile.js +88 -0
- package/dist/core/profile.js.map +1 -0
- package/dist/core/providers/amazon.js +36 -0
- package/dist/core/providers/amazon.js.map +1 -0
- package/dist/core/providers/ashby.js +31 -0
- package/dist/core/providers/ashby.js.map +1 -0
- package/dist/core/providers/google.js +46 -0
- package/dist/core/providers/google.js.map +1 -0
- package/dist/core/providers/greenhouse.js +55 -0
- package/dist/core/providers/greenhouse.js.map +1 -0
- package/dist/core/providers/http.js +36 -0
- package/dist/core/providers/http.js.map +1 -0
- package/dist/core/providers/index.js +53 -0
- package/dist/core/providers/index.js.map +1 -0
- package/dist/core/providers/lever.js +32 -0
- package/dist/core/providers/lever.js.map +1 -0
- package/dist/core/providers/playwright_generic.js +53 -0
- package/dist/core/providers/playwright_generic.js.map +1 -0
- package/dist/core/providers/types.js +2 -0
- package/dist/core/providers/types.js.map +1 -0
- package/dist/core/providers/workday.js +44 -0
- package/dist/core/providers/workday.js.map +1 -0
- package/dist/core/render.js +253 -0
- package/dist/core/render.js.map +1 -0
- package/dist/core/reports.js +257 -0
- package/dist/core/reports.js.map +1 -0
- package/dist/core/resources.js +40 -0
- package/dist/core/resources.js.map +1 -0
- package/dist/core/scan_engine.js +164 -0
- package/dist/core/scan_engine.js.map +1 -0
- package/dist/core/scheduler.js +117 -0
- package/dist/core/scheduler.js.map +1 -0
- package/dist/db.js +60 -0
- package/dist/db.js.map +1 -0
- package/dist/http/app.js +35 -0
- package/dist/http/app.js.map +1 -0
- package/dist/http/dashboard.js +131 -0
- package/dist/http/dashboard.js.map +1 -0
- package/dist/mcp/define.js +35 -0
- package/dist/mcp/define.js.map +1 -0
- package/dist/mcp/server.js +103 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/apply_prefill.js +167 -0
- package/dist/mcp/tools/apply_prefill.js.map +1 -0
- package/dist/mcp/tools/batch_evaluate.js +143 -0
- package/dist/mcp/tools/batch_evaluate.js.map +1 -0
- package/dist/mcp/tools/evaluate_job.js +181 -0
- package/dist/mcp/tools/evaluate_job.js.map +1 -0
- package/dist/mcp/tools/generate_materials.js +126 -0
- package/dist/mcp/tools/generate_materials.js.map +1 -0
- package/dist/mcp/tools/get_report.js +24 -0
- package/dist/mcp/tools/get_report.js.map +1 -0
- package/dist/mcp/tools/ops.js +321 -0
- package/dist/mcp/tools/ops.js.map +1 -0
- package/dist/mcp/tools/outreach.js +481 -0
- package/dist/mcp/tools/outreach.js.map +1 -0
- package/dist/mcp/tools/render_pdf.js +27 -0
- package/dist/mcp/tools/render_pdf.js.map +1 -0
- package/dist/mcp/tools/scan_portals.js +35 -0
- package/dist/mcp/tools/scan_portals.js.map +1 -0
- package/dist/mcp/tools/scheduler.js +32 -0
- package/dist/mcp/tools/scheduler.js.map +1 -0
- package/dist/mcp/tools/stories.js +172 -0
- package/dist/mcp/tools/stories.js.map +1 -0
- package/dist/mcp/tools/tracker.js +183 -0
- package/dist/mcp/tools/tracker.js.map +1 -0
- package/dist/mcp/tools/visa.js +219 -0
- package/dist/mcp/tools/visa.js.map +1 -0
- package/dist/migrations/001_initial.sql +505 -0
- package/dist/migrations/002_llm_and_digest.sql +42 -0
- package/dist/server.js +55 -0
- package/dist/server.js.map +1 -0
- package/fonts/dm-sans-latin-ext.woff2 +0 -0
- package/fonts/dm-sans-latin.woff2 +0 -0
- package/fonts/space-grotesk-latin-ext.woff2 +0 -0
- package/fonts/space-grotesk-latin.woff2 +0 -0
- package/modes/career_packet.md +91 -0
- package/modes/negotiation_playbook.md +64 -0
- package/modes/outreach_tone.md +80 -0
- package/modes/report_format.md +83 -0
- package/modes/rubric.md +119 -0
- package/modes/tailoring_rules.md +102 -0
- package/package.json +67 -0
- package/portals.example.yml +95 -0
- package/templates/cover-template.html +64 -0
- package/templates/cv-template.html +421 -0
- package/templates/cv-template.tex +123 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// job_ops-mcp CLI entry point. Subcommands:
|
|
3
|
+
// init — scaffold cv.md / config/profile.yml / portals.yml from the .example files,
|
|
4
|
+
// run migrations, prompt for project root. Idempotent (never overwrites).
|
|
5
|
+
// start — boot MCP + HTTP server. Auto-installs Chromium on first run.
|
|
6
|
+
// doctor — diagnose Node version, Chromium presence, config files, LLM key.
|
|
7
|
+
// connect — print copy-paste config for Claude Desktop + generic MCP clients.
|
|
8
|
+
import { existsSync, copyFileSync, mkdirSync, readFileSync, statSync } from 'node:fs';
|
|
9
|
+
import { resolve, dirname } from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
import { spawnSync, spawn } from 'node:child_process';
|
|
12
|
+
import { createInterface } from 'node:readline/promises';
|
|
13
|
+
import { stdin as input, stdout as output } from 'node:process';
|
|
14
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const PACKAGE_ROOT = resolve(here, '..'); // install root (where dist/, modes/, templates/, examples live)
|
|
16
|
+
const PKG = JSON.parse(readFileSync(resolve(PACKAGE_ROOT, 'package.json'), 'utf-8'));
|
|
17
|
+
// ── arg parser (tiny — no deps) ─────────────────────────────────────────────
|
|
18
|
+
function parseArgs(argv) {
|
|
19
|
+
const [, , cmd = 'help', ...rest] = argv;
|
|
20
|
+
const flags = new Map();
|
|
21
|
+
const positional = [];
|
|
22
|
+
for (let i = 0; i < rest.length; i++) {
|
|
23
|
+
const a = rest[i];
|
|
24
|
+
if (a.startsWith('--')) {
|
|
25
|
+
const [k, ...vparts] = a.slice(2).split('=');
|
|
26
|
+
const v = vparts.length ? vparts.join('=') : (rest[i + 1] && !rest[i + 1].startsWith('--') ? rest[++i] : true);
|
|
27
|
+
flags.set(k, v);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
positional.push(a);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return { cmd, flags, positional };
|
|
34
|
+
}
|
|
35
|
+
// ── color (tty-aware, no deps) ──────────────────────────────────────────────
|
|
36
|
+
const COLOR = process.stdout.isTTY;
|
|
37
|
+
const c = {
|
|
38
|
+
bold: (s) => COLOR ? `\x1b[1m${s}\x1b[0m` : s,
|
|
39
|
+
green: (s) => COLOR ? `\x1b[32m${s}\x1b[0m` : s,
|
|
40
|
+
red: (s) => COLOR ? `\x1b[31m${s}\x1b[0m` : s,
|
|
41
|
+
yellow: (s) => COLOR ? `\x1b[33m${s}\x1b[0m` : s,
|
|
42
|
+
dim: (s) => COLOR ? `\x1b[2m${s}\x1b[0m` : s,
|
|
43
|
+
};
|
|
44
|
+
const tick = () => COLOR ? c.green('✓') : 'OK ';
|
|
45
|
+
const cross = () => COLOR ? c.red('✗') : 'FAIL ';
|
|
46
|
+
const warn = () => COLOR ? c.yellow('!') : 'WARN ';
|
|
47
|
+
// ── init ────────────────────────────────────────────────────────────────────
|
|
48
|
+
async function cmdInit(flags) {
|
|
49
|
+
const yes = !!flags.get('yes');
|
|
50
|
+
console.log(c.bold(`\njob_ops-mcp init`));
|
|
51
|
+
console.log(c.dim(`package: ${PKG.name}@${PKG.version}`));
|
|
52
|
+
console.log(c.dim(`install root: ${PACKAGE_ROOT}\n`));
|
|
53
|
+
const cwd = process.cwd();
|
|
54
|
+
console.log(`Project root: ${c.bold(cwd)}`);
|
|
55
|
+
console.log(c.dim('(This is where cv.md, config/profile.yml, portals.yml will live. You can move them later — point the server at the new location with MCP_JSA_PROJECT_ROOT.)\n'));
|
|
56
|
+
const examples = [
|
|
57
|
+
{ src: 'cv.example.md', dst: 'cv.md', label: 'CV (markdown)' },
|
|
58
|
+
{ src: 'config/profile.example.yml', dst: 'config/profile.yml', label: 'profile / targeting' },
|
|
59
|
+
{ src: 'portals.example.yml', dst: 'portals.yml', label: 'tracked portals + filters' },
|
|
60
|
+
];
|
|
61
|
+
let scaffolded = 0, kept = 0;
|
|
62
|
+
for (const { src, dst, label } of examples) {
|
|
63
|
+
const srcAbs = resolve(PACKAGE_ROOT, src);
|
|
64
|
+
const dstAbs = resolve(cwd, dst);
|
|
65
|
+
if (!existsSync(srcAbs)) {
|
|
66
|
+
console.log(` ${cross()} example missing: ${src}`);
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (existsSync(dstAbs)) {
|
|
70
|
+
console.log(` ${warn()} ${dst} already exists — not overwriting (${label})`);
|
|
71
|
+
kept++;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
mkdirSync(dirname(dstAbs), { recursive: true });
|
|
75
|
+
copyFileSync(srcAbs, dstAbs);
|
|
76
|
+
console.log(` ${tick()} scaffolded ${dst} (${label})`);
|
|
77
|
+
scaffolded++;
|
|
78
|
+
}
|
|
79
|
+
// Run migrations by importing db.ts — getDb() applies pending migrations on first open.
|
|
80
|
+
// Set MCP_JSA_PROJECT_ROOT to cwd BEFORE config.ts gets imported so the data dir lives
|
|
81
|
+
// next to the user's cv.md / profile.yml, not inside the package install.
|
|
82
|
+
process.env.MCP_JSA_PROJECT_ROOT = process.env.MCP_JSA_PROJECT_ROOT || cwd;
|
|
83
|
+
try {
|
|
84
|
+
const { config: cfg } = await import('./config.js');
|
|
85
|
+
const { getDb } = await import('./db.js');
|
|
86
|
+
getDb();
|
|
87
|
+
const { ensureActiveCareerPacket } = await import('./core/profile.js');
|
|
88
|
+
const seed = ensureActiveCareerPacket();
|
|
89
|
+
console.log(`\n ${tick()} data dir: ${cfg.dataDir}`);
|
|
90
|
+
console.log(` ${tick()} SQLite migrations applied`);
|
|
91
|
+
console.log(` ${tick()} career_packet ${seed.created ? 'seeded' : 'present'} (v${seed.version})`);
|
|
92
|
+
}
|
|
93
|
+
catch (e) {
|
|
94
|
+
console.log(` ${cross()} migration error: ${e?.message ?? e}`);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
console.log(c.bold('\nNext steps:'));
|
|
98
|
+
console.log(` 1. Edit ${c.bold('cv.md')}, ${c.bold('config/profile.yml')}, and ${c.bold('portals.yml')} — replace every <TODO> placeholder.`);
|
|
99
|
+
console.log(` 2. Run ${c.bold('npx job_ops-mcp doctor')} to confirm everything is wired.`);
|
|
100
|
+
console.log(` 3. Run ${c.bold('npx job_ops-mcp start')} to boot the server.`);
|
|
101
|
+
console.log(` 4. Run ${c.bold('npx job_ops-mcp connect')} for Claude Desktop config.\n`);
|
|
102
|
+
if (scaffolded === 0 && kept > 0) {
|
|
103
|
+
console.log(c.dim('(All example files already present; init is idempotent — re-run safe.)'));
|
|
104
|
+
}
|
|
105
|
+
void yes; // reserved for future non-interactive prompts
|
|
106
|
+
}
|
|
107
|
+
// ── start ───────────────────────────────────────────────────────────────────
|
|
108
|
+
async function cmdStart(flags) {
|
|
109
|
+
// Default project root = cwd, so users who ran `init` get their files picked up.
|
|
110
|
+
if (!process.env.MCP_JSA_PROJECT_ROOT)
|
|
111
|
+
process.env.MCP_JSA_PROJECT_ROOT = process.cwd();
|
|
112
|
+
const skipBrowserCheck = !!flags.get('skip-chromium-check');
|
|
113
|
+
if (!skipBrowserCheck)
|
|
114
|
+
await ensureChromium();
|
|
115
|
+
await import('./server.js');
|
|
116
|
+
}
|
|
117
|
+
async function ensureChromium() {
|
|
118
|
+
// Detect a previously-installed Chromium by attempting `playwright.chromium.executablePath()`.
|
|
119
|
+
try {
|
|
120
|
+
const { chromium } = await import('playwright');
|
|
121
|
+
const path = chromium.executablePath();
|
|
122
|
+
if (path && existsSync(path))
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
catch { /* fall through to install */ }
|
|
126
|
+
console.log(c.bold('\n[one-time setup]'));
|
|
127
|
+
console.log('Playwright Chromium not found — downloading now (~150MB, one-time).');
|
|
128
|
+
console.log(c.dim(' $ npx playwright install chromium'));
|
|
129
|
+
const res = spawnSync('npx', ['playwright', 'install', 'chromium'], { stdio: 'inherit' });
|
|
130
|
+
if (res.status !== 0) {
|
|
131
|
+
console.error(c.red('Chromium install failed. Run `npx playwright install chromium` manually and re-try.'));
|
|
132
|
+
process.exit(1);
|
|
133
|
+
}
|
|
134
|
+
console.log(c.green('Chromium ready.\n'));
|
|
135
|
+
}
|
|
136
|
+
// ── doctor ──────────────────────────────────────────────────────────────────
|
|
137
|
+
async function cmdDoctor() {
|
|
138
|
+
console.log(c.bold(`\njob_ops-mcp doctor\n`));
|
|
139
|
+
let failures = 0;
|
|
140
|
+
// 1. Node version
|
|
141
|
+
const nodeMajor = Number(process.versions.node.split('.')[0]);
|
|
142
|
+
if (nodeMajor >= 20)
|
|
143
|
+
console.log(` ${tick()} Node ${process.versions.node} (>= 20 required)`);
|
|
144
|
+
else {
|
|
145
|
+
console.log(` ${cross()} Node ${process.versions.node} — need >= 20. Install from https://nodejs.org/`);
|
|
146
|
+
failures++;
|
|
147
|
+
}
|
|
148
|
+
// 2. Chromium
|
|
149
|
+
let chromiumOk = false;
|
|
150
|
+
try {
|
|
151
|
+
const { chromium } = await import('playwright');
|
|
152
|
+
const p = chromium.executablePath();
|
|
153
|
+
if (p && existsSync(p)) {
|
|
154
|
+
console.log(` ${tick()} Playwright Chromium: ${p}`);
|
|
155
|
+
chromiumOk = true;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
catch { /* fall through */ }
|
|
159
|
+
if (!chromiumOk) {
|
|
160
|
+
console.log(` ${cross()} Playwright Chromium missing. Fix: ${c.bold('npx playwright install chromium')}`);
|
|
161
|
+
failures++;
|
|
162
|
+
}
|
|
163
|
+
// 3. Project root + user config
|
|
164
|
+
const projectRoot = process.env.MCP_JSA_PROJECT_ROOT || process.cwd();
|
|
165
|
+
console.log(` ${tick()} project root: ${projectRoot}`);
|
|
166
|
+
for (const file of ['cv.md', 'config/profile.yml', 'portals.yml']) {
|
|
167
|
+
const p = resolve(projectRoot, file);
|
|
168
|
+
if (existsSync(p)) {
|
|
169
|
+
const size = statSync(p).size;
|
|
170
|
+
const tooSmall = size < 200;
|
|
171
|
+
if (tooSmall) {
|
|
172
|
+
console.log(` ${warn()} ${file} present but suspiciously small (${size} bytes) — did you replace the placeholders?`);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
console.log(` ${tick()} ${file} (${size} bytes)`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
console.log(` ${cross()} ${file} missing. Fix: ${c.bold('npx job_ops-mcp init')}`);
|
|
180
|
+
failures++;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// 4. LLM key (only required for api / batch paths)
|
|
184
|
+
const provider = (process.env.MCP_JSA_LLM_PROVIDER || 'gemini').toLowerCase();
|
|
185
|
+
const haveKey = (provider === 'gemini' && !!process.env.GEMINI_API_KEY)
|
|
186
|
+
|| (provider === 'deepseek' && !!process.env.DEEPSEEK_API_KEY);
|
|
187
|
+
if (haveKey)
|
|
188
|
+
console.log(` ${tick()} LLM provider: ${provider} (key set)`);
|
|
189
|
+
else if (provider === 'none')
|
|
190
|
+
console.log(` ${tick()} LLM provider: none (chat-mode only)`);
|
|
191
|
+
else
|
|
192
|
+
console.log(` ${warn()} LLM provider: ${provider} but no API key. chat-mode tools work; api/batch tools will error. Set ${c.bold(provider === 'gemini' ? 'GEMINI_API_KEY' : 'DEEPSEEK_API_KEY')} to enable.`);
|
|
193
|
+
// 5. Visa scoring flag
|
|
194
|
+
const visaOn = (process.env.MCP_JSA_VISA_SCORING ?? 'true').toLowerCase() !== 'false';
|
|
195
|
+
console.log(` ${tick()} visa scoring: ${visaOn ? 'on (0.5/0.3/0.2)' : 'off (0.6/0.4, visa tools hidden)'}`);
|
|
196
|
+
console.log('');
|
|
197
|
+
if (failures > 0) {
|
|
198
|
+
console.log(c.red(`${failures} check(s) failed.`));
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
console.log(c.green('All required checks passed. Run `npx job_ops-mcp start` to boot.\n'));
|
|
202
|
+
}
|
|
203
|
+
// ── connect ─────────────────────────────────────────────────────────────────
|
|
204
|
+
async function cmdConnect(flags) {
|
|
205
|
+
const port = String(flags.get('port') ?? process.env.MCP_JSA_PORT ?? '7891');
|
|
206
|
+
const host = String(flags.get('host') ?? process.env.MCP_JSA_HOST ?? '127.0.0.1');
|
|
207
|
+
const url = `http://${host}:${port}/mcp`;
|
|
208
|
+
// Host-resolvable from inside a Docker container (LibreChat default deploy shape).
|
|
209
|
+
// host.docker.internal works out-of-the-box on Docker Desktop (macOS/Windows) and on
|
|
210
|
+
// Linux when the compose file sets `extra_hosts: ["host.docker.internal:host-gateway"]`.
|
|
211
|
+
const dockerHost = 'host.docker.internal';
|
|
212
|
+
const dockerUrl = `http://${dockerHost}:${port}/mcp`;
|
|
213
|
+
console.log(c.bold(`\njob_ops-mcp connect\n`));
|
|
214
|
+
console.log(`Server endpoint: ${c.bold(url)}\n`);
|
|
215
|
+
console.log(c.bold('Generic MCP client (streamable-HTTP, stateless):'));
|
|
216
|
+
console.log(JSON.stringify({
|
|
217
|
+
name: 'job_ops-mcp',
|
|
218
|
+
transport: 'streamable-http',
|
|
219
|
+
url,
|
|
220
|
+
}, null, 2));
|
|
221
|
+
console.log(c.bold('\nClaude Desktop — claude_desktop_config.json:'));
|
|
222
|
+
console.log(c.dim('macOS: ~/Library/Application Support/Claude/claude_desktop_config.json'));
|
|
223
|
+
console.log(c.dim('Windows: %APPDATA%/Claude/claude_desktop_config.json\n'));
|
|
224
|
+
console.log(JSON.stringify({
|
|
225
|
+
mcpServers: {
|
|
226
|
+
'job_ops-mcp': {
|
|
227
|
+
command: 'npx',
|
|
228
|
+
args: ['-y', PKG.name, 'start'],
|
|
229
|
+
env: {
|
|
230
|
+
MCP_JSA_PORT: port,
|
|
231
|
+
MCP_JSA_HOST: host,
|
|
232
|
+
MCP_JSA_PROJECT_ROOT: process.cwd(),
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
}, null, 2));
|
|
237
|
+
console.log(c.bold('\nClaude Desktop — manual streamable-HTTP (if the npx form is unsupported):'));
|
|
238
|
+
console.log(c.dim('First boot the server in a separate terminal: `npx job_ops-mcp start`, then:'));
|
|
239
|
+
console.log(JSON.stringify({
|
|
240
|
+
mcpServers: {
|
|
241
|
+
'job_ops-mcp': { transport: { type: 'streamable-http', url } },
|
|
242
|
+
},
|
|
243
|
+
}, null, 2));
|
|
244
|
+
// ── LibreChat ────────────────────────────────────────────────────────────
|
|
245
|
+
// LibreChat's MCP transport for HTTP endpoints is `type: streamable-http`
|
|
246
|
+
// (NOT `sse` — that's a separate legacy transport). Add to `librechat.yaml`
|
|
247
|
+
// under `mcpServers:`. Docs: librechat.ai/docs/configuration/librechat_yaml/object_structure/mcp_servers
|
|
248
|
+
console.log(c.bold('\nLibreChat — librechat.yaml (host-process deploy):'));
|
|
249
|
+
console.log(c.dim('Add under top-level `mcpServers:` in your librechat.yaml, then restart LibreChat.\n'));
|
|
250
|
+
console.log(yamlBlock({
|
|
251
|
+
mcpServers: {
|
|
252
|
+
'job_ops-mcp': {
|
|
253
|
+
type: 'streamable-http',
|
|
254
|
+
url,
|
|
255
|
+
timeout: 60000,
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
}));
|
|
259
|
+
console.log(c.bold('\nLibreChat in Docker — librechat.yaml + SSRF allowlist:'));
|
|
260
|
+
console.log(c.dim('Inside a container, 127.0.0.1 points at the CONTAINER, not your host. Swap to ' +
|
|
261
|
+
'host.docker.internal (Docker Desktop) or a LAN IP (Linux + extra_hosts).\n' +
|
|
262
|
+
'LibreChat ALSO blocks private/internal addresses by default — you must allowlist ' +
|
|
263
|
+
'them under `mcpSettings.allowedAddresses`. Both blocks below go into librechat.yaml:\n'));
|
|
264
|
+
console.log(yamlBlock({
|
|
265
|
+
mcpServers: {
|
|
266
|
+
'job_ops-mcp': {
|
|
267
|
+
type: 'streamable-http',
|
|
268
|
+
url: dockerUrl,
|
|
269
|
+
timeout: 60000,
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
mcpSettings: {
|
|
273
|
+
allowedAddresses: [`${dockerHost}:${port}`],
|
|
274
|
+
},
|
|
275
|
+
}));
|
|
276
|
+
console.log(c.dim('\nLinux note: if `host.docker.internal` does not resolve, either add\n' +
|
|
277
|
+
' extra_hosts:\n' +
|
|
278
|
+
' - "host.docker.internal:host-gateway"\n' +
|
|
279
|
+
'under the LibreChat service in your docker-compose.yml, or swap the URL for your\n' +
|
|
280
|
+
"host's LAN IP and allowlist that IP:port instead."));
|
|
281
|
+
console.log('');
|
|
282
|
+
}
|
|
283
|
+
// ── tiny YAML serializer (object → block-style YAML, two-space indent) ──────
|
|
284
|
+
// Just enough for `mcpServers` + `mcpSettings.allowedAddresses` shapes — no deps.
|
|
285
|
+
function yamlBlock(o, indent = 0) {
|
|
286
|
+
const pad = ' '.repeat(indent);
|
|
287
|
+
if (o === null || o === undefined)
|
|
288
|
+
return `${pad}~`;
|
|
289
|
+
if (typeof o === 'string')
|
|
290
|
+
return /^[\w./:@#$%^&*()+=,?!{}\[\]-]+$/.test(o) ? o : JSON.stringify(o);
|
|
291
|
+
if (typeof o === 'number' || typeof o === 'boolean')
|
|
292
|
+
return String(o);
|
|
293
|
+
if (Array.isArray(o)) {
|
|
294
|
+
if (o.length === 0)
|
|
295
|
+
return '[]';
|
|
296
|
+
return o.map(v => `${pad}- ${yamlBlock(v, indent + 1).replace(/^\s+/, '')}`).join('\n');
|
|
297
|
+
}
|
|
298
|
+
if (typeof o === 'object') {
|
|
299
|
+
const entries = Object.entries(o);
|
|
300
|
+
if (entries.length === 0)
|
|
301
|
+
return '{}';
|
|
302
|
+
return entries.map(([k, v]) => {
|
|
303
|
+
const isObj = v && typeof v === 'object' && !Array.isArray(v);
|
|
304
|
+
const isArr = Array.isArray(v);
|
|
305
|
+
if (isObj || isArr) {
|
|
306
|
+
const child = yamlBlock(v, indent + 1);
|
|
307
|
+
return `${pad}${k}:\n${child}`;
|
|
308
|
+
}
|
|
309
|
+
return `${pad}${k}: ${yamlBlock(v, indent + 1)}`;
|
|
310
|
+
}).join('\n');
|
|
311
|
+
}
|
|
312
|
+
return JSON.stringify(o);
|
|
313
|
+
}
|
|
314
|
+
// ── help ────────────────────────────────────────────────────────────────────
|
|
315
|
+
function cmdHelp() {
|
|
316
|
+
console.log(`
|
|
317
|
+
${c.bold('job_ops-mcp')} — self-hosted MCP server for an end-to-end job search pipeline.
|
|
318
|
+
|
|
319
|
+
USAGE
|
|
320
|
+
npx job_ops-mcp <command> [flags]
|
|
321
|
+
|
|
322
|
+
COMMANDS
|
|
323
|
+
init Scaffold cv.md / config/profile.yml / portals.yml from examples
|
|
324
|
+
and run SQLite migrations. Idempotent.
|
|
325
|
+
start Boot the MCP + HTTP server. Auto-installs Chromium on first run.
|
|
326
|
+
doctor Diagnose Node version, Chromium, config files, LLM key.
|
|
327
|
+
connect Print copy-paste MCP client config (Claude Desktop + generic).
|
|
328
|
+
help Show this message.
|
|
329
|
+
|
|
330
|
+
ENV
|
|
331
|
+
MCP_JSA_PORT default 7891
|
|
332
|
+
MCP_JSA_HOST default 127.0.0.1
|
|
333
|
+
MCP_JSA_PROJECT_ROOT where cv.md / config/profile.yml / portals.yml live
|
|
334
|
+
default: current working dir
|
|
335
|
+
MCP_JSA_DATA_DIR SQLite location; default <install>/data
|
|
336
|
+
MCP_JSA_VISA_SCORING true | false (default true) — disables visa surface entirely
|
|
337
|
+
MCP_JSA_LLM_PROVIDER gemini | deepseek | none (api/batch tools only)
|
|
338
|
+
GEMINI_API_KEY / DEEPSEEK_API_KEY
|
|
339
|
+
|
|
340
|
+
LEARN MORE
|
|
341
|
+
README: ${PKG.homepage || 'https://github.com/<you>/job_ops-mcp'}
|
|
342
|
+
`);
|
|
343
|
+
}
|
|
344
|
+
// ── main ────────────────────────────────────────────────────────────────────
|
|
345
|
+
async function main() {
|
|
346
|
+
const { cmd, flags } = parseArgs(process.argv);
|
|
347
|
+
try {
|
|
348
|
+
switch (cmd) {
|
|
349
|
+
case 'init':
|
|
350
|
+
await cmdInit(flags);
|
|
351
|
+
break;
|
|
352
|
+
case 'start':
|
|
353
|
+
await cmdStart(flags);
|
|
354
|
+
break;
|
|
355
|
+
case 'doctor':
|
|
356
|
+
await cmdDoctor();
|
|
357
|
+
break;
|
|
358
|
+
case 'connect':
|
|
359
|
+
await cmdConnect(flags);
|
|
360
|
+
break;
|
|
361
|
+
case '--version':
|
|
362
|
+
case '-v':
|
|
363
|
+
case 'version':
|
|
364
|
+
console.log(PKG.version);
|
|
365
|
+
break;
|
|
366
|
+
case 'help':
|
|
367
|
+
case '--help':
|
|
368
|
+
case '-h':
|
|
369
|
+
default:
|
|
370
|
+
cmdHelp();
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
catch (e) {
|
|
375
|
+
console.error(c.red(`\n[fatal] ${e?.message ?? e}`));
|
|
376
|
+
process.exit(1);
|
|
377
|
+
}
|
|
378
|
+
// Suppress unused-import warning for spawn (reserved for future).
|
|
379
|
+
void spawn;
|
|
380
|
+
void createInterface;
|
|
381
|
+
void input;
|
|
382
|
+
void output;
|
|
383
|
+
}
|
|
384
|
+
main();
|
|
385
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Centralized config — every other module imports from here so env-var changes are obvious.
|
|
2
|
+
import { existsSync, mkdirSync } from 'node:fs';
|
|
3
|
+
import { resolve, dirname, isAbsolute } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const INSTALL_DIR = resolve(here, '..'); // dist/ → install root
|
|
7
|
+
function abs(p, base) {
|
|
8
|
+
return isAbsolute(p) ? p : resolve(base, p);
|
|
9
|
+
}
|
|
10
|
+
function envNum(name, fallback) {
|
|
11
|
+
const v = process.env[name];
|
|
12
|
+
if (!v)
|
|
13
|
+
return fallback;
|
|
14
|
+
const n = Number(v);
|
|
15
|
+
return Number.isFinite(n) ? n : fallback;
|
|
16
|
+
}
|
|
17
|
+
function envBool(name, fallback) {
|
|
18
|
+
const v = process.env[name];
|
|
19
|
+
if (!v)
|
|
20
|
+
return fallback;
|
|
21
|
+
return ['1', 'true', 'yes', 'on'].includes(v.toLowerCase());
|
|
22
|
+
}
|
|
23
|
+
export function loadConfig() {
|
|
24
|
+
const installDir = INSTALL_DIR;
|
|
25
|
+
// Project root defaults to CWD, NOT installDir — for npx users this means cv.md,
|
|
26
|
+
// profile.yml, portals.yml, the SQLite DB, and output/ all live next to each other
|
|
27
|
+
// in the user's working directory. installDir stays read-only.
|
|
28
|
+
const projectRoot = process.env.MCP_JSA_PROJECT_ROOT
|
|
29
|
+
? abs(process.env.MCP_JSA_PROJECT_ROOT, process.cwd())
|
|
30
|
+
: process.cwd();
|
|
31
|
+
const dataDir = abs(process.env.MCP_JSA_DATA_DIR || './data', projectRoot);
|
|
32
|
+
const outputDir = abs(process.env.MCP_JSA_OUTPUT_DIR || './output', projectRoot);
|
|
33
|
+
// modes/templates/fonts ship with the package — always read from installDir.
|
|
34
|
+
const modesDir = resolve(installDir, 'modes');
|
|
35
|
+
const templatesDir = resolve(installDir, 'templates');
|
|
36
|
+
const fontsDir = resolve(installDir, 'fonts');
|
|
37
|
+
const dbPath = resolve(dataDir, 'mcp-jsa.db');
|
|
38
|
+
for (const dir of [dataDir, outputDir]) {
|
|
39
|
+
if (!existsSync(dir))
|
|
40
|
+
mkdirSync(dir, { recursive: true });
|
|
41
|
+
}
|
|
42
|
+
const host = process.env.MCP_JSA_HOST || '127.0.0.1';
|
|
43
|
+
const port = envNum('MCP_JSA_PORT', 7891);
|
|
44
|
+
return {
|
|
45
|
+
installDir,
|
|
46
|
+
projectRoot,
|
|
47
|
+
dataDir,
|
|
48
|
+
outputDir,
|
|
49
|
+
modesDir,
|
|
50
|
+
templatesDir,
|
|
51
|
+
fontsDir,
|
|
52
|
+
dbPath,
|
|
53
|
+
port,
|
|
54
|
+
host,
|
|
55
|
+
baseUrl: `http://${host}:${port}`,
|
|
56
|
+
schedulerEnabled: envBool('MCP_JSA_SCHEDULER_ENABLED', false),
|
|
57
|
+
llmProvider: process.env.MCP_JSA_LLM_PROVIDER || 'none',
|
|
58
|
+
llmModel: process.env.MCP_JSA_LLM_MODEL || null,
|
|
59
|
+
visaScoringEnabled: envBool('MCP_JSA_VISA_SCORING', true),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
export const config = loadConfig();
|
|
63
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// One shared headless Chromium for the whole process. render_pdf, scan providers,
|
|
2
|
+
// and apply_prefill all use this — launching Chromium per call is ~300-800ms and
|
|
3
|
+
// memory-heavy.
|
|
4
|
+
let _browser = null;
|
|
5
|
+
let _launching = null;
|
|
6
|
+
export async function getSharedBrowser() {
|
|
7
|
+
if (_browser)
|
|
8
|
+
return _browser;
|
|
9
|
+
if (_launching)
|
|
10
|
+
return _launching;
|
|
11
|
+
_launching = (async () => {
|
|
12
|
+
const { chromium } = await import('playwright');
|
|
13
|
+
const b = await chromium.launch({ headless: true });
|
|
14
|
+
_browser = b;
|
|
15
|
+
_launching = null;
|
|
16
|
+
return b;
|
|
17
|
+
})();
|
|
18
|
+
return _launching;
|
|
19
|
+
}
|
|
20
|
+
export async function closeSharedBrowser() {
|
|
21
|
+
if (_browser) {
|
|
22
|
+
await _browser.close().catch(() => undefined);
|
|
23
|
+
_browser = null;
|
|
24
|
+
}
|
|
25
|
+
_launching = null;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/core/browser.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,iFAAiF;AACjF,gBAAgB;AAIhB,IAAI,QAAQ,GAAmB,IAAI,CAAC;AACpC,IAAI,UAAU,GAA4B,IAAI,CAAC;AAE/C,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,IAAI,UAAU;QAAE,OAAO,UAAU,CAAC;IAClC,UAAU,GAAG,CAAC,KAAK,IAAI,EAAE;QACvB,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,QAAQ,GAAG,CAAC,CAAC;QACb,UAAU,GAAG,IAAI,CAAC;QAClB,OAAO,CAAC,CAAC;IACX,CAAC,CAAC,EAAE,CAAC;IACL,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,IAAI,QAAQ,EAAE,CAAC;QAAC,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAAC,QAAQ,GAAG,IAAI,CAAC;IAAC,CAAC;IACjF,UAAU,GAAG,IAAI,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Content-hash for cross-source job dedup (study guide §3.2.5).
|
|
2
|
+
// Hashes a normalized triple — (company, title, location) — lowercased and stripped of
|
|
3
|
+
// whitespace runs so the same role at the same company on Greenhouse + Workday collapses
|
|
4
|
+
// to the same hash even when the URLs differ.
|
|
5
|
+
import { createHash } from 'node:crypto';
|
|
6
|
+
export function contentHash(parts) {
|
|
7
|
+
const norm = (s) => (s ?? '').toLowerCase().replace(/\s+/g, ' ').trim();
|
|
8
|
+
const blob = [norm(parts.company), norm(parts.title), norm(parts.location)].join('|');
|
|
9
|
+
return createHash('sha256').update(blob, 'utf-8').digest('hex');
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=content_hash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content_hash.js","sourceRoot":"","sources":["../../src/core/content_hash.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,uFAAuF;AACvF,yFAAyF;AACzF,8CAA8C;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,UAAU,WAAW,CAAC,KAAmE;IAC7F,MAAM,IAAI,GAAG,CAAC,CAA4B,EAAE,EAAE,CAC5C,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACtD,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtF,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAClE,CAAC"}
|
package/dist/core/csv.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// Minimal CSV parser — RFC 4180 with quoted fields, embedded commas, CRLF, escaped quotes.
|
|
2
|
+
// We avoid a dep here because LinkedIn's Connections.csv export and the DOL OFLC CSVs we
|
|
3
|
+
// ingest are both well-formed.
|
|
4
|
+
//
|
|
5
|
+
// Also exports helpers shared by every CSV importer:
|
|
6
|
+
// - pickHeader(row) : returns a `get(row, ...aliases)` closure that's O(1) per row
|
|
7
|
+
// (vs O(headers) per lookup the naive way)
|
|
8
|
+
// - parseMaybeNumber : strips $/, returns null when not finite
|
|
9
|
+
// - expandUserPath : ~ → $HOME, then absolutize against cwd
|
|
10
|
+
import { resolve } from 'node:path';
|
|
11
|
+
export function parseCsv(text) {
|
|
12
|
+
const rows = [];
|
|
13
|
+
let field = '';
|
|
14
|
+
let row = [];
|
|
15
|
+
let inQuotes = false;
|
|
16
|
+
for (let i = 0; i < text.length; i++) {
|
|
17
|
+
const ch = text[i];
|
|
18
|
+
if (inQuotes) {
|
|
19
|
+
if (ch === '"') {
|
|
20
|
+
if (text[i + 1] === '"') {
|
|
21
|
+
field += '"';
|
|
22
|
+
i++;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
inQuotes = false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
field += ch;
|
|
30
|
+
}
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (ch === '"') {
|
|
34
|
+
inQuotes = true;
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (ch === ',') {
|
|
38
|
+
row.push(field);
|
|
39
|
+
field = '';
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (ch === '\r')
|
|
43
|
+
continue;
|
|
44
|
+
if (ch === '\n') {
|
|
45
|
+
row.push(field);
|
|
46
|
+
field = '';
|
|
47
|
+
rows.push(row);
|
|
48
|
+
row = [];
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
field += ch;
|
|
52
|
+
}
|
|
53
|
+
if (field.length || row.length) {
|
|
54
|
+
row.push(field);
|
|
55
|
+
rows.push(row);
|
|
56
|
+
}
|
|
57
|
+
return rows.filter(r => r.length > 1 || (r[0] && r[0].trim().length));
|
|
58
|
+
}
|
|
59
|
+
export function rowsToObjects(rows) {
|
|
60
|
+
if (rows.length < 2)
|
|
61
|
+
return [];
|
|
62
|
+
const header = rows[0].map(h => h.trim());
|
|
63
|
+
return rows.slice(1).map(r => {
|
|
64
|
+
const o = {};
|
|
65
|
+
for (let i = 0; i < header.length; i++)
|
|
66
|
+
o[header[i]] = (r[i] ?? '').trim();
|
|
67
|
+
return o;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
// Header lookup with alias support. Build ONCE from the header row, then call the
|
|
71
|
+
// returned getter per data row — O(1) per lookup vs O(headers) for the naive approach.
|
|
72
|
+
// 200k DOL rows × 20 lookups stops being a hot spot.
|
|
73
|
+
export function pickHeader(header) {
|
|
74
|
+
const index = new Map();
|
|
75
|
+
for (let i = 0; i < header.length; i++)
|
|
76
|
+
index.set(header[i].toLowerCase().trim(), i);
|
|
77
|
+
return (row, ...aliases) => {
|
|
78
|
+
for (const a of aliases) {
|
|
79
|
+
const i = index.get(a.toLowerCase().trim());
|
|
80
|
+
if (i !== undefined)
|
|
81
|
+
return (row[i] ?? '').trim();
|
|
82
|
+
}
|
|
83
|
+
return '';
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
export function parseMaybeNumber(s) {
|
|
87
|
+
if (!s)
|
|
88
|
+
return null;
|
|
89
|
+
const n = Number(s.replace(/[,$]/g, ''));
|
|
90
|
+
return Number.isFinite(n) ? n : null;
|
|
91
|
+
}
|
|
92
|
+
export function expandUserPath(p) {
|
|
93
|
+
return resolve(p.startsWith('~') ? p.replace('~', process.env.HOME ?? '') : p);
|
|
94
|
+
}
|
|
95
|
+
// Try to skip LinkedIn's leading preamble.
|
|
96
|
+
export function findLinkedinHeader(rows) {
|
|
97
|
+
for (let i = 0; i < Math.min(rows.length, 12); i++) {
|
|
98
|
+
const r = rows[i];
|
|
99
|
+
if (!r)
|
|
100
|
+
continue;
|
|
101
|
+
const lower = r.map(c => c.toLowerCase());
|
|
102
|
+
if (lower.includes('first name') && lower.includes('last name') && lower.some(c => c.includes('connect')))
|
|
103
|
+
return i;
|
|
104
|
+
}
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=csv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csv.js","sourceRoot":"","sources":["../../src/core/csv.ts"],"names":[],"mappings":"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"}
|