Portcall
Portcall
Небольшой шлюз плагинов, который обслуживает локальные MCP-серверы по HTTP.
Название — морской каламбур: port call — port (гавань / сетевой порт) + call (остановка судна / запрос).
Что это
Portcall прослушивает один HTTP-порт и монтирует один или несколько MCP-серверов по отдельным путям:
/vault/mcp → mcpvault (Obsidian vault)
/healthz → liveness + mount listКаждая точка монтирования — это независимая конечная точка MCP. Клиенты регистрируют их по отдельности — агрегации инструментов нет, поэтому нет ни коллизий имён, ни необходимости поддерживать схему пространств имён.
Намеренно не предусмотрено открытие порта за пределами localhost. Поставьте перед ним туннель, обратный прокси или ничего; Portcall по умолчанию привязывается к 127.0.0.1, и ему всё равно, что находится выше по потоку.
Related MCP server: mcp-unify
Почему не stdio-мост
Очевидный способ вывести stdio MCP-сервер на HTTP — универсальный мост вроде supergateway. Это работает, но имеет структурную проблему: каждый запрос или сессия порождает дочерний процесс, и корректно собирать эти дочерние процессы легко напутать.
В частности, в supergateway дочерний процесс освобождается только из transport.onclose или transport.onerror. Никто не вызывает transport.close() при нормально завершённом запросе без сохранения состояния, поэтому onclose никогда не срабатывает, и каждый успешный запрос приводит к утечке процесса — очищаются только неудачные запросы. Его режим с сохранением состояния не даёт утечек (таймер сессии закрывает транспорт), но вместо этого он удерживает долгоживущий поток SSE GET, с которым некоторые прокси справляются плохо.
Обёртывание команды в npx усугубляет ситуацию: npx порождает настоящий сервер, поэтому при убийстве дочернего процесса убивается обёртка, а внучатый процесс остаётся сиротой.
Ответ Portcall — не порождать ничего, когда в этом нет необходимости.
Адаптеры
Адаптер | Для чего | Как |
| Серверы, которые экспортируют фабрику как библиотеку | Вызывает фабрику в том же процессе. Дочернего процесса не существует, поэтому собирать некого. |
| Сторонние серверы, которые говорят только на stdio | Пока не реализовано. Когда появится, должен освобождать дочерний процесс при нормальном завершении, а не только при ошибке, и обрабатывать завершение групп процессов для команд-обёрток. |
inProcess — интересный случай, который охватывает серверы, заслуживающие самостоятельного хостинга. Например, @bitbonsai/mcpvault экспортирует createServer(vaultPath, options), возвращающий Server из MCP SDK v2; его запись bin — это, по сути, serveStdio(() => createServer(...)). Portcall вызывает ту же функцию напрямую и полностью пропускает stdio.
SDK создаёт новый экземпляр сервера для каждого запроса и уничтожает его вместе с запросом, поэтому нет состояния сеанса, которое могло бы истечь по таймауту, и нет накапливающихся дескрипторов.
Версии протокола
Portcall построен на @modelcontextprotocol/server v2, который обслуживает две эпохи протокола из одного обработчика:
Современная (
2026-07-28) — конверт на каждый запрос. Запросы несут заголовкиMCP-Protocol-Version,Mcp-Methodи (для вызовов инструментов)Mcp-Name, а также блокparams._meta. Нет рукопожатияinitializeи долгоживущей сессии; обнаружение — черезserver/discover.Устаревшая (эпоха 2025) — по умолчанию обслуживается без сохранения состояния.
GETиDELETE(операции сеанса 2025) отвечают405. УстановитеPORTCALL_MODERN_ONLY=true, чтобы полностью отклонять устаревший трафик.
Поскольку современная эпоха работает на уровне запросов, нет постоянного потока SSE, который нужно держать открытым. Это обходит класс проблем с прокси: некоторые обратные прокси удерживают заголовки ответа до поступления первого байта тела, что бесконечно задерживает только что открытый, но молчащий поток SSE. Для тех потоков, которые всё же возникают, PORTCALL_KEEPALIVE_MS управляет интервалом комментариев SSE; уменьшите его, если впередистоящий прокси буферизует.
Конфигурация
Все значения, зависящие от хоста, берутся из окружения.
Переменная | По умолчанию | Назначение |
| (обязательно) | Абсолютный путь к хранилищу Obsidian для обслуживания |
|
| TCP-порт |
|
| Интерфейс привязки |
| (не задан) | Статический bearer-токен. Если не задан — аутентификация не требуется |
| (не задан) | Также смонтировать указанный плагин в |
| (не задан) | Обслуживать все точки монтирования в |
|
| Интервал keepalive SSE; |
|
| Отклонять запросы эпохи 2025 вместо их обслуживания |
PORTCALL_TOKEN защищает каждую точку монтирования с помощью Authorization: Bearer <token>. Обратите внимание, что некоторые MCP-клиенты — в том числе пользовательский интерфейс коннектора Claude — не позволяют задать заголовок запроса, поэтому для них токен придётся проверять выше по потоку (или вообще не использовать, контролируя доступ на сетевом уровне).
PORTCALL_PATH_PREFIX — это запасной вариант именно для таких клиентов: он перемещает все точки монтирования в выбранный вами сегмент, так что /vault/mcp становится /<prefix>/vault/mcp, и сам URL несёт в себе секрет. Из этого следует два момента, и сервер обеспечивает оба:
Ответы
404содержат толькоnot_found. Они никогда не перечисляют, что смонтировано.Список точек монтирования перемещается из публичного
/healthzв/<prefix>/healthz. Голый/healthzпо-прежнему отвечает, поэтому проверки живости продолжают работать, но не раскрывают никаких путей.
Относитесь к префиксу пути как к более слабой защите, чем заголовок. URL-адреса попадают в журналы доступа прокси, отчёты о сбоях и в любые записи, фиксирующие назначение, а утёкший префикс даёт тот же доступ, что и утёкший токен. Это поднимает планку — но это не аутентификация.
Какие плагины монтируются и где, объявляется в plugins.config.ts.
Запуск
Требуется Node 24 (см. .nvmrc).
npm install
npm run build
cp .env.example .env # then set PORTCALL_VAULT_PATH
npm startИ npm start, и npm run dev загружают .env, если он присутствует, и запускаются без него, если его нет, поэтому демон может вместо этого внедрять окружение напрямую. Уже заданные переменные окружения не переопределяются.
npm run dev запускает точку входа через tsx в режиме watch. Демон должен запускать собранный результат, а не tsx.
Проверьте, что он работает:
curl -s localhost:7100/healthzТесты
npm test # builds, then runs unit and integration tests
npm run typecheckНет тестовых зависимостей: раннер — node:test, а TypeScript загружает tsx (он уже нужен для npm run dev).
Интеграционные тесты — «чёрный ящик». Они запускают собранный сервер с одноразовым хранилищем на эфемерном порту и обращаются к нему по реальному HTTP, поэтому проверяют тот же артефакт, который запускает демон: маршрутизацию, алиас /mcp, bearer-аутентификацию и обе эпохи протокола. Модульные тесты покрывают разрешение точек монтирования и проверку bearer-токена, где тихая регрессия выглядела бы как мёртвый клиент, а не ошибка.
Структура
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Лицензия
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