teletype-mcp-server 0.1.0 → 0.1.1
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.
- package/.env.example +7 -0
- package/LAUNCHGUIDE.md +51 -0
- package/README-ru.md +49 -11
- package/README.md +68 -30
- package/dist/config.d.ts +4 -0
- package/dist/config.js +17 -0
- package/dist/config.js.map +1 -1
- package/dist/http.js +69 -1
- package/dist/http.js.map +1 -1
- package/dist/landing-page.d.ts +1 -0
- package/dist/landing-page.js +166 -0
- package/dist/landing-page.js.map +1 -0
- package/dist/oauth-page.d.ts +1 -0
- package/dist/oauth-page.js +242 -0
- package/dist/oauth-page.js.map +1 -0
- package/dist/oauth-store.d.ts +48 -0
- package/dist/oauth-store.js +131 -0
- package/dist/oauth-store.js.map +1 -0
- package/dist/oauth.d.ts +4 -0
- package/dist/oauth.js +382 -0
- package/dist/oauth.js.map +1 -0
- package/dist/request-context.d.ts +2 -0
- package/dist/request-context.js.map +1 -1
- package/dist/tool-policy.js +7 -0
- package/dist/tool-policy.js.map +1 -1
- package/docs/CLIENTS.md +651 -27
- package/docs/CONTRIBUTING.md +4 -2
- package/docs/OAUTH.md +54 -0
- package/docs/SECURITY.md +3 -1
- package/docs/ru/CLIENTS.md +651 -27
- package/docs/ru/CONTRIBUTING.md +4 -2
- package/docs/ru/OAUTH.md +54 -0
- package/docs/ru/SECURITY.md +3 -1
- package/examples/clients/goose-stdio.yaml +13 -0
- package/examples/clients/openclaw.json +13 -0
- package/gemini-extension.json +22 -0
- package/lhm.plugin.json +1408 -0
- package/llms-install.md +17 -0
- package/package.json +9 -4
- package/plugin/.claude-plugin/plugin.json +37 -0
- package/plugin/.cursor-plugin/plugin.json +34 -0
- package/plugin/LICENSE +21 -0
- package/plugin/README.md +48 -0
- package/plugin/assets/README.md +12 -0
- package/plugin/assets/consent.js +32 -0
- package/plugin/assets/fonts/OFL.txt +93 -0
- package/plugin/assets/fonts/manrope.woff2 +0 -0
- package/plugin/assets/icon-400.png +0 -0
- package/plugin/assets/icon.png +0 -0
- package/plugin/assets/icon.svg +15 -0
- package/plugin/assets/landing.css +442 -0
- package/plugin/assets/landing.js +85 -0
- package/plugin/assets/logo.svg +16 -0
- package/plugin/commands/client-summary.md +14 -0
- package/plugin/commands/draft-reply.md +13 -0
- package/plugin/commands/escalate-issue.md +15 -0
- package/plugin/commands/shift-handover.md +10 -0
- package/plugin/commands/triage-inbox.md +13 -0
- package/plugin/mcp.json +10 -0
- package/plugin/plugin.json +15 -0
- package/plugin/skills/teletype-support/SKILL.md +3 -1
- package/plugin/skills/teletype-support/references/installation.md +31 -0
- package/server.json +18 -4
- package/smithery.yaml +3 -2
package/.env.example
CHANGED
|
@@ -7,6 +7,13 @@ PUBLIC_BASE_URL=http://127.0.0.1:4311
|
|
|
7
7
|
# Comma-separated additional browser origins. Values must not contain paths.
|
|
8
8
|
ALLOWED_ORIGINS=
|
|
9
9
|
|
|
10
|
+
# Optional browser OAuth over project tokens. Disabled by default.
|
|
11
|
+
# Use HTTPS in production and Node.js 22.13+ or 24.x.
|
|
12
|
+
OAUTH_ENABLED=false
|
|
13
|
+
OAUTH_DB_PATH=
|
|
14
|
+
# Generate a private 32-byte key: openssl rand -hex 32
|
|
15
|
+
OAUTH_ENCRYPTION_KEY=
|
|
16
|
+
|
|
10
17
|
# Required for stdio. HTTP clients pass this credential per request in
|
|
11
18
|
# X-Teletype-Api-Token. It is not an HTTP fallback.
|
|
12
19
|
TELETYPE_API_TOKEN=
|
package/LAUNCHGUIDE.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Teletype MCP
|
|
2
|
+
|
|
3
|
+
## Tagline
|
|
4
|
+
|
|
5
|
+
Connect AI assistants to Teletype customer conversations and support workflows.
|
|
6
|
+
|
|
7
|
+
## Description
|
|
8
|
+
|
|
9
|
+
Teletype MCP connects MCP clients to a Teletype customer support project through its Public API. It provides tools for finding conversations, reading messages and customer profiles, drafting and sending replies, and managing workspace data. Use the hosted Streamable HTTP endpoint or run the MIT-licensed server locally over stdio. Access to a Teletype project and its Public API token is required. Teletype account terms and pricing apply separately.
|
|
10
|
+
|
|
11
|
+
## Setup Requirements
|
|
12
|
+
|
|
13
|
+
- `TELETYPE_API_TOKEN` (required for stdio): the project's Public API token from Teletype project settings. Keep it in the client's private environment or credential settings. Product and support: https://teletype.app and https://help.teletype.app.
|
|
14
|
+
- Hosted endpoint: `https://mcp.teletype.app/mcp` over Streamable HTTP. Send the token in `X-Teletype-Api-Token` on each request. OAuth is disabled on the public hosted endpoint.
|
|
15
|
+
- Local runtime: Node.js 20.19+, 22.13+, or 24.x. Run `npx -y teletype-mcp-server --stdio`.
|
|
16
|
+
- `TELETYPE_MCP_READ_ONLY` (optional): set to `true` to disable write tools. Local uploads are disabled by default.
|
|
17
|
+
|
|
18
|
+
## Category
|
|
19
|
+
|
|
20
|
+
Communication
|
|
21
|
+
|
|
22
|
+
## Features
|
|
23
|
+
|
|
24
|
+
- Find conversations by status, channel, and customer.
|
|
25
|
+
- Read conversation messages and customer profiles.
|
|
26
|
+
- Draft replies with the supplied MCP prompts.
|
|
27
|
+
- Send replies and manage conversations when write tools are enabled.
|
|
28
|
+
- Inspect channels, templates, operators, and other workspace metadata.
|
|
29
|
+
- Triage unanswered conversations and prepare customer summaries.
|
|
30
|
+
- Use a read-only configuration for workflows that should not change project data.
|
|
31
|
+
- Connect through hosted HTTP, local stdio, a Docker stdio image, or a Claude Desktop bundle.
|
|
32
|
+
|
|
33
|
+
## Getting Started
|
|
34
|
+
|
|
35
|
+
- "Find the unanswered conversations in my Teletype project and summarize which need attention first. Do not change anything."
|
|
36
|
+
- "Read this customer's conversation and draft a reply for my review."
|
|
37
|
+
- Tool: `find_conversations`, find dialogs with filters instead of loading unrelated data.
|
|
38
|
+
- Tool: `list_workspace_metadata`, list channels, response templates, and other project settings.
|
|
39
|
+
- Tool: `get_project_status`, inspect project status and technical health.
|
|
40
|
+
|
|
41
|
+
## Tags
|
|
42
|
+
|
|
43
|
+
mcp, teletype, customer-support, messaging, conversations, helpdesk, claude, cursor
|
|
44
|
+
|
|
45
|
+
## Documentation URL
|
|
46
|
+
|
|
47
|
+
https://github.com/Teletype-App/teletype-mcp-server#readme
|
|
48
|
+
|
|
49
|
+
## Health Check URL
|
|
50
|
+
|
|
51
|
+
https://mcp.teletype.app/healthz
|
package/README-ru.md
CHANGED
|
@@ -10,6 +10,10 @@ MCP-сервер для [Teletype](https://teletype.app). Его инструм
|
|
|
10
10
|
|
|
11
11
|
## Быстрый старт
|
|
12
12
|
|
|
13
|
+
[](https://cursor.com/link/mcp/install?name=teletype&config=eyJ1cmwiOiJodHRwczovL21jcC50ZWxldHlwZS5hcHAvbWNwIiwiaGVhZGVycyI6eyJYLVRlbGV0eXBlLUFwaS1Ub2tlbiI6IiR7ZW52OlRFTEVUWVBFX0FQSV9UT0tFTn0ifX0%3D) [](https://insiders.vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522teletype%2522%252C%2522type%2522%253A%2522http%2522%252C%2522url%2522%253A%2522https%253A%252F%252Fmcp.teletype.app%252Fmcp%2522%252C%2522headers%2522%253A%257B%2522X-Teletype-Api-Token%2522%253A%2522%2524%257Binput%253Ateletype-api-token%257D%2522%257D%252C%2522inputs%2522%253A%255B%257B%2522type%2522%253A%2522promptString%2522%252C%2522id%2522%253A%2522teletype-api-token%2522%252C%2522description%2522%253A%2522Teletype%2520Public%2520API%2520token%2522%252C%2522password%2522%253Atrue%257D%255D%257D)
|
|
14
|
+
|
|
15
|
+
VS Code запросит токен проекта при подключении. Для Cursor заранее задайте `TELETYPE_API_TOKEN` в окружении приложения. Подробности в [инструкции клиентов](docs/ru/CLIENTS.md#cursor).
|
|
16
|
+
|
|
13
17
|
**Хостед-сервер (основной способ).** Teletype запускает MCP-сервер по адресу `https://mcp.teletype.app/mcp`. Для подключения нужен Public API токен проекта. Локальная установка не требуется. В Claude Code:
|
|
14
18
|
|
|
15
19
|
```bash
|
|
@@ -31,7 +35,7 @@ claude mcp add --transport http teletype https://mcp.teletype.app/mcp \
|
|
|
31
35
|
}
|
|
32
36
|
```
|
|
33
37
|
|
|
34
|
-
Для Claude Code и Codex есть плагины, которые ставят сервер и скилл `teletype-support` одним шагом. См. [Плагины для Claude Code и
|
|
38
|
+
Для Claude Code и Codex есть плагины, которые ставят сервер и скилл `teletype-support` одним шагом. См. [Плагины для Claude Code, Codex и Cursor](#плагины-для-claude-code-codex-и-cursor).
|
|
35
39
|
|
|
36
40
|
**Локальный запуск.** Пользователи Claude Desktop на macOS и Windows могут скачать `.mcpb` из [релизов проекта](https://github.com/Teletype-App/teletype-mcp-server/releases), открыть его и ввести токен Teletype Public API. Для запуска из исходного кода выполните `npm ci && npm run build`, затем подключите в MCP-клиенте команду `node /absolute/path/to/dist/index.js --stdio` с переменной окружения `TELETYPE_API_TOKEN`.
|
|
37
41
|
|
|
@@ -62,7 +66,7 @@ TELETYPE_API_TOKEN=ваш-токен npx -y teletype-mcp-server doctor --stdio
|
|
|
62
66
|
|
|
63
67
|
Для Cursor, VS Code с Copilot, Codex, Claude Code, OpenCode, Antigravity CLI и других клиентов есть [инструкции по подключению MCP](docs/ru/CLIENTS.md). Примеры охватывают хостед HTTP и локальный stdio. Отдельный OpenAI-совместимый endpoint нужен только для необязательной команды `eval:model`.
|
|
64
68
|
|
|
65
|
-
Для Claude Code и Codex есть плагины, которые ставят сервер, скилл `teletype-support` и поддержечные слэш-команды одним шагом. См. [Плагины для Claude Code и
|
|
69
|
+
Для Claude Code и Codex есть плагины, которые ставят сервер, скилл `teletype-support` и поддержечные слэш-команды одним шагом. См. [Плагины для Claude Code, Codex и Cursor](#плагины-для-claude-code-codex-и-cursor).
|
|
66
70
|
|
|
67
71
|
## Возможности
|
|
68
72
|
|
|
@@ -117,20 +121,24 @@ TELETYPE_API_TOKEN=ваш-токен npx -y teletype-mcp-server doctor --stdio
|
|
|
117
121
|
- `teletype://dialogs/{dialogId}`: полная переписка конкретного диалога по его ID.
|
|
118
122
|
- `teletype://clients/{clientId}`: профиль клиента, теги и заметки по ID клиента.
|
|
119
123
|
|
|
120
|
-
## Плагины для Claude Code и
|
|
124
|
+
## Плагины для Claude Code, Codex и Cursor
|
|
121
125
|
|
|
122
|
-
Репозиторий
|
|
126
|
+
Репозиторий содержит маркетплейсы Claude Code, Codex и Cursor. Каталог `plugin/` объединяет манифесты `.claude-plugin/plugin.json` и `.cursor-plugin/plugin.json`, переносимые манифесты [Agent Plugins](https://agent-plugins.org) `plugin.json` и `mcp.json`, общий [скилл поддержки](plugin/skills/teletype-support/SKILL.md) и команды. Настройка и доступ к данным описаны в [README плагина](plugin/README.md).
|
|
123
127
|
|
|
124
128
|
### Claude Code
|
|
125
129
|
|
|
126
|
-
Плагин объединяет хостед-сервер (`https://mcp.teletype.app/mcp`, авторизация заголовком `X-Teletype-Api-Token`, подставляемым из
|
|
130
|
+
Плагин объединяет хостед-сервер (`https://mcp.teletype.app/mcp`, авторизация заголовком `X-Teletype-Api-Token`, подставляемым из секретного поля настройки плагина), скилл `teletype-support` с регламентами поддержки и пять слэш-команд, повторяющих MCP-промпты сервера: `/triage-inbox`, `/draft-reply`, `/client-summary`, `/escalate-issue`, `/shift-handover`.
|
|
127
131
|
|
|
128
132
|
```bash
|
|
129
133
|
/plugin marketplace add Teletype-App/teletype-mcp-server
|
|
130
134
|
/plugin install teletype@teletype-mcp-server
|
|
131
135
|
```
|
|
132
136
|
|
|
133
|
-
|
|
137
|
+
При включении плагина введите токен в поле **Teletype Public API token**. Поле `userConfig` обязательное и секретное: Claude хранит значение в защищённом хранилище и подставляет его в заголовок. Используйте актуальную версию Claude Code с поддержкой `userConfig`. Скилл несёт многошаговые регламенты, которым не место в описаниях инструментов: порядок разбора очереди, dry-run перед неоднозначной отправкой, получение категории перед закрытием. Он срабатывает на задачах поддержки без всякой слэш-команды. Те же пять сценариев существуют как MCP-промпты для клиентов, которые их показывают. Команды закрывают сессии, где промптов не видно.
|
|
138
|
+
|
|
139
|
+
### Cursor
|
|
140
|
+
|
|
141
|
+
Нативный манифест Cursor подключает хостед-сервер, общий скилл и команды. В маркетплейс-установке задайте `TELETYPE_API_TOKEN` через **Plugins → Configure**. Для подключения напрямую без плагина используйте [инструкцию Cursor](docs/ru/CLIENTS.md#cursor).
|
|
134
142
|
|
|
135
143
|
### Codex
|
|
136
144
|
|
|
@@ -152,6 +160,14 @@ env_http_headers = { "X-Teletype-Api-Token" = "TELETYPE_API_TOKEN" }
|
|
|
152
160
|
|
|
153
161
|
### Другие агенты
|
|
154
162
|
|
|
163
|
+
Установите скилл поддержки через [Skills CLI](https://github.com/vercel-labs/skills):
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
npx skills add Teletype-App/teletype-mcp-server --skill teletype-support
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
При запросе выберите своего агента и область установки. Команда устанавливает инструкции для работы с поддержкой. Сам MCP-сервер подключите отдельно по [инструкции клиента](docs/ru/CLIENTS.md).
|
|
170
|
+
|
|
155
171
|
Скилл использует открытый формат [Agent Skills](https://agentskills.io), который поддерживают OpenCode, Cursor, Gemini CLI, GitHub Copilot, Goose и другие. npm-пакет поставляет скилл, поэтому после обычной установки:
|
|
156
172
|
|
|
157
173
|
```bash
|
|
@@ -225,7 +241,9 @@ TRANSPORT=stdio TELETYPE_API_TOKEN=... npm start
|
|
|
225
241
|
X-Teletype-Api-Token: <token>
|
|
226
242
|
```
|
|
227
243
|
|
|
228
|
-
Не передавайте токен Teletype в `Authorization`.
|
|
244
|
+
Не передавайте токен проекта Teletype в `Authorization`. Для удалённого доступа нужен HTTPS. Владелец токена сможет работать с данными проекта через MCP с учётом ограничений сервера.
|
|
245
|
+
|
|
246
|
+
На публичном сервере `https://mcp.teletype.app/mcp` OAuth выключен. Для подключения передавайте токен проекта в `X-Teletype-Api-Token`. В коде сохранён опциональный [OAuth](docs/ru/OAUTH.md) для собственного сервера. По умолчанию он отключён и требует отдельной настройки.
|
|
229
247
|
|
|
230
248
|
```bash
|
|
231
249
|
TRANSPORT=http HOST=127.0.0.1 PORT=4311 npm start
|
|
@@ -233,10 +251,12 @@ TRANSPORT=http HOST=127.0.0.1 PORT=4311 npm start
|
|
|
233
251
|
|
|
234
252
|
Маршруты HTTP:
|
|
235
253
|
|
|
236
|
-
| Метод | Путь
|
|
237
|
-
| ----- |
|
|
238
|
-
|
|
|
239
|
-
| GET | `/
|
|
254
|
+
| Метод | Путь | Назначение |
|
|
255
|
+
| ----- | ----------- | --------------------------------------------- |
|
|
256
|
+
| GET | `/` | Лендинг на русском и английском |
|
|
257
|
+
| GET | `/assets/*` | Скрипты, стили, логотип и шрифты лендинга |
|
|
258
|
+
| POST | `/mcp` | MCP через Streamable HTTP без хранения сеанса |
|
|
259
|
+
| GET | `/healthz` | Проверка доступности сервера |
|
|
240
260
|
|
|
241
261
|
Для каждого HTTP-запроса создаётся отдельная пара MCP Server/transport, поэтому одновременные арендаторы не делят ответы и контекст. Сервер ограничивает число параллельных запросов глобально и для каждого токена. При превышении лимита он отвечает `429` с `Retry-After`. Через HTTP сервер не читает локальные файлы.
|
|
242
262
|
|
|
@@ -253,6 +273,15 @@ docker run --rm -p 127.0.0.1:4311:4311 \
|
|
|
253
273
|
|
|
254
274
|
Для публичного домена укажите его источник (origin) в `PUBLIC_BASE_URL` и настройте HTTPS на обратном прокси.
|
|
255
275
|
|
|
276
|
+
Для MCP-клиента, который запускает контейнер через stdio, соберите target `stdio` и передайте токен из своего приватного окружения. Флаг `-i` оставляет stdin открытым. Флаг `-t` мешает обмену MCP-сообщениями, поэтому его не добавляйте:
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
docker build --target stdio -t teletype-mcp-stdio .
|
|
280
|
+
docker run --rm -i -e TELETYPE_API_TOKEN teletype-mcp-stdio
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Вариант stdio запускается от того же непривилегированного пользователя, не открывает HTTP-порт и не использует HTTP health check. Переменная `TELETYPE_MCP_READ_ONLY=true` отключает пишущие инструменты.
|
|
284
|
+
|
|
256
285
|
## Конфигурация
|
|
257
286
|
|
|
258
287
|
| Переменная | Значение по умолчанию |
|
|
@@ -261,6 +290,9 @@ docker run --rm -p 127.0.0.1:4311:4311 \
|
|
|
261
290
|
| `HOST` / `PORT` | `127.0.0.1` / `4311` |
|
|
262
291
|
| `PUBLIC_BASE_URL` | `http://127.0.0.1:4311` |
|
|
263
292
|
| `ALLOWED_ORIGINS` | дополнительные Origin через запятую |
|
|
293
|
+
| `OAUTH_ENABLED` | `false` |
|
|
294
|
+
| `OAUTH_DB_PATH` | путь к постоянной SQLite-базе для OAuth |
|
|
295
|
+
| `OAUTH_ENCRYPTION_KEY` | приватный ключ OAuth из 64 hex-символов |
|
|
264
296
|
| `TELETYPE_API_TOKEN` | обязателен для stdio |
|
|
265
297
|
| `TELETYPE_API_BASE` | `https://api.teletype.app/public/api/v1` |
|
|
266
298
|
| `TELETYPE_PROJECT_URL` | `teletype.app` |
|
|
@@ -342,3 +374,9 @@ npm run eval:model > eval-report.json
|
|
|
342
374
|
`npm run test:mutation` запускает полную мутационную проверку с нижним порогом 33% и сохраняет отчёты в `reports/mutation/`. Она занимает больше времени и не входит в `npm run check`.
|
|
343
375
|
|
|
344
376
|
О раскрытии уязвимостей читайте в [SECURITY-ru.md](docs/ru/SECURITY.md), об участии в разработке в [CONTRIBUTING-ru.md](docs/ru/CONTRIBUTING.md). Лицензия проекта: MIT.
|
|
377
|
+
|
|
378
|
+
## Поддержка и конфиденциальность
|
|
379
|
+
|
|
380
|
+
- [Центр помощи Teletype](https://help.teletype.app)
|
|
381
|
+
- [Сообщить о проблеме сервера](https://github.com/Teletype-App/teletype-mcp-server/issues)
|
|
382
|
+
- [Политика конфиденциальности Teletype](https://teletype.app/files/policy.pdf)
|
package/README.md
CHANGED
|
@@ -10,6 +10,10 @@ MCP server for [Teletype](https://teletype.app). Its tools cover daily support w
|
|
|
10
10
|
|
|
11
11
|
## Quick start
|
|
12
12
|
|
|
13
|
+
[](https://cursor.com/link/mcp/install?name=teletype&config=eyJ1cmwiOiJodHRwczovL21jcC50ZWxldHlwZS5hcHAvbWNwIiwiaGVhZGVycyI6eyJYLVRlbGV0eXBlLUFwaS1Ub2tlbiI6IiR7ZW52OlRFTEVUWVBFX0FQSV9UT0tFTn0ifX0%3D) [](https://insiders.vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522teletype%2522%252C%2522type%2522%253A%2522http%2522%252C%2522url%2522%253A%2522https%253A%252F%252Fmcp.teletype.app%252Fmcp%2522%252C%2522headers%2522%253A%257B%2522X-Teletype-Api-Token%2522%253A%2522%2524%257Binput%253Ateletype-api-token%257D%2522%257D%252C%2522inputs%2522%253A%255B%257B%2522type%2522%253A%2522promptString%2522%252C%2522id%2522%253A%2522teletype-api-token%2522%252C%2522description%2522%253A%2522Teletype%2520Public%2520API%2520token%2522%252C%2522password%2522%253Atrue%257D%255D%257D)
|
|
14
|
+
|
|
15
|
+
VS Code asks for the project token when connecting. For Cursor, set `TELETYPE_API_TOKEN` in the app environment before opening the connection. See the [client guide](docs/CLIENTS.md#cursor).
|
|
16
|
+
|
|
13
17
|
**Hosted server (recommended).** Teletype runs the MCP server at `https://mcp.teletype.app/mcp`. Connect with your project's Public API token. No local installation is needed. In Claude Code:
|
|
14
18
|
|
|
15
19
|
```bash
|
|
@@ -31,7 +35,7 @@ or merge [this file](examples/clients/claude-code-remote.json) into `.mcp.json`
|
|
|
31
35
|
}
|
|
32
36
|
```
|
|
33
37
|
|
|
34
|
-
For Claude Code and Codex, plugins install the server and the `teletype-support` skill in one step. See [Plugins for Claude Code and
|
|
38
|
+
For Claude Code and Codex, plugins install the server and the `teletype-support` skill in one step. See [Plugins for Claude Code, Codex, and Cursor](#plugins-for-claude-code-codex-and-cursor).
|
|
35
39
|
|
|
36
40
|
**Run locally.** Claude Desktop users on macOS or Windows can download the `.mcpb` file from the project's [releases](https://github.com/Teletype-App/teletype-mcp-server/releases), open it, and enter their Teletype Public API token when prompted. To run from source, use `npm ci && npm run build`, then point an MCP client at `node /absolute/path/to/dist/index.js --stdio` with `TELETYPE_API_TOKEN` in its environment.
|
|
37
41
|
|
|
@@ -59,7 +63,7 @@ For Cursor, Zed, and other MCP clients, use the same command, arguments, and env
|
|
|
59
63
|
|
|
60
64
|
For Cursor, VS Code with Copilot, Codex, Claude Code, OpenCode, Antigravity CLI, and other supported clients, see [MCP clients](docs/CLIENTS.md). The examples cover hosted HTTP and local stdio connections. A separate OpenAI-compatible endpoint is optional and only used by `eval:model`.
|
|
61
65
|
|
|
62
|
-
For Claude Code and Codex there are plugins that install the server, the `teletype-support` skill, and support slash commands in one step. See [Plugins for Claude Code and
|
|
66
|
+
For Claude Code and Codex there are plugins that install the server, the `teletype-support` skill, and support slash commands in one step. See [Plugins for Claude Code, Codex, and Cursor](#plugins-for-claude-code-codex-and-cursor).
|
|
63
67
|
|
|
64
68
|
## Tools
|
|
65
69
|
|
|
@@ -114,20 +118,24 @@ The server provides these support prompts:
|
|
|
114
118
|
- `teletype://dialogs/{dialogId}`: full message history for a specific dialogue by ID.
|
|
115
119
|
- `teletype://clients/{clientId}`: client profile, tags, and notes by client ID.
|
|
116
120
|
|
|
117
|
-
## Plugins for Claude Code and
|
|
121
|
+
## Plugins for Claude Code, Codex, and Cursor
|
|
118
122
|
|
|
119
|
-
The repository
|
|
123
|
+
The repository contains marketplaces for Claude Code, Codex, and Cursor. The `plugin/` directory includes `.claude-plugin/plugin.json` and `.cursor-plugin/plugin.json`, the portable [Agent Plugins](https://agent-plugins.org) manifests `plugin.json` and `mcp.json`, the shared [support skill](plugin/skills/teletype-support/SKILL.md), and commands. See the [plugin README](plugin/README.md) for configuration and data access.
|
|
120
124
|
|
|
121
125
|
### Claude Code
|
|
122
126
|
|
|
123
|
-
The plugin bundles the hosted MCP server (`https://mcp.teletype.app/mcp`, authenticated with the `X-Teletype-Api-Token` header
|
|
127
|
+
The plugin bundles the hosted MCP server (`https://mcp.teletype.app/mcp`, authenticated with the `X-Teletype-Api-Token` header supplied by the plugin's sensitive configuration field), the `teletype-support` skill with the support workflows and safety rules, and five slash commands that mirror the server's MCP prompts: `/triage-inbox`, `/draft-reply`, `/client-summary`, `/escalate-issue`, `/shift-handover`.
|
|
124
128
|
|
|
125
129
|
```bash
|
|
126
130
|
/plugin marketplace add Teletype-App/teletype-mcp-server
|
|
127
131
|
/plugin install teletype@teletype-mcp-server
|
|
128
132
|
```
|
|
129
133
|
|
|
130
|
-
|
|
134
|
+
When enabling the plugin, enter the token in the **Teletype Public API token** field. This required sensitive `userConfig` field stores the value in Claude's secure credential store and supplies the HTTP header. Use an up-to-date Claude Code version with `userConfig` support. The skill carries the multi-step regulations that do not fit tool descriptions: triage order, dry-run before an ambiguous send, category lookup before closing. It triggers on support tasks without a slash command. The five workflows also exist as MCP prompts for clients that show them. The commands cover the sessions where they are not shown.
|
|
135
|
+
|
|
136
|
+
### Cursor
|
|
137
|
+
|
|
138
|
+
The native Cursor manifest connects to the hosted server and includes the shared skill and commands. For a marketplace installation, set `TELETYPE_API_TOKEN` under **Plugins → Configure**. To connect directly without a plugin, follow the [Cursor setup guide](docs/CLIENTS.md#cursor).
|
|
131
139
|
|
|
132
140
|
### Codex
|
|
133
141
|
|
|
@@ -149,6 +157,14 @@ Codex also reads skills without plugins from `.agents/skills` in the repository
|
|
|
149
157
|
|
|
150
158
|
### Other agents
|
|
151
159
|
|
|
160
|
+
Install the support skill with the [Skills CLI](https://github.com/vercel-labs/skills):
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
npx skills add Teletype-App/teletype-mcp-server --skill teletype-support
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Select your agent and installation scope when prompted. This command installs the workflow instructions. Connect the MCP server separately using the [client guide](docs/CLIENTS.md).
|
|
167
|
+
|
|
152
168
|
The skill uses the open [Agent Skills](https://agentskills.io) format, supported by OpenCode, Cursor, Gemini CLI, GitHub Copilot, Goose, and others. The npm package ships the skill, so after a regular install:
|
|
153
169
|
|
|
154
170
|
```bash
|
|
@@ -222,7 +238,9 @@ Endpoint: `POST /mcp`. Send the Teletype API token with every request in this he
|
|
|
222
238
|
X-Teletype-Api-Token: <token>
|
|
223
239
|
```
|
|
224
240
|
|
|
225
|
-
Do not send the Teletype token in `Authorization`.
|
|
241
|
+
Do not send the Teletype project token in `Authorization`. Use HTTPS for remote access. Anyone with the project token can access its data through the MCP server, subject to deployment restrictions.
|
|
242
|
+
|
|
243
|
+
OAuth is disabled on the public hosted endpoint at `https://mcp.teletype.app/mcp`. Connect with your project token in `X-Teletype-Api-Token`. For self-hosting, the code includes optional [OAuth](docs/OAUTH.md), disabled by default and enabled through separate configuration.
|
|
226
244
|
|
|
227
245
|
```bash
|
|
228
246
|
TRANSPORT=http HOST=127.0.0.1 PORT=4311 npm start
|
|
@@ -230,10 +248,12 @@ TRANSPORT=http HOST=127.0.0.1 PORT=4311 npm start
|
|
|
230
248
|
|
|
231
249
|
HTTP endpoints:
|
|
232
250
|
|
|
233
|
-
| Method | Path
|
|
234
|
-
| ------ |
|
|
235
|
-
|
|
|
236
|
-
| GET | `/
|
|
251
|
+
| Method | Path | Purpose |
|
|
252
|
+
| ------ | ----------- | --------------------------------------------- |
|
|
253
|
+
| GET | `/` | Russian and English landing page |
|
|
254
|
+
| GET | `/assets/*` | landing page scripts, styles, logo, and fonts |
|
|
255
|
+
| POST | `/mcp` | stateless Streamable HTTP MCP |
|
|
256
|
+
| GET | `/healthz` | health probe |
|
|
237
257
|
|
|
238
258
|
Each HTTP request gets its own MCP Server and transport pair, so concurrent tenants do not share responses or context. The server limits concurrent requests globally and per token. It returns `429` with `Retry-After` when a limit is reached. The HTTP transport cannot read local files.
|
|
239
259
|
|
|
@@ -250,27 +270,39 @@ docker run --rm -p 127.0.0.1:4311:4311 \
|
|
|
250
270
|
|
|
251
271
|
For a public domain, set its origin in `PUBLIC_BASE_URL` and terminate HTTPS at the reverse proxy.
|
|
252
272
|
|
|
273
|
+
For an MCP client that starts a container over stdio, build the `stdio` target and forward the token from your private environment. Keep stdin open with `-i` and omit `-t`, which would interfere with MCP messages:
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
docker build --target stdio -t teletype-mcp-stdio .
|
|
277
|
+
docker run --rm -i -e TELETYPE_API_TOKEN teletype-mcp-stdio
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
The stdio target runs as the same unprivileged user and does not expose an HTTP port or use an HTTP health check. Set `TELETYPE_MCP_READ_ONLY=true` to disable write tools.
|
|
281
|
+
|
|
253
282
|
## Configuration
|
|
254
283
|
|
|
255
|
-
| Variable | Default
|
|
256
|
-
| ----------------------------- |
|
|
257
|
-
| `TRANSPORT` | `http`
|
|
258
|
-
| `HOST` / `PORT` | `127.0.0.1` / `4311`
|
|
259
|
-
| `PUBLIC_BASE_URL` | `http://127.0.0.1:4311`
|
|
260
|
-
| `ALLOWED_ORIGINS` | additional comma-separated origins
|
|
261
|
-
| `
|
|
262
|
-
| `
|
|
263
|
-
| `
|
|
264
|
-
| `
|
|
265
|
-
| `
|
|
266
|
-
| `
|
|
267
|
-
| `
|
|
268
|
-
| `
|
|
269
|
-
| `
|
|
270
|
-
| `
|
|
271
|
-
| `
|
|
272
|
-
| `
|
|
273
|
-
| `
|
|
284
|
+
| Variable | Default |
|
|
285
|
+
| ----------------------------- | -------------------------------------------------- |
|
|
286
|
+
| `TRANSPORT` | `http` |
|
|
287
|
+
| `HOST` / `PORT` | `127.0.0.1` / `4311` |
|
|
288
|
+
| `PUBLIC_BASE_URL` | `http://127.0.0.1:4311` |
|
|
289
|
+
| `ALLOWED_ORIGINS` | additional comma-separated origins |
|
|
290
|
+
| `OAUTH_ENABLED` | `false` |
|
|
291
|
+
| `OAUTH_DB_PATH` | persistent SQLite path when OAuth is enabled |
|
|
292
|
+
| `OAUTH_ENCRYPTION_KEY` | private 64-character hex key when OAuth is enabled |
|
|
293
|
+
| `TELETYPE_API_TOKEN` | required for stdio |
|
|
294
|
+
| `TELETYPE_API_BASE` | `https://api.teletype.app/public/api/v1` |
|
|
295
|
+
| `TELETYPE_PROJECT_URL` | `teletype.app` |
|
|
296
|
+
| `TELETYPE_MCP_LOCALE` | `en` (`ru` for Russian text) |
|
|
297
|
+
| `TELETYPE_MCP_READ_ONLY` | `true` unregisters write tools |
|
|
298
|
+
| `TELETYPE_MCP_TOOLSETS` | comma-separated toolsets to register |
|
|
299
|
+
| `REQUEST_TIMEOUT_MS` | `15000` |
|
|
300
|
+
| `MAX_RESPONSE_BYTES` | `5000000` |
|
|
301
|
+
| `MAX_UPLOAD_BYTES` | `20000000` |
|
|
302
|
+
| `MAX_CONCURRENT_REQUESTS` | `32` |
|
|
303
|
+
| `MAX_CONCURRENT_PER_TOKEN` | `4` |
|
|
304
|
+
| `ENABLE_LOCAL_UPLOADS` | `false` |
|
|
305
|
+
| `TELETYPE_ALLOWED_FILE_ROOTS` | comma-separated permitted directories |
|
|
274
306
|
|
|
275
307
|
`PUBLIC_BASE_URL` and each entry in `ALLOWED_ORIGINS` must be an origin without a path, query, or fragment. The server validates the value whenever a client sends an `Origin` header.
|
|
276
308
|
|
|
@@ -339,3 +371,9 @@ The report also includes outcome, first-attempt, answer, and safety rates. Each
|
|
|
339
371
|
`npm run test:mutation` runs the full mutation suite with a 33% score floor and writes reports to `reports/mutation/`. It takes longer and is not part of `npm run check`.
|
|
340
372
|
|
|
341
373
|
See [SECURITY.md](docs/SECURITY.md) for vulnerability reporting and [CONTRIBUTING.md](docs/CONTRIBUTING.md) for contribution guidelines. The project uses the MIT license.
|
|
374
|
+
|
|
375
|
+
## Support and privacy
|
|
376
|
+
|
|
377
|
+
- [Teletype help center](https://help.teletype.app)
|
|
378
|
+
- [Report a server issue](https://github.com/Teletype-App/teletype-mcp-server/issues)
|
|
379
|
+
- [Teletype privacy policy](https://teletype.app/android/policy.html)
|
package/dist/config.d.ts
CHANGED
|
@@ -18,5 +18,9 @@ export interface Config {
|
|
|
18
18
|
logLevel: "debug" | "info" | "warn" | "error";
|
|
19
19
|
readOnly: boolean;
|
|
20
20
|
toolsets: ToolsetName[] | null;
|
|
21
|
+
oauth?: {
|
|
22
|
+
databasePath: string;
|
|
23
|
+
encryptionKey: string;
|
|
24
|
+
};
|
|
21
25
|
}
|
|
22
26
|
export declare function loadConfig(env?: NodeJS.ProcessEnv): Config;
|
package/dist/config.js
CHANGED
|
@@ -32,6 +32,22 @@ export function loadConfig(env = process.env) {
|
|
|
32
32
|
.map((item) => item.trim())
|
|
33
33
|
.filter(Boolean);
|
|
34
34
|
const allowedOrigins = [...new Set([origin(publicBaseUrl), ...configuredOrigins.map(origin)])];
|
|
35
|
+
let oauth;
|
|
36
|
+
if (env.OAUTH_ENABLED === "true") {
|
|
37
|
+
const issuer = new URL(publicBaseUrl);
|
|
38
|
+
if (issuer.protocol !== "https:" &&
|
|
39
|
+
!["localhost", "127.0.0.1", "[::1]"].includes(issuer.hostname)) {
|
|
40
|
+
throw new Error("OAuth requires HTTPS, except on a loopback host.");
|
|
41
|
+
}
|
|
42
|
+
if (issuer.username || issuer.password) {
|
|
43
|
+
throw new Error("OAuth public URL must not contain credentials.");
|
|
44
|
+
}
|
|
45
|
+
const encryptionKey = env.OAUTH_ENCRYPTION_KEY;
|
|
46
|
+
if (!env.OAUTH_DB_PATH || !encryptionKey || !/^[a-f0-9]{64}$/i.test(encryptionKey)) {
|
|
47
|
+
throw new Error("OAuth requires OAUTH_DB_PATH and a 64-character hex OAUTH_ENCRYPTION_KEY.");
|
|
48
|
+
}
|
|
49
|
+
oauth = { databasePath: env.OAUTH_DB_PATH, encryptionKey };
|
|
50
|
+
}
|
|
35
51
|
const projectUrl = env.TELETYPE_PROJECT_URL || "teletype.app";
|
|
36
52
|
if (!/^[a-z0-9.-]+(?::\d+)?$/i.test(projectUrl)) {
|
|
37
53
|
throw new Error("TELETYPE_PROJECT_URL must be a hostname with an optional port.");
|
|
@@ -41,6 +57,7 @@ export function loadConfig(env = process.env) {
|
|
|
41
57
|
port: integer(env.PORT, 4311, "PORT"),
|
|
42
58
|
host: env.HOST || "127.0.0.1",
|
|
43
59
|
publicBaseUrl,
|
|
60
|
+
oauth,
|
|
44
61
|
allowedOrigins,
|
|
45
62
|
apiToken: env.TELETYPE_API_TOKEN?.trim() || undefined,
|
|
46
63
|
apiBase: httpUrl(env.TELETYPE_API_BASE || "https://api.teletype.app/public/api/v1", "TELETYPE_API_BASE"),
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAoB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAoB,MAAM,kBAAkB,CAAC;AAwBtE,SAAS,OAAO,CAAC,KAAyB,EAAE,QAAgB,EAAE,IAAY;IACxE,IAAI,CAAC,KAAK;QAAE,OAAO,QAAQ,CAAC;IAC5B,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,8BAA8B,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,MAAM,CAAC,KAAa;IAC3B,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAC9B,IAAI,MAAM,CAAC,QAAQ,KAAK,GAAG,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CAAC,sDAAsD,KAAK,EAAE,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC;AAED,SAAS,OAAO,CAAC,KAAa,EAAE,IAAY;IAC1C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAC9B,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,0BAA0B,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC7D,WAAW,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACrC,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;IAC/D,MAAM,aAAa,GAAG,GAAG,CAAC,eAAe,IAAI,uBAAuB,CAAC;IACrE,MAAM,iBAAiB,GAAG,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC;SAClD,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,OAAO,CAAC,CAAC;IACnB,MAAM,cAAc,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,GAAG,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,IAAI,KAAsB,CAAC;IAC3B,IAAI,GAAG,CAAC,aAAa,KAAK,MAAM,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC;QACtC,IACE,MAAM,CAAC,QAAQ,KAAK,QAAQ;YAC5B,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,EAC9D,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACtE,CAAC;QACD,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACpE,CAAC;QACD,MAAM,aAAa,GAAG,GAAG,CAAC,oBAAoB,CAAC;QAC/C,IAAI,CAAC,GAAG,CAAC,aAAa,IAAI,CAAC,aAAa,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;YACnF,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;QAC/F,CAAC;QACD,KAAK,GAAG,EAAE,YAAY,EAAE,GAAG,CAAC,aAAa,EAAE,aAAa,EAAE,CAAC;IAC7D,CAAC;IACD,MAAM,UAAU,GAAG,GAAG,CAAC,oBAAoB,IAAI,cAAc,CAAC;IAC9D,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;IACpF,CAAC;IAED,MAAM,GAAG,GAAW;QAClB,SAAS;QACT,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC;QACrC,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,WAAW;QAC7B,aAAa;QACb,KAAK;QACL,cAAc;QACd,QAAQ,EAAE,GAAG,CAAC,kBAAkB,EAAE,IAAI,EAAE,IAAI,SAAS;QACrD,OAAO,EAAE,OAAO,CACd,GAAG,CAAC,iBAAiB,IAAI,wCAAwC,EACjE,mBAAmB,CACpB;QACD,UAAU;QACV,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,MAAM,EAAE,oBAAoB,CAAC;QAC/E,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,SAAS,EAAE,oBAAoB,CAAC;QAClF,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,UAAU,EAAE,kBAAkB,CAAC;QAC7E,qBAAqB,EAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,EAAE,EAAE,yBAAyB,CAAC;QAC1F,qBAAqB,EAAE,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,CAAC,EAAE,0BAA0B,CAAC;QAC3F,kBAAkB,EAAE,GAAG,CAAC,oBAAoB,KAAK,MAAM;QACvD,gBAAgB,EAAE,CAAC,GAAG,CAAC,2BAA2B,IAAI,EAAE,CAAC;aACtD,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;aAC1B,MAAM,CAAC,OAAO,CAAC;QAClB,QAAQ,EACN,GAAG,CAAC,SAAS,KAAK,OAAO,IAAI,GAAG,CAAC,SAAS,KAAK,MAAM,IAAI,GAAG,CAAC,SAAS,KAAK,OAAO;YAChF,CAAC,CAAC,GAAG,CAAC,SAAS;YACf,CAAC,CAAC,MAAM;QACZ,QAAQ,EAAE,GAAG,CAAC,sBAAsB,KAAK,MAAM;QAC/C,QAAQ,EAAE,gBAAgB,CAAC,GAAG,CAAC,qBAAqB,CAAC;KACtD,CAAC;IAEF,IAAI,SAAS,KAAK,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,GAAG,CAAC,kBAAkB,IAAI,GAAG,CAAC,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;IAChF,CAAC;IACD,IAAI,GAAG,CAAC,qBAAqB,GAAG,GAAG,CAAC,qBAAqB,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAC;IACvF,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/http.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
2
3
|
import express from "express";
|
|
3
4
|
import { toNodeHandler } from "@modelcontextprotocol/node";
|
|
4
5
|
import { createMcpHandler } from "@modelcontextprotocol/server";
|
|
@@ -7,6 +8,8 @@ import { buildServer } from "./server.js";
|
|
|
7
8
|
import { log } from "./log.js";
|
|
8
9
|
import { RequestLimiter } from "./request-limiter.js";
|
|
9
10
|
import { SERVER_VERSION } from "./version.js";
|
|
11
|
+
import { mountProjectOAuth } from "./oauth.js";
|
|
12
|
+
import { landingPage } from "./landing-page.js";
|
|
10
13
|
const API_TOKEN_HEADER = "x-teletype-api-token";
|
|
11
14
|
export function createHttpApp(cfg) {
|
|
12
15
|
const app = express();
|
|
@@ -20,7 +23,37 @@ export function createHttpApp(cfg) {
|
|
|
20
23
|
},
|
|
21
24
|
});
|
|
22
25
|
app.disable("x-powered-by");
|
|
26
|
+
app.use("/assets", express.static(fileURLToPath(new URL("../plugin/assets/", import.meta.url)), {
|
|
27
|
+
dotfiles: "deny",
|
|
28
|
+
index: false,
|
|
29
|
+
redirect: false,
|
|
30
|
+
maxAge: "1d",
|
|
31
|
+
setHeaders: (res) => res.setHeader("X-Content-Type-Options", "nosniff"),
|
|
32
|
+
}));
|
|
33
|
+
app.get("/", (req, res) => {
|
|
34
|
+
const savedLocale = req.headers.cookie
|
|
35
|
+
?.split(";")
|
|
36
|
+
.map((part) => part.trim())
|
|
37
|
+
.find((part) => part.startsWith("teletype_oauth_locale="))
|
|
38
|
+
?.slice("teletype_oauth_locale=".length);
|
|
39
|
+
const locale = savedLocale === "ru" || savedLocale === "en"
|
|
40
|
+
? savedLocale
|
|
41
|
+
: req.acceptsLanguages("en", "ru") === "ru"
|
|
42
|
+
? "ru"
|
|
43
|
+
: "en";
|
|
44
|
+
res
|
|
45
|
+
.set({
|
|
46
|
+
"Cache-Control": "no-store",
|
|
47
|
+
"Content-Language": locale,
|
|
48
|
+
"Referrer-Policy": "no-referrer",
|
|
49
|
+
"X-Content-Type-Options": "nosniff",
|
|
50
|
+
"Content-Security-Policy": "default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; frame-ancestors 'none'; base-uri 'none'; form-action 'none'",
|
|
51
|
+
})
|
|
52
|
+
.type("html")
|
|
53
|
+
.send(landingPage(cfg.publicBaseUrl, locale));
|
|
54
|
+
});
|
|
23
55
|
app.use(express.json({ limit: "1mb", strict: true }));
|
|
56
|
+
const oauth = mountProjectOAuth(app, cfg);
|
|
24
57
|
app.get(["/healthz", "/health", "/live"], (_req, res) => {
|
|
25
58
|
res.json({ ok: true, service: "teletype-mcp-server", version: SERVER_VERSION });
|
|
26
59
|
});
|
|
@@ -40,8 +73,35 @@ export function createHttpApp(cfg) {
|
|
|
40
73
|
const requestId = randomUUID();
|
|
41
74
|
const startedAt = performance.now();
|
|
42
75
|
res.set("X-Request-Id", requestId);
|
|
43
|
-
|
|
76
|
+
let token = String(req.headers[API_TOKEN_HEADER] ?? "").trim();
|
|
77
|
+
let oauthReadOnly;
|
|
78
|
+
const challenge = () => {
|
|
79
|
+
if (oauth)
|
|
80
|
+
res.set("WWW-Authenticate", `Bearer resource_metadata="${new URL("/.well-known/oauth-protected-resource/mcp", cfg.publicBaseUrl).href}"`);
|
|
81
|
+
};
|
|
82
|
+
if (oauth && req.headers.authorization) {
|
|
83
|
+
if (token) {
|
|
84
|
+
res.status(400).json({ error: "multiple_authentication_methods" });
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
const bearer = /^Bearer ([A-Za-z0-9_-]{43})$/i.exec(req.headers.authorization)?.[1];
|
|
89
|
+
if (!bearer)
|
|
90
|
+
throw new Error("Invalid bearer token.");
|
|
91
|
+
const info = await oauth.verifyAccessToken(bearer);
|
|
92
|
+
if (typeof info.extra?.apiToken !== "string")
|
|
93
|
+
throw new Error("Missing project credential.");
|
|
94
|
+
token = info.extra.apiToken;
|
|
95
|
+
oauthReadOnly = !info.scopes.includes("write");
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
challenge();
|
|
99
|
+
res.status(401).json({ error: "invalid_oauth_token" });
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
44
103
|
if (!token) {
|
|
104
|
+
challenge();
|
|
45
105
|
res.status(401).json({
|
|
46
106
|
error: "teletype_api_token_required",
|
|
47
107
|
message: `Pass the Public API token in ${API_TOKEN_HEADER}.`,
|
|
@@ -66,6 +126,10 @@ export function createHttpApp(cfg) {
|
|
|
66
126
|
maxUploadBytes: cfg.maxUploadBytes,
|
|
67
127
|
requestId,
|
|
68
128
|
logLevel: cfg.logLevel,
|
|
129
|
+
toolPolicy: {
|
|
130
|
+
readOnly: cfg.readOnly || oauthReadOnly === true,
|
|
131
|
+
toolsets: cfg.toolsets,
|
|
132
|
+
},
|
|
69
133
|
}, () => nodeMcpHandler(req, res, req.body));
|
|
70
134
|
}
|
|
71
135
|
catch (error) {
|
|
@@ -114,7 +178,11 @@ export async function startHttpServer(cfg) {
|
|
|
114
178
|
else
|
|
115
179
|
resolve(server);
|
|
116
180
|
});
|
|
181
|
+
server.once("close", () => app.emit("close"));
|
|
117
182
|
server.once("error", reject);
|
|
183
|
+
}).catch((error) => {
|
|
184
|
+
app.emit("close");
|
|
185
|
+
throw error;
|
|
118
186
|
});
|
|
119
187
|
log("info", "http_server_started", { host: cfg.host, port: cfg.port });
|
|
120
188
|
return listener;
|
package/dist/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,OAA2D,MAAM,SAAS,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function landingPage(publicBaseUrl: string, locale: "ru" | "en"): string;
|