Files
Reactive-Resume/packages/mcp/src/tool-annotations.test.ts
T

116 lines
4.2 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { MCP_TOOL_NAME } from "./mcp-tool-names";
import { TOOL_META } from "./tool-meta";
describe("MCP_TOOL_NAME", () => {
it("uses canonical unprefixed snake_case tool names", () => {
for (const name of Object.values(MCP_TOOL_NAME)) {
expect(name).toMatch(/^[a-z]+(?:_[a-z]+)*$/);
expect(name.split("_").at(0)).not.toBe("reactive");
}
});
it("uses the canonical read and patch names", () => {
expect(MCP_TOOL_NAME.getResume).toBe("read_resume");
expect(MCP_TOOL_NAME.patchResume).toBe("apply_resume_patch");
});
it("uses canonical application tool names", () => {
expect(MCP_TOOL_NAME.listApplications).toBe("list_applications");
expect(MCP_TOOL_NAME.readApplication).toBe("read_application");
expect(MCP_TOOL_NAME.createApplication).toBe("create_application");
expect(MCP_TOOL_NAME.attachApplicationDocument).toBe("attach_application_document");
expect(MCP_TOOL_NAME.autofillApplicationFromJob).toBe("autofill_application_from_job");
});
it("uses unique values for every tool", () => {
const values = Object.values(MCP_TOOL_NAME);
expect(new Set(values).size).toBe(values.length);
});
});
describe("tool annotations", () => {
it("provides annotations for every registered tool", () => {
for (const name of Object.values(MCP_TOOL_NAME)) {
expect(TOOL_META[name].annotations).toBeDefined();
}
});
it("marks list/get tools as readOnly + idempotent + non-destructive", () => {
const readOnlyTools = [
MCP_TOOL_NAME.listResumes,
MCP_TOOL_NAME.listResumeTags,
MCP_TOOL_NAME.getResume,
MCP_TOOL_NAME.getResumeAnalysis,
MCP_TOOL_NAME.getResumeStatistics,
MCP_TOOL_NAME.listApplications,
MCP_TOOL_NAME.readApplication,
MCP_TOOL_NAME.listApplicationTags,
MCP_TOOL_NAME.getApplicationStats,
];
for (const name of readOnlyTools) {
const annotations = TOOL_META[name].annotations;
expect(annotations.readOnlyHint, name).toBe(true);
expect(annotations.destructiveHint, name).toBe(false);
expect(annotations.idempotentHint, name).toBe(true);
}
});
it("marks PDF download URL generation as read-only but non-idempotent", () => {
const annotations = TOOL_META[MCP_TOOL_NAME.downloadResumePdf].annotations;
expect(annotations.readOnlyHint).toBe(true);
expect(annotations.idempotentHint).toBe(false);
expect(annotations.destructiveHint).toBe(false);
});
it("marks deleteResume as destructive (but still idempotent)", () => {
const annotations = TOOL_META[MCP_TOOL_NAME.deleteResume].annotations;
expect(annotations.destructiveHint).toBe(true);
expect(annotations.idempotentHint).toBe(true);
expect(annotations.readOnlyHint).toBe(false);
});
it("marks application delete tools as destructive", () => {
for (const name of [MCP_TOOL_NAME.deleteApplication, MCP_TOOL_NAME.bulkDeleteApplications]) {
const annotations = TOOL_META[name].annotations;
expect(annotations.readOnlyHint, name).toBe(false);
expect(annotations.destructiveHint, name).toBe(true);
}
});
it("marks creation/import/duplicate as non-readonly and non-idempotent", () => {
for (const name of [
MCP_TOOL_NAME.createResume,
MCP_TOOL_NAME.importResume,
MCP_TOOL_NAME.duplicateResume,
MCP_TOOL_NAME.patchResume,
MCP_TOOL_NAME.updateResume,
]) {
const annotations = TOOL_META[name].annotations;
expect(annotations.readOnlyHint, name).toBe(false);
expect(annotations.idempotentHint, name).toBe(false);
expect(annotations.destructiveHint, name).toBe(false);
}
});
it("marks lockResume / unlockResume as idempotent and non-destructive", () => {
for (const name of [MCP_TOOL_NAME.lockResume, MCP_TOOL_NAME.unlockResume]) {
const annotations = TOOL_META[name].annotations;
expect(annotations.idempotentHint, name).toBe(true);
expect(annotations.destructiveHint, name).toBe(false);
expect(annotations.readOnlyHint, name).toBe(false);
}
});
it("marks only job-posting autofill as open-world", () => {
expect(TOOL_META[MCP_TOOL_NAME.autofillApplicationFromJob].annotations.openWorldHint).toBe(true);
});
it("declares no tools as open-world by default", () => {
for (const [name, { annotations }] of Object.entries(TOOL_META)) {
if (name === MCP_TOOL_NAME.autofillApplicationFromJob) continue;
expect(annotations.openWorldHint).toBe(false);
}
});
});