@olykov/node-red-contrib-mcp-server-readonly
@olykov/node-red-contrib-mcp-server-readonly
Generische Model Context Protocol (MCP)-Servernodes für Node-RED: Machen Sie jeden Flow als MCP-Tool über einen OAuth-geschützten Endpunkt verfügbar, mit optionaler schreibgeschützter Node-RED-Admin-Flow-Inspektion. Keine Hausautomations- oder andere Domänenkopplung – dies ist ein nackter Baustein, um Node-RED-Flows in MCP-Tools zu verwandeln, die KI-Assistenten (Claude, Codex usw.) aufrufen können.
Breaking Change in 0.5.0 – nur noch öffentlicher Client (PKCE). Client-Secrets und die node-seitige Redirect-URI-Whitelist sind entfernt: Der offene Client-Registrierungs-Endpunkt hat jedem Aufrufer jedes konfigurierte Secret ausgehändigt, und Redirect-URIs werden ohnehin vom Identity Provider bei
/authorizevalidiert. Migration: Stellen Sie den IdP-Client auf öffentlich mit PKCE um (ein weiterhin vertraulicher Client schlägt beim Token-Austausch mitinvalid_clientfehl), stellen Sie sicher, dass die MCP-Client-Callback-URLs beim IdP auf der Whitelist stehen, und wenn der Node vor einem gespeicherten Secret warnt, öffnen Sie seine Konfiguration, klicken Sie auf Fertig und stellen Sie bereit, um es zu löschen. MCP-Clients, die vor dem Upgrade verbunden waren, haben möglicherweise die alte Registrierung zwischengespeichert – entfernen Sie den Server im Client und fügen Sie ihn erneut hinzu, wenn die Anmeldung nicht richtig funktioniert.
Nodes
mcp-server(Konfigurationsknoten) – hostet einen eigenständigen MCP-JSON-RPC-Endpunkt unterPOST /mcp/<path>, OAuth-2.0-Protected-Resource-Discovery (RFC 9728), Authorization-Server-Discovery (RFC 8414) mit Proxy zu einem echten OIDC-Identity-Provider sowie einen Shim für die dynamische Client-Registrierung, sodass OAuth-fähige MCP-Clients (z. B. Claude.ai) sich selbst registrieren und authentifizieren können. Mehreremcp-server-Knoten können koexistieren, jeder mit eigenem Pfad und eigener unabhängiger Auth-Konfiguration.mcp-in– definiert ein MCP-Tool (Name, Beschreibung, JSON-Schema-Parameter und ein optionales Zugriffsgate pro Tool). Wenn ein MCP-Client das Tool aufruft, sendet der Knoten eine Nachricht mit den Aufrufargumenten; verdrahten Sie den Rest des Flows, um die eigentliche Arbeit zu erledigen. Die Argumente inmsg.payloadsind nicht vertrauenswürdige Aufrufereingaben – das JSON-Schema ist Dokumentation für das Modell, keine Validierung – daher muss der Flow sie validieren und maskieren, bevor sie in Shell-Befehlen, Dateipfaden, URLs oder Abfragen verwendet werden.mcp-out– löst einen ausstehenden Tool-Aufruf auf. Verdrahten Sie das Ende Ihres Flows hierher, wobeimsg._mcpCallIdintakt ist (aus der ursprünglichenmcp-in-Nachricht) undmsg.payloadauf das Ergebnis gesetzt ist.
Eine einzelne mcp-in → ... → mcp-out-Kette ist ein MCP-Tool. Bauen Sie beliebig viele Ketten gegen denselben mcp-server-Knoten, um ein ganzes Toolset verfügbar zu machen.
Admin-Read-only-API-Tools
Aktivieren Sie Admin-Read-only-API-Tools auf einem mcp-server-Knoten, um zusätzlich ein Tool verfügbar zu machen, das auf Node-REDs eigener Admin-HTTP-API arbeitet, gesteuert durch einen konfigurierbaren JWT-Anspruch (Standard: groups enthält admin):
get_flow– listet alle Flow-Tabs (id, label, Knotenanzahl) auf oder gibt das vollständige JSON eines Tabs zurück, wenn mit eineridaufgerufen.
Konfigurieren eines mcp-server-Knotens
Allgemein: Name,
path(→ registriertPOST /mcp/<path>), die öffentlicheServer-URL, unter der diese Node-RED-Instanz erreichbar ist, optionaler Servername/Anweisungen, die dem Modell angezeigt werden, und ein optionaler Hostname-Filter (siehe unten).Auth: eine OIDC-
Identity-Provider-Issuer-URL (erforderlich – Endpunkte werden automatisch aus/.well-known/openid-configurationermittelt, mit PocketID-artigen Fallback-Pfaden; wenn Sie dies leer lassen, entsteht ein defektes OAuth-Discovery-Dokument mit relativen Endpunkten und ohne funktionierende Authentifizierung, daher lässt der Editor Sie ohne sie nicht bereitstellen), eine Client-ID (der IdP-Client muss öffentlich mit PKCE sein – Client-Secrets werden nicht mehr unterstützt, und Redirect-URIs werden nur beim IdP konfiguriert und validiert), Scopes, Token-Audience, ein optionales lokales Debug-Token, das den IdP für lokale Tests vollständig umgeht (setzen Sie eine beliebige Platzhalter-URL in Identity provider und verlassen Sie sich auf das Debug-Token – es wird nie kontaktiert, wenn das Debug-Token übereinstimmt; dergroups-Anspruch, den der Debug-Benutzer erhält, ist konfigurierbar, sodass auch die Zugriffsgates lokal getestet werden können), und dasAccess-claim- /Server-access-Gate (siehe unten).Admin: Aktivieren/Deaktivieren der Admin-Read-only-API-Tools, Admin-Token (für die Node-RED-Admin-API), Admin-API-Port und das
Read-only-access-Gate, das zusätzlich nur die schreibgeschützten Admin-Tools einschränkt.
Zugriffskontrolle
Ein Anspruchsname, viele Wertelisten. Access claim auf dem Auth-Tab (Standard groups) benennt den einzelnen JWT-Anspruch, gegen den jedes Gate prüft. Jedes andere Autorisierungsfeld ist eine kommagetrennte Any-of-Liste der Werte dieses Anspruchs – media, ops besteht, wenn der Anspruch mindestens einen davon enthält. Eine leere Liste erlegt keine Einschränkung auf.
Verschachtelte Ansprüche werden über einen Punktpfad angesprochen, für Anbieter, die Rollen nicht auf oberster Ebene des Tokens ablegen: realm_access.roles liest Keycloaks Realm-Rollen, und jede Tiefe funktioniert. Ein Schlüssel, der wörtlich existiert, gewinnt immer, sodass ein Anspruch, der tatsächlich einen Punkt im Namen hat, weiterhin auf sich selbst aufgelöst wird. Nur Zeichenfolgen und Arrays von Zeichenfolgen werden abgeglichen – das Zeigen des Anspruchs auf ein Containerobjekt gewährt nichts, anstatt versehentlich zu matchen.
Feld | Wo | Einschränkung |
| mcp-server, Auth-Tab | jedes Tool auf diesem Server |
| mcp-in | dieses eine Tool, zusätzlich |
| mcp-server, Admin-Tab |
|
Die Listen werden mit UND kombiniert. Ein Tool zu erreichen bedeutet, die Liste des Servers und die eigene Liste des Tools zu erfüllen. Admin-Read-only-API-Tools sind kein Sonderfall – ihr Feld ist einfach die Tool-Liste für get_flow.
Access claim: groups Server access: staff
tool A: (empty) tool B: media Admin access: admin
groups=[staff] → A
groups=[staff, media] → A, B
groups=[staff, admin] → A + get_flow
groups=[media] → nothing (server list not cleared)
groups=[guest] → nothing
Server access empty:
groups=[media] → A, B
groups=[guest] → AJeder mit einem gültigen Token verbindet sich weiterhin – initialize gelingt immer – aber Tools, die ein Aufrufer nicht erreichen kann, werden in tools/list und in den initialize-Anweisungen ausgeblendet. Ein direkter tools/call auf eines davon wird als MCP-Tool-Ergebnis mit isError: true und einer erklärenden Nachricht abgelehnt (kein roher JSON-RPC-Protokollfehler), sodass der Grund das aufrufende Modell erreicht, anstatt in einem generischen „Tool-Ausführung fehlgeschlagen“ zusammenzufallen.
Die Client-Achse: erforderlicher Scope
Die obigen Listen beantworten, was dieser Benutzer tun darf. Required scope beantwortet eine andere Frage – was dieser Client im Namen des Benutzers tun durfte – und beide werden mit UND geprüft.
Sie sind nicht austauschbar. Eine Gruppe sagt, wer an der Tastatur sitzt; ein Scope sagt, wie viel von der Autorität dieser Person an die Software delegiert wurde, die das Token hält. Wenn man sie in ein Feld zusammenfasst, wird nur eines berücksichtigt: Ein Client mit einem Nur-Lese-Scope, der von jemandem bedient wird, der schreiben darf, würde schreiben. Die Gewährung des Clients muss die Rechte des Benutzers begrenzen, nicht ignoriert werden.
Der erforderliche Scope wird automatisch zu scopes_supported hinzugefügt, sodass im Scopes-Feld nichts wiederholt werden muss, und er wird in der WWW-Authenticate-Challenge bei einer 401 genannt.
Der Scope-Anspruch wird so gelesen, wie OAuth es definiert (RFC 6749 §3.3): eine durch Leerzeichen getrennte Zeichenfolge oder ein Array, falls Ihr Anbieter eines sendet. Der Anspruchsname ist nicht konfigurierbar, da er standardisiert ist; scp wird als Fallback für Microsoft Entra und Okta gelesen. Das Feld selbst ist eine kommagetrennte Any-of-Liste. Leer bedeutet keine Einschränkung, sodass eine Installation, die es nie ausfüllt, nicht betroffen ist; ein konfigurierter Scope, den das Token nicht trägt, wird abgelehnt, auch wenn das Token überhaupt keinen Scope-Anspruch hat.
Upgrade: Das Admin-Gate hat kein eigenes Anspruchsnamen-Feld mehr – es prüft wie alles andere gegen den
Access claimdes Auth-Tabs. Wenn Sie einen anderen Anspruchsnamen für Admin-Tools festgelegt hatten, verschieben Sie diesen Wert auf den Auth-Tab oder passen Sie die Admin-Liste entsprechend an. Ein Wert, der wörtlich ein Komma enthält, wird jetzt als Liste statt als eine einzelne Zeichenfolge gelesen. Die Gate-Felder wurden auch umbenannt (Required claim/Required value→Access claim/Server access/Admin access); die zugrunde liegenden Einstellungen sind unverändert, sodass bestehende Flows unverändert weiter funktionieren.
Protokoll
Der Endpunkt spricht MCP-Protokollversion 2024-11-05 über einfaches HTTP-POST – jede Anfrage ist eine JSON-RPC-Nachricht, jede Antwort ein JSON-Body. initialize, tools/list, tools/call und ping werden unterstützt; es gibt keinen SSE/Streaming-GET-Kanal und keine serverinitiierten Nachrichten. Dies ist die Teilmenge, die heutige OAuth-fähige MCP-Clients (z. B. Claude) tatsächlich gegen einen Nur-Tools-Server verwenden. Die beworbene Version ist absichtlich festgelegt, anstatt das Angebot des Clients zu spiegeln.
Hostname-Filter
Standardmäßig deaktiviert. Wenn Nur Anfragen für diesen Hostnamen bedienen aktiviert ist, antwortet der Knoten nur auf Anfragen, deren Host-Header mit dem Hostnamen in seiner Server-URL übereinstimmt. Dadurch können mehrere mcp-server-Knoten denselben path auf einer Node-RED-Instanz teilen, wobei jeder nur auf seinen eigenen virtuellen Host antwortet – nützlich hinter einem Reverse-Proxy, der mehrere Hostnamen für ein Node-RED-Backend bedient. Lassen Sie es für einen einzelnen Server deaktiviert, oder wenn ein Reverse-Proxy den Host-Header umschreibt.
Reverse-Proxy
Jeder mcp-server-Knoten ist seine eigene OAuth-Ressource – anders als ein einzelner gemeinsamer MCP-Endpunkt registriert jede Instanz ihre eigenen Discovery- und Registrierungsrouten, unter ihrem path. Für einen Knoten mit path: docker und Server-URL: https://mcp.example.com existieren diese sechs Routen:
Methode & Pfad | Zweck |
| Der JSON-RPC-MCP-Endpunkt (durch Bearer-Token geschützt) |
| Ressourcen-Metadaten (RFC 9728), Pfad-eingefügte Form |
| Ressourcen-Metadaten (RFC 9728), RFC-8414-Form |
| Auth-Server-Metadaten (RFC 8414), Pfad-eingefügte Form |
| Auth-Server-Metadaten (RFC 8414), RFC-8414-Form |
| Shim für dynamische Client-Registrierung |
Client-ID-Metadaten-Dokumente (CIMD). MCP 2026-07-28 verwirft die dynamische Client-Registrierung zugunsten von CIMD, bei dem die ID eines Clients die HTTPS-URL eines Metadaten-Dokuments ist, das er selbst hostet. Dieser Knoten bewirbt client_id_metadata_document_supported, indem er spiegelt, was das Discovery-Dokument Ihres IdP sagt – es wird hier nie konfiguriert, weil der IdP die Client-ID auflöst und dieser Server nicht versprechen kann, Unterstützung zu bieten, die der IdP nicht hat. Discovery wird einmal abgerufen und für die Lebensdauer des Knotens zwischengespeichert, sodass das Aktivieren oder Deaktivieren von CIMD beim IdP beim nächsten Neustart oder Bereitstellen von Node-RED übernommen wird – nicht live.
Der DCR-Shim ist standardmäßig deaktiviert und sollte deaktiviert bleiben. Er existiert für eine Situation: einen Client, der CIMD nicht verwenden kann, der mit einem IdP spricht, der DCR selbst nicht kann. Wenn er aktiviert ist, bewirbt dieser Server sich selbst als Autorisierungsserver, damit der Registrierungsendpunkt auffindbar ist – was auch bedeutet, dass das iss, das Ihr IdP zurückgibt, nicht mit dem Issuer übereinstimmt, den der Client aufgezeichnet hat, und ein Client, der RFC 9207 durchsetzt (von MCP 2026-07-28 gefordert), sich weigern wird, den Ablauf abzuschließen. Wenn er deaktiviert ist, werden Clients direkt zum IdP geschickt und müssen CIMD oder eine vorregistrierte Client-ID verwenden. Ein Knoten, der vor der Einführung dieses Schalters konfiguriert wurde, behält den Shim an, da er das bisher getan hat.
Beide Mechanismen bleiben absichtlich verfügbar. Clients wählen in der Reihenfolge der Spezifikation – zuerst vorregistriert, dann CIMD, dann DCR –, sodass ein Client ohne CIMD-Unterstützung weiterhin genau wie zuvor den Registrierungs-Shim verwendet. Welchen Mechanismus jeder Client verwendet hat, ist im Log ablesbar: MCP CIMD client authenticated: <url> beim ersten Mal, wenn ein CIMD-Client nach einem Neustart gesehen wird, und MCP DCR fallback für einen Client, der sich registriert hat, obwohl der IdP CIMD bewirbt. Zusammen decken die beiden Zeilen jeden Client ab, der den Server erreicht.
Tokens von einem CIMD-Client tragen diese Dokument-URL als Audience anstelle Ihrer vorregistrierten Client-ID, und sie werden akzeptiert, wann immer der IdP CIMD bewirbt. Dieser Knoten führt keine eigene zweite Zulassungsliste, daher ist die Liste der akzeptierten Metadaten-Dokumente des IdP die Grenze – jeder CIMD-Client auf dieser Liste kann diesen Server erreichen, wobei das Claim-Gate die verbleibende Prüfung ist.
Beide Well-Known-Formen werden beworben, weil verschiedene MCP-Clients unterschiedliche abfragen – bieten Sie beide an. Da die Routen jeder Instanz die Formen /mcp/<path> und /.well-known/*/mcp/<path> teilen, deckt ein Satz Wildcard-Regeln jeden aktuellen und zukünftigen mcp-server-Knoten ab (solange alle über dieselbe Domain/denselben Upstream erreichbar sind) – keine Reverse-Proxy-Änderung erforderlich, wenn ein neuer path hinzugefügt wird. Beispiel mit Caddy über caddy-docker-proxy-Labels:
labels:
caddy_1: mcp.example.com
caddy_1.reverse_proxy_0: /mcp/* "{{upstreams 1880}}"
caddy_1.reverse_proxy_1: /.well-known/oauth-protected-resource/mcp/* "{{upstreams 1880}}"
caddy_1.reverse_proxy_2: /.well-known/oauth-authorization-server/mcp/* "{{upstreams 1880}}"Node-RED selbst gibt für jeden Pfad, der keine tatsächlich registrierte Route ist, einen 404 zurück, sodass die Wildcard nichts über das hinaus exponiert, was jeder bereitgestellte mcp-server-Knoten bereits registriert. Wenn ein path auf einer anderen Domain als die anderen erreichbar sein muss, geben Sie ihm einen eigenen caddy_N-Site-Block (oder kombinieren Sie ihn mit Hostname-Filterung oben).
Was der Identitätsanbieter unterstützen muss (gleiche Anforderungen wie lib/mcp-auth.js):
Ein OIDC-Anbieter mit Discovery – Endpunkte werden aus
‹issuerUrl›/.well-known/openid-configurationgelesen, mit Rückgriff auf das Pfad-Layout von PocketID, falls Discovery nicht verfügbar ist.JWT-Zugriffstokens, signiert mit einem Schlüssel, der auf dem JWKS des Anbieters veröffentlicht ist (Tokens werden lokal verifiziert; opaque/nur-Introspection-Zugriffstokens werden nicht unterstützt).
Ein öffentlicher Client mit PKCE (S256), Grant-Typen
authorization_code+refresh_token, und die Redirect-URI(s) des MCP-Clients sind auf die Whitelist gesetzt (für Claude.ai:https://claude.ai/api/mcp/auth_callback). Redirect-URIs werden nur beim Identitätsanbieter konfiguriert und validiert – der Knoten führt keine eigene Zulassungsliste mehr, sodass die Wildcard-Unterstützung des IdP (z. B. die von PocketID) unverändert funktioniert. Client-Secrets werden nicht mehr unterstützt: Der offene Client-Registrierungs-Endpunkt hat jedes konfigurierte Secret jedem Aufrufer ausgehändigt, sodass es nie wirklich geheim sein konnte. Falls ein Secret aus einer früheren Version noch gespeichert ist, wird es mit einer Warnung ignoriert – stellen Sie den IdP-Client auf öffentlich um, öffnen Sie dann die Konfiguration des Knotens, klicken Sie auf Fertig und stellen Sie bereit, um das gespeicherte Secret zu löschen und die Warnung zu beseitigen.
Getestet mit Caddy (Reverse-Proxy) + PocketID (Identitätsanbieter) + Claude.ai und Hermes (MCP-Clients). Jeder spezifikationskonforme OIDC-Anbieter, der JWT-Zugriffstokens ausstellt, sollte hinter einem beliebigen Reverse-Proxy, der die obigen Routen weiterleitet, auf dieselbe Weise funktionieren.
Beispiele
Siehe examples/ für neun importierfertige Flows (Jellyfin, Calibre, Docker, Music Assistant, Radarr, iRobot/rest980, Overseerr, Sonarr, Spotify), jeder mit einem eigenen mcp-server-Knoten (Serverbeschreibung vorausgefüllt, Server URL/Identity provider für Sie zum Ausfüllen leer gelassen) und mcp-in/mcp-out-Tools – eine gute Referenz zum Anbinden eigener Tools.
Entwicklung
npm install
npm testLizenz
ISC
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
MCP server for Argo RPG Platform — connects AI assistants to campaign data via OAuth2
Self-hosted MCP gateway: turn any API, database or MCP server into AI connectors — no code.
MCP Hub: AI service discovery, per-user OAuth, and multi-service workflow orchestration
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/olykov/node-red-contrib-mcp-server-readonly'
If you have feedback or need assistance with the MCP directory API, please join our Discord server