KI-Agenten & MCP

MCP-Postfach: KI-Agenten bestätigen ihre Anmeldung selbst

Ein autonomer Agent kommt bis zu „Prüfen Sie Ihre E-Mails auf den Code“ und bleibt dort stehen. Das ist die vollständige Lösung: sechs MCP-Tools, kein Konto und kein Schlüssel, und eines davon blockiert, bis die Nachricht tatsächlich ankommt.

  • Fortgeschritten
  • 13 Min. Lesezeit
Ein kleiner grauer Roboter hält einem offenen Postfach einen blauen Briefumschlag entgegen, dazwischen wartet eine Stoppuhr

Was ein Agent braucht, das eine REST-API ihm nicht gibt

Diese Website hat eine REST-API, und ein Programmierer, der sie einbindet, kommt gut zurecht. Ein Agent nicht: Er kann nicht die Referenz öffnen, sich für einen von drei Endpunkten entscheiden und von Hand eine Anfrage mit dem richtigen Query-String zusammenbauen. Er fragt einen Server, was er kann, erhält maschinenlesbare Schemas und ruft eines davon auf.

Deshalb wird alles, was der Dienst tut, ein zweites Mal bereitgestellt — als Tools. Sechs an der Zahl, und kein Zustand, der zwischen den Aufrufen verwaltet werden müsste:

MCP-ToolWofür es da ist
create_inboxErzeugt eine neue Adresse, die der Agent sofort weitergeben kann. Serverseitig wird nichts reserviert, deshalb kann es nicht fehlschlagen. Nimmt optional einen lesbaren prefix entgegen; ein zufälliges Suffix hält die Adresse eindeutig.
list_domainsDie öffentlichen Domains, die jeder nutzen darf — nützlich, wenn ein Formular gerade eine davon abgelehnt hat.
list_messagesAlles, was an einer Adresse wartet, neueste zuerst. Antwortet sofort, auch wenn nichts da ist.
read_messageEine vollständige Nachricht: Absender, Betreff, Klartext, HTML, Anhänge. Hier steht der Code oder der Anmeldelink.
wait_for_messageBlockiert, bis etwas eintrifft, und liefert es dann vollständig. Das Tool, das aufgerufen wird, sobald ein Formular abgeschickt wurde.
delete_messageEntfernt eine Nachricht sofort, statt 5 Tage auf ihren Ablauf zu warten. Idempotent, ein wiederholter Aufruf durch den Agenten kostet also nichts.

Der Server beantwortet auch initialize mit einem kurzen Absatz an Anweisungen, den die meisten Clients direkt an das Modell weiterreichen. Ein Agent weiß deshalb schon beim Start, wofür dieser Dienst gedacht ist und wo seine eine wirkliche Einschränkung liegt, ohne dass jemand das in einen Prompt schreiben musste.

Einen Client in einer Zeile verbinden

Der Endpunkt ist eine einzige URL, und für die öffentlichen Domains gibt es nichts, wofür man sich anmelden müsste. Jeder MCP-Client nimmt die gleiche Art von Konfiguration entgegen — Claude Desktop, Claude Code, Cursor, Continue, das OpenAI Agents SDK und alles andere, das das Protokoll spricht:

mcp.json
{"mcpServers":{"grabmail":{"url":"https://grabmail.io/mcp"}}}

Der Transport ist Streamable HTTP: ein POST mit JSON-RPC 2.0 als Inhalt, eine JSON-Antwort, kein offen gehaltener Stream. Sie können das Ganze deshalb schon von einem Terminal aus prüfen, bevor überhaupt ein Agent im Spiel ist:

die Tools auflisten, über die Shell
curl -sX POST https://grabmail.io/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Clients, die vor der Nachfrage bei einem Menschen selbst nach einem Server suchen, finden /.well-known/mcp.json auf der Domain — dort stehen derselbe Endpunkt und sein Transport.

Der gesamte Anmeldeablauf in vier Tool-Aufrufen

Das ist die Abfolge, die fast jeder Agent braucht, und mehr steckt nicht dahinter:

  1. create_inbox aufrufen. Zurück kommen eine Adresse, ein Alias, die Domain und ein Hinweis, welches von beiden der Agent weitergeben soll. Angelegt wurde dabei nichts — das Postfach beginnt zu existieren, sobald die erste Nachricht darin landet.
  2. Den Alias ins Formular eintragen. Der Dienst, bei dem man sich anmeldet, erhält eine funktionierende Adresse, die das Postfach erreicht, sich aber nicht zum Lesen daraus verwenden lässt.
  3. wait_for_message mit der Adresse aufrufen. Direkt nach dem Absenden, nicht zeitgesteuert. Es blockiert; es pollt nicht in einer Schleife, die der Agent selbst schreiben müsste.
  4. Den Code aus der Nachricht lesen. Der vollständige Inhalt kommt bereits mit der Warteantwort zurück, ein zweiter Aufruf ist deshalb meist gar nicht nötig — read_message braucht man nur für etwas, das schon früher angekommen ist.
Ihr Agentnimmt sich eine Adresse und einen AliasDie Websiteerhält den Alias, sendet den CodeGrabMailhält, was ankommtwait_for_message, bis zu 25 sliefert die ganze Nachricht, oder timed_out
Vier Aufrufe, und nur einer davon wartet. Der Alias geht an die Website hinaus; die Adresse bleibt beim Agenten — auf sie hört er.

Warum wait_for_message zurückkehrt, bevor die Mail da ist

Es ist das Tool, das einen Agenten erst praktisch einsetzbar macht, und dasjenige, dessen Verhalten am meisten überrascht — eine Minute Zeit ist es also wert. Ein Aufruf sieht so aus:

auf eine Nachricht mit „code“ im Betreff warten
curl -sX POST https://grabmail.io/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":
        {"name":"wait_for_message",
         "arguments":{"address":"demo.5kuqarzuch@grabmail.io",
                       "subject_contains":"code"}}}'

Es blockiert bis zu 25 Sekunden lang. Ist bis dahin nichts angekommen, schlägt es nicht fehl — es kommt mit einer schlichten Antwort zurück und bittet darum, erneut aufgerufen zu werden:

Antwort nach einer Wartezeit ohne Nachricht
{
  "timed_out": true,
  "waited_seconds": 25,
  "message": null,
  "note": "Nothing arrived yet. Call wait_for_message again ..."
}
Warum überhaupt eine Obergrenze
Jede Sekunde Wartezeit ist ein Server-Worker, der nichts anderes tut als zu schlafen, und davon gibt es nur eine feste Anzahl. Ein Warten, das fünf Minuten dauern könnte, wäre ein Agent, der einen Slot blockiert, den hundert andere brauchen. 25 Sekunden liegen außerdem innerhalb des Standard-Timeouts jedes Clients, sodass der Aufruf zurückkehrt, statt dass der Client selbst aufgibt.
Nur 8 gleichzeitige Wartevorgänge
Darüber hinaus antwortet das Tool sofort mit timed_out und einem entsprechenden Hinweis. Eine Rückmeldung zu bekommen, es erneut zu versuchen, ist besser, als ohne es zu wissen hinter sieben anderen Agenten in einer Warteschlange zu stehen.
Filtern, damit nicht die falsche Mail den Wartevorgang beendet
from_contains und subject_contains sorgen dafür, dass beim Warten alles andere ignoriert wird, was währenddessen eintrifft. since_id ist das, was man übergibt, wenn im Postfach schon etwas lag: Geben Sie die neueste bereits gesehene ID mit, dann erfüllt nur wirklich neue Mail den Aufruf.

Den Alias weitergeben, die Adresse pollen

Jedes Postfach hier hat eine zweite, zwölf Zeichen lange Adresse, die in dasselbe Postfach zustellt, es aber nicht auslesen kann. Dieser Unterschied zählt für einen Agenten weit mehr als für einen Menschen, denn ein Agent trägt bereitwillig ein, was immer er bekommen hat, in welches Feld auch immer er findet.

create_inbox gibt deshalb nicht einfach eine Adresse zurück und hofft das Beste. Es liefert beide zurück, dazu ein next_step, das sagt, welche welche ist — der Agent liest sein eigenes Tool-Ergebnis, sodass die Anweisung dort ankommt, wo sie gebraucht wird, statt auf einer Dokumentationsseite zu stehen, die niemand in der Schleife lesen kann.

Was in die eigenen Anweisungen des Agenten gehört

Die Tools beschreiben sich selbst gut genug, dass ein fähiges Modell das auch ohne Anleitung richtig macht. Fünf Zeilen machen daraus etwas Verlässliches statt nur Wahrscheinliches:

  • Eine Adresse pro Anmeldung. Nicht eine Adresse, die überall wiederverwendet wird: Ein Postfach mit der Mail von sechs Diensten bedeutet sechs Bestätigungen, die ein Agent auseinanderhalten muss, und ein Leck, das alle auf einmal offenlegt.
  • Den Alias weitergeben, nie die Adresse. Das ausdrücklich zu sagen lohnt sich, auch wenn es schon im Tool-Ergebnis steht.
  • wait_for_message direkt nach dem Absenden aufrufen und bei timed_out einfach erneut aufrufen, statt das als Fehlschlag zu werten. Zwei- oder dreimal ist normal.
  • since_id übergeben, wenn das Postfach nicht neu ist — sonst erfüllt eine alte Nachricht den Wartevorgang, und der Agent liest einen Code, der schon vor einer Stunde abgelaufen ist.
  • Die Nachricht löschen, sobald der Code verwendet wurde. Nicht erforderlich — ohnehin ist nach 5 Tagen alles weg —, aber es schließt das Zeitfenster früher, und es kostet nur einen idempotenten Aufruf.

Als Anweisungsblock geschrieben, ist das ungefähr so lang wie hier:

Systemprompt oder eine Zeile in AGENTS.md
Wenn Sie eine E-Mail-Adresse brauchen, rufen Sie create_inbox auf und geben Sie
den ALIAS weiter, den es zurückgibt — niemals die Adresse. Rufen Sie direkt nach
dem Absenden des Formulars wait_for_message mit der Adresse auf. Antwortet es
mit timed_out, rufen Sie es erneut auf — das ist normal, nichts ist verloren.
Übergeben Sie since_id, wenn im Postfach schon Mail lag. Löschen Sie die Nachricht, sobald der Code verwendet wurde.

Die Grenzen, die man kennen sollte, bevor man darauf aufbaut

Alle sind veröffentlicht statt selbst entdeckt, und keine davon lässt sich mit einem Tarif anheben:

GrenzeWertWas das für einen Agenten bedeutet
Ein Wartevorgang25 SekundenDanach timed_out. Erneut aufrufen; nicht als Fehler behandeln.
Gleichzeitige Wartevorgänge8 WartevorgängeDarüber hinaus antwortet das Tool sofort und sagt das auch. Als Ausweg list_messages verwenden.
LesezugriffeEiner pro Sekunde, pro AdresseWeit über dem, was eine Tool-Aufruf-Schleife tut. Ein blockierendes Warten ist eine einzige Anfrage, nicht sechzig.
Nachrichtengrößemax. 5 MBWird schon während der SMTP-Verbindung abgelehnt, sodass der Absender Bescheid weiß, statt dass der Agent auf etwas wartet, das nie ankommt.
Speicherdauer5 TageEine feste Grenze, durchgesetzt von einem Job. Alles, was der Agent behalten muss, muss er selbst festhalten.

Es gibt keinen Endpunkt zum Senden und kein Tool dafür. Dieser Dienst empfängt nur, und genau das hindert ein unauthentifiziertes Postfach daran, zum Spam-Relay zu werden — ein Agent, der einem Menschen antworten muss, braucht also anderswo ein echtes Postfach.

Wenn ein Formular die öffentlichen Domains ablehnt

Viele Dienste führen Listen mit Wegwerf-Mail-Domains, und die drei öffentlichen Domains hier stehen darauf. Ein Agent erlebt das als Formular, das die gerade erhaltene Adresse ablehnt — oder schlimmer, sie annimmt und nie etwas verschickt.

Die dauerhafte Lösung ist eine Domain, die Ihnen gehört. Ein MX-Eintrag macht jede Adresse darauf zu einem Postfach hier; sie steht auf keiner Liste, weil sie auf dieser Website nirgendwo genannt wird, und dieselben sechs Tools funktionieren darauf unverändert — nur create_inbox nicht, weil es Adressen auf den öffentlichen Domains erzeugt. Der Agent verwendet einfach beliebiger-name@ihre-domain und ruft darauf wait_for_message auf.

MX-Eintrag für Ihre Domain10 smtp.grabmail.io

Die vollständige Anleitung finden Sie hier — der Eintrag, was seine Veröffentlichung beweist, und die Grenzen eines Postfachs ohne Passwort.

Was ein Agent damit nicht tun sollte

Der ehrliche Teil — und der, der einen ganzen Nachmittag erspart:

  • Nichts, was man später wiederherstellen müsste. Alles, was Geld, Identität oder Arbeit enthält. Das Postfach ist nach 5 Tagen wieder leer und für jeden lesbar, der die Adresse kennt — ein Passwort-Reset, der nächstes Jahr dorthin geschickt wird, erreicht also niemanden, oder jemand anderen.
  • Nicht als zweiter Faktor. Ein Postfach ohne Passwort ist kein Faktor.
  • Nicht für irgendetwas Privates. Nicht weil wir mitlesen, sondern weil die Adresse das einzige Geheimnis dabei ist — und ein Agent hat sie womöglich längst in ein Log, ein Transkript oder eine Commit-Nachricht geschrieben.
  • Nicht für große Mengen. Ein Agent, der zu Hunderten Konten eröffnet, ist genau das Verhalten, für das jede Sperrliste existiert, und der schnellste Weg, die öffentlichen Domains für alle anderen sperren zu lassen.

Wofür es tatsächlich gedacht ist — der Bestätigungsschritt, der zwischen einem Agenten und dem steht, worum er eigentlich gebeten wurde — nimmt es genau die eine Hürde, die ihn zuverlässig aufhält.

Fragen

Brauche ich einen API-Key oder ein Konto?

Nein. Die öffentlichen Domains, die Tools und eine eigene Domain sind alle kostenlos und unauthentifiziert. Der einzige Fall, der einen Schlüssel braucht, ist eine Domain, die auf Anfrage geschlossen wurde — die verlangt dann einen Authorization-Header.

Mit welchen Clients funktioniert das?

Mit jedem Client, der das Model Context Protocol spricht — Claude Desktop, Claude Code, Cursor, Continue, das OpenAI Agents SDK und die anderen. Der Transport ist Streamable HTTP, der Standard bei aktuellen Clients, und drei Protokollversionen werden akzeptiert, sodass auch ein älterer Client noch eine Verbindung bekommt.

Warum liefert wait_for_message timed_out zurück?

Weil ein einzelner Wartevorgang bewusst auf 25 Sekunden begrenzt ist. Das ist kein Fehler, und nichts geht verloren: einfach erneut aufrufen. Mail braucht regelmäßig länger, als die Seite, die sie versprochen hat, glauben macht, und zwei oder drei Wartevorgänge hintereinander sind eine ganz normale Anmeldung.

Kann der Agent stattdessen meine eigene Domain verwenden?

Ja, dabei ändert sich nur die Adresse. Richten Sie einen MX-Eintrag auf smtp.grabmail.io, und jede Adresse auf dieser Domain wird über dieselben Tools lesbar. Nur create_inbox ist auf die öffentlichen Domains beschränkt, weil es der einzige Aufruf ist, der einen Namen für Sie erfindet.

Kann ein Agent darüber E-Mails versenden?

Nein. Es gibt bewusst kein Tool und keinen Endpunkt zum Versenden: Ein unauthentifizierter Dienst, der Mails verschicken könnte, wäre binnen eines Tages ein Spam-Relay. Unser SPF ist v=spf1 -all und unser DMARC ist p=reject, also ist alles gefälscht, was vorgibt, von einer Adresse hier zu stammen.

Ist das Postfach privat?

Nein, und das ist die eine Einschränkung, die man einem Agenten ausdrücklich mitgeben sollte. Bei einer öffentlichen Domain kann jeder, der die Adresse kennt oder errät, sie lesen. Verwenden Sie eine nicht erratbare Adresse, geben Sie den Alias statt der Adresse weiter, und lassen Sie nichts Privates in ihre Nähe kommen.

Können zwei Agenten gleichzeitig auf dieselbe Adresse warten?

Ja, und beide bekommen die Nachricht, sobald sie ankommt. Begrenzt ist die Zahl der Wartevorgänge, die gleichzeitig über den ganzen Dienst hinweg laufen, auf 8; darüber hinaus antwortet das Tool sofort und sagt das auch, und list_messages funktioniert weiterhin.

Wie lange bleiben die Nachrichten erhalten?

5 Tage ab Ankunft, gelesen oder nicht, und es gibt keine Einstellung, die das verlängert. Jede Nachricht trägt expires_at, sodass ein Agent dieses Datum nie selbst berechnen muss.

Was unterscheidet das vom Aufruf der REST-API aus einem Skript?

Für ein Skript macht das keinen Unterschied, und dort passt die REST-API besser — die Anleitung zum Testen von Verifizierungsabläufen deckt diese Form ab, inklusive Fristen und Hilfsfunktionen. MCP ist für den Fall gedacht, in dem niemand die Schleife geschrieben hat: Das Modell entscheidet selbst, ein Postfach zu öffnen, und braucht dafür Tools, die es entdecken kann, statt welche, die nur dokumentiert sind.

Probieren Sie es aus, solange es frisch ist

Eine Adresse braucht einen Klick, kein Konto und keine Karte. Alles in dieser Anleitung funktioniert damit sofort.

Willkommen zurück

Ihre Postfächer und Ihre Domains an einem Ort.