fintablo-mcp

fintablo-mcp

Read-only MCP server that computes financial answers, such as work-in-progress (NPV), from the Fintablo API using natural language queries.

Category
访问服务器

README

fintablo-mcp

Только для чтения MCP-сервер поверх API Fintablo. Задайте финансовый вопрос на естественном языке — сервер вычисляет ответ в коде на основе актуальных данных API: без ручных выгрузок и устаревших срезов.

Главный инструмент: get_nzp — незавершённое производство (НЗП) по сделке, восстановленное из примитивов API и сверенное с собственной цифрой Fintablo.

Только чтение по умолчанию. В клиенте нет ни одного метода записи. Fintablo не получает от этого сервера никаких изменений — независимо от того, о чём попросили модель.

Формула НЗП

Расходы привязываются к этапам сделки, а не к сделке целиком. Открытые этапы (без даты акта) → НЗП; этапы, закрытые актом, → списаны. Для каждого открытого этапа — четыре слоя:

НЗП = Σ по открытым этапам [ операции + обязательства + зарплата + зарплатные налоги ]
Слой Источник Нюанс
операции прямые списания по этапу (/v1/transaction) сумма берётся из поля value, за вычетом НДС по строке (nds — это процент)
обязательства все обязательства по этапу (/v1/obligation) считаются целиком, даже если ещё не подписаны актом; поле amount уже без НДС
зарплата сдельная зарплата по этапу (/v1/deal-salary) сумма из поля value
зарплатные налоги НДФЛ + взносы оценка — пропорционально зарплате (см. ниже)

Выручка и «списано» сходятся к 100 %, итог НЗП — к ~98–99 %, остаток приходится целиком на слой зарплатных налогов.

Как расходы привязаны к этапам

В API сделка содержит массив stages[], у каждого этапа свой id, actDate и amount (выручка без НДС). У самих расходов нет отдельного поля stageId — они привязываются через поле dealId.

  • Операции (/v1/transaction): документация прямо говорит, что при прикреплении операции к этапу в dealId передаётся идентификатор этапа. Поэтому операции запрашиваются по id этапа (?dealId=<stageId>).
  • Обязательства и сдельная зарплата (/v1/obligation, /v1/deal-salary): здесь документация описывает dealId только как «идентификатор сделки», без оговорки про этап. Значит, Fintablo может хранить там либо id сделки, либо id этапа. Чтобы результат был верным в любом случае, сервер запрашивает эти слои по всем кандидатам сразу — id сделки + id всех этапов — и убирает дубликаты по id записи. Каждая запись затем относится к этапу по своему собственному dealId: если он совпадает с этапом — к этому этапу; если это id сделки целиком («на уровне сделки») — к первому открытому этапу, чтобы попасть в НЗП ровно один раз.

Сделка без этапов считается как единый расчётный объект (по собственным id/actDate/amount).

Известная неопределённость — как распознать неверный результат

⚠️ Документация Fintablo гарантирует привязку к этапу через dealId только для операций ДДС. Для обязательств и сдельной зарплаты поведение в спецификации не зафиксировано, и проверить его можно только на живой сделке с этапами. Сервер написан так, чтобы быть корректным при любом из вариантов (см. выше), но если цифра НЗП выглядит не так, как ожидается, в первую очередь проверьте именно эти два слоя.

На что смотреть:

  • Обязательства или зарплата «потерялись». Если по многоэтапной сделке вы видите в Fintablo обязательства/сдельную зарплату, а в НЗП соответствующий слой нулевой или заметно меньше — сообщите об этом: вероятно, привязка dealId устроена иначе, чем предполагалось.
  • Обязательство «уровня сделки» попало не на тот этап. Обязательство, привязанное к сделке целиком (а не к конкретному этапу), относится к первому открытому этапу. В разбивке по этапам (perStage) оно окажется на этом этапе — это намеренное упрощение. На итоговую сумму НЗП это не влияет (запись считается один раз), но распределение по этапам может выглядеть неожиданно.
  • Зарплата считается только сдельная. Слой зарплаты берётся из /v1/deal-salary (сдельная зарплата, привязанная к сделке). Зарплата, начисленная через Ведомость месяца (/v1/salary), в расчёт НЗП не попадает. Если в производстве есть труд, который проводится не как сдельный, этот слой будет занижен.
  • Зарплатные налоги — всегда оценка. См. раздел «О слое зарплатных налогов»: это коэффициент, а не фактические суммы.

Все перечисленное — вопросы бизнес-логики, а не ошибки в коде. Окончательно закрыть их можно, сверив результат с эталонной цифрой Fintablo на реальной сделке с этапами (см. Golden-тесты).

Инструменты

Инструмент Назначение
get_nzp НЗП по одной сделке по её коду (основной)
list_partners справочник контрагентов
list_partner_groups группы контрагентов
list_categories статьи ОПиУ, с фильтром по pnlType
fintablo_get ограниченный сырой GET для исследования (allowlist путей, лимит размера)

Установка

npm install
cp .env.example .env        # добавьте ваш FINTABLO_TOKEN
npm run dev                 # запуск на stdio (tsx)
npm run inspect             # открыть MCP Inspector
npm test                    # запустить тесты математики

Сборка и подключение в Claude Desktop:

npm run build

Затем добавьте запись из claude_desktop_config.example.json в ваш claude_desktop_config.json (используйте абсолютный путь к dist/index.js).

Контракт API (проверено)

Эндпоинты и имена полей в src/fintablo/client.ts сверены с OpenAPI-спецификацией FinTablo (https://my.fintablo.ru/api/FinTablo-v1-swagger.yaml, она же отрисованная документация на https://my.fintablo.ru/api/docs):

  • Базовый URL: https://api.fintablo.ru, все ресурсы под /v1.
  • Авторизация: заголовок Authorization: Bearer <token>. Лимит — 300 запросов в минуту (клиент делает retry/backoff на 429 и 5xx).
  • Операции живут на /v1/transaction: сумма — value, тип — group (income/outcome/transfer), НДС — nds (процент). Разбитые операции приходят отдельными строками (через parentId), а не вложенным массивом.
  • Пагинация различается: /transactionpage + pageSize (до 1000), /dealpage (по 500), справочники (/partner, /partner-group, /category) не пагинируются.
  • Сделка ищется по name (поля code в API нет; человекочитаемый код вроде 02-26/Б — это имя сделки).
  • Обязательства (/v1/obligation): amount уже без НДС, отдельное поле nds — это сумма НДС. Привязка dealId к этапу спецификацией не гарантирована — см. «Известная неопределённость».
  • Сдельная зарплата (/v1/deal-salary): сумма — value. Не путать с /v1/salary (ведомость месяца — другой формат). Привязка dealId к этапу так же не гарантирована (см. там же).

О слое зарплатных налогов

Слой payrollTax — это оценка: общий коэффициент PAYROLL_TAX_RATE (НДФЛ + взносы), применённый к сумме зарплаты этапа. Реальные эффективные ставки различаются по сотрудникам, и привязать их к конкретному этапу из сырых данных нельзя.

При этом ведомость месяца /v1/salary возвращает фактические tax (НДФЛ) и fee (взносы) по сотруднику за месяц. Это месячные итоги, поэтому для разнесения по сделкам/этапам всё равно нужна пропорция — но их можно использовать, чтобы откалибровать PAYROLL_TAX_RATE по эталонным сделкам.

Golden-тесты

test/nzp.test.ts содержит синтетические проверки плюс TODO на самую ценную работу: записать реальные фикстуры DealData для 11-24/Г и 02-26/Б, затем проверять, что computeNzp(...) совпадает с эталонными цифрами в пределах допуска. Эти две сделки — ваша регрессионная сеть: любое будущее изменение API, ломающее математику, будет поймано.

Открытые вопросы, которые закроют именно эти фикстуры:

  • наследуют ли строки-части разбитой операции group/nds родителя (сейчас по умолчанию outcome);
  • значение PAYROLL_TAX_RATE, при котором итог сходится к ~98–99 %.

Структура

src/
  index.ts              # MCP-сервер: stdio + регистрация инструментов
  fintablo/
    client.ts           # клиент API: авторизация, пагинация, retry/backoff, raw→domain
    types.ts            # доменные типы, от которых зависит математика
  domain/
    nzp.ts              # формула — ЧИСТАЯ, без I/O, покрыта тестами
    vat.ts              # вычет НДС по строке (по проценту)
test/
  nzp.test.ts           # тесты математики + каркас golden-тестов

Лицензия

MIT

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选