Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions examples/pdf-server/server.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,48 @@ describe("display_pdf transport-error handling", () => {
});
});

describe("read_pdf_bytes result content", () => {
let tmpDir: string;
let tmpFile: string;

beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "pdf-read-bytes-"));
tmpFile = path.join(tmpDir, "test.pdf");
fs.writeFileSync(tmpFile, Buffer.from("%PDF-1.4\n%test\n"));
allowedLocalFiles.add(tmpFile);
});

afterEach(() => {
allowedLocalFiles.delete(tmpFile);
fs.rmSync(tmpDir, { recursive: true, force: true });
});

it("mirrors structuredContent as JSON text for clients that only read content", async () => {
const server = createServer();
const client = new Client({ name: "t", version: "1" });
const [ct, st] = InMemoryTransport.createLinkedPair();
await Promise.all([server.connect(st), client.connect(ct)]);

try {
const result = await client.callTool({
name: "read_pdf_bytes",
arguments: { url: tmpFile, offset: 0, byteCount: 8 },
});
expect(result.isError).toBeFalsy();

const content = result.content as { type: string; text: string }[];
expect(content).toHaveLength(1);
expect(content[0].type).toBe("text");
const parsed = JSON.parse(content[0].text);
expect(parsed).toEqual(result.structuredContent);
expect(Buffer.from(parsed.bytes, "base64").toString()).toBe("%PDF-1.4");
} finally {
await client.close();
await server.close();
}
});
});

describe("extractFormSchema field-tree handling", () => {
async function schemaFor(bytes: Uint8Array) {
const doc = await getDocument({ data: bytes }).promise;
Expand Down
26 changes: 12 additions & 14 deletions examples/pdf-server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1416,22 +1416,20 @@ export function createServer(options: CreateServerOptions = {}): McpServer {
// Base64 encode for JSON transport
const bytes = Buffer.from(data).toString("base64");
const hasMore = offset + data.length < totalBytes;
const chunk = {
url: normalized,
bytes,
offset,
byteCount: data.length,
totalBytes,
hasMore,
};

return {
content: [
{
type: "text",
text: `${data.length} bytes at ${offset}/${totalBytes}`,
},
],
structuredContent: {
url: normalized,
bytes,
offset,
byteCount: data.length,
totalBytes,
hasMore,
},
// Per the MCP spec, also return the serialized structured content
// as text so clients that only read content[] still get the bytes.
content: [{ type: "text", text: JSON.stringify(chunk) }],
structuredContent: chunk,
};
} catch (err) {
return {
Expand Down