job_ops-mcp 0.4.2 → 0.4.3

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.
@@ -10,6 +10,61 @@
10
10
  const FETCH_TIMEOUT_MS = 12_000;
11
11
  const MAX_JD_CHARS = 18_000;
12
12
  const USER_AGENT = 'Mozilla/5.0 (compatible; mcp-jsa/0.1)';
13
+ /**
14
+ * Best-effort extraction of the company name from a known ATS URL. Returns a
15
+ * Title-Cased company name when the URL matches a recognised host, else null.
16
+ * Exported for tests + direct use in adoptJobFromJD.
17
+ *
18
+ * greenhouse: https://(job-boards|boards|job-boards.eu).greenhouse.io/<slug>
19
+ * ashby: https://jobs.ashbyhq.com/<slug>
20
+ * lever: https://jobs.lever.co/<slug>
21
+ * workday: https://<tenant>.wd<N>.myworkdayjobs.com/<site>
22
+ * amazon: https://*.amazon.jobs/* → "Amazon"
23
+ * google careers: https://www.google.com/about/careers/* → "Google"
24
+ */
25
+ export function extractCompanyFromUrl(url) {
26
+ if (!url)
27
+ return null;
28
+ let parsed;
29
+ try {
30
+ parsed = new URL(url);
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ const host = parsed.hostname.toLowerCase();
36
+ const path = parsed.pathname;
37
+ if (/(?:^|\.)greenhouse\.io$/.test(host)) {
38
+ const m = path.match(/^\/([^/]+)/);
39
+ if (m)
40
+ return titleCaseSlug(m[1]);
41
+ }
42
+ if (host === 'jobs.ashbyhq.com') {
43
+ const m = path.match(/^\/([^/]+)/);
44
+ if (m)
45
+ return titleCaseSlug(m[1]);
46
+ }
47
+ if (host === 'jobs.lever.co') {
48
+ const m = path.match(/^\/([^/]+)/);
49
+ if (m)
50
+ return titleCaseSlug(m[1]);
51
+ }
52
+ const wd = host.match(/^([^.]+)\.wd\d+\.myworkdayjobs\.com$/);
53
+ if (wd)
54
+ return titleCaseSlug(wd[1]);
55
+ if (host === 'www.amazon.jobs' || host === 'amazon.jobs')
56
+ return 'Amazon';
57
+ if (host === 'www.google.com' && /^\/about\/careers/.test(path))
58
+ return 'Google';
59
+ return null;
60
+ }
61
+ function titleCaseSlug(slug) {
62
+ return slug
63
+ .split(/[-_]+/)
64
+ .filter(Boolean)
65
+ .map(w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())
66
+ .join(' ');
67
+ }
13
68
  export async function normalizeJD(input) {
14
69
  const trimmed = input.trim();
15
70
  if (looksLikeUrl(trimmed)) {
@@ -42,11 +97,15 @@ async function fetchFromUrl(url) {
42
97
  const ogSite = extractMeta(html, 'og:site_name');
43
98
  const ogTitle = extractMeta(html, 'og:title');
44
99
  const text = htmlToPlainText(html);
100
+ // URL-derived company is authoritative for known ATS hosts. og:site_name on those
101
+ // hosts is often the ATS vendor ("Greenhouse"), not the hiring company, so prefer
102
+ // the slug. Fall back to OG site_name for unknown hosts.
103
+ const company_guess = extractCompanyFromUrl(url) ?? ogSite ?? null;
45
104
  return {
46
105
  source: 'url',
47
106
  source_url: url,
48
107
  title_guess: ogTitle ?? title ?? null,
49
- company_guess: ogSite ?? null,
108
+ company_guess,
50
109
  text: text.slice(0, MAX_JD_CHARS),
51
110
  raw_html: html.slice(0, MAX_JD_CHARS * 2),
52
111
  fetched_at: new Date().toISOString(),
@@ -1 +1 @@
1
- {"version":3,"file":"jd_normalize.js","sourceRoot":"","sources":["../../src/core/jd_normalize.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"jd_normalize.js","sourceRoot":"","sources":["../../src/core/jd_normalize.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,EAAE;AACF,yCAAyC;AACzC,8DAA8D;AAC9D,iDAAiD;AACjD,EAAE;AACF,sFAAsF;AACtF,wFAAwF;AACxF,gDAAgD;AAEhD,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAChC,MAAM,YAAY,GAAO,MAAM,CAAC;AAChC,MAAM,UAAU,GAAS,uCAAuC,CAAC;AAEjE;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAA8B;IAClE,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QAAC,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;IACrD,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC;IAE7B,IAAI,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACnC,IAAI,CAAC;YAAE,OAAO,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,CAAC;IACD,IAAI,IAAI,KAAK,kBAAkB,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACnC,IAAI,CAAC;YAAE,OAAO,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,CAAC;IACD,IAAI,IAAI,KAAK,eAAe,EAAE,CAAC;QAC7B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACnC,IAAI,CAAC;YAAE,OAAO,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,CAAC;IACD,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC9D,IAAI,EAAE;QAAE,OAAO,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,IAAI,IAAI,KAAK,iBAAiB,IAAI,IAAI,KAAK,aAAa;QAAE,OAAO,QAAQ,CAAC;IAC1E,IAAI,IAAI,KAAK,gBAAgB,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,QAAQ,CAAC;IACjF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,IAAI;SACR,KAAK,CAAC,OAAO,CAAC;SACd,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;SAC9D,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAYD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAa;IAC7C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1B,OAAO,YAAY,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO;QACL,MAAM,EAAE,OAAO;QACf,UAAU,EAAE,IAAI;QAChB,WAAW,EAAE,IAAI;QACjB,aAAa,EAAE,IAAI;QACnB,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC;QACpC,QAAQ,EAAE,IAAI;QACd,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACrC,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,CAAS;IAC7B,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACzE,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,GAAW;IACrC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,gBAAgB,CAAC,CAAC;IACrE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,OAAO,EAAE,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,iCAAiC,EAAE;YAClF,MAAM,EAAE,UAAU,CAAC,MAAM;YACzB,QAAQ,EAAE,QAAQ;SACnB,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAK,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAI,WAAW,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC9C,MAAM,IAAI,GAAM,eAAe,CAAC,IAAI,CAAC,CAAC;QACtC,kFAAkF;QAClF,kFAAkF;QAClF,yDAAyD;QACzD,MAAM,aAAa,GAAG,qBAAqB,CAAC,GAAG,CAAC,IAAI,MAAM,IAAI,IAAI,CAAC;QACnE,OAAO;YACL,MAAM,EAAE,KAAK;YACb,UAAU,EAAE,GAAG;YACf,WAAW,EAAE,OAAO,IAAI,KAAK,IAAI,IAAI;YACrC,aAAa;YACb,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC;YACjC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,GAAG,CAAC,CAAC;YACzC,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACrC,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,GAAW;IAC3C,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,IAAI,GAAG,uBAAuB,GAAG,GAAG,EAAE,GAAG,CAAC,CAAC;IACjE,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACzB,OAAO,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3D,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,QAAgB;IACjD,8FAA8F;IAC9F,MAAM,EAAE,GAAG,IAAI,MAAM,CACnB,uCAAuC,QAAQ,CAAC,OAAO,CAAC,wBAAwB,EAAE,MAAM,CAAC,oCAAoC,EAC7H,GAAG,CACJ,CAAC;IACF,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACzB,OAAO,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAChD,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,kFAAkF;IAClF,OAAO,cAAc,CACnB,IAAI;SACD,OAAO,CAAC,+BAA+B,EAAE,GAAG,CAAC;SAC7C,OAAO,CAAC,6BAA6B,EAAI,GAAG,CAAC;SAC7C,OAAO,CAAC,mCAAmC,EAAE,GAAG,CAAC;SACjD,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC;SAC7B,OAAO,CAAC,uDAAuD,EAAE,IAAI,CAAC;SACtE,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC;SACxB,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC;SAC1B,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC;SAC1B,IAAI,EAAE,CACV,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,cAAc,CAAC,CAAS;IAC/B,OAAO,CAAC;SACL,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,OAAO,CAAC,QAAQ,EAAG,GAAG,CAAC;SACvB,OAAO,CAAC,OAAO,EAAI,GAAG,CAAC;SACvB,OAAO,CAAC,OAAO,EAAI,GAAG,CAAC;SACvB,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,OAAO,CAAC,QAAQ,EAAG,GAAG,CAAC;SACvB,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;AAC1E,CAAC"}
@@ -83,10 +83,37 @@ export const generateMaterialsTool = defineTool({
83
83
  }
84
84
  },
85
85
  });
86
+ /**
87
+ * Concatenates the materials fields that end up in the actual delivered resume + cover
88
+ * letter. Used by the visa-rail scan. Internal-only fields (tailoring_notes, debug
89
+ * scratch) are deliberately excluded — a chat note saying "I made sure not to mention
90
+ * visa" should NOT trip the rail. Exported for tests.
91
+ */
92
+ export function candidateFacingMaterialsText(m) {
93
+ const parts = [];
94
+ if (typeof m?.tagline === 'string')
95
+ parts.push(m.tagline);
96
+ if (m?.experience_bullets && typeof m.experience_bullets === 'object') {
97
+ for (const v of Object.values(m.experience_bullets)) {
98
+ if (Array.isArray(v)) {
99
+ for (const b of v)
100
+ if (typeof b === 'string')
101
+ parts.push(b);
102
+ }
103
+ }
104
+ }
105
+ if (typeof m?.projects_section === 'string')
106
+ parts.push(m.projects_section);
107
+ if (typeof m?.skills_section === 'string')
108
+ parts.push(m.skills_section);
109
+ if (typeof m?.cover_letter_body === 'string')
110
+ parts.push(m.cover_letter_body);
111
+ return parts.join('\n');
112
+ }
86
113
  async function persistMaterials(job_id, m) {
87
- // Final visa rail across all generated text.
88
- const blob = JSON.stringify(m ?? {});
89
- const leaks = scanForVisaLeakage(blob);
114
+ // Visa rail across only the candidate-facing text. tailoring_notes is internal meta
115
+ // and may legitimately mention visa as a deliberate-omission note — don't trip on it.
116
+ const leaks = scanForVisaLeakage(candidateFacingMaterialsText(m));
90
117
  if (leaks.length) {
91
118
  throw new Error(`materials failed visa rail: ${JSON.stringify(leaks)} — not persisted`);
92
119
  }
@@ -1 +1 @@
1
- {"version":3,"file":"generate_materials.js","sourceRoot":"","sources":["../../../src/mcp/tools/generate_materials.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generate_materials.js","sourceRoot":"","sources":["../../../src/mcp/tools/generate_materials.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,15 @@
1
1
  import { z } from 'zod';
2
+ import { randomUUID } from 'node:crypto';
2
3
  import { renderPdf } from '../../core/render.js';
4
+ import { getDb, runInWriteLock } from '../../db.js';
3
5
  import { defineTool, okResult, errResult } from '../define.js';
4
6
  export const renderPdfTool = defineTool({
5
7
  name: 'render_pdf',
6
8
  title: 'Render resume/cover PDF',
7
- description: 'HTML → PDF via Playwright using the career-ops template. Returns a localhost link for each file.',
9
+ description: 'HTML → PDF via Playwright using the career-ops template. Returns a localhost link ' +
10
+ 'per file AND writes resume_path / cover_path onto the application row so the ' +
11
+ 'tracker, apply_prefill, and daily_digest can find the artifacts. Advances ' +
12
+ 'materials_drafted → ready_to_review in the job lifecycle.',
8
13
  inputSchema: {
9
14
  job_id: z.string().min(1),
10
15
  kind: z.enum(['resume', 'cover', 'both']).default('resume'),
@@ -14,9 +19,13 @@ export const renderPdfTool = defineTool({
14
19
  handler: async (args) => {
15
20
  try {
16
21
  const files = await renderPdf(args);
22
+ const persisted = await persistRenderedFiles(args.job_id, files);
17
23
  return okResult({
18
24
  job_id: args.job_id,
19
25
  files: files.map(f => ({ kind: f.kind, url: f.url, bytes: f.bytes, path: f.path })),
26
+ application_id: persisted.application_id,
27
+ application_status: persisted.status,
28
+ status_advanced: persisted.status_advanced,
20
29
  });
21
30
  }
22
31
  catch (err) {
@@ -24,4 +33,54 @@ export const renderPdfTool = defineTool({
24
33
  }
25
34
  },
26
35
  });
36
+ export async function persistRenderedFiles(job_id, files) {
37
+ const resume = files.find(f => f.kind === 'resume')?.path ?? null;
38
+ const cover = files.find(f => f.kind === 'cover')?.path ?? null;
39
+ return runInWriteLock(() => {
40
+ const db = getDb();
41
+ const existing = db.prepare(`
42
+ SELECT id, status FROM applications WHERE job_id = ?
43
+ `).get(job_id);
44
+ const PRE_RENDER = new Set(['materials_drafted', 'render_error']);
45
+ if (existing) {
46
+ const advance = PRE_RENDER.has(existing.status);
47
+ db.prepare(`
48
+ UPDATE applications SET
49
+ resume_path = COALESCE(?, resume_path),
50
+ cover_path = COALESCE(?, cover_path),
51
+ status = CASE WHEN status IN ('materials_drafted','render_error')
52
+ THEN 'ready_to_review'
53
+ ELSE status END,
54
+ last_status_change_at = CASE WHEN status IN ('materials_drafted','render_error')
55
+ THEN CURRENT_TIMESTAMP
56
+ ELSE last_status_change_at END,
57
+ updated_at = CURRENT_TIMESTAMP
58
+ WHERE id = ?
59
+ `).run(resume, cover, existing.id);
60
+ mirrorJobStatus(db, job_id);
61
+ const after = db.prepare(`SELECT status FROM applications WHERE id = ?`).get(existing.id);
62
+ return {
63
+ application_id: existing.id,
64
+ status: after.status,
65
+ status_advanced: advance && after.status === 'ready_to_review',
66
+ };
67
+ }
68
+ const id = randomUUID();
69
+ db.prepare(`
70
+ INSERT INTO applications (id, job_id, status, resume_path, cover_path, materials_v, last_status_change_at)
71
+ VALUES (?, ?, 'ready_to_review', ?, ?, 1, CURRENT_TIMESTAMP)
72
+ `).run(id, job_id, resume, cover);
73
+ mirrorJobStatus(db, job_id);
74
+ return { application_id: id, status: 'ready_to_review', status_advanced: true };
75
+ });
76
+ }
77
+ // Mirror status onto jobs.status — only advance from earlier states. Don't push a job
78
+ // already in applied / screen / onsite / offer / rejected backwards.
79
+ function mirrorJobStatus(db, job_id) {
80
+ db.prepare(`
81
+ UPDATE jobs SET status = 'ready_to_review', updated_at = CURRENT_TIMESTAMP
82
+ WHERE id = ?
83
+ AND status IN ('sourced','ready_to_apply','materials_drafted')
84
+ `).run(job_id);
85
+ }
27
86
  //# sourceMappingURL=render_pdf.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"render_pdf.js","sourceRoot":"","sources":["../../../src/mcp/tools/render_pdf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE/D,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,CAAC;IACtC,IAAI,EAAE,YAAY;IAClB,KAAK,EAAE,yBAAyB;IAChC,WAAW,EAAE,kGAAkG;IAC/G,WAAW,EAAE;QACX,MAAM,EAAO,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9B,IAAI,EAAS,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;QAClE,UAAU,EAAG,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+EAA+E,CAAC;QAC5H,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;KACxD;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACtB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC;YACpC,OAAO,QAAQ,CAAC;gBACd,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;aACpF,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,SAAS,CAAC,sBAAsB,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"render_pdf.js","sourceRoot":"","sources":["../../../src/mcp/tools/render_pdf.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "job_ops-mcp",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "Self-hosted MCP server for the full job-search loop: portal scanning, JD evaluation, tailored resume + cover PDFs, outreach drafting, story bank, negotiation brief — chat-driven, human-in-the-loop.",
5
5
  "type": "module",
6
6
  "private": false,
@@ -50,6 +50,7 @@
50
50
  "connect": "node dist/cli.js connect",
51
51
  "dev": "tsx watch src/cli.ts start",
52
52
  "typecheck": "tsc --noEmit",
53
+ "test": "npm run build && node --test 'tests/**/*.test.mjs'",
53
54
  "prepublishOnly": "npm run build",
54
55
  "playwright:install": "playwright install chromium"
55
56
  },