frontpage-mcp
by tpc134
README.md
# frontpage-mcp
**Give an AI agent complete control of Microsoft FrontPage 2003.**
Modern models can describe a "Y2K website" but can't actually *build* one the
way it was built — because the authentic 2000s look was never hand-written
HTML. It was **FrontPage**: Themes with generated banner/button GIFs, shared
borders, navigation-structure link bars, webbot components, hover-button Java
applets, `<marquee>`, `<bgsound>` MIDI, `Page-Enter` transitions and
`<font>`-tag styling that modern tooling can't reproduce.
This MCP server drives the real thing through FrontPage 2003's official COM
object model (`FrontPage.Application`) — the same API VBA used. The agent can
launch the app, create webs, apply themes, build navigation structures, insert
components, edit the live document DOM, publish — and **screenshot the result**
through the era-correct IE renderer to iterate visually.
Everything below was verified against a real FrontPage 2003 install.
```
┌──────────────┐ stdio JSON-RPC ┌─────────────────┐ COM (STA thread) ┌──────────────┐
│ AI client │ ◄────────────────► │ frontpage-mcp │ ◄────────────────► │ FRONTPG.EXE │
│ (Claude etc.)│ │ (Python) │ │ FrontPage │
└──────────────┘ └─────────────────┘ └──────────────┘
```
## Requirements
- Windows
- **Microsoft FrontPage 2003** installed, licensed, and past first-run setup
(open it once manually first)
- Python 3.10+
## Install
```bash
pip install -e .
# or, for your MCP client, point it directly at the package:
# python -m frontpage_mcp
```
MCP client config (Claude Desktop, Devin, etc.):
```json
{
"mcpServers": {
"frontpage-2003": {
"command": "python",
"args": ["-m", "frontpage_mcp"]
}
}
}
```
If installed into a venv, point `command` at that interpreter, e.g.
`"C:\\path\\to\\.venv\\Scripts\\python.exe"`.
## The authentic-2003 workflow
The server ships with `instructions` that teach the agent this recipe:
1. `fp_launch` → attach or start FrontPage
2. `fp_create_web("C:\\sites\\my2003")` — a real FrontPage web (`_vti_*` metadata included)
3. `fp_list_themes` → `fp_apply_theme("blends", vivid=True, active_graphics=True)`
4. `fp_set_shared_borders(top=True, left=True)`
5. `fp_new_page` / `fp_set_html` for each page, then `fp_nav_add` to build the
navigation structure → link bars regenerate automatically
6. `fp_insert_component("hit_counter")`, `("timestamp")`,
`("navigation_bar")`, `fp_insert_marquee`, `fp_insert_hover_button`,
`fp_set_bgsound("midi.mid")`, `fp_set_page_transition`
7. `fp_save_page` → `fp_set_view("preview")` → `fp_screenshot` to **see** it
8. `fp_publish("C:\\inetpub\\wwwroot")` — emits the full period artifact set:
`_derived/*_hbtn.gif` button images, `_themes/` assets, `_fpclass/` applets,
`_borders/` fragments, `_private/*.cnt` counter files
## Tools (63)
| Group | Tools |
|---|---|
| Lifecycle | `fp_launch` `fp_attach` `fp_quit` `fp_status` `fp_screenshot` |
| Webs | `fp_list_webs` `fp_open_web` `fp_create_web` `fp_close_web` `fp_web_info` `fp_set_web_title` `fp_list_files` `fp_create_folder` `fp_recalc_hyperlinks` `fp_publish` `fp_get/set_web_property` |
| Themes | `fp_list_themes` `fp_apply_theme` `fp_remove_theme` `fp_get_theme` |
| Borders & nav | `fp_set/get_shared_borders` `fp_get_navigation` `fp_nav_add` `fp_nav_remove` `fp_nav_rename` `fp_nav_include_in_bars` `fp_nav_add_linkbar` `fp_apply_navigation` |
| Pages | `fp_list_pages` `fp_new_page` `fp_open_page` `fp_activate_page` `fp_save_page` `fp_save_page_as` `fp_close_page` `fp_set_view` |
| HTML | `fp_get_html` `fp_set_html` `fp_set_body_html` `fp_insert_html` `fp_get_selection` `fp_select_text` `fp_eval_js` `fp_optimize_html` |
| Page style | `fp_set_page_properties` `fp_set_meta` `fp_set_page_transition` `fp_set_bgsound` |
| Components | `fp_insert_component` (include / hit_counter / timestamp / substitution / navigation_bar / page_banner / table_of_contents / search / confirmation_field) · `fp_insert_webbot` (raw) · `fp_insert_hover_button` · `fp_insert_marquee` · `fp_insert_flash` · `fp_dhtml_hover` · `fp_list_webbots` · `fp_set_webbot_attribute` · `fp_provision_fpclass` |
| Verification | `fp_open_in_browser` · `fp_check_assets` |
| Escape hatches | `fp_exec_command` (run ANY menu command by caption path) `fp_list_menu` |
### Notes on specific features
- **Webbots** are inserted as `<!--webbot bot="..." startspan/endspan -->`
comment pairs; FrontPage regenerates the inner markup on save —
byte-for-byte identical to what the 2003 editor produced.
- **Hit counter / Search** require FrontPage Server Extensions on the *host*
at browse time; the markup itself is generated correctly either way.
- **Hover buttons** are real Java applets (`fphover.class`). The server copies
the class files from your Office install into `<web>/_fpclass/` automatically.
- **`fp_eval_js`** executes JScript against the page DOM. The design surface
doesn't implement `execScript`, so the tool automatically uses the Preview
document — call `fp_set_view("preview")` first.
- **Localized FrontPage** (e.g. Chinese/Japanese builds): menu captions differ,
use `fp_list_menu` to discover the right `fp_exec_command` paths.
- **`NavigationNode.Children` is 0-based** (unlike most FrontPage collections,
which are 1-based — `PageWindows` is also 0-based). The session layer probes
`Item(0)` and enumerates accordingly; reading `Item(Count)` throws
`0x800A0009`. The persisted structure lives in `<web>/_vti_pvt/structure.cnf`
and is plain text — the source of truth if a node ever looks "phantom" via COM.
- **ANSI paths only.** FrontPage 2003 predates Unicode filenames: a path
containing characters outside the system codepage fails with a modal
dialog. The bridge rejects such paths up front — use an ASCII junction
(`mklink /J C:\work <real-path>`) when working inside non-ANSI folders.
- **Preview limits.** The embedded preview cannot render external `file://`
stylesheets or Flash/plugins. `fp_open_in_browser()` opens the page in the
real system browser; `fp_check_assets()` flags missing referenced files.
## Architecture
- `src/frontpage_mcp/session.py` — all COM calls marshalled onto a dedicated
STA worker thread (FrontPage objects are apartment-bound); returns only
plain data across the thread boundary.
- `src/frontpage_mcp/server.py` — MCP tools (works with `mcp` 1.x *and* 2.x).
- `src/frontpage_mcp/webbots.py` — webbot/retro markup builders.
- `src/frontpage_mcp/capture.py` — `FRONTPG.EXE` window screenshot (PIL).
- `src/frontpage_mcp/enums.py` — constants lifted from the FRONTPG.EXE type
library (`{3824BCD5-7042-11CE-8E17-0020AF9F9648}`).
## Developing
```bash
python scripts/smoke_test.py
```
drives a real end-to-end pass: creates `%TEMP%\fp_smoke_site`, applies a theme,
builds nav structure, inserts webbots + a hover button, saves, previews and
screenshots to `%TEMP%\frontpage-mcp-smoke.png`.
## Verified environment
Developed and smoke-tested (30/30) against a live FrontPage install:
| | |
|---|---|
| OS | Windows 10 22H2 (19045), 64-bit |
| System locale | Japanese (ANSI codepage CP932) |
| FrontPage | 2003 SP3 — `FRONTPG.EXE` 11.0.5516.0 (app reports 6.0.2.5516), Chinese UI |
| Python | 3.14.2 64-bit (3.12 also tested during development) |
| Packages | pywin32 312, comtypes 1.4.16, mcp 2.3.0, Pillow 12.2.0 |
Notably exercised on this setup: CP932 host with Chinese FrontPage UI (menu
captions, non-ANSI path failures — hence the junction workaround), a real
disk-based web, and a full end-to-end site restoration plus five exercise
pages authored entirely through the COM bridge.
## Legal
MIT license. Microsoft FrontPage is a trademark of Microsoft; this project is
an independent interoperability bridge and is not affiliated with Microsoft.
You need your own licensed copy of FrontPage 2003.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo recent community issues