Skip to main content
Glama
README.md
# myteam-mcp

MCP-сервер (Model Context Protocol) для HR-платформы **«МояКоманда»** ([моякоманда.рф](https://xn--80aalwjbieb2o.xn--p1ai/)). Даёт AI-ассистентам (Claude и другим MCP-клиентам) доступ к сущностям и действиям HR-платформы через её REST API: сотрудники, команды, календарь и отсутствия, заявки, база знаний, опросы, новости и геймификация.

> Не путать с мессенджером *VK Teams / Myteam* (mail.ru) — это другой продукт с другим API.

## Возможности

- **Два транспорта**: `stdio` (локально, у каждого свой токен) и `http` (Streamable HTTP, один общий сервер на пространство с **проброской авторизации per-request**).
- **~30 курируемых инструментов** по основным HR-сценариям + универсальный `myteam_request` для доступа к любому из ~2900 методов API.
- **Безопасность по умолчанию**: изменяющие операции и «сырой» доступ к API выключены и включаются явными флагами.
- **Права ролей соблюдаются автоматически** — API отдаёт данные в рамках роли пользователя, которому принадлежит токен.
- Готовые **Docker-образ** и **Helm-чарт**.

## Как это работает

Авторизация в «МояКоманда» — Laravel Sanctum. Токен получается методом `POST /api/login-mobile` (email/телефон + пароль) и передаётся во всех запросах заголовком `Authorization: Bearer <token>`. Базовый адрес — домен вашего тенанта (например `https://company.ismyteam.ru`), все методы под префиксом `/api`. Swagger доступен внутри пространства по адресу `/api-docs`.

## Установка

```bash
git clone https://github.com/pohodnya/myteam-mcp.git
cd myteam-mcp
npm install
npm run build
```

Требуется Node.js >= 20.

## Получение токена

```bash
npm run login -- https://company.ismyteam.ru user@company.ru 'ваш-пароль'
# выведет токен в stdout
```

или задайте `MYTEAM_BASE_URL`, `MYTEAM_LOGIN`, `MYTEAM_PASSWORD` и запустите `npm run login`.

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

| Переменная | Обязательна | Описание |
|---|---|---|
| `MYTEAM_BASE_URL` | да | URL тенанта, напр. `https://company.ismyteam.ru` |
| `MYTEAM_TOKEN` | для stdio | Bearer-токен API. В http может приходить per-request |
| `MYTEAM_TRANSPORT` | нет | `stdio` (по умолчанию) или `http` |
| `MYTEAM_HTTP_HOST` / `MYTEAM_HTTP_PORT` | нет | Хост/порт http-транспорта (`0.0.0.0` / `3000`) |
| `MYTEAM_ENABLE_WRITE` | нет | `true` — разрешить изменяющие операции |
| `MYTEAM_ENABLE_RAW` | нет | `true` — включить инструмент `myteam_request` |
| `MYTEAM_TIMEOUT_MS` | нет | Таймаут запросов, мс (`30000`) |

## Запуск в Claude Desktop / Claude Code (stdio)

```json
{
  "mcpServers": {
    "myteam": {
      "command": "node",
      "args": ["/абсолютный/путь/myteam-mcp/dist/index.js"],
      "env": {
        "MYTEAM_BASE_URL": "https://company.ismyteam.ru",
        "MYTEAM_TOKEN": "ваш-токен"
      }
    }
  }
}
```

## Общий сервер с проброской авторизации (http)

Один инстанс на всё пространство; токен не хранится на сервере, а берётся из заголовка `Authorization` каждого запроса — каждый пользователь работает под своей ролью.

```bash
MYTEAM_BASE_URL=https://company.ismyteam.ru MYTEAM_TRANSPORT=http npm start
```

```bash
curl -X POST http://localhost:3000/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'Authorization: Bearer <токен-пользователя>' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

Health-check без авторизации: `GET /health`.

## OAuth 2.1 мост (per-user авторизация для коннекторов)

У «МояКоманда» нет OAuth — только логин по email/паролю. Чтобы работать с коннекторами claude.ai (которым нужен OAuth 2.1 + Dynamic Client Registration), сервер умеет **сам выступать Authorization Server**: показывает форму входа, аутентифицирует пользователя через `/api/login-mobile` и выдаёт собственный `access_token` (зашифрованный Sanctum-токен). На `/mcp` токен расшифровывается обратно.

Включение:

```bash
MYTEAM_BASE_URL=https://company.ismyteam.ru \
MYTEAM_TRANSPORT=http \
MYTEAM_ENABLE_OAUTH=true \
MYTEAM_OAUTH_SECRET='случайная-строка-не-короче-16-символов' \
MYTEAM_PUBLIC_URL=https://mcp.company.ru \
npm start
```

Реализовано: `Authorization Code + PKCE (S256)`, DCR (`POST /register`), метаданные
`/.well-known/oauth-authorization-server` и `/.well-known/oauth-protected-resource`,
`401` с заголовком `WWW-Authenticate` на `/mcp`. Коды и токены self-contained (AES-256-GCM),
серверное состояние не хранится — мост работает в stateless-режиме и масштабируется.

В коннекторе claude.ai укажите URL `https://mcp.company.ru/mcp` — остальное (discovery,
регистрация, вход) пройдёт автоматически. Каждый пользователь входит под своей учётной
записью и работает в рамках прав своей роли.

> Header-passthrough (без OAuth) остаётся доступным одновременно: если в заголовке пришёл
> «сырой» Sanctum-токен, он используется напрямую.

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

**Система**: `get_company_info`, `whoami`, `healthz`
**Сотрудники и команды**: `list_users`, `search_users_by_filter`, `get_user`, `get_user_work`, `get_user_subordinates`, `list_teams`, `get_team`, `get_team_structure`
**Календарь и отсутствия**: `list_calendar_events`, `list_absences`, `who_is_absent`, `memorable_dates`
**Заявки**: `list_requests`, `get_request`, `requests_catalog`, `requests_need_action`
**База знаний**: `search_knowledge_base`, `list_kb_categories`, `get_kb_article`
**Опросы**: `list_surveys`, `get_survey`, `get_survey_participants`, `get_survey_questions`, `get_survey_statistics`, `list_survey_templates`
**ИПР (развитие)**: `list_development_plans`, `my_development_plans`, `get_user_development_plans`, `get_development_plan`
**Эффективность**: `list_evaluations`, `get_evaluation`, `get_evaluation_participants`, `get_evaluation_user_card`, `get_evaluation_matrix` (9-Box), `list_kpi`, `get_kpi`, `get_kpi_user_info`
**Вовлечённость**: `get_news_feed`, `get_my_activities`, `get_rating`, `get_prize_store`, `get_user_thanks`

**Изменяющие** (`MYTEAM_ENABLE_WRITE=true`): `create_calendar_event`, `send_thanks`, `share_coins`, `run_development_plan`, `set_development_material_status`, `save_kpi_progress`, `submit_evaluation_answer`, `complete_evaluation`, `answer_survey_question`, `publish_survey`, `remind_survey_participants`
**Расширенный** (`MYTEAM_ENABLE_RAW=true`): `myteam_request` — произвольный вызов любого эндпоинта `/api/...`

## Docker

```bash
docker build -t myteam-mcp .
docker run --rm -p 3000:3000 \
  -e MYTEAM_BASE_URL=https://company.ismyteam.ru \
  myteam-mcp
```

По умолчанию образ стартует в http-режиме с проброской токена.

## Helm

```bash
helm install myteam-mcp ./helm/myteam-mcp \
  --set config.baseUrl=https://company.ismyteam.ru
```

По умолчанию `token.passthrough=true` (per-request). Для общего токена:

```bash
helm install myteam-mcp ./helm/myteam-mcp \
  --set config.baseUrl=https://company.ismyteam.ru \
  --set token.passthrough=false \
  --set token.existingSecret=my-secret
```

## Разработка

```bash
npm run dev          # watch-режим (stdio)
npm test             # тесты (vitest)
npm run test:coverage
npm run typecheck
```

## Архитектура

```
src/
  index.ts      точка входа, выбор транспорта
  config.ts     конфигурация из ENV
  client.ts     HTTP-клиент REST API (Bearer, таймауты, ошибки)
  auth.ts       логин через /api/login-mobile
  server.ts     фабрика MCP-сервера, регистрация инструментов
  http.ts       Streamable HTTP транспорт с проброской токена
  login.ts      CLI получения токена
  tools/        инструменты по модулям
```

## Лицензия

[MIT](./LICENSE)