@sylphx/pdf-reader-mcp 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -2
- package/dist/index.js +47 -7
- package/package.json +14 -19
package/README.md
CHANGED
|
@@ -593,6 +593,63 @@ Restart MCP client completely.
|
|
|
593
593
|
|
|
594
594
|
---
|
|
595
595
|
|
|
596
|
+
## 🌐 HTTP Transport (Remote Access)
|
|
597
|
+
|
|
598
|
+
By default, PDF Reader MCP uses stdio transport for local use. You can also run it as an HTTP server for remote access from multiple machines.
|
|
599
|
+
|
|
600
|
+
### Quick Start
|
|
601
|
+
|
|
602
|
+
```bash
|
|
603
|
+
# Run as HTTP server on port 8080
|
|
604
|
+
MCP_TRANSPORT=http npx @sylphx/pdf-reader-mcp
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
### Environment Variables
|
|
608
|
+
|
|
609
|
+
| Variable | Default | Description |
|
|
610
|
+
|----------|---------|-------------|
|
|
611
|
+
| `MCP_TRANSPORT` | `stdio` | Transport type: `stdio` or `http` |
|
|
612
|
+
| `MCP_HTTP_PORT` | `8080` | HTTP server port |
|
|
613
|
+
| `MCP_HTTP_HOST` | `0.0.0.0` | HTTP server hostname |
|
|
614
|
+
| `MCP_API_KEY` | - | Optional API key for authentication |
|
|
615
|
+
|
|
616
|
+
### Docker Deployment
|
|
617
|
+
|
|
618
|
+
```dockerfile
|
|
619
|
+
FROM oven/bun:1
|
|
620
|
+
WORKDIR /app
|
|
621
|
+
RUN bun add @sylphx/pdf-reader-mcp
|
|
622
|
+
ENV MCP_TRANSPORT=http
|
|
623
|
+
ENV MCP_HTTP_PORT=8080
|
|
624
|
+
EXPOSE 8080
|
|
625
|
+
CMD ["bun", "node_modules/@sylphx/pdf-reader-mcp/dist/index.js"]
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
### MCP Client Configuration (HTTP)
|
|
629
|
+
|
|
630
|
+
```json
|
|
631
|
+
{
|
|
632
|
+
"servers": {
|
|
633
|
+
"pdf-reader": {
|
|
634
|
+
"type": "http",
|
|
635
|
+
"url": "https://your-server.com/mcp",
|
|
636
|
+
"headers": {
|
|
637
|
+
"X-API-Key": "your-api-key"
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
### Endpoints
|
|
645
|
+
|
|
646
|
+
| Endpoint | Method | Description |
|
|
647
|
+
|----------|--------|-------------|
|
|
648
|
+
| `/mcp` | POST | JSON-RPC endpoint |
|
|
649
|
+
| `/mcp/health` | GET | Health check |
|
|
650
|
+
|
|
651
|
+
---
|
|
652
|
+
|
|
596
653
|
## 🏗️ Architecture
|
|
597
654
|
|
|
598
655
|
### Tech Stack
|
|
@@ -772,12 +829,11 @@ Special thanks to the open source community ❤️
|
|
|
772
829
|
This project uses the following [@sylphx](https://github.com/SylphxAI) packages:
|
|
773
830
|
|
|
774
831
|
- [@sylphx/mcp-server-sdk](https://github.com/SylphxAI/mcp-server-sdk) - MCP server framework
|
|
832
|
+
- [@sylphx/vex](https://github.com/SylphxAI/vex) - Schema validation
|
|
775
833
|
- [@sylphx/biome-config](https://github.com/SylphxAI/biome-config) - Biome configuration
|
|
776
834
|
- [@sylphx/tsconfig](https://github.com/SylphxAI/tsconfig) - TypeScript configuration
|
|
777
835
|
- [@sylphx/bump](https://github.com/SylphxAI/bump) - Version management
|
|
778
836
|
- [@sylphx/doctor](https://github.com/SylphxAI/doctor) - Project health checker
|
|
779
|
-
- [@sylphx/leaf](https://github.com/SylphxAI/leaf) - Documentation framework
|
|
780
|
-
- [@sylphx/leaf-theme-default](https://github.com/SylphxAI/leaf-theme-default) - Documentation theme
|
|
781
837
|
|
|
782
838
|
---
|
|
783
839
|
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { createServer, stdio } from "@sylphx/mcp-server-sdk";
|
|
4
|
+
import { createServer, http, stdio } from "@sylphx/mcp-server-sdk";
|
|
5
5
|
|
|
6
6
|
// src/handlers/readPdf.ts
|
|
7
7
|
import { image, text, tool, toolError } from "@sylphx/mcp-server-sdk";
|
|
@@ -509,7 +509,16 @@ var processSingleSource = async (source, options) => {
|
|
|
509
509
|
output.warnings = warnings;
|
|
510
510
|
}
|
|
511
511
|
if (pagesToProcess.length > 0) {
|
|
512
|
-
const
|
|
512
|
+
const MAX_CONCURRENT_PAGES = 5;
|
|
513
|
+
const pageContents = [];
|
|
514
|
+
for (let i = 0;i < pagesToProcess.length; i += MAX_CONCURRENT_PAGES) {
|
|
515
|
+
const batch = pagesToProcess.slice(i, i + MAX_CONCURRENT_PAGES);
|
|
516
|
+
const batchResults = await Promise.all(batch.map((pageNum) => extractPageContent(pdfDocument, pageNum, options.includeImages, sourceDescription)));
|
|
517
|
+
pageContents.push(...batchResults);
|
|
518
|
+
if (i + MAX_CONCURRENT_PAGES < pagesToProcess.length) {
|
|
519
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
520
|
+
}
|
|
521
|
+
}
|
|
513
522
|
output.page_contents = pageContents.map((items, idx) => ({
|
|
514
523
|
page: pagesToProcess[idx],
|
|
515
524
|
items
|
|
@@ -598,29 +607,60 @@ var readPdf = tool().description("Reads content/metadata/images from one or more
|
|
|
598
607
|
if (!result.success || !result.data?.page_contents)
|
|
599
608
|
continue;
|
|
600
609
|
for (const pageContent of result.data.page_contents) {
|
|
610
|
+
const pageTextParts = [];
|
|
611
|
+
const pageImages = [];
|
|
601
612
|
for (const item of pageContent.items) {
|
|
602
613
|
if (item.type === "text" && item.textContent) {
|
|
603
|
-
|
|
614
|
+
pageTextParts.push(item.textContent);
|
|
604
615
|
} else if (item.type === "image" && item.imageData) {
|
|
605
|
-
|
|
616
|
+
pageImages.push(item.imageData);
|
|
606
617
|
}
|
|
607
618
|
}
|
|
619
|
+
if (pageTextParts.length > 0) {
|
|
620
|
+
content.push(text(`[Page ${pageContent.page}]
|
|
621
|
+
${pageTextParts.join(`
|
|
622
|
+
`)}`));
|
|
623
|
+
}
|
|
624
|
+
for (const img of pageImages) {
|
|
625
|
+
content.push(image(img.data, "image/png"));
|
|
626
|
+
}
|
|
608
627
|
}
|
|
609
628
|
}
|
|
610
629
|
return content;
|
|
611
630
|
});
|
|
612
631
|
|
|
613
632
|
// src/index.ts
|
|
633
|
+
var transportType = process.env["MCP_TRANSPORT"] ?? "stdio";
|
|
634
|
+
var httpPort = Number.parseInt(process.env["MCP_HTTP_PORT"] ?? "8080", 10);
|
|
635
|
+
var httpHost = process.env["MCP_HTTP_HOST"] ?? "0.0.0.0";
|
|
636
|
+
var apiKey = process.env["MCP_API_KEY"];
|
|
637
|
+
function createTransport() {
|
|
638
|
+
if (transportType === "http") {
|
|
639
|
+
return http({
|
|
640
|
+
port: httpPort,
|
|
641
|
+
hostname: httpHost,
|
|
642
|
+
cors: "*"
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
return stdio();
|
|
646
|
+
}
|
|
614
647
|
var server = createServer({
|
|
615
648
|
name: "pdf-reader-mcp",
|
|
616
|
-
version: "1.
|
|
649
|
+
version: "2.1.0",
|
|
617
650
|
instructions: "MCP Server for reading PDF files and extracting text, metadata, images, and page information.",
|
|
618
651
|
tools: { read_pdf: readPdf },
|
|
619
|
-
transport:
|
|
652
|
+
transport: createTransport()
|
|
620
653
|
});
|
|
621
654
|
async function main() {
|
|
622
655
|
await server.start();
|
|
623
|
-
if (
|
|
656
|
+
if (transportType === "http") {
|
|
657
|
+
console.log(`[PDF Reader MCP] Server running on http://${httpHost}:${httpPort}/mcp`);
|
|
658
|
+
console.log(`[PDF Reader MCP] Health check: http://${httpHost}:${httpPort}/mcp/health`);
|
|
659
|
+
if (apiKey) {
|
|
660
|
+
console.log("[PDF Reader MCP] API key authentication enabled (X-API-Key header)");
|
|
661
|
+
}
|
|
662
|
+
console.log("[PDF Reader MCP] Project root:", process.cwd());
|
|
663
|
+
} else if (process.env["DEBUG_MCP"]) {
|
|
624
664
|
console.error("[PDF Reader MCP] Server running on stdio");
|
|
625
665
|
console.error("[PDF Reader MCP] Project root:", process.cwd());
|
|
626
666
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sylphx/pdf-reader-mcp",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "An MCP server providing tools to read PDF files.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -12,9 +12,7 @@
|
|
|
12
12
|
"LICENSE"
|
|
13
13
|
],
|
|
14
14
|
"exports": {
|
|
15
|
-
".":
|
|
16
|
-
"import": "./dist/index.js"
|
|
17
|
-
}
|
|
15
|
+
".": "./dist/index.js"
|
|
18
16
|
},
|
|
19
17
|
"publishConfig": {
|
|
20
18
|
"access": "public"
|
|
@@ -45,7 +43,7 @@
|
|
|
45
43
|
"tool"
|
|
46
44
|
],
|
|
47
45
|
"scripts": {
|
|
48
|
-
"build": "bunup",
|
|
46
|
+
"build": "bunup --no-dts",
|
|
49
47
|
"watch": "tsc --watch",
|
|
50
48
|
"inspector": "npx @modelcontextprotocol/inspector dist/index.js",
|
|
51
49
|
"test": "bun test",
|
|
@@ -58,9 +56,9 @@
|
|
|
58
56
|
"check": "biome check .",
|
|
59
57
|
"check:fix": "biome check --write .",
|
|
60
58
|
"validate": "bun run check && bun run test",
|
|
61
|
-
"docs:dev": "
|
|
62
|
-
"docs:build": "
|
|
63
|
-
"docs:preview": "
|
|
59
|
+
"docs:dev": "vitepress dev docs",
|
|
60
|
+
"docs:build": "vitepress build docs",
|
|
61
|
+
"docs:preview": "vitepress preview docs",
|
|
64
62
|
"start": "node dist/index.js",
|
|
65
63
|
"typecheck": "tsc --noEmit",
|
|
66
64
|
"benchmark": "bun bench",
|
|
@@ -77,28 +75,25 @@
|
|
|
77
75
|
"pdfjs-dist": "^5.4.449",
|
|
78
76
|
"pngjs": "^7.0.0"
|
|
79
77
|
},
|
|
78
|
+
"overrides": {
|
|
79
|
+
"esbuild": "^0.25.0",
|
|
80
|
+
"preact": "^10.28.2"
|
|
81
|
+
},
|
|
80
82
|
"devDependencies": {
|
|
81
83
|
"@biomejs/biome": "^2.3.8",
|
|
82
|
-
"@solidjs/router": "^0.15.4",
|
|
83
84
|
"@sylphx/biome-config": "^0.4.1",
|
|
84
85
|
"@sylphx/bump": "^1.6.1",
|
|
85
86
|
"@sylphx/doctor": "^1.32.1",
|
|
86
|
-
"@sylphx/leaf": "^1.0.0",
|
|
87
|
-
"@sylphx/leaf-theme-default": "^1.0.0",
|
|
88
87
|
"@sylphx/tsconfig": "^0.3.1",
|
|
89
88
|
"@types/glob": "^8.1.0",
|
|
90
|
-
"@types/node": "^
|
|
89
|
+
"@types/node": "^25.0.3",
|
|
91
90
|
"@types/pngjs": "^6.0.5",
|
|
92
|
-
"bunup": "
|
|
91
|
+
"bunup": "0.16.10",
|
|
93
92
|
"lefthook": "^2.0.7",
|
|
94
|
-
"solid-js": "^1.9.10",
|
|
95
93
|
"typedoc": "^0.28.15",
|
|
96
94
|
"typedoc-plugin-markdown": "^4.9.0",
|
|
97
95
|
"typescript": "^5.9.3",
|
|
98
|
-
"
|
|
96
|
+
"vitepress": "^1.6.4"
|
|
99
97
|
},
|
|
100
|
-
"packageManager": "bun@1.3.1"
|
|
101
|
-
"overrides": {
|
|
102
|
-
"js-yaml": "^4.1.0"
|
|
103
|
-
}
|
|
98
|
+
"packageManager": "bun@1.3.1"
|
|
104
99
|
}
|