Portcall
Portcall
Ein kleiner Plugin-Gateway, der lokale MCP-Server über HTTP bereitstellt.
Der Name ist ein nautisches Wortspiel: port call — port (Hafen / Netzwerk-Port) + call (ein Schiffsstopp / eine Anfrage).
Was es ist
Portcall lauscht auf einem HTTP-Port und mountet einen oder mehrere MCP-Server unter separaten Pfaden:
/vault/mcp → mcpvault (Obsidian vault)
/healthz → liveness + mount listJeder Mount ist ein unabhängiger MCP-Endpunkt. Clients registrieren sie separat – es gibt keine Tool-Aggregation, also keine Namenskollisionen und kein Namespacing-Schema, das gepflegt werden müsste.
Das Freigeben des Ports über localhost hinaus ist bewusst nicht im Scope. Setzen Sie einen Tunnel, einen Reverse-Proxy oder gar nichts davor; Portcall bindet standardmäßig an 127.0.0.1 und kümmert sich nicht darum, was vorgelagert ist.
Related MCP server: mcp-unify
Warum keine stdio-Brücke
Der naheliegende Weg, einen stdio-MCP-Server auf HTTP zu bringen, ist eine generische Brücke wie supergateway. Das funktioniert, hat aber ein strukturelles Problem: Jede Anfrage oder Sitzung erzeugt einen Kindprozess, und das Einsammeln dieser Kinder ist leicht falsch zu machen.
In supergateway im Speziellen wird das Kind nur über transport.onclose oder transport.onerror zurückgeholt. Nichts ruft transport.close() bei einer normal abgeschlossenen zustandslosen Anfrage auf, also feuert onclose nie und jede erfolgreiche Anfrage leakt einen Prozess – nur fehlgeschlagene Anfragen werden aufgeräumt. Der zustandsbehaftete Modus leakt nicht (ein Sitzungstimer schließt den Transport), hält aber stattdessen einen langlebigen GET-SSE-Stream, den einige Proxys schlecht behandeln.
Das Verpacken des Befehls in npx macht es schlimmer: npx forkt den echten Server, also tötet das Töten des Kindes den Wrapper und verwaist das Enkelkind.
Portcalls Antwort ist, nichts zu spawnen, wenn es nicht nötig ist.
Adapter
Adapter | Für | Wie |
| Server, die eine Factory als Bibliothek exportieren | Ruft die Factory im Prozess auf. Es existiert kein Kindprozess, also gibt es nichts einzusammeln. |
| Drittanbieter-Server, die nur stdio sprechen | Noch nicht implementiert. Wenn es kommt, muss es das Kind bei normalem Abschluss einsammeln, nicht nur bei Fehlern, und Prozessgruppen-Kills für Wrapper-Befehle behandeln. |
inProcess ist der interessante Fall und deckt die Server ab, die sich lohnen, selbst zu hosten. @bitbonsai/mcpvault exportiert zum Beispiel createServer(vaultPath, options), das einen MCP-SDK-v2-Server zurückgibt; sein bin-Eintrag ist im Wesentlichen serveStdio(() => createServer(...)). Portcall ruft dieselbe Funktion direkt auf und überspringt stdio vollständig.
Das SDK baut pro Anfrage eine frische Serverinstanz und entsorgt sie mit der Anfrage, also gibt es keinen Sitzungszustand, der ausläuft, und keine sich ansammelnden Handles.
Protokollversionen
Portcall basiert auf @modelcontextprotocol/server v2, das zwei Protokoll-Ären aus einem einzigen Handler bedient:
Modern (
2026-07-28) – Pro-Anfrage-Umschlag. Anfragen tragenMCP-Protocol-Version,Mcp-Methodund (für Tool-Aufrufe)Mcp-Name-Header plus einenparams._meta-Block. Es gibt keineninitialize-Handshake und keine langlebige Sitzung; Discovery istserver/discover.Legacy (2025-Ära) – standardmäßig zustandslos bedient.
GETundDELETE(2025-Sitzungsoperationen) antworten mit405. Setzen SiePORTCALL_MODERN_ONLY=true, um Legacy-Verkehr komplett abzulehnen.
Da die moderne Ära pro Anfrage ist, gibt es keinen dauerhaften SSE-Stream, der offen gehalten werden muss. Das umgeht eine Klasse von Proxy-Problemen: Einige Reverse-Proxys halten Antwort-Header zurück, bis das erste Body-Byte ankommt, was einen gerade geöffneten, aber stillen SSE-Stream unbegrenzt blockiert. Für die Streams, die doch vorkommen, steuert PORTCALL_KEEPALIVE_MS das SSE-Kommentar-Frame-Intervall; senken Sie es, wenn ein vorgelagerter Proxy puffert.
Konfiguration
Alle host-spezifischen Werte kommen aus der Umgebung.
Variable | Standard | Bedeutung |
| (erforderlich) | Absoluter Pfad zum Obsidian-Vault, das bedient werden soll |
|
| TCP-Port |
|
| Bind-Interface |
| (nicht gesetzt) | Statisches Bearer-Token. Nicht gesetzt bedeutet keine Authentifizierung |
| (nicht gesetzt) | Mountet das benannte Plugin zusätzlich unter |
| (nicht gesetzt) | Bedient jeden Mount unter |
|
| SSE-Keepalive-Intervall; |
|
| Lehnt 2025-Ära-Anfragen ab, statt sie zu bedienen |
PORTCALL_TOKEN schützt jeden Mount mit Authorization: Bearer <token>. Beachten Sie, dass einige MCP-Clients – darunter Clauses benutzerdefinierte Connector-UI – keine Möglichkeit bieten, einen Request-Header zu setzen, also muss das Token für diese stattdessen vorgelagert erzwungen werden (oder weggelassen werden, mit Zugriffskontrolle auf Netzwerkebene).
PORTCALL_PATH_PREFIX ist der Fallback genau für diese Clients: Es verschiebt jeden Mount unter ein Segment Ihrer Wahl, sodass /vault/mcp zu /<prefix>/vault/mcp wird und die URL selbst das Geheimnis trägt. Zwei Dinge folgen daraus, und der Server erzwingt beide:
404-Antworten sagen nurnot_found. Sie listen nie auf, was gemountet ist.Die Mount-Liste wandert aus dem öffentlichen
/healthzin/<prefix>/healthz. Das nackte/healthzantwortet weiterhin, damit Liveness-Probes funktionieren, gibt aber keine Pfade preis.
Behandeln Sie ein Pfad-Präfix als schwächer als einen Header. URLs erreichen Proxy-Zugriffsprotokolle, Absturzberichte und alles, was ein Ziel aufzeichnet, und ein geleaktes gewährt denselben Zugriff wie ein geleaktes Token. Es erhöht die Hürde – es ist keine Authentifizierung.
Welche Plugins gemountet sind und wo, wird in plugins.config.ts deklariert.
Ausführen
Erfordert Node 24 (siehe .nvmrc).
npm install
npm run build
cp .env.example .env # then set PORTCALL_VAULT_PATH
npm startSowohl npm start als auch npm run dev laden .env, falls vorhanden, und starten ohne, falls nicht, sodass ein Daemon die Umgebung direkt injizieren kann. Bereits in der Umgebung gesetzte Variablen werden nicht überschrieben.
npm run dev führt den Einstiegspunkt über tsx mit Watch aus. Ein Daemon sollte das gebaute Ergebnis ausführen, nicht tsx.
Prüfen Sie, ob es läuft:
curl -s localhost:7100/healthzTests
npm test # builds, then runs unit and integration tests
npm run typecheckKeine Test-Abhängigkeiten: Der Runner ist node:test, und tsx (bereits für npm run dev benötigt) lädt das TypeScript.
Die Integrationstests sind Black-Box. Sie starten den gebauten Server gegen ein Wegwerf-Vault auf einem ephemeren Port und treiben ihn über echtes HTTP, sodass sie dasselbe Artefakt testen, das ein Daemon ausführt – Routing, den /mcp-Alias, Bearer-Auth und beide Protokoll-Ären. Die Unit-Tests decken Mount-Auflösung und den Bearer-Check ab, wo eine stille Regression wie ein toter Client aussehen würde, nicht wie ein Fehler.
Layout
src/
server.ts HTTP entry point, wiring, health, shutdown
routes.ts mount resolution and URL normalisation
auth.ts bearer token check
config.ts environment parsing
log.ts structured logging
types.ts the Plugin interface
adapters/
inProcess.ts library-factory adapter
plugins/
vault.ts mcpvault
plugins.config.ts which plugins mount at which paths
test/
integration.test.ts black-box tests against the built server
routes.test.ts mount resolution
auth.test.ts bearer token check
helpers.ts server harness and MCP request buildersLizenz
MIT
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 Servers
- AlicenseNot gradedqualityCmaintenanceA universal MCP server that acts as a unified gateway for dynamically connecting and managing multiple MCP servers via a single HTTP endpoint.106MIT
- AlicenseNot gradedqualityCmaintenanceUnifies multiple MCP servers behind a single endpoint with lazy loading, auto-cleanup, Python plugins, and role-based filtering.2MIT

FlowMCP Serverofficial
AlicenseNot gradedqualityDmaintenanceProvides LocalServer and RemoteServer implementations for running MCP servers locally via stdio or remotely via HTTP/SSE, with simple and advanced deployment options.1MIT- AlicenseNot gradedqualityCmaintenanceThis server bridges a stdio MCP server to HTTP, allowing MCP clients that communicate over HTTP to use the server's tools. It includes a per-tool allow/deny filter for security.MIT
Related MCP Connectors
A basic MCP server to operate on the Postman API.
A MCP server built for developers enabling Git based project management with project and personal…
An MCP server that let you interact with Cycloid.io Internal Development Portal and Platform
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/pizza6899-crypto/portcall'
If you have feedback or need assistance with the MCP directory API, please join our Discord server