plaid-mcp
plaid-mcp
Постоянный MCP-сервер Plaid для ИИ-ассистента (Elowen), работающего в эфемерном контейнере.
plaid-mcp — это долгоживущий, размещенный извне сервис, который хранит секретный ключ Plaid и зашифрованные токены доступа для каждого связанного финансового учреждения. Ассистент вызывает инструменты mcp__plaid__* во время выполнения; он никогда не видит необработанные токены доступа, только непрозрачные значения item_id и account_id, которые Plaid уже считает публичными.
Elowen (ephemeral container)
└─ calls mcp__plaid__* tools
└─ plaid-mcp (persistent, nanoclaw-hosted)
├─ Plaid SDK + PLAID_SECRET (never leaves this service)
├─ access_token store (SQLite, AES-256-GCM at rest)
└─ /link/start, /link/callback (HTTPS, browser-facing)
└─ Plaid REST API / Plaid Link JSИнтерфейсы
Один процесс Node.js предоставляет два полностью раздельных интерфейса:
MCP-сервер. Либо
stdio(агент запускает этот бинарный файл как подпроцесс), либоhttp(потоковый HTTP по адресуPOST /mcp, защищенный токеном). Выбирается с помощьюMCP_TRANSPORT. Для описанного выше сценария семейного бюджета лучше использоватьhttp, чтобы парк эфемерных контейнеров агентов мог использовать один постоянный сервер.HTTPS-мини-приложение для привязки по адресу
/link/*. Используется только во время однократного процесса привязки банка — пользователь открывает URL, предоставленный ассистентом, входит в свой банк через Plaid Link, и всё готово. После этого браузер для данного учреждения больше не потребуется.
Related MCP server: plaid-mcp
Инструменты MCP
Инструмент | Что он делает |
| Все связанные элементы (Items) с флагом состояния |
| Кэшированный список счетов (тип, подтип, маска, последний баланс) для одного или всех учреждений. |
| Балансы в реальном времени через |
| Транзакции за период, ~250 на страницу, непрозрачный курсор пагинации. |
| Поиск транзакций с фильтрацией на стороне сервера. Возвращает компактные строки. |
| Предварительно агрегированные ежемесячные итоги, сгруппированные по |
| Снимок позиций (тикер, количество, рыночная стоимость, себестоимость). |
| Покупки/продажи/дивиденды за период. |
| Процентные ставки/выписки по кредитным картам, студенческие кредиты, детали ипотеки. |
| Возвращает |
| Опрос до получения статуса |
| Отзыв элемента Plaid и удаление локального токена. |
Все ответы инструментов представляют собой JSON внутри одного элемента контента text (работает во всех клиентах MCP, включая те, которые не поддерживают structuredContent).
Однократный процесс привязки
Elowen вызывает
initiate_link({ institution_hint: "Chase" }). Сервер:вызывает
/link/token/createв Plaid,сохраняет строку в
link_sessions(статусpending),возвращает
{ url: "https://<LINK_BASE_URL>/link/start?s=<uuid>&sig=<hmac>", session_id, expires_at }.
Elowen отправляет URL пользователю.
Пользователь открывает его в браузере. Страница загружает Plaid Link JS с официального CDN с этим
link_tokenи отображает кнопку "Open Plaid Link".onSuccessв Plaid Link отправляет POST-запрос{ public_token, institution }вместе с подписанным ID сессии на/link/callback./link/callbackобмениваетpublic_tokenнаaccess_token+item_id, шифрует токен доступа с помощью AES-256-GCM, сохраняет его и помечает сессию какsucceeded.Elowen опрашивает
link_status(session_id), видитsucceededсitem_idи продолжает работу.
Параметры подписанного URL (s, sig) используют HMAC-SHA256 с ключом LINK_SESSION_SECRET. Строка в БД является источником истины — HMAC просто дешево отсеивает некорректные запросы до обращения к SQLite.
Конфигурация
Все настройки задаются через переменные окружения (загружаются из .env).
Переменная | Обязательно | По умолчанию | Описание | ||
| Да | — | Из панели управления Plaid | ||
| Да | — | Из панели управления Plaid. Никогда не покидает этот сервис. | ||
| Нет |
|
|
|
|
| Нет |
| Зафиксированная версия API | ||
| Нет |
| Список через запятую. Обычно: | ||
| Нет |
| Список кодов стран ISO через запятую | ||
| Нет |
| Стабильный | ||
| Да | — | 32 байта в hex ( | ||
| Да | — | ≥ 32 байта в hex. Ключ HMAC для подписанных URL привязки. | ||
| Нет |
| Время жизни сессии привязки | ||
| Да | — | Публичный HTTPS URL, к которому обратится браузер (например, | ||
| Нет |
| HTTP-порт. TLS терминируется выше по цепочке в nanoclaw. | ||
| Нет | — | Если задан, защищает маршруты интроспекции | ||
| Нет |
|
|
| |
| Да, если | — | Bearer-токен, требуемый для | ||
| Нет |
| Путь к SQLite. Примонтируйте сюда постоянный том. | ||
| Нет |
| Уровень логирования Pino. Все логи идут в stderr. |
Генерация секретов:
make keysХранение данных
SQLite (better-sqlite3) по пути $DB_PATH. Важны две таблицы:
items—item_id(PK), зашифрованныйaccess_token_blob(BLOB), имя/ID учреждения, статус, срок действия согласия.link_sessions— короткоживущие, удаляются автоматически после истеченияexpires_atи во время фоновой очистки каждые 60 секунд.
Токены доступа хранятся в формате [1-байт версия][12-байт IV][16-байт GCM tag][N-байт шифротекст]. Дешифрование завершается ошибкой, если GCM-тег не проходит проверку.
Модель безопасности
HTTP-транспорт MCP требует
Authorization: Bearer $MCP_BEARER_TOKENдля каждого запроса. Без этого парк агентов открыл бы доступ к каждому связанному банковскому счету всему интернету.Маршруты
/link/*, доступные из браузера, подписаны (HMAC) и привязаны к короткоживущей сессии в БД.Ожидается, что TLS терминируется выше по цепочке (в nanoclaw / Caddy / на вашем пограничном узле). Внутри контейнер работает по обычному HTTP; открывайте его только через прокси.
Каждый токен Plaid зашифрован при хранении. Даже имея файл SQLite, злоумышленник без
PLAID_ENCRYPTION_KEYне сможет использовать токены.Инструменты MCP никогда не возвращают токены доступа агенту. Через границу MCP проходят только непрозрачные строки
item_id/account_id.
Локальная разработка
npm install
make setup # creates .env from env.example
make keys >> .env # append fresh PLAID_ENCRYPTION_KEY / LINK_SESSION_SECRET / MCP_BEARER_TOKEN
# edit .env: PLAID_CLIENT_ID, PLAID_SECRET, LINK_BASE_URL
npm run dev # tsx with hot reloadДля тестирования привязки локально вам понадобится HTTPS-туннель (Plaid Link onSuccess не сработает с http://localhost). cloudflared, ngrok или настоящий обратный прокси Caddy — всё это подойдет; любое публичное доменное имя, которое они вам дадут, нужно указать в LINK_BASE_URL.
Docker
make build
make up
make logsФайл compose монтирует ./data:/data, чтобы БД SQLite сохранялась после перезагрузок. В развертывании nanoclaw замените это монтирование на управляемый кластером постоянный том.
Подключение агента к размещенному экземпляру
В конфигурации клиента MCP контейнера агента:
{
"mcpServers": {
"plaid": {
"url": "https://plaid-mcp.your-domain.example/mcp",
"headers": {
"Authorization": "Bearer <MCP_BEARER_TOKEN>"
}
}
}
}Агент получает bearer-токен через любой механизм внедрения секретов, который nanoclaw уже использует для других секретов агента. Он никогда не видит PLAID_SECRET или какой-либо токен доступа.
Лицензия
Внутренняя.
This server cannot be deployed
Maintenance
Related MCP Connectors
Personal finance for AI agents — onboard, import statements, categorize & budget over MCP.
An MCP server that provides read access to your cloud storage providers, bank accounts and more.
- JustOnceOAuthai.justonce
Persistent memory for AI assistants — one shared, OAuth-secured vault for every MCP client.
- BankSyncOAuthio.banksync
Connect AI agents to bank accounts, transactions, balances, and investments.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceSelf-hosted MCP server enabling Claude to query bank accounts, balances, and transactions through Plaid with OAuth and TLS.-
- AlicenseNot gradedqualityDmaintenanceA local MCP server that provides read-only SQL access to financial accounts via Plaid, enabling natural language queries about transactions, balances, and holdings.MIT
- FlicenseAqualityCmaintenancePersonal finance MCP server that integrates Plaid bank data with local SQLite memory for conversational budgeting, goal tracking, and transaction management.15-
- AlicenseNot gradedqualityBmaintenanceMCP server that exposes banking data (connections, accounts, balances, transactions) and agent skills, allowing AI agents to query and refresh financial data via stdio.1396Apache 2.0