Skip to main content
Glama
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.