We're releasing Python and TypeScript SDKs for Vespper.
Until now, connecting an agent to the Vespper DOCX MCP required writing a fair amount of boilerplate: open a session manually over HTTP, pass the right headers, track the session ID, patch the MCP tools, retrieve the document, and close everything at the end. Workable, but tedious.
The SDKs abstract all of that. Install once, and the session lifecycle, authentication, and tool patching are handled for you.
Getting started
TypeScript
npm install vespper
Python
pip install vespper
What the SDK does
Here's the same agent wired up with and without the SDK.
Before — raw HTTP calls:
import { readFileSync, writeFileSync } from "node:fs";
import { Agent } from "@mastra/core/agent";
import { createTool } from "@mastra/core/tools";
import { MCPClient } from "@mastra/mcp";
import { z } from "zod";
const MCP_URL = new URL("https://mcp.vespper.com/mcp");
const SESSION_URL = new URL("/v1/docx/sessions", MCP_URL);
const AUTHORIZATION = "Bearer " + process.env.VESPPER_API_KEY;
const DOCX_CONTENT_TYPE =
"application/vnd.openxmlformats-officedocument.wordprocessingml.document";
async function openDocumentSession(document: Buffer): Promise<string> {
const response = await fetch(SESSION_URL, {
method: "POST",
headers: { Authorization: AUTHORIZATION, "Content-Type": DOCX_CONTENT_TYPE },
body: document,
});
if (!response.ok) throw new Error("Opening document session failed: " + await response.text());
return ((await response.json()) as { session_id: string }).session_id;
}
async function closeDocumentSession(sessionId: string): Promise<void> {
const response = await fetch(
new URL(`/v1/docx/sessions/${sessionId}`, encodeURIComponent(MCP_URL.toString())),
{ method: "DELETE", headers: { Authorization: AUTHORIZATION } }
);
if (!response.ok && response.status !== 404)
throw new Error("Closing document session failed: " + await response.text());
}
const document = readFileSync("sample.docx");
const docx_b64 = document.toString("base64");
const sessionId = await openDocumentSession(document);
const sessionMeta = { "com.vespper/session-id": sessionId };
const mcp = new MCPClient({
servers: { vespperDocx: { url: MCP_URL, requestInit: { headers: { Authorization: AUTHORIZATION } } } },
});
// ... wrap each tool to inject sessionMeta, create agent, run, save, close
After — with the SDK:
import { writeFileSync } from "node:fs";
import { Agent } from "@mastra/core/agent";
import { MCPClient } from "@mastra/mcp";
import Vespper from "vespper";
const client = new Vespper();
const sessionId = await client.openSession("./sample.docx");
const mcp = new MCPClient({
id: "vespper-quickstart",
servers: {
vespperDocx: {
url: new URL("https://mcp.vespper.com/mcp"),
requestInit: {
headers: { Authorization: client.authorizationHeader },
},
},
},
});
await client.patchMCPTools({ mcp, sessionId, author: "Vespper Agent" });
const agent = new Agent({
name: "Example Agent",
instructions:
"You edit a Word document that is already loaded. Call read_document to load its HTML (or search_document to find text in a large document), then edit_document to apply the change as tracked edits.",
model: "openai/gpt-5.5",
tools: await mcp.listTools(),
});
await agent.generate("Add the word hello to the end of the document");
const finalDocument = client.getSessionDocument(sessionId);
writeFileSync("sample-redlined.docx", finalDocument);
await mcp.disconnect();
await client.closeSession(sessionId);
The session lifecycle, authorization header, and MCP tool patching are now one-liners. The agent just focuses on the task.
Learn more
Full documentation is at docs.vespper.com. If you run into anything or have questions, reach us at founders@vespper.com.

