Skip to main content
Glama
wilderfield

plaid-mcp

by wilderfield

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 предоставляет два полностью раздельных интерфейса:

  1. MCP-сервер. Либо stdio (агент запускает этот бинарный файл как подпроцесс), либо http (потоковый HTTP по адресу POST /mcp, защищенный токеном). Выбирается с помощью MCP_TRANSPORT. Для описанного выше сценария семейного бюджета лучше использовать http, чтобы парк эфемерных контейнеров агентов мог использовать один постоянный сервер.

  2. HTTPS-мини-приложение для привязки по адресу /link/*. Используется только во время однократного процесса привязки банка — пользователь открывает URL, предоставленный ассистентом, входит в свой банк через Plaid Link, и всё готово. После этого браузер для данного учреждения больше не потребуется.

Related MCP server: plaid-mcp

Инструменты MCP

Инструмент

Что он делает

list_linked_institutions()

Все связанные элементы (Items) с флагом состояния needs_relink (вызывает /item/get для каждого элемента).

list_accounts(item_id?)

Кэшированный список счетов (тип, подтип, маска, последний баланс) для одного или всех учреждений.

get_balances(account_ids?)

Балансы в реальном времени через /accounts/balance/get (платный эндпоинт Plaid).

get_transactions(start_date, end_date, account_ids?, cursor?)

Транзакции за период, ~250 на страницу, непрозрачный курсор пагинации.

search_transactions(query, since?, until?, min_amount?, max_amount?, category?)

Поиск транзакций с фильтрацией на стороне сервера. Возвращает компактные строки.

get_monthly_summary(month, group_by?)

Предварительно агрегированные ежемесячные итоги, сгруппированные по category или merchant. Позволяет экономить контекст LLM.

get_investment_holdings(account_ids?)

Снимок позиций (тикер, количество, рыночная стоимость, себестоимость).

get_investment_transactions(start_date, end_date, account_ids?)

Покупки/продажи/дивиденды за период.

get_liabilities(account_ids?)

Процентные ставки/выписки по кредитным картам, студенческие кредиты, детали ипотеки.

initiate_link(institution_hint?)

Возвращает { url, session_id, expires_at } — передайте URL пользователю.

link_status(session_id)

Опрос до получения статуса succeeded (с новым item_id), failed или expired.

remove_institution(item_id)

Отзыв элемента Plaid и удаление локального токена.

Все ответы инструментов представляют собой JSON внутри одного элемента контента text (работает во всех клиентах MCP, включая те, которые не поддерживают structuredContent).

Однократный процесс привязки

  1. 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 }.

  2. Elowen отправляет URL пользователю.

  3. Пользователь открывает его в браузере. Страница загружает Plaid Link JS с официального CDN с этим link_token и отображает кнопку "Open Plaid Link".

  4. onSuccess в Plaid Link отправляет POST-запрос { public_token, institution } вместе с подписанным ID сессии на /link/callback.

  5. /link/callback обменивает public_token на access_token + item_id, шифрует токен доступа с помощью AES-256-GCM, сохраняет его и помечает сессию как succeeded.

  6. Elowen опрашивает link_status(session_id), видит succeeded с item_id и продолжает работу.

Параметры подписанного URL (s, sig) используют HMAC-SHA256 с ключом LINK_SESSION_SECRET. Строка в БД является источником истины — HMAC просто дешево отсеивает некорректные запросы до обращения к SQLite.

Конфигурация

Все настройки задаются через переменные окружения (загружаются из .env).

Переменная

Обязательно

По умолчанию

Описание

PLAID_CLIENT_ID

Да

Из панели управления Plaid

PLAID_SECRET

Да

Из панели управления Plaid. Никогда не покидает этот сервис.

PLAID_ENV

Нет

sandbox

sandbox

development

production

PLAID_API_VERSION

Нет

2020-09-14

Зафиксированная версия API

PLAID_PRODUCTS

Нет

transactions

Список через запятую. Обычно: transactions,investments,liabilities

PLAID_COUNTRY_CODES

Нет

US

Список кодов стран ISO через запятую

PLAID_USER_ID

Нет

family-default

Стабильный client_user_id, отправляемый в Plaid

PLAID_ENCRYPTION_KEY

Да

32 байта в hex (openssl rand -hex 32). Ключ AES-256-GCM для хранения токенов.

LINK_SESSION_SECRET

Да

≥ 32 байта в hex. Ключ HMAC для подписанных URL привязки.

LINK_SESSION_TTL_SECONDS

Нет

900

Время жизни сессии привязки

LINK_BASE_URL

Да

Публичный HTTPS URL, к которому обратится браузер (например, https://plaid.example.com)

PORT

Нет

3333

HTTP-порт. TLS терминируется выше по цепочке в nanoclaw.

ADMIN_TOKEN

Нет

Если задан, защищает маршруты интроспекции /link/admin/*

MCP_TRANSPORT

Нет

http

stdio

http

MCP_BEARER_TOKEN

Да, если MCP_TRANSPORT=http

Bearer-токен, требуемый для POST /mcp

DB_PATH

Нет

./data/plaid-mcp.sqlite (Docker: /data/plaid-mcp.sqlite)

Путь к SQLite. Примонтируйте сюда постоянный том.

LOG_LEVEL

Нет

info

Уровень логирования Pino. Все логи идут в stderr.

Генерация секретов:

make keys

Хранение данных

SQLite (better-sqlite3) по пути $DB_PATH. Важны две таблицы:

  • itemsitem_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 или какой-либо токен доступа.

Лицензия

Внутренняя.

Maintenance

ActivityInactive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    Self-hosted MCP server enabling Claude to query bank accounts, balances, and transactions through Plaid with OAuth and TLS.
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    A local MCP server that provides read-only SQL access to financial accounts via Plaid, enabling natural language queries about transactions, balances, and holdings.
    MIT
  • F
    license
    A
    quality
    C
    maintenance
    Personal finance MCP server that integrates Plaid bank data with local SQLite memory for conversational budgeting, goal tracking, and transaction management.
    15
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP server that exposes banking data (connections, accounts, balances, transactions) and agent skills, allowing AI agents to query and refresh financial data via stdio.
    139
    6
    Apache 2.0