UW Blueprint SOW Document Generator
by rohan-sane-1
README.md
# UW Blueprint SOW Document Generator
An MCP server that formats Copilot-approved Statement of Work content into a
UW Blueprint-branded `.docx`, callable as a tool from a Copilot Studio chatbot. The
chatbot drafts and workshops section content conversationally; this server's only job is
guaranteeing the final document matches house formatting exactly.
Full architecture, security design, and rationale: see the implementation plan at
`C:\Users\rohan\.claude\plans\c-users-rohan-downloads-sows-s26-202609-velvet-moon.md`.
## Project layout
```
src/mcp_server/ MCP tool surface, auth, storage, config
src/formatting_engine/ Content-block -> python-docx rendering
templates/ master_template.docx (built, not hand-edited)
scripts/ One-time template-authoring tools
assets/fonts/ Poppins + Source Sans Pro .ttf source files
tests/unit, tests/integration
infra/main.bicep Azure deployment (secondary priority, review before applying)
```
## Setup
```bash
python -m venv .venv
.venv/Scripts/pip install -e ".[dev]"
cp .env.example .env
```
## Build the master template
Only needed once, or after a branding change. Requires the font files already staged in
`assets/fonts/` (Poppins extracted from a sample SOW; Source Sans Pro from Adobe's
`adobe-fonts/source-sans` OFL release -- see scripts/build_master_template.py for
provenance notes).
```bash
.venv/Scripts/python scripts/build_master_template.py
```
## Run tests
```bash
.venv/Scripts/python -m pytest tests/ -v
```
## Run the server locally
With no `SOW_MCP_ENTRA_TENANT_ID` set and `SOW_MCP_ENVIRONMENT=dev`, the server starts
with `DevStubTokenVerifier`, which accepts exactly one fixed bearer token
(`dev-local-token`) -- this proves the auth/discovery plumbing works before any real
Entra ID dependency exists. **This mode must never run outside local development.**
```bash
SOW_MCP_ENVIRONMENT=dev PYTHONPATH=src .venv/Scripts/python -m mcp_server.main
```
Then drive it with the official MCP Inspector (`npx @modelcontextprotocol/inspector`) or
any MCP client, authenticating with `Authorization: Bearer dev-local-token`.
## What's built vs. what's next
**Built and verified end-to-end** (real MCP wire protocol, not just unit tests): the full
tool surface (`start_draft`, `save_section`, `delete_section`, `get_draft`,
`list_drafts`, `get_document_status`, `list_draft_versions`, `restore_draft_version`,
`finalize_document`), the structured content-block schema and its `extra="forbid"`
rejection behavior, the formatting engine and master template (fonts embedded, styles
matching the confirmed UW Blueprint look), local filesystem storage with ETag
concurrency and version-based draft-loss recovery, and the Entra ID token-verification
code path (tested against the dev stub; real-tenant validation still needs a live App
Registration to exercise against).
**Still needed before production** (plan section 8, steps 5 onward):
1. Create the two Entra ID App Registrations (plan section 5) and test `EntraTokenVerifier`
against a real token.
2. Exercise `AzureBlobDraftStore`/`AzureBlobFinalizedStore` against a real storage
account or Azurite -- they're written against the documented SDK APIs but untested,
unlike the local store.
3. Review and apply `infra/main.bicep`, then deploy the container.
4. Register the custom MCP connector in Copilot Studio and do one real end-to-end run.
5. Open `templates/master_template.docx` in real Microsoft Word at least once as a final
visual/corruption check -- automated tests confirm it's well-formed OOXML that
python-docx round-trips cleanly, but that's not a substitute for a human look.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues