# MVG Frankfurt: Blech und Halbzeuge

> Sheet metal and stock parts from Frankfurt: prices, DFM feedback with images, lead times, quotes.

- name: de.mvg-frankfurt/mcp
- version: 2.1.0
- connection class: R0 (autonomous)
- trust: 83/100 flags: no-repository
- quality: 91/100 (strong)
- owner: not claimed
- descriptor: https://api.protogrid.dev/v1/servers/de.mvg-frankfurt%2Fmcp
- tools: https://api.protogrid.dev/v1/servers/de.mvg-frankfurt%2Fmcp/tools

**An agent can connect right now, no human step.** Remote endpoint, no authentication, reachable on the last probe.

## Connection (mcpServers)

```json
{
  "mcpServers": {
    "mvg-frankfurt": {
      "type": "http",
      "url": "https://mvg-frankfurt.de/mcp"
    }
  }
}
```


## Trust

- hygiene: 80
- liveness: 100
- freshness: 100
- provenance: 55
- drivers: +dns-namespace +website +reachable +uptime-100% +updated-7d-ago -no-repository
- Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed.

## Quality 91/100 (strong)

### protocol: 100 (weight 25)

- pass `protocol.modern`: supports 2026-07-28 (server/discover)
- pass `protocol.stateless`: answers without a session
- pass `protocol.transport`: streamable HTTP
- pass `protocol.list_ttl`: tool list is cacheable (ttlMs 3600000)

### authorization: n/a (weight 15)

- n/a `auth.prm`, `auth.as_metadata`, `auth.cimd`: no remote uses OAuth
- n/a `auth.secret_in_url`: no templated URL

### tool hygiene: 88 (weight 30)

- pass `tools.descriptions`: every tool has a description
- warn `tools.description_length`: 2 tools have descriptions over 1,024 characters, which crowds the context
- pass `tools.schemas`: every tool has an object input schema
- pass `tools.annotations`: 26 of 26 tools declare readOnlyHint or destructiveHint
- pass `tools.directory_hints`: every tool declares readOnlyHint, destructiveHint, idempotentHint and openWorldHint
- warn `tools.token_cost`: about 15,639 tokens to load every tool
- pass `tools.api_dump`: tools are not a one-to-one API dump
- pass `tools.hidden_text`: no hidden text in tool names, descriptions, schemas or annotations

### stability: 83 (weight 15)

- warn `stability.changes`: 25 tool changes in 30 days
- pass `stability.rug_pull`: no tool changed its meaning under the same name
- pass `stability.new_links`: no tool change named a new site

### dependencies: n/a (weight 15)

- n/a `deps.known_vulns`, `deps.mcp_sdk_version`, `deps.resolvable`: no npm or PyPI package

- tools: 26, about 15,639 tokens to load them all
- tool set hash: a02826417f9bde307f466ed1cae5d85a
- tools last changed: 2026-11-07T16:00:57.412Z
- badge: [![protogrid quality](https://protogrid.dev/badge/de.mvg-frankfurt/mcp.svg)](https://protogrid.dev/servers/de.mvg-frankfurt/mcp)
- Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed.

### Tool changes

- 2026-11-07 `reorder_from_order` changed (inputSchema)
- 2026-11-07 `check_order_status` changed (inputSchema)
- 2026-11-07 `list_orders` changed (inputSchema)
- 2026-11-07 `get_link` changed (inputSchema)
- 2026-11-07 `list_quotes` changed (inputSchema)
- 2026-11-07 `add_quote_parts` changed (inputSchema)
- 2026-11-07 `update_quote_parts` changed (inputSchema)
- 2026-11-07 `get_quote` changed (inputSchema)
- 2026-11-07 `create_quote` changed (inputSchema)
- 2026-11-07 `upload_status` changed (inputSchema)

Full history: https://api.protogrid.dev/v1/servers/de.mvg-frankfurt%2Fmcp/changes

## Remotes

- https://mvg-frankfurt.de/mcp (streamable-http, auth none, reachable true, uptime30d 1)

## Packages

_none_

## Tools (26)

- `add_quote_parts`: Stueckliste schrittweise: weitere Positionen (z. B. je hochgeladener Datei) an ein Angebot anhaengen. Ergebnis ist eine neue Fassung mit allen Positionen (supersedes = bisherige quote_id); mit der neuen quote_id weiterarbeiten. [Zugang: requires login: Scope quotes:write. Aendert Daten: ja (neue Angebotsfassung).]
- `check_manufacturability`: Konstruktionsgrenzen fuer Werkstoff + Dicke (max. Format, max. Laser-Dicke je Werkstoff aus dem Maschinenpark, kleinster Lochdurchmesser, Steg, Randabstand, Biegung, Mindestschenkel) und, mit part, Pruefung eines Kantteils ohne Datei (tolerance_mm = gewuenschte Masstoleranz +/- mm). Mit design_id oder upload_id (Anmeldung, designs:write) wird eine CAD-Datei geprueft (flache Teile inkl. Konturen: Stege, Schlitze, Inseln, Kleinteile). Ergebnis: status ok|warn|block, ampel (fertigbar|hinweis|pruefanfrage|nicht_fertigbar), requirements und feedback: counts {block, warn}, issues[] mit where (Kantung/Ort), limit (Grenzwert) und fix (anwendbare Aenderung Feld + Wert, price_effect_net in Cent), bends[] je Kantung und visual (part_svg_url Querschnitt, bending_svg_url Biegeschritte mit Werkzeug, Kollision rot). Nur bei counts 0/0 fehlerfrei melden. Beispiel: {"material":"edelstahl-1.4301","thickness_mm":2,"part":{"depth_mm":500,"segments_mm":[5,100,40],"bends":[{"angle_deg":90},{"angle_deg":90}]}}. [Zugang: oeffentlich, ohne Anmeldung. Aendert Daten: nein.]
- `check_order_status`: Status einer Bestellung des angemeldeten Kundenkontos (order_id oder Nummer aus list_orders). Nur mit OAuth-Zustimmung eines Kundenkontos. Hoechstens alle 15 Minuten abfragen. Statt Abfragen: Ereignis-Meldungen order.status_changed ueber POST /v1/webhooks (MVG-API-Key, Scope webhooks:write, signiert). [Zugang: requires login: OAuth-Zustimmung eines Kundenkontos, Scope orders:read. Aendert Daten: nein.]
- `configure_part`: Teil aus einer Vorlage (template + params aus list_part_templates) plus optionale Zusatzloecher: der Server baut die Geometrie wie der Teile-Editor, prueft die Fertigbarkeit (Lochabstand Rand/Steg, Mindest-Loch-Ø je Dicke, Format) und rechnet den Shop-Preis netto+brutto inkl. aller Kosten (Kanal online). Ergebnis: status (ready|needs_review|price_unavailable|editor_only), price, lead_time, manufacturing_notes, preview_url (bemasste SVG-Zeichnung, 7 Tage), editor_url (Teile-Editor mit genau diesem Teil, dort in den Warenkorb), draft_id (7 Tage; angemeldet create_quote mit {type:'part_draft', draft_id}). Beispiel Flansch: {template:'flansch', params:{D:200,d:60,nl:4,dl:9,lk:140}, material:'aluminium-almg3', thickness_mm:3, quantity:1}. Koordinaten der extra_holes in mm ab linker unterer Ecke. Anwendungen (group 'anwendung', z. B. {template:'fensterbank', params:{L:1200,tiefe:150,ue:40,auf:20,ab:40,tropf:1}, material:'aluminium-almg3', thickness_mm:2}): Aussenmasse, Ergebnis mit price, manufacturability, order_item (fuer get_price/create_quote) und page_url (Seite mit vorbelegten Massen, dort in den Warenkorb). Speichert keine Kundendaten. [Zugang: oeffentlich, ohne Anmeldung. Aendert Daten: nein (nur temporaerer Entwurf, 7 Tage).]
- `configure_plate`: Einfachster Weg fuer 'Ich brauche dieses Teil': rechteckige Platte length_mm x width_mm mit runden Loechern (holes: x_mm/y_mm = Lochmitte ab linker unterer Ecke, diameter_mm), optional corner_radius_mm. Sonst wie configure_part: Fertigbarkeit, Shop-Preis netto+brutto, Lieferzeit, preview_url, editor_url, draft_id. Beispiel: Platte 200 x 100 x 3 AlMg3 mit 6 Loechern Ø 9 -> {length_mm:200, width_mm:100, thickness_mm:3, material:'aluminium-almg3', holes:[{x_mm:20,y_mm:20,diameter_mm:9}, ...]}. [Zugang: oeffentlich, ohne Anmeldung. Aendert Daten: nein (nur temporaerer Entwurf, 7 Tage).]
- `create_quote`: Verbindliches Angebot (24 h) netto und brutto mit quote_id und checkout_url: der Link oeffnet den Warenkorb der Website mit genau diesen Positionen. Bestellen und bezahlen tut dort ein Mensch. Positionen wie get_price plus upload (aus create_upload) und design. requirements: block = nicht bestellbar (kein checkout_url), warn = Kunde bestaetigt im Warenkorb. Positionen als Liste items, Beispiel: {"items": [{"type": "sheet_cut", "material": "aluminium-almg3", "thickness_mm": 2, "length_mm": 1000, "width_mm": 500, "quantity": 2}], "delivery": {"mode": "shipping", "postal_code": "60314"}} [Zugang: requires login: Scope quotes:write. Aendert Daten: ja (Angebot).]
- `create_upload`: Signierter Link fuer EINE STEP-, DXF-, AI- oder EPS-Datei (15 Minuten, einmalig, STEP bis 50 MiB, DXF/AI/EPS bis 20 MiB; AI/EPS wird zu DXF in mm, Masse stehen in der Upload-Antwort unter vektor). Bytes per PUT auf upload_url; kannst du die Datei nicht lesen, gib dem Nutzer browser_upload_url. Danach create_quote mit {type:'upload', upload_id, material, quantity} (DXF/AI/EPS zusaetzlich thickness_mm). Nie Dateiinhalt als Text/Base64 senden. Wann browser_upload_url: wenn die Datei nur beim Nutzer liegt (Anhang nicht lesbar, Datei auf seinem Rechner). Link sofort weitergeben (15 min), dann mit upload_status pruefen, ob sie angekommen ist (state 'received'), erst danach create_quote. Stueckliste: filenames (bis 20) liefert je Datei einen eigenen Link. [Zugang: requires login: Scope designs:write. Aendert Daten: ja (Upload-Link).]
- `find_hole_operations`: Gewinde schneiden und Senkungen je Werkstoff und Dicke: Groessen mit Kernloch bzw. Durchgang, Preis je Stueck netto/brutto (Cent), ob die Groesse fuer diesen Werkstoff und diese Dicke geht (ok/warn/block mit Grund), Ruestpauschale je Auftrag und Lieferzeit-Regel. Verwendung in create_quote: hole_operations an der upload/design-Position. Beispiel: {"material":"aluminium-almg3","thickness_mm":4}. [Zugang: oeffentlich, ohne Anmeldung. Aendert Daten: nein.]
- `find_materials`: Bleche: Werkstoffe mit lesbarem Code (material), Dicken (mm + label), Tafelformaten und REACH-Hinweis. Halbzeuge (Rohre, Profile, Flach-, Rund-, Vierkantmaterial): art_nr, Abmessungen, kg/m, Stangenlaenge. query mit Massen wie 'flach 20x5 alu', 'rohr 30x2', 'edelstahl 1.4301'. Beispiel: 'Alu-Winkel 15 x 15 x 2' ist ein Halbzeug-Winkelprofil -> kind 'halbzeug', query 'winkel 15x15x2 alu', danach get_price type 'profile' (kein Kantteil). material bzw. art_nr gehen danach in get_price/create_quote/configure_part. Katalog durchsehen: kind 'halbzeug' mit kategorie, werkstoff und ranges (Massbereich), z. B. {"kind": "halbzeug", "kategorie": "U-Profil", "werkstoff": "edelstahl", "ranges": {"breite_mm": {"min": 30, "max": 50}}}. [Zugang: oeffentlich, ohne Anmeldung. Aendert Daten: nein.]
- `get_agent_guidance`: Reihenfolge, Einheiten, Verbote und Beispiele. Zu Beginn lesen. [Zugang: oeffentlich, ohne Anmeldung. Aendert Daten: nein.]
- `get_delivery_options`: Alle Lieferstufen (Termin fertig, Zustellfenster, Aufpreis) und die Versandkosten zur Postleitzahl fuer genau diese Positionen in einem Aufruf; dazu Abholung (ohne Versandkosten). Termine, keine Lagerangaben. Beispiel: {"items":[...], "postal_code":"60314"}. [Zugang: oeffentlich, ohne Anmeldung. Aendert Daten: nein.]
- `get_lead_time`: Fertigstellungs-/Abholtermin und Zustellfenster je Stufe (Economy, Standard, Express) inkl. Regel Express 24 h (bis Stichzeit bestellt: naechster Werktag gegen eigenen Aufpreis bei kleinen Zuschnitt-Mengen). Mit items gilt der Termin fuer genau diese Positionen; ohne items die allgemeinen Regeln. [Zugang: oeffentlich, ohne Anmeldung. Aendert Daten: nein.]
- `get_link`: Direkter Link fuer den Nutzer: kind 'checkout' (Warenkorb mit den Positionen, auch zum Weitergeben an Kollegen: wer den Link hat, sieht Positionen und Preis und kann bestellen), 'part' (Querschnitt mit Massen) oder 'bending' (Biegeschritte) einer Kantteil-Position (index). [Zugang: requires login: Scope quotes:read. Aendert Daten: nein.]
- `get_price`: Richtpreis netto und brutto (Kanal online, gleiche Engine wie der Shop) fuer Blech-Zuschnitt (sheet_cut), Kantteil (sheet) und Halbzeug-Zuschnitt (profile), dazu Zubehoer. Alle Kosten stecken im Preis, bei delivery.mode=shipping auch Versand. Nichts wird gespeichert; verbindlich und mit Warenkorb-Link wird es mit create_quote. type 'sheet' (Kantteil) nur fuer gekantetes Blech nach Zeichnung (Schenkel + Biegungen); Profile von der Stange (Winkel 15x15x2, Flach 40x5, Rohr) sind type 'profile' mit art_nr aus find_materials. Platten/Flansche MIT Loechern: configure_plate/configure_part. Antwort enthaelt pcf_kg_co2e (CO2e-Schaetzung cradle-to-gate, je Zeile und gesamt, Methode in pcf_method). Positionen IMMER als Liste items, auch bei einer Position. Beispiel: {"items": [{"type": "sheet_cut", "material": "aluminium-almg3", "thickness_mm": 2, "length_mm": 1000, "width_mm": 500, "quantity": 2}], "delivery": {"mode": "shipping", "postal_code": "60314"}} [Zugang: oeffentlich, ohne Anmeldung. Aendert Daten: nein.]
- `get_quote`: Ein frueheres Angebot (jede Fassung) erneut lesen, mit checkout_url. [Zugang: requires login: Scope quotes:read. Aendert Daten: nein.]
- `get_sheet_rules`: Biegeregeln und Konstruktionsgrenzen je Blech-Werkstoff und Dicke fuer CAD-Programme: inner_radius_mm und k_factor der Kantbank (gemessen, wie unsere Abwicklung), bend_deduction_90_mm, min_flange_mm, hole_to_bend_mm, Loch/Steg/Rand, max. Format; cad_material.steve = Werkstoff-ID der STEVE-CAD-Bibliothek (exact=false: gleiche Familie). version = Pruefsumme; neu laden, wenn sie sich aendert. Ohne Filter das ganze Werk. Verbindlich bleibt check_manufacturability/create_quote. [Zugang: requires login: Scope catalog:read. Aendert Daten: nein.]
- `get_shipping_estimate`: Packstueck-Rechner: wie die Teile verpackt werden (Karton, Flachpaket, Bund, Palette) und was der Versand netto/brutto kostet (Richtwert; verbindlich ist der Versand in get_price/create_quote mit delivery.mode=shipping). [Zugang: oeffentlich, ohne Anmeldung. Aendert Daten: nein.]
- `list_orders`: Bestellungen des angemeldeten Kundenkontos (wie unter /konto): Nummer, Datum, Betrag, Zahl- und Auftragsstatus, Status-Link. Nur mit OAuth-Zustimmung eines Kundenkontos. [Zugang: requires login: OAuth-Zustimmung eines Kundenkontos, Scope orders:read. Aendert Daten: nein.]
- `list_part_templates`: Alle Formen des Teile-Editors (/teile-designer): Rechteck, Quadrat, Ronde, Ring, Lochkreis-Flansch, Lochplatte, Langloch-Platte, Laschen, Knotenbleche, gekantete Winkel/Wannen ... je Vorlage id, Name, Parameter (key, Einheit, min/max, Vorgabe) und ein Beispiel-Aufruf fuer configure_part. Gruppe 'anwendung': fertige Kantteile fuer den Bau (fensterbank, mauerabdeckung, attikahaube, ortgangblech, traufblech, wandanschluss, kehlblech, sockelprofil, tropfkante, abdeckwinkel = L-Winkel; wanne und kiesfangleiste ueber den Teile-Editor) mit erlaubten Werkstoffen/Staerken und aliases (Suchbegriffe wie Mauerkrone, Wetterschenkel, Eckwinkel, Attikaabdeckung). query filtert auch nach aliases ('flansch', 'fensterbank', 'mauerkrone'), group nach Gruppe. [Zugang: oeffentlich, ohne Anmeldung. Aendert Daten: nein.]
- `list_quotes`: Angebote dieses Zugangs, neueste zuerst: quote_id, Datum, Ablauf, Status, Positionen, Summe, dfm_status, supersedes. Mit offset/limit blaettern. [Zugang: requires login: Scope quotes:read. Aendert Daten: nein.]
- `normalize_material`: Freier Werkstoff-Text (z. B. 'V2A 2mm', 'AlMg3', '1.4301 geschliffen', 'verzinkt 1,5') -> passende Blech-Werkstoffe mit 'material'-Code und Dicken. Vor get_price nutzen, wenn der Nutzer den Werkstoff frei beschreibt. Beispiel: {"query": "V2A 2mm"}. [Zugang: oeffentlich, ohne Anmeldung. Aendert Daten: nein.]
- `reorder_from_order`: Teile einer frueheren Bestellung des angemeldeten Kundenkontos erneut anbieten (order_id oder Nummer aus list_orders; optional parts mit part_id und quantity). Preise und Fertigbarkeit werden HEUTE neu gerechnet, nie der alte Preis. Ergebnis: Angebot mit checkout_url in den Warenkorb, KEINE Bestellung, bestellt und bezahlt wird im Browser von einem Menschen. Nur mit OAuth-Zustimmung eines Kundenkontos. [Zugang: requires login: OAuth-Zustimmung eines Kundenkontos, Scope orders:read. Aendert Daten: ja (Angebot).]
- `search_docs`: Sucht in Magazin, Konstruktionsrichtlinien, FAQ, Preis-, Versand- und Werkstoffseiten. Mit path statt query wird eine Seite vollstaendig gelesen (path aus einem Treffer). [Zugang: oeffentlich, ohne Anmeldung. Aendert Daten: nein.]
- `update_quote_parts`: Mengen aendern, Positionen entfernen (remove) oder ergaenzen (add_items). Ergebnis ist ein NEUES Angebot mit eigener quote_id und supersedes; das alte bleibt unveraendert abrufbar. index = lines[].index des Angebots. [Zugang: requires login: Scope quotes:write. Aendert Daten: ja (neue Angebotsfassung).]
- `upload_status`: Stand eines Uploads aus create_upload: waiting (Link offen, noch keine Datei), received (Datei da, weiter mit create_quote), expired (neuen Link holen). Hoechstens alle 10 Sekunden abfragen. [Zugang: requires login: Scope designs:write. Aendert Daten: nein.]
- `whoami`: Fuer wen spricht dieser Zugang, welche Rechte gelten? [Zugang: requires login: Scope catalog:read. Aendert Daten: nein.]
