import "dotenv/config";
import { writeFileSync } from "node:fs";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import Vespper, { type SuggestEditResult } from "vespper";
const OLD =
'<p class="...">This report summarizes our Q4 performance. Revenue grew steadily across all regions, and operating margins improved compared to the prior quarter.</p>';
const client = new Vespper();
const sessionId = await client.openSession("./sample.docx");
const mcp = new Client({ name: "suggestions-example", version: "0.1.0" });
await mcp.connect(
new StreamableHTTPClientTransport(new URL("https://mcp.vespper.com/mcp"), {
requestInit: {
headers: { Authorization: client.authorizationHeader },
},
}),
);
await client.patchMCPTools({ mcp, sessionId, suggest: true });
// Your agent makes this call. With suggest: true, it only locates the edit
// in the document and returns it as a suggestion. Nothing is applied.
const result = await mcp.callTool({
name: "edit_document",
arguments: {
edits: [{ old: OLD, new: OLD.replace("grew steadily", "grew 12%") }],
},
});
const { suggestions } = result.structuredContent as SuggestEditResult;
// After the user accepts the suggestions, apply them.
const accepted = suggestions.map((suggestion) => ({
old: suggestion.old,
new: suggestion.new,
}));
for await (const outcome of client.applyEdits(sessionId, accepted, {
author: "Vespper Agent",
})) {
if (!outcome.ok) console.error(outcome.position, outcome.reason);
}
writeFileSync("sample-redlined.docx", client.getSessionDocument(sessionId));
await mcp.close();
await client.closeSession(sessionId);