mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-08-24 15:22:20 +10:00
feat(mcp): add cover-letter PDF downloads (#3304)
* feat(mcp): add cover-letter PDF downloads * fix(mcp): bind signed PDF targets * test(mcp): cover unavailable cover letters * fix(api): accept legacy PDF download targets * fix(server): limit legacy PDF tokens to resumes --------- Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
This commit is contained in:
co-authored by
Amruth Pillai
parent
45303fb465
commit
6d9ebccc63
+30
-21
@@ -8,6 +8,7 @@ import { Buffer } from "node:buffer";
|
||||
import { resolveUserFromRequestHeaders } from "@reactive-resume/api/context";
|
||||
import { createResumePdfDownloadUrl } from "@reactive-resume/api/features/resume/export";
|
||||
import { env } from "@reactive-resume/env/server";
|
||||
import { resumeHasCoverLetter } from "@reactive-resume/resume/export-sections";
|
||||
import { resumeDataSchema } from "@reactive-resume/schema/resume/data";
|
||||
import { MCP_TOOL_NAME } from "./mcp-tool-names";
|
||||
import { TOOL_META } from "./tool-meta";
|
||||
@@ -157,32 +158,40 @@ export function registerTools(server: McpServer, client: RouterClient<typeof rou
|
||||
}),
|
||||
);
|
||||
|
||||
// ── Download Resume PDF ────────��──────────────────────────────
|
||||
// ── Download Resume or Cover Letter PDF ───────────────────────
|
||||
server.registerTool(
|
||||
T.downloadResumePdf,
|
||||
TOOL_META[T.downloadResumePdf],
|
||||
withErrorHandling("creating PDF download URL", async ({ id }: { id: string }) => {
|
||||
const resume = await client.resume.getById({ id });
|
||||
const user = await resolveUserFromRequestHeaders(requestHeaders);
|
||||
if (!user) throw new Error("Unauthorized");
|
||||
withErrorHandling(
|
||||
"creating PDF download URL",
|
||||
async ({ id, target }: { id: string; target?: "resume" | "cover-letter" }) => {
|
||||
const resume = await client.resume.getById({ id });
|
||||
const user = await resolveUserFromRequestHeaders(requestHeaders);
|
||||
if (!user) throw new Error("Unauthorized");
|
||||
|
||||
const signedUrl = createResumePdfDownloadUrl({ resumeId: id, userId: user.id });
|
||||
const documentTarget = target ?? "resume";
|
||||
if (documentTarget === "cover-letter" && !resumeHasCoverLetter(resume.data))
|
||||
throw new Error("No visible cover letter found for this resume.");
|
||||
|
||||
return text(
|
||||
JSON.stringify(
|
||||
{
|
||||
resumeId: id,
|
||||
name: resume.name,
|
||||
downloadUrl: signedUrl.url,
|
||||
expiresAt: signedUrl.expiresAt,
|
||||
expiresInSeconds: signedUrl.expiresInSeconds,
|
||||
contentType: "application/pdf",
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
}),
|
||||
const signedUrl = createResumePdfDownloadUrl({ resumeId: id, userId: user.id, target: documentTarget });
|
||||
|
||||
return text(
|
||||
JSON.stringify(
|
||||
{
|
||||
resumeId: id,
|
||||
target: documentTarget,
|
||||
name: documentTarget === "cover-letter" ? `${resume.name} Cover Letter` : resume.name,
|
||||
downloadUrl: signedUrl.url,
|
||||
expiresAt: signedUrl.expiresAt,
|
||||
expiresInSeconds: signedUrl.expiresInSeconds,
|
||||
contentType: "application/pdf",
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
// ── Create Resume ─────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user