Skip to main content
Glama

{"type":"text"}

Portcall

Una pasarela de plugins pequeña que sirve servidores MCP locales a través de HTTP.

El nombre es un juego de palabras náutico: port callport (puerto / puerto de red) + call (escala de un barco / petición).

Qué es

Portcall escucha en un puerto HTTP y monta uno o más servidores MCP en rutas separadas:

/vault/mcp   → mcpvault (Obsidian vault)
/healthz     → liveness + mount list

Cada montaje es un endpoint MCP independiente. Los clientes los registran por separado: no hay agregación de herramientas, por lo que no hay colisiones de nombres ni esquema de espacios de nombres que mantener.

Exponer el puerto más allá de localhost está deliberadamente fuera de alcance. Pon un túnel, un proxy inverso o nada delante; Portcall se vincula a 127.0.0.1 por defecto y no le importa lo que haya río arriba.

Related MCP server: mcp-unify

Por qué no un puente stdio

La forma obvia de poner un servidor MCP stdio en HTTP es un puente genérico como supergateway. Eso funciona, pero tiene un problema estructural: cada petición o sesión lanza un proceso hijo, y es fácil equivocarse al recolectar esos hijos.

En supergateway concretamente, el hijo solo se reclama desde transport.onclose o transport.onerror. Nada llama a transport.close() en una petición sin estado completada normalmente, por lo que onclose nunca se dispara y cada petición exitosa pierde un proceso — solo las peticiones fallidas se limpian. Su modo con estado no pierde (un temporizador de sesión cierra el transporte), pero mantiene un flujo SSE GET de larga duración, que algunos proxies manejan mal.

Envolver el comando en npx lo empeora: npx bifurca el servidor real, por lo que matar al hijo mata al envoltorio y deja huérfano al nieto.

La respuesta de Portcall es no lanzar nada cuando no es necesario.

Adaptadores

Adaptador

Para

Cómo

inProcess

Servidores que exportan una fábrica como biblioteca

Llama a la fábrica en el mismo proceso. No existe ningún proceso hijo, por lo que no hay nada que recolectar.

stdio

Servidores de terceros que solo hablan stdio

Aún no implementado. Cuando llegue, debe reclamar al hijo en la finalización normal, no solo en caso de error, y manejar los asesinatos de grupos de procesos para comandos envoltorio.

inProcess es el caso interesante y cubre los servidores que merece la pena autoalojar. @bitbonsai/mcpvault, por ejemplo, exporta createServer(vaultPath, options) que devuelve un Server del SDK v2 de MCP; su entrada bin es esencialmente serveStdio(() => createServer(...)). Portcall llama a la misma función directamente y se salta stdio por completo.

El SDK crea una instancia de servidor nueva por petición y la elimina con la petición, por lo que no hay estado de sesión que expire ni manejadores que se acumulen.

Versiones del protocolo

Portcall está construido sobre @modelcontextprotocol/server v2, que atiende dos eras de protocolo desde un único manejador:

  • Moderno (2026-07-28) — sobre por petición. Las peticiones llevan las cabeceras MCP-Protocol-Version, Mcp-Method y (para llamadas a herramientas) Mcp-Name, además de un bloque params._meta. No hay protocolo de inicio initialize ni sesión de larga duración; el descubrimiento es server/discover.

  • Legado (era 2025) — se sirve sin estado por defecto. GET y DELETE (operaciones de sesión de 2025) responden 405. Establece PORTCALL_MODERN_ONLY=true para rechazar el tráfico heredado por completo.

Debido a que la era moderna es por petición, no hay un flujo SSE permanente que mantener abierto. Eso evita una clase de problema de proxy: algunos proxies inversos retienen las cabeceras de respuesta hasta que llega el primer byte del cuerpo, lo que detiene indefinidamente un flujo SSE recién abierto pero silencioso. Para los flujos que sí ocurren, PORTCALL_KEEPALIVE_MS controla el intervalo de comentarios SSE; redúcelo si un proxy delante está almacenando en búfer.

Configuración

Todos los valores específicos del host provienen del entorno.

Variable

Por defecto

Significado

PORTCALL_VAULT_PATH

(obligatorio)

Ruta absoluta al almacén de Obsidian que se va a servir

PORTCALL_PORT

7100

Puerto TCP

PORTCALL_HOST

127.0.0.1

Interfaz de enlace

PORTCALL_TOKEN

(sin definir)

Token estático de portador. Sin definir significa sin autenticación

PORTCALL_ALIAS_ROOT_MCP

(sin definir)

Monta también el plugin nombrado en /mcp

PORTCALL_PATH_PREFIX

(sin definir)

Sirve cada montaje bajo /<prefijo>/…

PORTCALL_KEEPALIVE_MS

15000

Intervalo de keepalive SSE; 0 lo desactiva

PORTCALL_MODERN_ONLY

false

Rechaza las peticiones de la era 2025 en lugar de servirlas

PORTCALL_TOKEN protege cada montaje con Authorization: Bearer <token>. Ten en cuenta que algunos clientes MCP — entre ellos la interfaz de conector personalizado de Claude — no ofrecen forma de establecer una cabecera de petición, por lo que para esos el token debe aplicarse río arriba (u omitirse, con el acceso controlado en la capa de red).

PORTCALL_PATH_PREFIX es el recurso para exactamente esos clientes: mueve cada montaje bajo un segmento que elijas, de modo que /vault/mcp se convierte en /<prefijo>/vault/mcp y la propia URL lleva el secreto. De ello se derivan dos cosas, y el servidor las aplica ambas:

  • Las respuestas 404 dicen solo not_found. Nunca enumeran lo que está montado.

  • El listado de montajes sale del /healthz público y pasa a /<prefix>/healthz. El /healthz simple sigue respondiendo, por lo que las sondas de actividad siguen funcionando, pero no revela rutas.

Trata un prefijo de ruta como más débil que una cabecera. Las URL llegan a los registros de acceso del proxy, a los informes de errores y a cualquier cosa que registre un destino, y una filtrada otorga el mismo acceso que un token filtrado. Sube el listón: no es autenticación.

Qué plugins están montados, y dónde, se declara en plugins.config.ts.

Ejecución

Requiere Node 24 (ver .nvmrc).

npm install
npm run build
cp .env.example .env    # then set PORTCALL_VAULT_PATH
npm start

Tanto npm start como npm run dev cargan .env si existe y arrancan sin él si no existe, por lo que un demonio puede inyectar el entorno directamente. Las variables ya establecidas en el entorno no se sobrescriben.

npm run dev ejecuta el punto de entrada a través de tsx con watch. Un demonio debería ejecutar la salida compilada, no tsx.

Comprueba que está activo:

curl -s localhost:7100/healthz

Pruebas

npm test        # builds, then runs unit and integration tests
npm run typecheck

Sin dependencias de prueba: el ejecutor es node:test, y tsx (ya necesario para npm run dev) carga el TypeScript.

Las pruebas de integración son de caja negra. Lanzan el servidor compilado contra un almacén desechable en un puerto efímero y lo manejan a través de HTTP real, por lo que ejercitan el mismo artefacto que ejecuta un demonio: enrutamiento, el alias /mcp, autenticación de portador y ambas eras de protocolo. Las pruebas unitarias cubren la resolución de montajes y la comprobación del portador, donde una regresión silenciosa parecería un cliente muerto en lugar de un error.

Estructura

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 builders

Licencia

MIT

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

  • A
    license
    Not graded
    quality
    C
    maintenance
    A universal MCP server that acts as a unified gateway for dynamically connecting and managing multiple MCP servers via a single HTTP endpoint.
    10
    6
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Unifies multiple MCP servers behind a single endpoint with lazy loading, auto-cleanup, Python plugins, and role-based filtering.
    2
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides LocalServer and RemoteServer implementations for running MCP servers locally via stdio or remotely via HTTP/SSE, with simple and advanced deployment options.
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    This 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

View all related MCP servers

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

View all MCP Connectors

Latest Blog Posts

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