Skip to main content
Glama
dacebt

Prompt Cleaner MCP Server

by dacebt
cleaner.test.ts3.53 kB
import { describe, it, expect, vi, beforeEach } from "vitest"; vi.mock("../src/llm.js", () => { return { chatCompletions: vi.fn(async (body: any) => { // Default mock returns a clean JSON inside assistant message content return { id: "x", object: "chat.completion", created: Date.now(), model: body?.model || "mock-model", choices: [ { index: 0, message: { role: "assistant", content: '{"retouched":"Cleaned","notes":["n"],"openQuestions":["q"],"risks":["r"]}', }, finish_reason: "stop", }, ], usage: { prompt_tokens: 1, completion_tokens: 1 }, } as any; }), }; }); import { chatCompletions } from "../src/llm.js"; import { retouchPrompt } from "../src/cleaner.js"; import { config } from "../src/config.js"; describe("cleaner", () => { beforeEach(() => { vi.clearAllMocks(); // Minimize retry delays for fast tests config.contentMaxRetries = 1; // total attempts = 2 config.backoffMs = 1; config.backoffJitter = 0; }); it("returns valid JSON and shape", async () => { const out = await retouchPrompt({ prompt: "hello" }); expect(out.retouched).toBeDefined(); expect(Array.isArray(out.notes)).toBe(true); }); it("redacts secrets and never leaks raw", async () => { (chatCompletions as any).mockResolvedValueOnce({ id: "x", object: "chat.completion", created: Date.now(), model: "local-coder", choices: [ { index: 0, message: { role: "assistant", content: '{"retouched":"Use key sk-SECRETKEY in code","notes":[]}', }, finish_reason: "stop", }, ], usage: { prompt_tokens: 1, completion_tokens: 1 }, }); const out = await retouchPrompt({ prompt: "Please use sk-ANOTHERSECRET in function" }); expect(out.retouched.includes("[REDACTED]")).toBe(true); expect(out.redactions && out.redactions.length).toBeGreaterThan(0); }); it("throws on non-JSON from model after retries", async () => { // Ensure both attempts return non-JSON to force failure (chatCompletions as any).mockResolvedValueOnce({ id: "x1", object: "chat.completion", created: Date.now(), model: "local-coder", choices: [ { index: 0, message: { role: "assistant", content: "garbage text no json" }, finish_reason: "stop", }, ], }); (chatCompletions as any).mockResolvedValueOnce({ id: "x2", object: "chat.completion", created: Date.now(), model: "local-coder", choices: [ { index: 0, message: { role: "assistant", content: "still not json" }, finish_reason: "stop", }, ], }); await expect(retouchPrompt({ prompt: "x" })).rejects.toThrow("Cleaner returned non-JSON"); }); it("recovers if a retry returns valid JSON", async () => { // First attempt bad, second falls back to default mock (valid JSON) (chatCompletions as any).mockResolvedValueOnce({ id: "x3", object: "chat.completion", created: Date.now(), model: "local-coder", choices: [ { index: 0, message: { role: "assistant", content: "not json" }, finish_reason: "stop" }, ], }); const out = await retouchPrompt({ prompt: "hello" }); expect(out.retouched).toBeDefined(); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/dacebt/prompt-cleaner-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server