Sno Station
Sno Station은 AI 에이전트를 하나의 팀으로 묶는 오픈소스 워크스테이션으로, 로컬 머신에서 에이전트 협업을 가능하게 함
MCP 서버로 AI 비서가 macOS와 웹에서 PowerPoint 프레젠테이션을 편집하게 합니다
An MCP server that lets AI assistants edit open PowerPoint presentations on macOS and the web
AI가 요약 · README에서
플러그인TypeScript · ShellGitHub @kzarzycki직접 설치운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
설치형 프로젝트는 배포 도메인 없이도 확인할 수 있습니다. 개인 저장소는 GitHub 로그인으로, 조직 저장소는 위의 저장소 확인 파일로 직접 확인해 주세요.
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
An MCP server that lets AI assistants manipulate live, open PowerPoint presentations on macOS and PowerPoint Web via Office.js APIs.
Unlike file-based tools (python-pptx), PowerPoint MCP works with presentations that are already open — changes appear instantly, and you keep full access to PowerPoint's UI, animations, and formatting.
This repository includes Codex plugin metadata in .codex-plugin/ and Codex repo instructions in AGENTS.md.
The Codex plugin MCP config in .mcp.json uses the shared HTTP MCP endpoint:README 전문 보기 ↗An MCP server that lets AI assistants manipulate live, open PowerPoint presentations on macOS and PowerPoint Web via Office.js APIs.
Unlike file-based tools (python-pptx), PowerPoint MCP works with presentations that are already open — changes appear instantly, and you keep full access to PowerPoint's UI, animations, and formatting.
This repository includes Codex plugin metadata in .codex-plugin/ and Codex repo instructions in AGENTS.md.
For local development:
git clone https://github.com/kzarzycki/powerpoint-mcp.git
cd powerpoint-mcp
npm install
npm run build
The Codex plugin MCP config in .mcp.json uses the shared HTTP MCP endpoint:
{
"mcpServers": {
"powerpoint-mcp": {
"type": "http",
"url": "http://localhost:3001/mcp"
}
}
}
The Codex plugin ships a SessionStart hook in hooks/hooks.json. On session start it runs scripts/start-http-bridge.sh, which starts the built bridge with node ./dist/index.cjs --http --bridge if the HTTP MCP server or add-in bridge is not already healthy.
Then restart PowerPoint, open a presentation, and click the bridge add-in in the ribbon. For manual local development, start the TypeScript source directly with node --experimental-strip-types ./server/index.ts --http --bridge.
Zero-config install from the marketplace. MCP auto-starts, add-in auto-sideloads, skill included.
/plugin marketplace add kzarzycki/powerpoint-mcp
/plugin install powerpoint-mcp@powerpoint-mcp
Then restart PowerPoint, open a presentation, and click the bridge add-in in the ribbon.
Build and install as a one-click .mcpb extension (from source):
git clone https://github.com/kzarzycki/powerpoint-mcp.git
cd powerpoint-mcp
npm install && npm run build:mcpb
open powerpoint-mcp-*.mcpb # opens Claude Desktop installer
The extension auto-starts the bridge and auto-sideloads the add-in. Restart PowerPoint after first install.
Known limitations:
git clone https://github.com/kzarzycki/powerpoint-mcp.git
cd powerpoint-mcp
npm install
npm run sideload # copies manifest to PowerPoint's add-in folder
npm start -- --http --bridge # starts the MCP HTTP transport (:3001/mcp) + add-in bridge (:8080)
Then point your MCP client at the HTTP transport. Create or merge into the project's .mcp.json:
{
"mcpServers": {
"powerpoint-mcp": {
"type": "http",
"url": "http://localhost:3001/mcp"
}
}
}
Restart PowerPoint, open a presentation, and click the bridge add-in in the ribbon. For STDIO mode and other standalone options, see skills/powerpoint-mcp/references/setup.md.
This project was inspired by the Claude in PowerPoint add-in. The first time I tried it, I was amazed — it edits live, open decks via Office.js, and the results are far better than file-based pptx tools. But it only works inside the add-in, which means no access to CLAUDE.md, skills, or any other Claude Code features. PowerPoint MCP brings those same Office.js capabilities to Claude Code (and any MCP client) so you get live editing with the full power of your coding environment.
The project was originally named powerpoint-bridge and renamed to powerpoint-mcp in v0.5.0. The "bridge server" component keeps its name — it bridges MCP and the Office.js add-in over WebSocket.
AI Assistant <--MCP STDIO/HTTP--> Bridge Server (Node.js) <--WS/WSS--> PowerPoint Add-in (Office.js)
| |
STDIO (default) Desktop: WKWebView sandbox
or HTTP (:3001/mcp) Web: browser iframe
localhost:8080 (HTTP) Office.js API 1.1-1.8
or :8443 (HTTPS) executes commands on
serves add-in files + WS live presentation
Two MCP transports are supported:
--stdio flag; the MCP client spawns the server process directly127.0.0.1:3001/mcp; enabled by the --http flag (e.g. node server/index.ts --http --bridge for development with .mcp.json)Three components in one repo:
addin/ — Office.js taskpane add-in that loads inside PowerPoint and connects as a WebSocket clientserver/ — Node.js bridge server: HTTP + WS + MCP transport (HTTPS/WSS opt-in via BRIDGE_TLS=1)skills/powerpoint-mcp/ — Claude Code skill with tool docs, code patterns, and setup guide (auto-installed with plugin)certs/ — Optional local TLS certificates for HTTPS mode (generated, gitignored)brew install node
| Tool | Description |
|---|---|
list_presentations | Lists all connected presentations with their IDs and status |
inspect_deck | Deck overview: slide dimensions, theme (colors + fonts), and all slides with layout and shape count |
inspect_layouts | Slide layouts with names, types, placeholders, and positions. Supports field selection |
inspect_slide | Returns detailed shape info for a slide (text, positions, sizes, fills) |
scan_slide | Lightweight shape scanner: IDs, types, and positions |
screenshot_slide | Captures a visual screenshot of a slide as PNG (requires PowerPoint 16.96+) |
preview_deck | Returns thumbnails + text for all/selected slides in one call (efficient full-deck review) |
copy_slides | Copies slides between two open presentations (data stays server-side, never in Claude context) |
insert_image | Inserts an image from a file path, URL, or base64 data onto a slide |
get_local_copy | Returns a local file path for the presentation (passthrough for local, exports cloud files to temp .pptx) |
search_fluent_icons | Search Microsoft Fluent UI icons by keyword and insert as SVG |
execute_officejs | Runs arbitrary Office.js code inside the live presentation |
add_slide | Add a new slide from a named layout at a specific position, with placeholder text pre-filled |
duplicate_slide | Duplicate a slide within the same presentation; data stays server-side |
read_deck_text | Lightweight text extractor: slide titles and body text as plain strings (~20x smaller than inspect_slide) |
read_shape_paragraphs | Read raw OOXML <a:p> paragraphs from a shape's text body, preserving all formatting |
edit_shape_paragraphs | Replace paragraph content of a shape with raw OOXML <a:p> XML |
read_slide_xml |
When multiple presentations are open, pass presentationId (from list_presentations) to target a specific one.
insert_image tool), not shape API; positioning works but no shape-level manipulation after insertionedit_slide_chart), not via Office.js chart APIPowerPoint MCP assumes a single-user, locally-trusted machine. Both network servers bind to the loopback interface only:
127.0.0.1:8080 (or 127.0.0.1:8443 with BRIDGE_TLS=1)127.0.0.1:3001; the default STDIO transport opens no network portHost header is not 127.0.0.1:3001 / localhost:3001)/mcp request bodies to 16 MiB (16,777,216 bytes), enforced while the body streams in rather than after it is fully buffered. The ceiling covers the largest supported request — a base64-encoded image via insert_image — with headroom: base64 inflates raw bytes by ~4/3, so 16 MiB admits a ~12 MB source image plus the surrounding JSON-RPC envelope. An oversized or over-length chunked upload gets a 413 response (Request body too large) instead of being buffered into memory; the connection remains usable for the next request.GET https://registry.npmjs.org/powerpoint-mcp/latest to check for a newer version. Nothing is sent beyond the request itself; no presentation data, telemetry, or identifiers. Disable it with BRIDGE_NO_UPDATE_CHECK=1 or the --no-update-check flag.Local file and URL access. The insert_image tool reads arbitrary local file paths (sourceType: 'file') and fetches arbitrary URLs (sourceType: 'url') with the full privileges of the server process. A URL fetch can reach internal/loopback addresses (SSRF), and a file read can pull in any file the user can read. Only run the bridge on a trusted, single-user machine.
Local-trust posture. The add-in executes whatever JavaScript the bridge sends it over the local WebSocket. The bridge WebSocket enforces an Origin allowlist: it only accepts the upgrade when the request's Origin header exactly matches the bridge's own currently-serving origin (http://localhost:PORT, or https://localhost:PORT with BRIDGE_TLS=1) — the origin the add-in's own served page always connects from, on both PowerPoint for Mac and PowerPoint Web (the WAC host frame at officeapps.live.com never opens this socket itself; the taskpane iframe it hosts navigates directly to the bridge origin first). A missing, malformed, or foreign Origin is rejected before the socket can register or answer any pending request — a real browser/webview always sends Origin on a WebSocket handshake, so no legitimate client is excluded. This is an origin policy, not authentication: it stops a foreign page's script from driving the bridge, but any local process that can reach the loopback port and mimic that Origin header still can. Do not run PowerPoint MCP on a shared or multi-user host.
execute_officejs runs arbitrary code inside PowerPoint's Office.js runtime. This is by design — it gives the AI full access to the Office.js API. Only use this with MCP clients you trust.
Planned hardening. Before binding to any non-loopback interface or shipping a remote-MCP deployment, the bridge needs a per-session handshake token and an authenticated transport.
Add-in not appearing in PowerPoint
npm run sideload and restart PowerPoint~/Library/Containers/com.microsoft.Powerpoint/Data/Documents/wef/manifest.xmlAdd-in shows "Disconnected"
Make sure the bridge server is running. In plugin mode the server auto-starts with Claude Code — call any tool to verify. For standalone installs, run npm start -- --bridge and verify with curl http://127.0.0.1:8080/health. The add-in auto-reconnects with exponential backoff.
Using HTTPS mode (required for PowerPoint Web) HTTPS is required for PowerPoint Web and optional for desktop. To enable:
brew install mkcert && mkcert -install (one-time, trusts the CA in browsers)npm run setup-certs to generate localhost certificatesnpm run sideload:https and restart PowerPointaddin/manifest-https.xmlBRIDGE_TLS=1 npm start -- --bridge| Platform | Status |
|---|---|
| macOS | Supported (primary) |
| PowerPoint Web | Supported — requires HTTPS mode, sideload via browser (all tools work) |
| Windows | Untested — different sideloading path |
| Linux | Not supported (no PowerPoint for Linux) |
The add-in uses Office.AutoShowTaskpaneWithDocument to minimize manual activation:
| Platform | Behavior |
|---|---|
| macOS desktop | Taskpane auto-opens when the add-in is sideloaded. Closing the pane keeps the WebSocket connection alive (shared runtime with lifetime="long"). |
| PowerPoint Web | One ribbon click per document per browser session to activate. After activation, the pane auto-reopens on page reload. Closing the pane keeps the connection alive within the session. |
| New file from template | OOXML template embedding can pre-activate the add-in (see below) |
Requires SharedRuntime 1.1 (PowerPoint 16.46+ on Mac, 2102+ on Windows). Centralized Deployment via Microsoft 365 admin center can eliminate the manual click for organizational use.
External tools can embed the add-in reference directly into .pptx templates so the add-in activates on first open without prior installation. This requires injecting two OOXML parts into the .pptx zip:
ppt/webextensions/webextension1.xml — add-in reference with Office.AutoShowTaskpaneWithDocument propertyppt/webextensions/taskpane.xml — taskpane configuration (dock state, visibility, width)Plus the corresponding entries in [Content_Types].xml and relationship files.
Set visibility="0" if the add-in must already be sideloaded; set visibility="1" to prompt users to install it on first open.
For a complete working example, see Office-OOXML-EmbedAddin. The add-in ID to reference is AE89909C-2813-4B08-9E1B-49E7379BD0E6 with storeType="Registry" and store="developer" for sideloaded installations.
See CONTRIBUTING.md for development setup and guidelines.
| Read the full raw OOXML of a slide, or filter to a specific shape |
edit_slide_xml | Edit slide XML and reimport (xml mode or JS code mode for DOM manipulation) |
read_slide_zip | Read multiple files from the exported slide zip (slide XML, rels, chart XMLs, Content_Types) |
edit_slide_zip | Update multiple files in the slide zip and reimport in a single operation |
edit_slide_chart | Create a chart on a slide from structured data (column, bar, line, pie, doughnut, area) via OOXML |
read_speaker_notes | Read speaker notes from slides as plain text |
edit_speaker_notes | Set speaker notes on one or more slides; accepts markdown text |
format_shapes | Apply fill color and font formatting to multiple shapes on a slide in one call |
search_text | Search for text across all slides — like grep for slides; supports regex |
verify_slides | Run programmatic checks on a slide (overlaps, out-of-bounds, empty text, unused placeholders) |