Add independent MCP PDF report delivery

This commit is contained in:
2026-09-27 11:09:13 +02:00
parent 0c18c86a47
commit 6c36d78063
9 changed files with 555 additions and 20 deletions
+44 -4
View File
@@ -118,14 +118,15 @@ Authentication is implemented with `Flask-HTTPAuth`. The current code checks `BE
## MCP PoC
`mcp_server.py` provides a local stdio-only Model Context Protocol server. It is
`mcp_server.py` provides a Model Context Protocol server. It is
a thin adapter over the same domain services used by Flask: article lookup,
direct roll calculation, product-length calculation, material-weight calculation,
transport analysis, and configured production-machine feasibility.
The available PoC tools are `get_article`, `search_articles`,
`calculate_material_weight`, `calculate_product_length`,
`calculate_roll_diameter`, `analyze_transport_capacity`, `get_machine`,
`check_production_feasibility`, and `calculate_machine_max_product_length`.
`check_production_feasibility`, `calculate_machine_max_product_length`, and
`generate_calculation_pdf`.
Install the pinned dependencies, including `mcp==1.26.0`, in the existing
environment, then start it with:
@@ -135,8 +136,16 @@ environment, then start it with:
.venv/bin/python mcp_server.py
```
The PoC has no MCP resources, HTTP/SSE transport, remote authentication, or
dedicated target-length calculation tool or extrapolation support.
The server supports the existing `stdio` transport (the default) and
`streamable-http`. MCP PDF delivery requires `streamable-http`; it has no
dependency on the Flask web application. Native MCP resources are intentionally
not used because the installed MCPO 0.0.20 does not preserve resource links or
embedded resources. The PoC has no remote authentication or dedicated
target-length calculation tool or extrapolation support.
In `stdio` mode, `generate_calculation_pdf` returns a structured
`artifact_delivery_unavailable` response rather than creating an unreachable
report. Existing calculation tools work in either transport.
Tool calling semantics:
@@ -173,6 +182,37 @@ Tool calling semantics:
use `calculate_material_weight` when the core is unknown and only material
weight is needed. On success, it returns `transport_roll_inputs`, the
browser-equivalent transport bundle.
- `generate_calculation_pdf` is strictly opt-in: call it only after the user
explicitly asks for a PDF or calculation report. Supply the original inputs
from `calculate_roll_diameter`, never calculated diameters, weights, warnings,
or notes. It recalculates through the same RollCalc domain service and uses
the existing one-page renderer. Ordinary calculation calls neither generate
nor suggest a PDF.
For example, calculate a roll normally with `calculate_roll_diameter`. If the
user later asks “Mach mir daraus ein PDF”, call `generate_calculation_pdf` with
the original calculation inputs. Its successful response contains a safe
`filename`, expiry metadata, and a browser-ready `download_url`; MCPO/OpenWebUI
can present that URL as a download link. PDFs exist only in the MCP host's local
temporary store, not in Flask or shared storage. Each URL has a 256-bit opaque
capability token and expires after 24 hours during report-store access; whoever
possesses the URL can download the report until expiry. The user’s browser must
be able to reach the MCP-host public origin over HTTPS.
For independent PDF delivery, configure and run the MCP host as follows:
```bash
export ROLLCALC_MCP_TRANSPORT=streamable-http
export ROLLCALC_MCP_HOST=0.0.0.0
export ROLLCALC_MCP_PORT=8000
export ROLLCALC_MCP_ARTIFACT_PUBLIC_BASE_URL=https://rollcalc-mcp.example.internal
.venv/bin/python mcp_server.py
```
`ROLLCALC_MCP_ARTIFACT_PUBLIC_BASE_URL` is the externally browser-reachable
origin for this MCP service, not the Flask website URL. MCPO connects to the
MCP host with `--server-type streamable-http -- https://<mcp-host>/mcp`; the
browser follows the returned `/reports/<capability>.pdf` URL directly.
- `analyze_transport_capacity` uses roll/core diameters in mm; roll width and
transport dimensions in m; and roll/payload weights in kg.
`product_length_m` is the material length represented by one roll, used only