Operationen
Themen:
Alle zehn Tools sind als ReadOnly = true, Idempotent = true und Destructive = false markiert
(MCP-Tool-Annotationen, die dem aufrufenden Client mitgeben, dass wiederholte Aufrufe risikolos
sind). Kein Tool schreibt, löscht oder sendet — weder in der jobs-/mappings-Tabelle, noch in
den Service-Bus-Queues, noch in einem Quell-/Zielsystem.
Auch innerhalb der reinen Lesezugriffe gibt es eine bewusste zweite Grenze: Betriebs-/ Konfigurationsdaten (Job-Namen, Schemata, Fehlermeldungen, Zeitstempel) sind unkritisch und werden vollständig zurückgegeben. Fachliche Nutz-/Kundendaten — z. B. der Inhalt einer Service-Bus-Nachricht — werden dagegen nie zurückgegeben, selbst wenn das zugrunde liegende Tool ansonsten “nur liest”. Details dazu unten bei den Peek-Tools.
Jobs & Mappings (Table Storage)
Lesen ausschließlich aus den beiden Tabellen jobs/mappings, über dieselben In-Memory-Caches
wie JobApi/MappingApi (IJobService.Jobs/IMappingService.Mappings — reine Query<T>()-Reads,
kein Upsert/Delete im Codepfad).
| Tool | Liest | Liest nicht |
|---|---|---|
list_jobs | Alle konfigurierten Jobs: Quelle/Ziel-Connection, Richtung, Priorität, Zeitplan, Mapping-Name, aus der jobs-Tabelle | Keine Connection-Credentials (nur der Name der Connection, nicht ihre Zugangsdaten) |
get_job | Ein einzelner Job anhand seines RowKey (Job-Name) — dieselben Felder wie list_jobs | dito |
list_mappings | Alle Feld-Mappings zwischen Quell- und Zielsystemen aus der mappings-Tabelle | Keine tatsächlichen Datensatz-Inhalte — nur die Mapping-Konfiguration (welches Feld auf welches Feld abgebildet wird), nicht produzierte/synchronisierte Daten |
get_mapping | Ein einzelnes Mapping anhand seines Namens (der Mapping-Name, auf den ein Job verweist und unter dem list_mappings es auflistet) | dito |
Warum keine Credentials möglich sind: IConnectionService.GetConnector(name) liefert nur die
IConnector-Instanz zurück, nicht das zugrunde liegende ConnectionSetting-Objekt. Felder wie
ClientSecret, Password oder ApiKeyValue sind private Felder in den konkreten Connectoren und
nicht Teil des IConnector-Interfaces — es gibt schlicht keinen Rückgabewert, über den sie
herauskommen könnten.
Service Bus (Diagnose)
Reine Peek-/Status-Operationen über IServiceBusService. Die beiden Peek-Tools erzeugen den
Empfänger ohne PeekLock und rufen ausschließlich receiver.PeekMessagesAsync(...) auf — es gibt
im Codepfad kein ReceiveMessagesAsync, CompleteMessageAsync, DeadLetterMessageAsync oder
AbandonMessageAsync. Auch SendMessageAsync (existiert auf IServiceBusService für
GetChanges) ist von keinem MCP-Tool aus erreichbar.
| Tool | Liest | Liest nicht |
|---|---|---|
list_queue_statuses | Laufzeit-Status (aktive/dead-letter/geplante Nachrichtenanzahl) aller Export-Queues | Keine einzelnen Nachrichten — nur Zähler |
get_queue_status | Laufzeit-Status einer einzelnen Queue für eine Job-Priorität | dito |
peek_queue_messages | Sequenznummer, JobName, SourceKey, Enqueue-Zeitpunkt, Zustellversuche und BodySize (Größe des Nachrichteninhalts in Bytes) je Nachricht | Den Nachrichteninhalt selbst (Body) nicht — siehe Kasten unten |
peek_dead_letter_queue_messages | Zusätzlich zu den obigen Feldern: DeadLetterReason, DeadLetterErrorDescription, ErrorMessage, ErrorTimeStamp, ErrorStackTrace, OperationId | dito — auch hier nur BodySize, nie Body |
Der Body einer Queue-Nachricht enthält die fachlichen Nutzdaten des jeweiligen Jobs — z. B.
bei einem BC-Artikelstamm-Job Produktcode, Bezeichnung und Dimensionswerte, bei anderen Jobs unter
Umständen Kundennamen, Adressen oder Preise. Das ist etwas grundlegend anderes als Betriebsmetadaten
wie ein Fehlertext oder ein Zeitstempel. Beide Peek-Tools geben deshalb bewusst nie den
Nachrichteninhalt zurück — nur dessen Größe in Bytes (BodySize), berechnet über
message.Body.ToMemory().Length, ohne den Inhalt jemals zu deserialisieren oder als String zu
lesen. Für die Fehleranalyse reichen die übrigen Felder (insbesondere bei
peek_dead_letter_queue_messages die Fehlerdetails) in aller Regel aus.
Connector-Metadaten (echtes Ziel-/Quellsystem-Schema)
| Tool | Liest | Liest nicht |
|---|---|---|
list_connector_tables | Tabellen-/Entitätsnamen einer Connection direkt aus den Metadaten des Zielsystems — zum Abgleich mit den in Jobs/Mappings konfigurierten Namen | Keine tatsächlichen Datensätze aus der Tabelle — nur ihren Namen |
get_connector_table_schema | Spalten-Metadaten (Typ, Nullable, maximale Länge, bei SQL-Dezimalspalten Precision/Scale, Primary Key) einer Tabelle/Entität — zum Validieren eines Mappings gegen das tatsächliche Schema, statt sich auf die Mapping-Konfiguration allein zu verlassen | Keine tatsächlichen Datensätze/Zeilenwerte — nur die Spalten-Struktur |
Beide Tools nehmen einen connectionName entgegen (den RowKey aus der connections-Tabelle —
siehe Verbindungen, z. B. BC_Test oder CRM_Test) sowie
einen tableName/Ressourcennamen. Für BC/NAV gibt es zusätzlich den apiPath (derselbe Wert wie
TableMapping.SourcePath/TargetPath im Mapping), da beide Connectoren ihr Schema über einen
versionierten OData-$metadata-Endpunkt beziehen. Bei BC ist er optional: leer bedeutet v2.0
(die Standard-API); Custom-APIs (z. B. publisher/gruppe/v1.0) brauchen ihren Pfad weiterhin.
Bei den SQL-Connectoren hat apiPath eine andere Bedeutung, siehe unten.
Diese beiden Tools sind die einzigen mit OpenWorld = true — sie greifen tatsächlich auf das
externe Quell-/Zielsystem der jeweiligen Connection zu, nicht nur auf die eigene
DataBridge-Infrastruktur. Ungültige Connection-Namen liefern eine klare Meldung
(„Connection ‘…’ is not configured or not initialized") statt einer rohen
KeyNotFoundException — es lässt sich also nicht durch Ausprobieren beliebiger Namen etwas über
das System herausfinden, das über list_jobs/get_job nicht sowieso schon sichtbar wäre.
Schlägt der Zugriff auf das Zielsystem fehl (falscher apiPath, unbekannte Tabelle, Host nicht
erreichbar), enthält das Fehlerergebnis die Ursache, z. B. GET …/api/nope/v1.0/$metadata returned 404 Not Found — technisch als McpException, weil der MCP-SDK nur deren Message an den Client
durchreicht (siehe Funktionsweise).
list_connector_tables/get_connector_table_schema funktionieren für alle Connectoren:
D365BC, D365NAV, D365CE (Dataverse), OpenAPI sowie die SQL-Connectoren MSSQL, MySQL,
Oracle und PostgreSQL. Der Rückgabewert ist je Connector unterschiedlich vollständig, da
nicht jedes System dieselbe Metadaten-Tiefe bietet:
| Connector | Typ | Nullable | Max. Länge | Precision/Scale | Primary Key |
|---|---|---|---|---|---|
| D365BC / D365NAV | ✅ | ✅ | ✅ (nur Strings) | ❌ | ✅ |
| D365CE (Dataverse) | ✅ | ✅ | ✅ (nur Strings) | ❌ | ✅ |
| OpenAPI | ✅ | ✅ | ✅ (falls maxLength im Schema) | ❌ | ❌ (kein natives Konzept — immer null) |
| MSSQL / MySQL / PostgreSQL | ✅ | ✅ | ✅ (nur Strings) | ✅ (nur Dezimalspalten) | ✅ |
| Oracle | ✅ | ✅ | ✅ (in Zeichen, CHAR_LENGTH) | ✅ (nur Dezimalspalten) | ✅ |
SQL-Connectoren: Schema über apiPath
Bei den SQL-Connectoren gibt apiPath das Schema an, in dem die Tabelle liegt — bei
MySQL die Datenbank. Ohne apiPath wird das Standard-Schema der Verbindung verwendet
(MSSQL SCHEMA_NAME(), MySQL DATABASE(), PostgreSQL current_schema(), Oracle der
angemeldete Benutzer). Damit werden gleichnamige Tabellen in unterschiedlichen Schemas
(z. B. dbo.Customers und archive.Customers) nicht vermischt.
| Connector | Metadatenquelle | apiPath |
|---|---|---|
| MSSQL | INFORMATION_SCHEMA | Schema, z. B. dbo |
| PostgreSQL | INFORMATION_SCHEMA | Schema, z. B. public |
| MySQL | INFORMATION_SCHEMA | Datenbank |
| Oracle | USER_TAB_COLUMNS/USER_CONSTRAINTS, mit apiPath ALL_*-Views | Owner/Schema, z. B. HR |
Tabellen- und Schemaname werden groß-/kleinschreibungsunabhängig verglichen und als Parameter an die Datenbank übergeben. Die Metadaten werden je Connector-Instanz zwischengespeichert — Schemaänderungen an der Datenbank werden erst nach einem Neustart der Function App sichtbar.
SQL-Connectoren: Datentypen
Die Datentypen aus dem Datenbank-Katalog werden auf .NET-Typen abgebildet. Dabei werden
Precision und Scale sowie bei MySQL der vollständige Spaltentyp (COLUMN_TYPE) berücksichtigt.
Unbekannte Typen (z. B. json, xml, Array-Typen) erscheinen als String.
| .NET-Typ | MSSQL | PostgreSQL | MySQL | Oracle |
|---|---|---|---|---|
Guid | uniqueidentifier | uuid | — | — |
Boolean | bit | boolean | tinyint(1)/boolean, bit(1) | boolean (23ai) |
Byte | tinyint | — | tinyint unsigned | — |
Int16 | smallint | smallint | tinyint, smallint, year | number(1–4,0) |
Int32 | int | integer | int, mediumint, smallint unsigned | number(5–9,0) |
Int64 | bigint | bigint | bigint, int unsigned, bit(n>1) | number(10–18,0) |
Decimal | decimal, numeric, money | numeric | decimal, bigint unsigned | number mit Nachkommastellen, ab 19 Stellen oder ohne Angabe |
Single | real, float(1–24) | real | float | binary_float |
Double | float | double precision | double | binary_double, float |
DateOnly | date | date | date | — |
DateTime | datetime, datetime2, smalldatetime | timestamp | datetime, timestamp | date, timestamp, timestamp with local time zone |
DateTimeOffset | datetimeoffset | timestamp with time zone | — | timestamp with time zone |
TimeSpan | time | time, interval | time | interval |
Byte[] | binary, varbinary, image, timestamp/rowversion | bytea | binary, varbinary, blob-Typen | blob, raw |
String | Zeichentypen, xml | Zeichentypen, json/jsonb | Zeichentypen, json | Zeichentypen, clob, json |
Besonderheiten:
- MSSQL
timestampist der alte Name vonrowversion, eine binäre Zeilenversion und kein Datum — daherByte[]. - MySQL speichert
BOOLEANalstinyint(1); erst der vollständige Spaltentyp macht darausBoolean. Vorzeichenlose Ganzzahlen erhalten den nächstgrößeren Typ, damit der Wertebereich passt.timestamphat keinen Offset und wird daherDateTime. - Oracle kennt keine eigenen Ganzzahltypen;
NUMBER(p,0)wird nach der Anzahl der Stellen aufInt16/Int32/Int64abgebildet.DATEenthält immer eine Uhrzeit und wird daherDateTime, nichtDateOnly. - GUIDs, die als Text gespeichert sind (MySQL
char(36), Oraclevarchar2(36)), erscheinen alsString.
Zusammenfassung: was über MCP grundsätzlich nicht möglich ist
- Keine Schreib-, Lösch- oder Sende-Operation auf
jobs/mappings/Service-Bus-Queues oder einem Ziel-/Quellsystem — es gibt für keines der zehn Tools einen Codepfad zuUpsert,Delete,SendMessageAsync,CompleteMessageAsynco. Ä. - Keine Connection-Credentials (Passwörter, Client-Secrets, API-Keys) — die sind strukturell nie Teil eines Rückgabewerts.
- Kein tatsächlicher Nachrichteninhalt aus einer Service-Bus-Queue — nur dessen Byte-Größe.
- Keine tatsächlichen Datensatz-Werte aus einem Ziel-/Quellsystem über die Connector-Tools — nur Tabellennamen und Spalten-Struktur, keine Zeilen.