Skip to main content
Glama
rohan-sane-1

UW Blueprint SOW Document Generator

by rohan-sane-1

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)

Related MCP server: Word MCP Server

Setup

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).

.venv/Scripts/python scripts/build_master_template.py

Run tests

.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.

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.

Related MCP Connectors

Related MCP Servers