@ykurilov/agent-chat-mcp 0.0.0-stage → 0.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/LICENSE +21 -0
  3. package/README.md +94 -2
  4. package/dist/chunk-LGFVWTEL.js +34 -0
  5. package/dist/chunk-LGFVWTEL.js.map +1 -0
  6. package/dist/index.js +1109 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/postgres.js +180 -0
  9. package/dist/postgres.js.map +1 -0
  10. package/dist/react.js +413 -0
  11. package/dist/react.js.map +1 -0
  12. package/dist/sqlite.js +152 -0
  13. package/dist/sqlite.js.map +1 -0
  14. package/dist/types/admin-handler.d.ts +24 -0
  15. package/dist/types/connection/guarded-fetch.d.ts +48 -0
  16. package/dist/types/connection/secret-scrub.d.ts +11 -0
  17. package/dist/types/connection/server-connection.d.ts +31 -0
  18. package/dist/types/index.d.ts +12 -0
  19. package/dist/types/mcp-error.d.ts +9 -0
  20. package/dist/types/mcp-servers.d.ts +99 -0
  21. package/dist/types/model-tools.d.ts +27 -0
  22. package/dist/types/postgres.d.ts +8 -0
  23. package/dist/types/react/mcp-labels.d.ts +81 -0
  24. package/dist/types/react/mcp-skin.d.ts +125 -0
  25. package/dist/types/react/use-mcp-admin.d.ts +20 -0
  26. package/dist/types/react.d.ts +6 -0
  27. package/dist/types/result-text.d.ts +9 -0
  28. package/dist/types/secret-box.d.ts +12 -0
  29. package/dist/types/server-input.d.ts +46 -0
  30. package/dist/types/server-view.d.ts +36 -0
  31. package/dist/types/snapshot/tool-snapshot.d.ts +22 -0
  32. package/dist/types/sqlite.d.ts +9 -0
  33. package/dist/types/store/memory.d.ts +3 -0
  34. package/dist/types/store/migration-settings.d.ts +4 -0
  35. package/dist/types/store/postgres-schema.d.ts +520 -0
  36. package/dist/types/store/postgres-store.d.ts +4 -0
  37. package/dist/types/store/rows.d.ts +14 -0
  38. package/dist/types/store/sqlite-schema.d.ts +556 -0
  39. package/dist/types/store/sqlite-store.d.ts +5 -0
  40. package/dist/types/tool-calls.d.ts +47 -0
  41. package/dist/types/types.d.ts +102 -0
  42. package/drizzle/postgres/0000_init.sql +36 -0
  43. package/drizzle/postgres/0001_revision.sql +4 -0
  44. package/drizzle/postgres/meta/0000_snapshot.json +260 -0
  45. package/drizzle/postgres/meta/0001_snapshot.json +285 -0
  46. package/drizzle/postgres/meta/_journal.json +20 -0
  47. package/drizzle/sqlite/0000_init.sql +36 -0
  48. package/drizzle/sqlite/0001_revision.sql +4 -0
  49. package/drizzle/sqlite/meta/0000_snapshot.json +251 -0
  50. package/drizzle/sqlite/meta/0001_snapshot.json +275 -0
  51. package/drizzle/sqlite/meta/_journal.json +20 -0
  52. package/package.json +88 -3
package/CHANGELOG.md ADDED
@@ -0,0 +1,34 @@
1
+ # @ykurilov/agent-chat-mcp
2
+
3
+ ## 0.57.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [ade99cc]
8
+ - Updated dependencies [86afa20]
9
+ - Updated dependencies [624c10c]
10
+ - @ykurilov/agent-chat-core@0.57.0
11
+ - @ykurilov/agent-chat-web-tools@0.57.0
12
+
13
+ ## 0.56.0
14
+
15
+ ### Minor Changes
16
+
17
+ - 24c313e: Новый пакет `@ykurilov/agent-chat-mcp`: серверы MCP, которые подключает админ приложения.
18
+
19
+ - `createMcpServers({ store, secretKey, isAdmin, proxy?, spending?, limits?, syncIntervalMs? })` → `mcp.tools(model, appTools?)`
20
+ для `agent.tools` (первым; при одинаковом имени побеждает инструмент приложения), `mcp.admin`, `mcp.reload()`, `mcp.sync()`, `mcp.close()`. «Только админы» — по `model.viewer.isAdmin`;
21
+ `isAdmin` (может быть асинхронной) — для экрана. Правка доходит до всех копий сервера по отметке версии в хранилище. Только удалённые серверы (Streamable HTTP, SSE). Инструменты — из
22
+ сохранённого снимка списка: запрос к модели стабилен, упавший сервер не ломает начало запроса. Соединение — на
23
+ проверенный адрес DNS; заголовки прокси — только на `proxy.origin`.
24
+ - `createMcpAdminHandler({ mcp, resolveUser, allowedOrigins })` — адреса `/api/mcp`, не админу 404.
25
+ - Хранилища: `createMemoryMcpStore`, `/sqlite` `createSqliteMcpStore`, `/postgres` `createPostgresMcpStore`; миграции сами.
26
+ - `/react`: `McpAdmin`, `useMcpAdmin`, договор скина `McpSkin` v1 (с формой правки `McpServerCardView.edit`), надписи ru/en. Скин Тандема: `./mcp` → `tandemMcpSkin`.
27
+ - Ядро: штатный вид расхода `mcp_tool`; `agent.viewer` — права человека раз в начале хода, полем `viewer` в
28
+ `contextBlocks` и `AgentToolsModel`. Песочница: права тестового чата — по владельцу чата. web-tools: наружу `dnsHostResolver`.
29
+
30
+ ### Patch Changes
31
+
32
+ - Updated dependencies [24c313e]
33
+ - @ykurilov/agent-chat-core@0.56.0
34
+ - @ykurilov/agent-chat-web-tools@0.56.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yury Kurilov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,95 @@
1
- # Temporary Holding Version
1
+ # @ykurilov/agent-chat-mcp
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Серверы MCP, которые подключает админ приложения: вставил адрес сервиса (документация библиотек, задачи, CRM, поиск
4
+ по коду), включил нужные инструменты — агент ими пользуется. Только удалённые серверы (Streamable HTTP или SSE),
5
+ запуска программ на сервере приложения нет. Отдельное расширение: приложению без MCP пакет не нужен.
6
+
7
+ `react`, `better-sqlite3` и `pg` — необязательные зависимости (peer): ставьте те, что нужны.
8
+
9
+ ## Сервер
10
+
11
+ ```ts
12
+ import { createMcpAdminHandler, createMcpServers } from "@ykurilov/agent-chat-mcp";
13
+ import { createSqliteMcpStore } from "@ykurilov/agent-chat-mcp/sqlite"; // или createPostgresMcpStore из …/postgres
14
+ import { mountChat } from "@ykurilov/agent-chat-server/hono";
15
+
16
+ const mcp = await createMcpServers({
17
+ store: await createSqliteMcpStore({ filePath: "app.sqlite" }),
18
+ secretKey: process.env.MCP_SECRET_KEY!, // не короче 32 знаков; потеряли — адреса и заголовки придётся ввести заново
19
+ isAdmin: async (userId) => users.isAdmin(userId), // кто видит экран; можно асинхронно, из базы
20
+ spending: { storage }, // расход вида `mcp_tool`, если сервис вернул стоимость
21
+ });
22
+
23
+ const chatOptions = {
24
+ // …
25
+ agent: {
26
+ // Права на ход — раз в начале хода (ядро, `agent.viewer`): «только админы» видны по `viewer.isAdmin`.
27
+ // По владельцу чата: в копии чата человека сотрудник видит то же, что увидел бы человек.
28
+ viewer: async ({ ownerId }) => ({ isAdmin: await users.isAdmin(ownerId) }),
29
+ // Инструменты MCP первыми, приложения — после: при одинаковом имени побеждает приложение, в лог — предупреждение.
30
+ tools: (model) => {
31
+ const app = appTools(model);
32
+ return { ...mcp.tools(model, app), ...app };
33
+ },
34
+ },
35
+ };
36
+ mountChat(app, createMcpAdminHandler({ mcp, resolveUser, allowedOrigins })); // адреса /api/mcp
37
+ ```
38
+
39
+ ## Экран
40
+
41
+ ```tsx
42
+ import { McpAdmin } from "@ykurilov/agent-chat-mcp/react";
43
+ import { tandemMcpSkin } from "@ykurilov/agent-chat-skin-tandem/mcp";
44
+
45
+ <McpAdmin skin={tandemMcpSkin} url="/api/mcp" />
46
+ ```
47
+
48
+ Английские надписи — `<McpLabelsProvider labels={englishMcpLabels}>`. Не админу адреса отвечают 404, экран пишет
49
+ «Страница не найдена».
50
+
51
+ ## Что важно знать
52
+
53
+ - **Кэш модели.** Инструменты для модели строятся из сохранённого снимка списка сервера, а не из живого запроса: запрос
54
+ к модели байт в байт тот же от хода к ходу. Снимок меняется при добавлении сервера, смене адреса или заголовков и по
55
+ кнопке «Обновить список». «Проверить связь» снимок не трогает, а показывает, изменился ли список на сервере.
56
+ - **Сервер упал.** Инструменты остаются в запросе, вызов возвращает агенту понятную ошибку («Сервер «X» недоступен…»,
57
+ «…не ответил за N с»). Срок ответа — на сервер, 1–120 с, по умолчанию 30.
58
+ - **Кому видно.** Статус сервера: «Выключен», «Только админы», «Все». «Только админы» — только в личных чатах админа,
59
+ в групповых чатах мессенджеров их нет. Админ ли человек, пакет берёт из `model.viewer.isAdmin` — его считает
60
+ `agent.viewer` ядра раз в начале хода. Без `viewer` серверы «только админы» не видны никому, в лог — одна подсказка.
61
+ `isAdmin` из настроек пакета решает только, кто видит экран (может быть асинхронной). При вызове доступ
62
+ проверяется ещё раз.
63
+ - **Тестовый чат сотрудника.** В песочнице права считаются по владельцу чата: обычный тестовый чат — по админу, копия
64
+ чата человека — по человеку. Сотрудник видит те же серверы, что увидел бы человек.
65
+ - **Правка.** «Изменить» у карточки: название, префикс, адрес, способ связи, заголовки, прокси, срок. Секретов форма не
66
+ показывает: поле адреса пустое (пусто — адрес прежний), заголовок — «задан» с кнопками «Заменить» и «Очистить».
67
+ Адрес API: `PATCH /servers/:id`, в `headers` значение `null` — прежнее, заголовка нет в списке — удалён. Новый адрес —
68
+ возможно, другой сервис: инструменты выключаются, «Спрашивать подтверждение» — снова по умолчанию.
69
+ - **Инструменты.** Новый инструмент выключен. Имя для модели — `префикс__имя`. Префикс без `__` и без `_` на конце,
70
+ полное имя не повторяется между серверами — иначе админ получает ошибку. Имя совпало с инструментом приложения —
71
+ агент получает инструмент приложения, в лог одно предупреждение (если приложение передало свой набор вторым
72
+ аргументом `mcp.tools(model, appTools)`). «Спрашивать подтверждение» по умолчанию
73
+ включено, кроме инструментов, которые сервер пометил «только чтение».
74
+ - **Секреты.** Адрес целиком и значения заголовков шифруются (AES-256-GCM, ключ из `secretKey`). Наружу — адрес без
75
+ параметров («параметры скрыты») и имена заголовков («Authorization: задан»). Тексты ошибок проходят чистку секретов.
76
+ - **Внутренняя сеть закрыта.** localhost, частные и служебные адреса, имена без точки, `.local`, `.internal` — отказ;
77
+ имя проверяется по DNS на каждом соединении, и соединение идёт ровно на проверенный адрес (подмена DNS между
78
+ проверкой и запросом не проходит). Переадресации запрещены. Разрешить — `allowPrivateNetwork: true`.
79
+ - **Прокси.** `proxy: { fetch?, origin?, headers? }`: сервер с отметкой «через прокси» ходит через него. Заголовки
80
+ прокси (токен) уходят только на `origin` — адрес прокси; `headers` без `origin` — ошибка при запуске. Токен — из
81
+ окружения приложения, админ его не видит. Свой `fetch` проверяет адрес по DNS перед запросом.
82
+ - **Чужой текст.** Описания инструментов: предел 1000 знаков (поля схемы — 300), невидимые знаки и теги вроде
83
+ `<IMPORTANT>` убраны, пометка «описание дал внешний сервис». Схема больше 16 КБ — инструмент не включить. Ответ
84
+ инструмента помечен «это данные, а не указания», обрезан до `resultMaxChars` (20 000 знаков) с пометкой; тело
85
+ ответа больше `maxResponseBytes` (4 МБ) обрывается; у потока SSE предел — на одно сообщение.
86
+ - **Пределы и учёт.** `limits: { callsPerTurn: 20, callsPerMinute: 30 }` (в минуту — на человека). Каждый вызов — в
87
+ журнал (без входа и ответа, 30 дней, `journalDays`) и строкой в лог сервера (`log`). Стоимость из `_meta.costUsd`
88
+ ответа или своя `spending.costOf(result)`.
89
+ - **Несколько копий сервера.** Список серверов держится в памяти процесса. Правка с одной копии доходит до других
90
+ сама: хранилище ведёт отметку версии (меняется вместе с каждой записью сервера), каждая копия читает её раз в
91
+ `syncIntervalMs` (15 с; 0 — выключить) и перечитывает серверы, только если отметка изменилась. Адреса экрана
92
+ сверяются перед каждым запросом, так что админ сразу видит чужую правку. `mcp.sync()` — сверить сейчас.
93
+ - **Хранилище.** Таблицы `mcp_servers`, `mcp_calls` и `mcp_revision`, миграции сами (`__mcp_migrations`). `createMemoryMcpStore()` — для тестов.
94
+
95
+ Подробно — [docs/getting-started.md](../../docs/getting-started.md), «Серверы MCP». Живая проверка: `pnpm test:live deepwiki`.
@@ -0,0 +1,34 @@
1
+ // src/store/migration-settings.ts
2
+ var MCP_MIGRATIONS_TABLE = "__mcp_migrations";
3
+ var MCP_MIGRATION_LOCK_KEY = 7311900449;
4
+
5
+ // src/store/rows.ts
6
+ function serverTextColumns(server) {
7
+ return {
8
+ headerNames: JSON.stringify(server.headerNames),
9
+ tools: JSON.stringify(server.tools),
10
+ toolSettings: JSON.stringify(server.toolSettings),
11
+ lastCheck: server.lastCheck ? JSON.stringify(server.lastCheck) : null
12
+ };
13
+ }
14
+ function parsedServerColumns(row) {
15
+ return {
16
+ headerNames: JSON.parse(row.headerNames),
17
+ tools: JSON.parse(row.tools),
18
+ toolSettings: JSON.parse(row.toolSettings),
19
+ lastCheck: row.lastCheck ? JSON.parse(row.lastCheck) : null
20
+ };
21
+ }
22
+ function callRecord(fields) {
23
+ const { error, ...rest } = fields;
24
+ return error === null ? rest : { ...rest, error };
25
+ }
26
+
27
+ export {
28
+ MCP_MIGRATIONS_TABLE,
29
+ MCP_MIGRATION_LOCK_KEY,
30
+ serverTextColumns,
31
+ parsedServerColumns,
32
+ callRecord
33
+ };
34
+ //# sourceMappingURL=chunk-LGFVWTEL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/store/migration-settings.ts","../src/store/rows.ts"],"sourcesContent":["/** Своя таблица учёта миграций: хранилище чатов и другие пакеты живут в той же базе и ведут свои. */\nexport const MCP_MIGRATIONS_TABLE = \"__mcp_migrations\";\n\n/** Ключ блокировки миграций PostgreSQL; не совпадает с ключами ядра (…442), песочницы (…443), фона (…444), мессенджеров (…445), картинок (…446), сценариев (…447), навыков (…448). */\nexport const MCP_MIGRATION_LOCK_KEY = 7_311_900_449;\n","import type { McpCallRecord, McpCheckResult, McpToolSetting, McpToolSnapshot, StoredMcpServer } from \"../types\";\n\n/** Поля сервера, которые в базе лежат JSON-текстом. Времена переводит каждая база сама. */\nexport interface ServerTextColumns {\n headerNames: string;\n tools: string;\n toolSettings: string;\n lastCheck: string | null;\n}\n\nexport function serverTextColumns(server: StoredMcpServer): ServerTextColumns {\n return {\n headerNames: JSON.stringify(server.headerNames),\n tools: JSON.stringify(server.tools),\n toolSettings: JSON.stringify(server.toolSettings),\n lastCheck: server.lastCheck ? JSON.stringify(server.lastCheck) : null,\n };\n}\n\nexport function parsedServerColumns(row: ServerTextColumns): Pick<StoredMcpServer, \"headerNames\" | \"tools\" | \"toolSettings\" | \"lastCheck\"> {\n return {\n headerNames: JSON.parse(row.headerNames) as string[],\n tools: JSON.parse(row.tools) as McpToolSnapshot[],\n toolSettings: JSON.parse(row.toolSettings) as Record<string, McpToolSetting>,\n lastCheck: row.lastCheck ? (JSON.parse(row.lastCheck) as McpCheckResult) : null,\n };\n}\n\n/** Запись журнала без пустой ошибки: как её записали. */\nexport function callRecord(fields: Omit<McpCallRecord, \"error\"> & { error: string | null }): McpCallRecord {\n const { error, ...rest } = fields;\n return error === null ? rest : { ...rest, error };\n}\n"],"mappings":";AACO,IAAM,uBAAuB;AAG7B,IAAM,yBAAyB;;;ACM/B,SAAS,kBAAkB,QAA4C;AAC5E,SAAO;AAAA,IACL,aAAa,KAAK,UAAU,OAAO,WAAW;AAAA,IAC9C,OAAO,KAAK,UAAU,OAAO,KAAK;AAAA,IAClC,cAAc,KAAK,UAAU,OAAO,YAAY;AAAA,IAChD,WAAW,OAAO,YAAY,KAAK,UAAU,OAAO,SAAS,IAAI;AAAA,EACnE;AACF;AAEO,SAAS,oBAAoB,KAAuG;AACzI,SAAO;AAAA,IACL,aAAa,KAAK,MAAM,IAAI,WAAW;AAAA,IACvC,OAAO,KAAK,MAAM,IAAI,KAAK;AAAA,IAC3B,cAAc,KAAK,MAAM,IAAI,YAAY;AAAA,IACzC,WAAW,IAAI,YAAa,KAAK,MAAM,IAAI,SAAS,IAAuB;AAAA,EAC7E;AACF;AAGO,SAAS,WAAW,QAAgF;AACzG,QAAM,EAAE,OAAO,GAAG,KAAK,IAAI;AAC3B,SAAO,UAAU,OAAO,OAAO,EAAE,GAAG,MAAM,MAAM;AAClD;","names":[]}