| Filename | Latest commit message | Latest commit date |
|---|---|---|
* feat: compile example servers to JavaScript for npm consumption
Add TypeScript compilation for server code so the example packages can be
imported and used by consumers without requiring TypeScript compilation.
Changes:
- Add tsconfig.server.json to each example for compiling server code
- Update package.json exports to point to compiled dist/server/server.js
- Add types field pointing to dist/server/server.d.ts
- Update build scripts to include server compilation step
- Fix .ts import extensions to .js in customer-segmentation-server
This enables importing the createServer function from published packages:
import { createServer } from '@modelcontextprotocol/server-basic-react';
* fix: add type assertion for Nominatim API response
* chore: regenerate schemas
* refactor: split server examples into library and binary entry points
- server.ts: exports createServer() only (library entry point)
- main.ts: entry point with main() that runs the server (binary)
- package.json: adds bin field for npx support, uses inline bun build
- tsconfig.server.json: emitDeclarationOnly, outputs to dist/
This allows:
1. Importing the server as a library: import { createServer } from '@modelcontextprotocol/server-basic-react'
2. Running with npx: npx @modelcontextprotocol/server-basic-react [--stdio]
Added migration script at scripts/migrate-server-examples.ts
* refactor: migrate remaining server examples to library/binary structure
Apply the same refactoring to all 13 remaining server examples:
- scenario-modeler-server, shadertoy-server, map-server
- cohort-heatmap-server, customer-segmentation-server, video-resource-server
- system-monitor-server, budget-allocator-server, sheet-music-server
- threejs-server, integration-server, transcript-server, wiki-explorer-server
Each now has:
- server.ts: exports createServer() (library)
- main.ts: runs the server (binary with shebang)
- bin field in package.json for npx support
* chore: remove unused server-utils.ts from video-resource-server/src
* update
* fix(build): make Windows-compatible by removing chmod and fixing bun externals
- Remove 'chmod +x dist/index.js' which doesn't exist on Windows
- Add '--external ./server.js' to prevent bun from treating the import as a second entry point
* fix(build): use .ts import for bun compatibility
- Change import from './server.js' to './server.ts' in main.ts files
- Remove --external flag since bun should inline everything
- Fixes Windows build where bun couldn't resolve .js to .ts properly
* fix(build): use --external for Windows bun compatibility
Bun on Windows incorrectly treats imported .ts files as entry points.
Use --external './server.js' to work around this, creating a runtime
dependency between index.js and server.js.
* style: fix prettier formatting in pdf-server/main.ts
* fix(build): remove quotes from --external for Windows cmd.exe compatibility
* fix(build): use glob pattern for --external to work on all platforms
The literal path --external ./server.js was not matching the import.
Using glob pattern --external "./server*" correctly externalizes the server module.
* fix(build): use */server.js pattern for --external
The "./server*" pattern was not matching on Windows.
Using "*/server.js" matches any path ending in /server.js which works cross-platform.
* fix(build): use *server.js pattern without slash for Windows compatibility
* update package-lock
* chore: regenerate package-lock.json for cross-platform compatibility
* fix(build): use ./server.js instead of glob pattern for Windows compatibility
* fix(build): use double quotes for banner to fix Windows cmd.exe compatibility
---------
Co-authored-by: Olivier Chafik <ochafik@anthropic.com>
|
||
| .. | ||
| src | ||
| .gitignore | ||
| grid-cell.png | ||
| main.ts | ||
| mcp-app.html | ||
| package.json | ||
| README.md | ||
| screenshot.png | ||
| server.ts | ||
| tsconfig.json | ||
| tsconfig.server.json | ||
| vite.config.ts | ||
PDF Server
A simple interactive PDF viewer that uses PDF.js. Launch it w/ a few PDF files and/or URLs as CLI args (+ support loading any additional pdf from arxiv.org).
What This Example Demonstrates
1. Chunked Data Through Size-Limited Tool Calls
On some host platforms, tool calls have size limits, so large PDFs cannot be sent in a single response. This example shows a possible workaround:
Server side (pdf-loader.ts):
// Returns chunks with pagination metadata
async function loadPdfBytesChunk(entry, offset, byteCount) {
return {
bytes: base64Chunk,
offset,
byteCount,
totalBytes,
hasMore: offset + byteCount < totalBytes,
};
}
Client side (mcp-app.ts):
// Load in chunks with progress
while (hasMore) {
const chunk = await app.callServerTool("read_pdf_bytes", { pdfId, offset });
chunks.push(base64ToBytes(chunk.bytes));
offset += chunk.byteCount;
hasMore = chunk.hasMore;
updateProgress(offset, chunk.totalBytes);
}
2. Model Context Updates
The viewer keeps the model informed about what the user is seeing:
app.updateModelContext({
structuredContent: {
title: pdfTitle,
currentPage,
totalPages,
pageText: pageText.slice(0, 5000),
selection: selectedText ? { text, start, end } : undefined,
},
});
This enables the model to answer questions about the current page or selected text.
3. Display Modes: Fullscreen vs Inline
- Inline mode: App requests height changes to fit content
- Fullscreen mode: App fills the screen with internal scrolling
// Request fullscreen
app.requestDisplayMode({ mode: "fullscreen" });
// Listen for mode changes
app.ondisplaymodechange = (mode) => {
if (mode === "fullscreen") enableScrolling();
else disableScrolling();
};
4. External Links (openLink)
The viewer demonstrates opening external links (e.g., to the original arxiv page):
titleEl.onclick = () => app.openLink(sourceUrl);
Usage
# Default: loads a sample arxiv paper
bun examples/pdf-server/server.ts
# Load local files (converted to file:// URLs)
bun examples/pdf-server/server.ts ./docs/paper.pdf /path/to/thesis.pdf
# Load from URLs
bun examples/pdf-server/server.ts https://arxiv.org/pdf/2401.00001.pdf
# Mix local and remote
bun examples/pdf-server/server.ts ./local.pdf https://arxiv.org/pdf/2401.00001.pdf
# stdio mode for MCP clients
bun examples/pdf-server/server.ts --stdio ./papers/
Security: Dynamic URLs (via view_pdf tool) are restricted to arxiv.org. Local files must be in the initial list.
Tools
| Tool | Visibility | Purpose |
|---|---|---|
list_pdfs |
Model | List indexed PDFs |
display_pdf |
Model + UI | Display interactive viewer in chat |
read_pdf_bytes |
App only | Chunked binary loading |
Architecture
server.ts # MCP server (233 lines)
├── src/
│ ├── types.ts # Zod schemas (75 lines)
│ ├── pdf-indexer.ts # URL-based indexing (44 lines)
│ ├── pdf-loader.ts # Chunked loading (171 lines)
│ └── mcp-app.ts # Interactive viewer UI
Key Patterns Shown
| Pattern | Implementation |
|---|---|
| App-only tools | _meta: { ui: { visibility: ["app"] } } |
| Chunked responses | hasMore + offset pagination |
| Model context | app.updateModelContext() |
| Display modes | app.requestDisplayMode() |
| External links | app.openLink() |
| Size negotiation | app.sendSizeChanged() |
Dependencies
pdfjs-dist: PDF rendering@modelcontextprotocol/ext-apps: MCP Apps SDK
