mammoth-mcp 1.0.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 +98 -0
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.js +166 -0
- package/package.json +82 -0
package/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# mammoth-mcp
|
|
2
|
+
|
|
3
|
+
[](https://npmjs.com/package/mammoth-mcp)
|
|
4
|
+
[](https://npmjs.com/package/mammoth-mcp)
|
|
5
|
+
|
|
6
|
+
A Model Context Protocol (MCP) server for converting DOCX files to HTML using [mammoth.js](https://github.com/mwilliamson/mammoth.js).
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **convert_docx_to_html**: Convert DOCX files to clean HTML
|
|
11
|
+
- **convert_docx_to_html_with_images**: Convert DOCX files to HTML with embedded base64 images
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
$ pnpm install
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Development
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
$ npm run dev
|
|
23
|
+
$ npm run build
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
### Configure MCP Client
|
|
29
|
+
|
|
30
|
+
Add the server to your MCP client configuration (e.g., Claude Desktop):
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"mcpServers": {
|
|
35
|
+
"mammoth": {
|
|
36
|
+
"command": "node",
|
|
37
|
+
"args": ["/absolute/path/to/mammoth-mcp/dist/cjs/index.js"]
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Or if installed globally:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"mcpServers": {
|
|
48
|
+
"mammoth": {
|
|
49
|
+
"command": "mammoth-mcp"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Available Tools
|
|
56
|
+
|
|
57
|
+
#### convert_docx_to_html
|
|
58
|
+
|
|
59
|
+
Convert a DOCX file to HTML.
|
|
60
|
+
|
|
61
|
+
**Parameters:**
|
|
62
|
+
- `filePath` (string, required): Absolute path to the DOCX file
|
|
63
|
+
|
|
64
|
+
**Example:**
|
|
65
|
+
```typescript
|
|
66
|
+
{
|
|
67
|
+
"filePath": "/path/to/document.docx"
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
#### convert_docx_to_html_with_images
|
|
72
|
+
|
|
73
|
+
Convert a DOCX file to HTML with images embedded as base64 data URIs.
|
|
74
|
+
|
|
75
|
+
**Parameters:**
|
|
76
|
+
- `filePath` (string, required): Absolute path to the DOCX file
|
|
77
|
+
|
|
78
|
+
**Example:**
|
|
79
|
+
```typescript
|
|
80
|
+
{
|
|
81
|
+
"filePath": "/path/to/document-with-images.docx"
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## How It Works
|
|
86
|
+
|
|
87
|
+
This MCP server uses mammoth.js to convert DOCX documents to clean, semantic HTML. The conversion preserves:
|
|
88
|
+
|
|
89
|
+
- Headings
|
|
90
|
+
- Paragraphs
|
|
91
|
+
- Lists
|
|
92
|
+
- Tables
|
|
93
|
+
- Bold/italic/underline formatting
|
|
94
|
+
- Images (when using the `with_images` variant)
|
|
95
|
+
|
|
96
|
+
## LICENSE
|
|
97
|
+
|
|
98
|
+
MIT
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from))
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
}
|
|
14
|
+
return to;
|
|
15
|
+
};
|
|
16
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
|
|
25
|
+
// src/index.ts
|
|
26
|
+
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
27
|
+
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
28
|
+
var import_mammoth = __toESM(require("mammoth"));
|
|
29
|
+
var fs = __toESM(require("fs/promises"));
|
|
30
|
+
var path = __toESM(require("path"));
|
|
31
|
+
var import_zod = require("zod");
|
|
32
|
+
var server = new import_mcp.McpServer({
|
|
33
|
+
name: "mammoth-mcp",
|
|
34
|
+
version: "1.0.0"
|
|
35
|
+
});
|
|
36
|
+
server.registerTool(
|
|
37
|
+
"convert_docx_to_html",
|
|
38
|
+
{
|
|
39
|
+
description: "Convert a DOCX file to HTML using mammoth. Supports reading from a file path and returns the HTML content.",
|
|
40
|
+
inputSchema: {
|
|
41
|
+
filePath: import_zod.z.string().describe("Absolute path to the DOCX file to convert")
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
async ({ filePath }) => {
|
|
45
|
+
try {
|
|
46
|
+
const absolutePath = path.resolve(filePath);
|
|
47
|
+
await fs.access(absolutePath);
|
|
48
|
+
const result = await import_mammoth.default.convertToHtml({ path: absolutePath });
|
|
49
|
+
let output = `# Conversion Result
|
|
50
|
+
|
|
51
|
+
`;
|
|
52
|
+
output += `**File**: ${absolutePath}
|
|
53
|
+
|
|
54
|
+
`;
|
|
55
|
+
output += `## HTML Output:
|
|
56
|
+
|
|
57
|
+
\`\`\`html
|
|
58
|
+
${result.value}
|
|
59
|
+
\`\`\`
|
|
60
|
+
|
|
61
|
+
`;
|
|
62
|
+
if (result.messages.length > 0) {
|
|
63
|
+
output += `## Messages:
|
|
64
|
+
|
|
65
|
+
`;
|
|
66
|
+
result.messages.forEach((msg) => {
|
|
67
|
+
output += `- ${msg.type}: ${msg.message}
|
|
68
|
+
`;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
content: [
|
|
73
|
+
{
|
|
74
|
+
type: "text",
|
|
75
|
+
text: output
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
};
|
|
79
|
+
} catch (error) {
|
|
80
|
+
return {
|
|
81
|
+
content: [
|
|
82
|
+
{
|
|
83
|
+
type: "text",
|
|
84
|
+
text: `Error converting DOCX file: ${error instanceof Error ? error.message : String(error)}`
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
isError: true
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
);
|
|
92
|
+
server.registerTool(
|
|
93
|
+
"convert_docx_to_html_with_images",
|
|
94
|
+
{
|
|
95
|
+
description: "Convert a DOCX file to HTML with embedded images as base64 data URIs",
|
|
96
|
+
inputSchema: {
|
|
97
|
+
filePath: import_zod.z.string().describe("Absolute path to the DOCX file to convert")
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
async ({ filePath }) => {
|
|
101
|
+
try {
|
|
102
|
+
const absolutePath = path.resolve(filePath);
|
|
103
|
+
await fs.access(absolutePath);
|
|
104
|
+
const result = await import_mammoth.default.convertToHtml(
|
|
105
|
+
{ path: absolutePath },
|
|
106
|
+
{
|
|
107
|
+
convertImage: import_mammoth.default.images.imgElement(async (image) => {
|
|
108
|
+
const buffer = await image.read();
|
|
109
|
+
const base64 = buffer.toString("base64");
|
|
110
|
+
const contentType = image.contentType || "image/png";
|
|
111
|
+
return {
|
|
112
|
+
src: `data:${contentType};base64,${base64}`
|
|
113
|
+
};
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
);
|
|
117
|
+
let output = `# Conversion Result (with images)
|
|
118
|
+
|
|
119
|
+
`;
|
|
120
|
+
output += `**File**: ${absolutePath}
|
|
121
|
+
|
|
122
|
+
`;
|
|
123
|
+
output += `## HTML Output:
|
|
124
|
+
|
|
125
|
+
\`\`\`html
|
|
126
|
+
${result.value}
|
|
127
|
+
\`\`\`
|
|
128
|
+
|
|
129
|
+
`;
|
|
130
|
+
if (result.messages.length > 0) {
|
|
131
|
+
output += `## Messages:
|
|
132
|
+
|
|
133
|
+
`;
|
|
134
|
+
result.messages.forEach((msg) => {
|
|
135
|
+
output += `- ${msg.type}: ${msg.message}
|
|
136
|
+
`;
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
content: [
|
|
141
|
+
{
|
|
142
|
+
type: "text",
|
|
143
|
+
text: output
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
};
|
|
147
|
+
} catch (error) {
|
|
148
|
+
return {
|
|
149
|
+
content: [
|
|
150
|
+
{
|
|
151
|
+
type: "text",
|
|
152
|
+
text: `Error converting DOCX file: ${error instanceof Error ? error.message : String(error)}`
|
|
153
|
+
}
|
|
154
|
+
],
|
|
155
|
+
isError: true
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
);
|
|
160
|
+
async function main() {
|
|
161
|
+
await server.connect(new import_stdio.StdioServerTransport());
|
|
162
|
+
}
|
|
163
|
+
main().catch((error) => {
|
|
164
|
+
console.error("Server error:", error);
|
|
165
|
+
process.exit(1);
|
|
166
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mammoth-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"packageManager": "pnpm@10.12.1",
|
|
5
|
+
"description": "MCP for mammoth - Convert DOCX files to HTML",
|
|
6
|
+
"main": "dist/cjs/index.js",
|
|
7
|
+
"types": "dist/cjs/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"mammoth-mcp": "dist/cjs/index.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"dev": "father dev",
|
|
13
|
+
"dev:inspector": "npm run dev & sleep 2 && npm run inspector",
|
|
14
|
+
"build": "father build && chmod +x dist/cjs/index.js",
|
|
15
|
+
"build:deps": "father prebundle",
|
|
16
|
+
"prepublishOnly": "father doctor && npm run build",
|
|
17
|
+
"inspector": "lsof -ti:6275 | xargs kill -9 2>/dev/null || true && lsof -ti:6278 | xargs kill -9 2>/dev/null || true && chmod +x dist/cjs/index.js && CLIENT_PORT=6275 SERVER_PORT=6278 mcp-inspector dist/cjs/index.js",
|
|
18
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
19
|
+
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
|
20
|
+
"format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,md}\"",
|
|
21
|
+
"format:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,json,md}\"",
|
|
22
|
+
"prepare": "husky",
|
|
23
|
+
"changeset": "changeset",
|
|
24
|
+
"version": "changeset version",
|
|
25
|
+
"release": "pnpm build && npm publish --provenance --access public"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"mcp",
|
|
29
|
+
"mammoth",
|
|
30
|
+
"docx",
|
|
31
|
+
"html",
|
|
32
|
+
"converter",
|
|
33
|
+
"model-context-protocol"
|
|
34
|
+
],
|
|
35
|
+
"authors": [
|
|
36
|
+
"Orchard <orchardyz@outlook.com>"
|
|
37
|
+
],
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/Orchardxyz/mammoth-mcp.git"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://github.com/Orchardxyz/mammoth-mcp#readme",
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/Orchardxyz/mammoth-mcp/issues"
|
|
46
|
+
},
|
|
47
|
+
"files": [
|
|
48
|
+
"dist",
|
|
49
|
+
"compiled"
|
|
50
|
+
],
|
|
51
|
+
"publishConfig": {
|
|
52
|
+
"access": "public"
|
|
53
|
+
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"@modelcontextprotocol/sdk": "1.25.1",
|
|
56
|
+
"mammoth": "1.11.0",
|
|
57
|
+
"zod": "^4.3.2"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@changesets/cli": "^2.27.1",
|
|
61
|
+
"@modelcontextprotocol/inspector": "^0.18.0",
|
|
62
|
+
"@types/node": "25.0.3",
|
|
63
|
+
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
|
64
|
+
"@typescript-eslint/parser": "^6.21.0",
|
|
65
|
+
"eslint": "^8.56.0",
|
|
66
|
+
"eslint-config-prettier": "^9.1.0",
|
|
67
|
+
"eslint-plugin-prettier": "^5.1.3",
|
|
68
|
+
"father": "^4.6.13",
|
|
69
|
+
"husky": "^9.0.11",
|
|
70
|
+
"lint-staged": "^15.2.2",
|
|
71
|
+
"prettier": "^3.2.5"
|
|
72
|
+
},
|
|
73
|
+
"lint-staged": {
|
|
74
|
+
"*.{ts,tsx}": [
|
|
75
|
+
"eslint --fix",
|
|
76
|
+
"prettier --write"
|
|
77
|
+
],
|
|
78
|
+
"*.{js,jsx,json,md}": [
|
|
79
|
+
"prettier --write"
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
}
|