career-compass-mcp 2.0.0 → 2.2.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.
Files changed (55) hide show
  1. package/README.md +391 -340
  2. package/build/bin/cli.d.ts +5 -5
  3. package/build/bin/cli.d.ts.map +1 -1
  4. package/build/bin/cli.js +55 -49
  5. package/build/bin/cli.js.map +1 -1
  6. package/build/src/dashboard-lite/render.d.ts +21 -0
  7. package/build/src/dashboard-lite/render.d.ts.map +1 -0
  8. package/build/src/dashboard-lite/render.js +216 -0
  9. package/build/src/dashboard-lite/render.js.map +1 -0
  10. package/build/src/dashboard-lite/server.d.ts +14 -0
  11. package/build/src/dashboard-lite/server.d.ts.map +1 -0
  12. package/build/src/dashboard-lite/server.js +50 -0
  13. package/build/src/dashboard-lite/server.js.map +1 -0
  14. package/build/src/schemas/career-schema.d.ts +108 -0
  15. package/build/src/schemas/career-schema.d.ts.map +1 -1
  16. package/build/src/schemas/career-schema.js +43 -0
  17. package/build/src/schemas/career-schema.js.map +1 -1
  18. package/build/src/server.d.ts.map +1 -1
  19. package/build/src/server.js +4 -1
  20. package/build/src/server.js.map +1 -1
  21. package/build/src/storage/file-store.d.ts +43 -0
  22. package/build/src/storage/file-store.d.ts.map +1 -1
  23. package/build/src/storage/file-store.js +133 -4
  24. package/build/src/storage/file-store.js.map +1 -1
  25. package/build/src/tools/career-kb.d.ts.map +1 -1
  26. package/build/src/tools/career-kb.js +120 -13
  27. package/build/src/tools/career-kb.js.map +1 -1
  28. package/build/src/tools/interview.d.ts.map +1 -1
  29. package/build/src/tools/interview.js +21 -4
  30. package/build/src/tools/interview.js.map +1 -1
  31. package/build/src/tools/opportunity.d.ts.map +1 -1
  32. package/build/src/tools/opportunity.js +19 -2
  33. package/build/src/tools/opportunity.js.map +1 -1
  34. package/build/src/tools/pipeline.d.ts.map +1 -1
  35. package/build/src/tools/pipeline.js +105 -47
  36. package/build/src/tools/pipeline.js.map +1 -1
  37. package/build/src/tools/resume.d.ts.map +1 -1
  38. package/build/src/tools/resume.js +28 -4
  39. package/build/src/tools/resume.js.map +1 -1
  40. package/build/src/tools/signal-digest.d.ts +15 -0
  41. package/build/src/tools/signal-digest.d.ts.map +1 -0
  42. package/build/src/tools/signal-digest.js +45 -0
  43. package/build/src/tools/signal-digest.js.map +1 -0
  44. package/build/src/untrusted.d.ts +63 -0
  45. package/build/src/untrusted.d.ts.map +1 -0
  46. package/build/src/untrusted.js +83 -0
  47. package/build/src/untrusted.js.map +1 -0
  48. package/build/src/version.d.ts +23 -0
  49. package/build/src/version.d.ts.map +1 -0
  50. package/build/src/version.js +66 -0
  51. package/build/src/version.js.map +1 -0
  52. package/data/example/career/education.yaml +20 -0
  53. package/data/example/career/journal.yaml +56 -0
  54. package/data/example/career/projects.yaml +47 -0
  55. package/package.json +3 -13
@@ -1,8 +1,17 @@
1
1
  import { z } from "zod";
2
- import { loadPipeline, savePipeline } from "../storage/file-store.js";
2
+ import { randomUUID } from "crypto";
3
+ import { mutatePipeline, appendJournalEntry, isCorruptDataError } from "../storage/file-store.js";
4
+ import { embedUntrusted } from "../untrusted.js";
3
5
  export function registerCareerKBTools(server) {
4
6
  server.registerTool("ingest_document", {
5
7
  title: "Ingest Career Document",
8
+ // Extracts structured data and returns it for review. Persisting it is a separate, explicit step.
9
+ annotations: {
10
+ readOnlyHint: true,
11
+ destructiveHint: false,
12
+ idempotentHint: true,
13
+ openWorldHint: false,
14
+ },
6
15
  description: "Paste any career document — performance review, award email, project summary, LinkedIn recommendation — and extract structured achievements to add to your Career KB.",
7
16
  inputSchema: {
8
17
  content: z.string().describe("Full document text to ingest"),
@@ -10,7 +19,7 @@ export function registerCareerKBTools(server) {
10
19
  associatedRole: z.string().optional().describe("Job role this document relates to"),
11
20
  associatedCompany: z.string().optional().describe("Company this document relates to"),
12
21
  datePeriod: z.string().optional().describe("Time period this covers, e.g. '2023 Q1' or '2022-2023'"),
13
- autoSave: z.boolean().default(false).describe("If true, automatically append extracted data to Career KB"),
22
+ autoSave: z.boolean().default(false).describe("If true, the output names the exact Career KB file each extracted item belongs in, so you can review before anything is written. This tool only extracts — it never writes."),
14
23
  },
15
24
  }, async ({ content, documentType, associatedRole, associatedCompany, datePeriod, autoSave }) => {
16
25
  return {
@@ -25,7 +34,7 @@ ${associatedCompany ? `**Company:** ${associatedCompany}` : ""}
25
34
  ${datePeriod ? `**Period:** ${datePeriod}` : ""}
26
35
 
27
36
  **Content:**
28
- ${content}
37
+ ${embedUntrusted("uploaded document", content)}
29
38
 
30
39
  ---
31
40
 
@@ -70,7 +79,7 @@ skills:
70
79
  Top 10 ATS-friendly keywords from this document.
71
80
 
72
81
  ${autoSave ? `
73
- **Auto-save requested:** After extraction, call the update tools to append this data to the Career KB files.
82
+ **Save requested:** present the extracted YAML and the exact file it belongs in, for the user to confirm before anything is written.
74
83
  ` : `
75
84
  **To save:** Review the YAML above and use your file editor to append to the relevant data/career/ files, or set autoSave=true to let Claude do it automatically.
76
85
  `}`,
@@ -79,28 +88,38 @@ ${autoSave ? `
79
88
  });
80
89
  server.registerTool("generate_rejection_response", {
81
90
  title: "Generate Rejection Response",
91
+ // Drafts the response AND, when applicationId is given, sets that application's status to rejected — an overwrite of existing state.
92
+ annotations: {
93
+ readOnlyHint: false,
94
+ destructiveHint: true,
95
+ idempotentHint: false,
96
+ openWorldHint: false,
97
+ },
82
98
  description: "Craft a graceful rejection response that keeps the door open, maintains relationships, and positions you for future opportunities.",
83
99
  inputSchema: {
84
100
  applicationId: z.string().optional().describe("Pipeline application ID"),
85
- company: z.string().optional(),
86
- role: z.string().optional(),
101
+ company: z.string().optional().describe("Company that sent the rejection. Filled in automatically when applicationId is given."),
102
+ role: z.string().optional().describe("Role you were rejected for. Filled in automatically when applicationId is given."),
87
103
  rejectionContent: z.string().describe("The rejection email or message content"),
88
- responseGoal: z.enum(["keep_door_open", "request_feedback", "decline_gracefully", "express_continued_interest"]).default("keep_door_open"),
104
+ responseGoal: z.enum(["keep_door_open", "request_feedback", "decline_gracefully", "express_continued_interest"]).default("keep_door_open").describe("What you want the reply to achieve: stay on good terms for future roles, ask why you were passed over, decline politely, or signal you would still take another opening there."),
89
105
  contactName: z.string().optional().describe("Person who sent the rejection"),
90
106
  hadGoodRapport: z.boolean().default(false).describe("Did you have positive interactions during the process?"),
91
107
  },
92
108
  }, async ({ applicationId, company, role, rejectionContent, responseGoal, contactName, hadGoodRapport }) => {
93
109
  if (applicationId) {
94
- const pipeline = await loadPipeline();
95
- const app = pipeline.applications.find(a => a.id === applicationId);
96
- if (app) {
110
+ // Same critical section as pipeline_update: this is a read-modify-write
111
+ // on the shared pipeline file, so it must not straddle the lock.
112
+ await mutatePipeline((pipeline) => {
113
+ const app = pipeline.applications.find(a => a.id === applicationId);
114
+ // No match: return without mutating; mutatePipeline skips the write.
115
+ if (!app)
116
+ return;
97
117
  company = company ?? app.company;
98
118
  role = role ?? app.role;
99
119
  // Auto-update status to rejected
100
120
  app.status = "rejected";
101
121
  app.dateUpdated = new Date().toISOString();
102
- await savePipeline(pipeline);
103
- }
122
+ });
104
123
  }
105
124
  return {
106
125
  content: [{
@@ -115,7 +134,7 @@ ${contactName ? `**From:** ${contactName}` : ""}
115
134
  **Prior rapport:** ${hadGoodRapport ? "Yes — positive relationship built" : "Limited"}
116
135
 
117
136
  **Rejection message:**
118
- ${rejectionContent}
137
+ ${embedUntrusted("rejection message", rejectionContent)}
119
138
 
120
139
  ---
121
140
 
@@ -144,5 +163,93 @@ ${applicationId ? `\n**Note:** Application ${applicationId} status has been auto
144
163
  }],
145
164
  };
146
165
  });
166
+ server.registerTool("capture_insight", {
167
+ title: "Capture Career Insight",
168
+ // Appends one entry to the career journal. Additive only: never rewrites or removes an existing entry.
169
+ annotations: {
170
+ readOnlyHint: false,
171
+ destructiveHint: false,
172
+ idempotentHint: false,
173
+ openWorldHint: false,
174
+ },
175
+ description: "Record a durable career signal to your journal — what an interview surfaced, why an offer felt right or wrong, the pattern behind a rejection, fresh proof of a skill. Append-only; over time these compound into the real shape of your career and enrich future resume, interview, and fit work.",
176
+ inputSchema: {
177
+ type: z.enum([
178
+ "fit_signal",
179
+ "interview_insight",
180
+ "offer_reflection",
181
+ "rejection_pattern",
182
+ "skill_evidence",
183
+ "win",
184
+ "note",
185
+ ]).describe("What kind of signal this is"),
186
+ summary: z.string().describe("One-line durable takeaway — the thing worth keeping"),
187
+ detail: z.string().optional().describe("Longer context, if useful"),
188
+ applicationId: z.string().optional().describe("Pipeline application ID this relates to"),
189
+ company: z.string().optional().describe("Company this insight relates to, if any. Lets later prompts surface it when you work on that company again."),
190
+ role: z.string().optional().describe("Role this insight relates to, if any."),
191
+ signals: z.array(z.string()).default([]).describe("Recurring strengths, gaps, or keywords to track over time"),
192
+ sentiment: z.enum(["positive", "neutral", "hard"]).optional().describe("Honest emotional read — 'hard' is valid and worth recording"),
193
+ source: z.enum([
194
+ "explore_opportunity",
195
+ "prepare_interview",
196
+ "evaluate_offer",
197
+ "rejection",
198
+ "ingest_document",
199
+ "manual",
200
+ ]).default("manual").describe("Which surface produced this insight"),
201
+ },
202
+ }, async ({ type, summary, detail, applicationId, company, role, signals, sentiment, source }) => {
203
+ const entry = {
204
+ id: randomUUID().slice(0, 8),
205
+ date: new Date().toISOString(),
206
+ type,
207
+ summary,
208
+ detail,
209
+ applicationId,
210
+ company,
211
+ role,
212
+ signals,
213
+ sentiment,
214
+ source,
215
+ };
216
+ let total;
217
+ try {
218
+ const all = await appendJournalEntry(entry);
219
+ total = all.length;
220
+ }
221
+ catch (error) {
222
+ if (isCorruptDataError(error)) {
223
+ return {
224
+ content: [{
225
+ type: "text",
226
+ text: `⚠️ Couldn't save the insight: your journal file exists but is unreadable, ` +
227
+ `so I stopped rather than risk overwriting it.\n\n` +
228
+ `Fix or restore \`journal.yaml\` (a timestamped \`.bak\` sits beside it), then try again.\n\n` +
229
+ `Nothing was written; the insight below is unsaved:\n> ${summary}`,
230
+ }],
231
+ };
232
+ }
233
+ throw error;
234
+ }
235
+ const meta = [
236
+ company && `**${company}**`,
237
+ role,
238
+ applicationId && `\`${applicationId}\``,
239
+ sentiment && `sentiment: ${sentiment}`,
240
+ ].filter(Boolean).join(" · ");
241
+ return {
242
+ content: [{
243
+ type: "text",
244
+ text: `📓 Captured to your career journal (**${type}**).\n\n` +
245
+ `> ${summary}\n` +
246
+ (detail ? `\n${detail}\n` : "") +
247
+ (meta ? `\n${meta}\n` : "") +
248
+ (signals.length ? `\nSignals: ${signals.map((s) => `\`${s}\``).join(", ")}\n` : "") +
249
+ `\nThat's **${total}** ${total === 1 ? "entry" : "entries"} on the record now. ` +
250
+ `These accrue — the more you capture, the sharper future resume, interview, and fit work gets.`,
251
+ }],
252
+ };
253
+ });
147
254
  }
148
255
  //# sourceMappingURL=career-kb.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"career-kb.js","sourceRoot":"","sources":["../../../src/tools/career-kb.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"career-kb.js","sourceRoot":"","sources":["../../../src/tools/career-kb.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"interview.d.ts","sourceRoot":"","sources":["../../../src/tools/interview.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA0M9D"}
1
+ {"version":3,"file":"interview.d.ts","sourceRoot":"","sources":["../../../src/tools/interview.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAyN9D"}
@@ -1,8 +1,17 @@
1
1
  import { z } from "zod";
2
2
  import { loadCareerData, loadPipeline } from "../storage/file-store.js";
3
+ import { formatSignalDigest } from "./signal-digest.js";
4
+ import { embedUntrusted } from "../untrusted.js";
3
5
  export function registerInterviewTools(server) {
4
6
  server.registerTool("prepare_interview", {
5
7
  title: "Prepare Interview",
8
+ // Reads the Career KB and pipeline and returns prep material. Writes nothing.
9
+ annotations: {
10
+ readOnlyHint: true,
11
+ destructiveHint: false,
12
+ idempotentHint: true,
13
+ openWorldHint: false,
14
+ },
6
15
  description: "Generate comprehensive interview prep: STAR stories, likely questions, company alignment, and bridge topics — tailored to interview type.",
7
16
  inputSchema: {
8
17
  applicationId: z.string().optional().describe("Pipeline application ID"),
@@ -64,7 +73,8 @@ ${achievements.map(a => `- **${a.role} @ ${a.company}**: ${a.metric} — ${a.con
64
73
  ## Full Career KB
65
74
  ${JSON.stringify(career, null, 2)}
66
75
 
67
- ${postingText ? `## Job Posting\n${postingText}` : ""}
76
+ ${formatSignalDigest(career.journal)}
77
+ ${postingText ? `## Job Posting\n${embedUntrusted("cached job posting", postingText)}` : ""}
68
78
 
69
79
  ---
70
80
 
@@ -108,11 +118,18 @@ Likely concerns they'll have about my background, and how to address them proact
108
118
  });
109
119
  server.registerTool("evaluate_offer", {
110
120
  title: "Evaluate Offer",
121
+ // Reads the Career KB and returns an offer analysis. Writes nothing.
122
+ annotations: {
123
+ readOnlyHint: true,
124
+ destructiveHint: false,
125
+ idempotentHint: true,
126
+ openWorldHint: false,
127
+ },
111
128
  description: "Analyze a job offer: break down total compensation, compare to market, build negotiation strategy, and draft counter scripts.",
112
129
  inputSchema: {
113
130
  applicationId: z.string().optional().describe("Pipeline application ID"),
114
- company: z.string().optional(),
115
- role: z.string().optional(),
131
+ company: z.string().optional().describe("Company making the offer. Used to pull the matching application for context."),
132
+ role: z.string().optional().describe("Role being offered."),
116
133
  offerDetails: z.string().describe("Full offer: base salary, bonus, equity, benefits, start date, title"),
117
134
  location: z.string().optional().describe("Work location (affects cost of living calc)"),
118
135
  currentComp: z.string().optional().describe("Your current total comp for comparison"),
@@ -135,7 +152,7 @@ Likely concerns they'll have about my background, and how to address them proact
135
152
  text: `# Offer Evaluation: ${role ?? "Role"} at ${company ?? "Company"}
136
153
 
137
154
  ## Offer Details
138
- ${offerDetails}
155
+ ${embedUntrusted("offer details", offerDetails)}
139
156
 
140
157
  ${location ? `**Location:** ${location}` : ""}
141
158
  ${currentComp ? `**Current comp:** ${currentComp}` : ""}
@@ -1 +1 @@
1
- {"version":3,"file":"interview.js","sourceRoot":"","sources":["../../../src/tools/interview.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"interview.js","sourceRoot":"","sources":["../../../src/tools/interview.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"opportunity.d.ts","sourceRoot":"","sources":["../../../src/tools/opportunity.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAqIhE"}
1
+ {"version":3,"file":"opportunity.d.ts","sourceRoot":"","sources":["../../../src/tools/opportunity.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAoJhE"}
@@ -1,8 +1,17 @@
1
1
  import { z } from "zod";
2
2
  import { loadCareerData } from "../storage/file-store.js";
3
+ import { formatSignalDigest } from "./signal-digest.js";
4
+ import { embedUntrusted } from "../untrusted.js";
3
5
  export function registerOpportunityTools(server) {
4
6
  server.registerTool("explore_opportunity", {
5
7
  title: "Explore Opportunity",
8
+ // Reads the Career KB and returns an analysis. Writes nothing.
9
+ annotations: {
10
+ readOnlyHint: true,
11
+ destructiveHint: false,
12
+ idempotentHint: true,
13
+ openWorldHint: false,
14
+ },
6
15
  description: "Analyze a job posting against your Career KB. Returns fit score, matched strengths, gaps, talking points, and a 'day in the life' brief.",
7
16
  inputSchema: {
8
17
  posting: z.string().describe("Full job posting text, or paste the raw text from a job board"),
@@ -28,10 +37,11 @@ export function registerOpportunityTools(server) {
28
37
  ## Career Context
29
38
  ${careerSummary}
30
39
 
40
+ ${formatSignalDigest(career.journal)}
31
41
  ## Job Posting
32
- ${posting}
42
+ ${embedUntrusted("job posting", posting)}
33
43
  ${company ? `\n**Company:** ${company}` : ""}
34
- ${notes ? `\n**Notes:** ${notes}` : ""}
44
+ ${notes ? `\n**Notes:** ${embedUntrusted("user notes", notes)}` : ""}
35
45
 
36
46
  ---
37
47
 
@@ -63,6 +73,13 @@ Should I pursue this? What's the strategic case for or against?`,
63
73
  });
64
74
  server.registerTool("research_company", {
65
75
  title: "Research Company",
76
+ // Reads the pipeline for context and returns a brief. Writes nothing.
77
+ annotations: {
78
+ readOnlyHint: true,
79
+ destructiveHint: false,
80
+ idempotentHint: true,
81
+ openWorldHint: false,
82
+ },
66
83
  description: "Build an intelligence brief on a company: product, funding, culture, tech stack, interview process, and strategic fit with your goals.",
67
84
  inputSchema: {
68
85
  company: z.string().describe("Company name"),
@@ -1 +1 @@
1
- {"version":3,"file":"opportunity.js","sourceRoot":"","sources":["../../../src/tools/opportunity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,MAAM,UAAU,wBAAwB,CAAC,MAAiB;IAExD,MAAM,CAAC,YAAY,CACjB,qBAAqB,EACrB;QACE,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EAAE,0IAA0I;QACvJ,WAAW,EAAE;YACX,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+DAA+D,CAAC;YAC7F,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;YAC3E,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+CAA+C,CAAC;SACvF;KACF,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;QACpC,MAAM,MAAM,GAAG,MAAM,cAAc,EAAE,CAAC;QACtC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,kIAAkI;qBACzI,CAAC;aACH,CAAC;QACJ,CAAC;QAED,MAAM,aAAa,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAEjD,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE;;;EAGd,aAAa;;;EAGb,OAAO;EACP,OAAO,CAAC,CAAC,CAAC,kBAAkB,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE;EAC1C,KAAK,CAAC,CAAC,CAAC,gBAAgB,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;gEA0B0B;iBACvD,CAAC;SACH,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,kBAAkB,EAClB;QACE,KAAK,EAAE,kBAAkB;QACzB,WAAW,EAAE,wIAAwI;QACrJ,WAAW,EAAE;YACX,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;YAC5C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;YACjE,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gDAAgD,CAAC;SAChG;KACF,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE;QACzC,MAAM,MAAM,GAAG,MAAM,cAAc,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,MAAM,EAAE,OAAO,CAAC;QAEhC,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,6BAA6B,OAAO;;mBAEjC,IAAI,IAAI,eAAe;EACxC,aAAa,CAAC,CAAC,CAAC,sCAAsC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE;;;EAG1E,OAAO,CAAC,CAAC,CAAC,mBAAmB,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe;uBACzD,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe;uBACtD,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sEAiCtC;iBAC7D,CAAC;SACH,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAkD;IAC5E,IAAI,CAAC,MAAM;QAAE,OAAO,2BAA2B,CAAC;IAChD,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAE/C,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClE,MAAM,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE5F,OAAO,aAAa,OAAO,CAAC,IAAI;eACnB,OAAO,CAAC,OAAO;oBACV,WAAW,IAAI,aAAa;kBAC9B,SAAS,IAAI,aAAa;oBACxB,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe;yBAC5C,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe,EAAE,CAAC;AAClF,CAAC"}
1
+ {"version":3,"file":"opportunity.js","sourceRoot":"","sources":["../../../src/tools/opportunity.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../../src/tools/pipeline.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,EAAkC,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAEvF,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,YAAY,EACb,MAAM,uBAAuB,CAAC;AAI/B,wBAAsB,SAAS,CAAC,IAAI,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC,CA4BhG;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,kBAAkB,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC,CAqBtG;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,GAAG,YAAY,CAIjF;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,GAAG,YAAY,CA4BnF;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,YAAY,CA8B5D;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,YAAY,CAsClE;AAID,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAkJ7D"}
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../../src/tools/pipeline.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,EAAkC,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAGvF,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,YAAY,EACb,MAAM,uBAAuB,CAAC;AAI/B,wBAAsB,SAAS,CAAC,IAAI,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC,CA2BhG;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,kBAAkB,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC,CAqBtG;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,GAAG,YAAY,CAIjF;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,GAAG,YAAY,CA4BnF;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,YAAY,CA8B5D;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,YAAY,CAsClE;AAID,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA+M7D"}
@@ -1,7 +1,8 @@
1
1
  import { z } from "zod";
2
- import { loadPipeline, savePipeline, isCorruptDataError } from "../storage/file-store.js";
2
+ import { loadPipeline, mutatePipeline, isCorruptDataError } from "../storage/file-store.js";
3
3
  import { ApplicationStatus } from "../schemas/career-schema.js";
4
4
  import { randomUUID } from "crypto";
5
+ import { embedUntrusted } from "../untrusted.js";
5
6
  // ─── Extracted Handler Functions ──────────────────────────────────────────────
6
7
  export async function handleAdd(args, pipeline) {
7
8
  const id = randomUUID().slice(0, 8);
@@ -27,13 +28,13 @@ export async function handleAdd(args, pipeline) {
27
28
  remote: "unknown",
28
29
  };
29
30
  pipeline.applications.push(newApp);
30
- await savePipeline(pipeline);
31
31
  return {
32
32
  content: [{ type: "text", text: `✅ Added application: **${args.role}** at **${args.company}**\nID: \`${id}\`\nStatus: applied` }],
33
33
  };
34
34
  }
35
35
  export async function handleUpdate(args, pipeline) {
36
36
  const idx = pipeline.applications.findIndex(a => a.id === args.id);
37
+ // Returns normally: mutatePipeline skips the write because nothing changed.
37
38
  if (idx === -1)
38
39
  return { content: [{ type: "text", text: `❌ Application ${args.id} not found.` }] };
39
40
  const app = pipeline.applications[idx];
@@ -53,7 +54,6 @@ export async function handleUpdate(args, pipeline) {
53
54
  }
54
55
  app.dateUpdated = new Date().toISOString();
55
56
  pipeline.applications[idx] = app;
56
- await savePipeline(pipeline);
57
57
  return {
58
58
  content: [{ type: "text", text: `✅ Updated **${app.role}** at **${app.company}** (${app.id})\nStatus: ${app.status}` }],
59
59
  };
@@ -160,39 +160,31 @@ export function handleNextActions(pipeline) {
160
160
  }
161
161
  // ─── Tool Registration ────────────────────────────────────────────────────────
162
162
  export function registerPipelineTools(server) {
163
- server.registerTool("manage_pipeline", {
164
- title: "Manage Application Pipeline",
165
- description: "Add, update, list, and analyze job applications. Track status from discovered through offer/rejection.",
163
+ server.registerTool("pipeline_view", {
164
+ title: "View Application Pipeline",
165
+ // Every action here reads. Nothing on this tool can reach a write path, so
166
+ // a host may run it without asking — which is the point: checking your own
167
+ // pipeline should not cost a permission prompt.
168
+ annotations: {
169
+ readOnlyHint: true,
170
+ destructiveHint: false,
171
+ idempotentHint: true,
172
+ openWorldHint: false,
173
+ },
174
+ description: "Read the job application pipeline: list applications, summarize stats, surface what needs attention, or fetch one application by id. Read-only — never modifies anything.",
166
175
  inputSchema: {
167
- action: z.enum(["add", "update", "list", "stats", "next_actions", "get"]).describe("Operation to perform"),
168
- // For add
169
- company: z.string().optional(),
170
- role: z.string().optional(),
171
- postingUrl: z.string().optional(),
172
- postingText: z.string().optional().describe("Full posting text to cache"),
173
- source: z.string().optional().describe("Where you found it: LinkedIn, Referral, Company site, etc."),
174
- referral: z.string().optional(),
175
- priority: z.enum(["high", "medium", "low"]).optional(),
176
- excitement: z.number().min(1).max(10).optional(),
177
- salaryMin: z.number().optional(),
178
- salaryMax: z.number().optional(),
179
- // For update
180
- id: z.string().optional().describe("Application ID (required for update/get)"),
181
- status: ApplicationStatus.optional(),
182
- notes: z.string().optional().describe("Note to add to this application"),
183
- followUpDue: z.string().optional().describe("ISO date for follow-up reminder"),
184
- contactName: z.string().optional(),
185
- contactTitle: z.string().optional(),
186
- contactEmail: z.string().optional(),
187
- interviewType: z.enum(["phone_screen", "behavioral", "technical", "panel", "final", "offer_call", "other"]).optional(),
188
- interviewDate: z.string().optional(),
189
- // For list
190
- filterStatus: ApplicationStatus.optional().describe("Filter by status"),
191
- filterPriority: z.enum(["high", "medium", "low"]).optional(),
192
- sortBy: z.enum(["date", "status", "priority", "company", "excitement"]).optional().default("date"),
193
- limit: z.number().optional().default(20),
176
+ action: z.enum(["list", "stats", "next_actions", "get"])
177
+ .describe("list = all applications (filterable); stats = funnel and response-rate summary; next_actions = what is overdue or due now; get = one application by id"),
178
+ id: z.string().optional().describe("Application id. Required when action=get."),
179
+ filterStatus: ApplicationStatus.optional().describe("action=list only: show only applications in this status"),
180
+ filterPriority: z.enum(["high", "medium", "low"]).optional().describe("action=list only: show only applications at this priority"),
181
+ sortBy: z.enum(["date", "status", "priority", "company", "excitement"]).optional().default("date").describe("action=list only: ordering. Defaults to most recently applied first."),
182
+ limit: z.number().int().min(1).max(500).optional().default(20).describe("action=list only: maximum applications to return (1-500)"),
194
183
  },
195
184
  }, async (args) => {
185
+ // Reads deliberately take no lock: the write path renames atomically, so a
186
+ // reader always sees a complete file, and locking reads would serialize the
187
+ // whole tool for nothing.
196
188
  let pipeline;
197
189
  try {
198
190
  pipeline = await loadPipeline();
@@ -204,20 +196,9 @@ export function registerPipelineTools(server) {
204
196
  throw error;
205
197
  }
206
198
  switch (args.action) {
207
- case "add": {
208
- if (!args.company || !args.role) {
209
- return { content: [{ type: "text", text: "❌ company and role are required for add action." }] };
210
- }
211
- return handleAdd(args, pipeline);
212
- }
213
- case "update": {
214
- if (!args.id)
215
- return { content: [{ type: "text", text: "❌ id is required for update action." }] };
216
- return handleUpdate(args, pipeline);
217
- }
218
199
  case "get": {
219
200
  if (!args.id)
220
- return { content: [{ type: "text", text: "❌ id is required for get action." }] };
201
+ return { content: [{ type: "text", text: "❌ id is required for action=get." }] };
221
202
  return handleGet(args, pipeline);
222
203
  }
223
204
  case "list":
@@ -230,12 +211,89 @@ export function registerPipelineTools(server) {
230
211
  return { content: [{ type: "text", text: `❌ Unknown action: ${args.action}` }] };
231
212
  }
232
213
  });
214
+ server.registerTool("pipeline_add", {
215
+ title: "Add Application to Pipeline",
216
+ // Appends a new application. Additive only: never rewrites or removes an
217
+ // existing one, so destructiveHint is false even though this writes.
218
+ annotations: {
219
+ readOnlyHint: false,
220
+ destructiveHint: false,
221
+ idempotentHint: false,
222
+ openWorldHint: false,
223
+ },
224
+ description: "Add one job application to the pipeline. Creates a new record; never modifies an existing one. Use pipeline_update to change an application already being tracked.",
225
+ inputSchema: {
226
+ company: z.string().describe("Company name"),
227
+ role: z.string().describe("Role title as posted"),
228
+ postingUrl: z.string().optional().describe("Link to the job posting"),
229
+ postingText: z.string().optional().describe("Full posting text to cache, so later interview prep can reference it without the link"),
230
+ source: z.string().optional().describe("Where you found it: LinkedIn, Referral, Company site, etc."),
231
+ referral: z.string().optional().describe("Name of the person who referred you, if any"),
232
+ priority: z.enum(["high", "medium", "low"]).optional().describe("How hard you intend to push on this one. Defaults to medium."),
233
+ excitement: z.number().min(1).max(10).optional().describe("How excited you are about the role, 1-10. Used later to compare excitement against outcomes."),
234
+ salaryMin: z.number().optional().describe("Bottom of the posted or expected salary range, in whole currency units"),
235
+ salaryMax: z.number().optional().describe("Top of the posted or expected salary range, in whole currency units"),
236
+ },
237
+ }, async (args) => {
238
+ try {
239
+ // Load + mutate + save as one critical section, so two adds dispatched in
240
+ // the same turn cannot overwrite each other.
241
+ return await mutatePipeline((pipeline) => handleAdd({ ...args, action: "add" }, pipeline));
242
+ }
243
+ catch (error) {
244
+ if (isCorruptDataError(error)) {
245
+ return { content: [{ type: "text", text: `❌ ${error.message}` }] };
246
+ }
247
+ throw error;
248
+ }
249
+ });
250
+ server.registerTool("pipeline_update", {
251
+ title: "Update Application in Pipeline",
252
+ // Overwrites fields on an existing application — a destructive update, so
253
+ // a host will always confirm before running it.
254
+ annotations: {
255
+ readOnlyHint: false,
256
+ destructiveHint: true,
257
+ idempotentHint: false,
258
+ openWorldHint: false,
259
+ },
260
+ description: "Update one application already in the pipeline: change its status, add a note, set a follow-up date, record a contact, or log an interview round. Overwrites the fields you supply and leaves the rest untouched.",
261
+ inputSchema: {
262
+ id: z.string().describe("Application id, as returned by pipeline_add or pipeline_view"),
263
+ status: ApplicationStatus.optional().describe("New status in the funnel"),
264
+ priority: z.enum(["high", "medium", "low"]).optional().describe("New priority"),
265
+ notes: z.string().optional().describe("A note to append. Existing notes are kept; this is added with today's date."),
266
+ followUpDue: z.string().optional().describe("ISO date (YYYY-MM-DD) to be reminded to follow up"),
267
+ contactName: z.string().optional().describe("Name of a person met in this process, appended to the application's contacts"),
268
+ contactTitle: z.string().optional().describe("That person's title"),
269
+ contactEmail: z.string().optional().describe("That person's email"),
270
+ interviewType: z.enum(["phone_screen", "behavioral", "technical", "panel", "final", "offer_call", "other"]).optional().describe("Type of an interview round to append"),
271
+ interviewDate: z.string().optional().describe("ISO date of that interview round"),
272
+ },
273
+ }, async (args) => {
274
+ try {
275
+ return await mutatePipeline((pipeline) => handleUpdate({ ...args, action: "update" }, pipeline));
276
+ }
277
+ catch (error) {
278
+ if (isCorruptDataError(error)) {
279
+ return { content: [{ type: "text", text: `❌ ${error.message}` }] };
280
+ }
281
+ throw error;
282
+ }
283
+ });
233
284
  server.registerTool("classify_email", {
234
285
  title: "Classify Email",
286
+ // Reads pipeline company names for context and returns a classification. Any pipeline change happens through a separate pipeline_update call the user approves.
287
+ annotations: {
288
+ readOnlyHint: true,
289
+ destructiveHint: false,
290
+ idempotentHint: true,
291
+ openWorldHint: false,
292
+ },
235
293
  description: "Classify a job-search-related email and extract structured data: type, company, role, contact, next action, and urgency.",
236
294
  inputSchema: {
237
295
  emailContent: z.string().describe("Full email content — paste subject line and body"),
238
- autoUpdatePipeline: z.boolean().default(false).describe("If true, automatically update the pipeline based on classification"),
296
+ autoUpdatePipeline: z.boolean().default(false).describe("If true, the classification includes the specific pipeline field changes it implies, so you can review them before anything is written. This tool only classifies — it never writes."),
239
297
  },
240
298
  }, async ({ emailContent, autoUpdatePipeline }) => {
241
299
  let pipeline;
@@ -255,7 +313,7 @@ export function registerPipelineTools(server) {
255
313
  text: `# Email Classification Request
256
314
 
257
315
  ## Email Content
258
- ${emailContent}
316
+ ${embedUntrusted("email", emailContent)}
259
317
 
260
318
  ## Known Companies in Pipeline
261
319
  ${companyList || "None yet"}