WangChengYeh/mcp_word
If you are the rightful owner of mcp_word and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
The MCP Word Add-in is a server that facilitates AI-driven document editing workflows in Microsoft Word through a proxy server and Office.js Add-in.
MCP Word — MCP Server + Office Add-in
Version: 0.1.0
Date: 2025-08-13
Language: English only
AI-driven document editing for Microsoft Word using a local MCP server (stdio) bridged to an Office.js task pane via Socket.IO over HTTPS. This project builds a MCP server (node server.js) alongside an Office.js Word Add-in client to enable AI-driven document editing workflows.
Architecture
flowchart LR
A[Codex CLI] -->|stdio| B[MCP Server]
B -->|WebSocket| C[Office.js]
Components
MCP Server (server.js)
- Imports
McpServerfrom@modelcontextprotocol/sdk/server/mcp.js - Imports
StdioServerTransportfrom@modelcontextprotocol/sdk/server/stdio.js - Dynamically loads tools via
registerToolsfrom eithertool.js(default) ortool_simple.js(when--simple) - Tool schemas follow
schema.jsonwith simple enums (noanyOf) - Forwards MCP tool payloads (JSON) to Socket.IO clients
- Emits
io.emit(toolName, toolParams)to the Office add‑in
Office Add-in (public/)
manifest.xml: Defines Add-in ID, version, provider, display name, description. Host: Document; Permissions: ReadWriteDocumenttaskpane.html: Loads Office.js and Socket.io client, includestaskpane.js, renders button or auto-start behaviortaskpane.js: UsesOffice.onReady()for Word host detection, establishes WebSocket withio(), listens for MCP tool events, calls Word functions viaWord.run(), implements error handlingtaskpane.yaml: For Script Lab snippet import with libraries including Socket.io
Snippet Upload
Upload to gist via package.json script:
npm run snippet # Runs: cd public && gh gist edit 5b44e6ba1c99baae62ebc0783e1469da --add taskpane.yaml
Workflow
- Install the MCP server:
npm install - Start the server: Use stdio from Codex CLI or fake master, use unix pipeline to provide input
- Sideload the Add-in: Load manifest in Word
- Send EditTask requests: Via Codex CLI or another service, e.g.
{ content: '...' } - Real-time edits: The Add-in client receives edits in real time and applies them to the document
Prerequisites
- Node.js 18.17+
- Microsoft Word (desktop) with sideloading enabled
- Local HTTPS certificate trusted by your OS/Office (self-signed is fine for dev)
Install
npm install
Run Server (HTTPS required)
The server requires TLS. Start with PEM key/cert or a PFX bundle.
# PEM key/cert
node server.js --key path/to/key.pem --cert path/to/cert.pem --port 3000
# or PFX/P12
node server.js --pfx path/to/cert.pfx --passphrase "your-passphrase" --port 3000
# optional verbose logging
node server.js --key key.pem --cert cert.pem --port 3000 --debug
# simple mode (hooks tool_simple.js for flow testing)
node server.js --key key.pem --cert cert.pem --port 3000 --simple
Tips:
- Use self-signed certs for dev and mark them trusted so Office/Browser accept
https://localhost:3000. - Static files are served from
public/. - Endpoints:
- Health:
GET https://localhost:3000/healthz
- Health:
Create a Local Dev Certificate
openssl req -x509 -newkey rsa:2048 -sha256 -days 365 -nodes \
-keyout key.pem -out cert.pem \
-subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
# Optional PFX/P12 bundle
openssl pkcs12 -export -out cert.pfx -inkey key.pem -in cert.pem -passout pass:your-passphrase
Trust the cert in your OS keychain so Word and your browser accept it.
Configure MCP Client
Point your MCP client to run server.js via Node.
Codex CLI (.codex/config.toml):
# Place in ./.codex/config.toml (project) or ~/.codex/config.toml (user)
[mcp_servers.mcp_word]
command = "node"
args = [
"/absolute/path/to/server.js",
"--key", "/abs/path/to/key.pem",
"--cert", "/abs/path/to/cert.pem",
"--port", "3000"
]
cwd = "/absolute/path/to/project"
# Optional: env vars
env = { NODE_ENV = "production" }
Notes:
- Use absolute paths for reliability.
- If using a PFX/P12 bundle: replace
--key/--certwith--pfx /abs/cert.pfx --passphrase "your-passphrase". - Restart the Codex Client after saving the config; tools
pingandeditTaskshould appear.
Claude Desktop (settings excerpt):
{
"mcpServers": {
"mcp-word": {
"command": "node",
"args": ["/absolute/path/to/server.js", "--key", "/abs/key.pem", "--cert", "/abs/cert.pem", "--port", "3000"],
"cwd": "/absolute/path/to/project"
}
}
}
Claude CLI:
claude mcp add mcp-word -- node /absolute/path/to/server.js --key /abs/key.pem --cert /abs/cert.pem --port 3000
Office Add-in
Two ways to connect Word to the server:
1) Sideload manifest
- Open Word → Add-ins → Sideload
public/manifest.xml - Manifest points to
public/taskpane.html - Ensure the same host/port and a trusted certificate
2) Script Lab (alternative)
- Option A (paste JS): Install Script Lab, create a new script and paste
public/taskpane.js, and add libraryhttps://cdn.socket.io/4.7.5/socket.io.min.js. - Option B (import YAML): In Script Lab, import from https://gist.github.com/WangChengYeh/5b44e6ba1c99baae62ebc0783e1469da
Tools
editTask
- Purpose: Send an edit instruction to the add-in via Socket.IO (event name
editTask) - Schema: Follows
schema.jsonrules with simple enums (noanyOfpatterns) - Args:
content(string, required): text to insert/replaceaction("insert" | "replace" | "append", default "insert")target("cursor" | "selection" | "document", default "selection")taskId(string, optional)meta(object, optional)
JSON-RPC example (MCP stdio frame):
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "editTask",
"arguments": {
"content": "Hello from MCP",
"action": "insert",
"target": "selection"
}
}
}
ping
- Purpose: Health check; echoes
messageor returns"pong" - Schema: Simple tool registration without complex patterns
Debugging
--debug: Dumps detailed logs and errors todebug.log- Records stdio stream input/output into
debug.log - Adds pipes after stdin and before stdout to record and forward if debug enabled
- Records JSON strings before Socket.IO send and after Socket.IO receive in
debug.log - Health endpoint:
GET https://localhost:3000/healthzshows connected clients - Stream logging in
debug.log:[time][stdin] json string: raw MCP stdio frames received[time][stdout] json string: raw MCP stdio responses[time][socket:send] json string: forwarded tool calls to Socket.IO[time][socket.recv] json string: received back from the add-in (e.g.,edit-complete)
Testing
Testing Modes
- Simple mode:
server.js --simplehookstool_simple.js(flow tests)- Unit:
npm run test:simple - Integration:
npm run test:int:simple
- Unit:
- Normal mode:
server.js(no--simple) hookstool.js(regular usage)- Unit:
npm test - Integration:
npm run test:int
- Unit:
Unit Tests
test.sh: Unit test with fake stdio for MCP client and socket connection for Office- Uses shell pipeline to provide input
- Generates test JavaScript as socket client
- Prepare
package.jsonbefore testing - Default test port: 3100 (3000 reserved for normal use)
test_simple.sh: Testsserver.js --simplemode usingtool_simple.js
Run via npm commands:
# Simple mode unit test
npm run test:simple
# Full unit test
npm test
Integration Tests
test.js: Integration test combining MCP client + MCP server (server.js)- Uses
Clientfrom@modelcontextprotocol/sdk/client/index.js - Lists tools and calls tools (e.g.,
ping,editTask) test_simple.js: Testsserver.js --simplemode
Run via npm commands:
# Simple mode integration test
npm run test:int:simple
# Full integration test
npm run test:int
End-to-End Testing
Use the provided script to verify end‑to‑end behavior. It auto-generates a dev cert, starts the server, opens a Socket.IO client, and sends MCP frames via stdio.
# Default smoke test
./test.sh
# Pipe custom MCP JSONL (one JSON object per line)
echo '{"jsonrpc":"2.0","id":10,"method":"tools/call","params":{"name":"editTask","arguments":{"content":"PipeMsg","action":"insert","target":"selection"}}}' | ./test.sh
# Multiple lines
cat <<'EOF' | ./test.sh
{"jsonrpc":"2.0","id":11,"method":"tools/call","params":{"name":"ping","arguments":{"message":"hello"}}}
{"jsonrpc":"2.0","id":12,"method":"tools/call","params":{"name":"editTask","arguments":{"content":"FromSTDIN","action":"insert","target":"selection"}}}
EOF
Notes:
- The proxy emits Socket.IO events named by the MCP tool. For
editTask, the event iseditTaskand the payload is the tool arguments object. - The script extracts expected content from the first
editTaskline. - Accepts self-signed certs for test convenience.
Extensibility
- Support additional
EditTasktypes (tables, images, formatting) - Add WebSocket authentication, logging, and error tracking
Project Structure
mcp_word/
├── server.js # MCP stdio + Socket.IO bridge (HTTPS)
├── tool.js # MCP tool registration + Socket.IO forwarding
├── tool_simple.js # Simplified tool set for flow tests (--simple)
├── public/
│ ├── manifest.xml # Office add-in manifest
│ ├── taskpane.html # Minimal task pane
│ ├── taskpane.js # Applies edit commands via Office.js
│ └── taskpane.yaml # Script Lab snippet for import
├── test.sh # E2E test runner (JSONL over stdio)
├── test_simple.sh # Unit test runner for --simple
├── test.js # Integration test (normal mode)
├── test_simple.js # Integration test (simple mode)
├── SPEC.md # Refined spec
└── README.md
Documentation Requirements
This README follows the SPEC requirements and includes (in order):
- Prerequisites: Node.js version, Microsoft Word, and trusted HTTPS cert note
- Install:
npm install - Run server: HTTPS launch examples (PEM and PFX), plus
--debug - Create a local dev certificate: OpenSSL commands to generate PEM and PFX
- Configure MCP client: Codex Client setup via
.codex/config.toml - Office add-in: Two options (Sideload manifest or Script Lab snippets)
- Tools: Document
editTaskandpingtools with args and examples - Debugging:
--debugand debug.log details - Testing: How to run tests by npm command
- Project structure and License
License
See LICENSE.