Metadata-Version: 2.4
Name: st-mcp-x
Version: 0.1.0
Summary: Keyless X (Twitter) MCP — профиль, лента твитов, аналитика вовлечённости
License-File: LICENSE
Requires-Python: >=3.13
Requires-Dist: httpx==0.28.1
Requires-Dist: mcp[cli]==1.28.1
Requires-Dist: python-dotenv==1.2.2
Provides-Extra: dev
Requires-Dist: ruff==0.15.21; extra == 'dev'
Requires-Dist: ty==0.0.59; extra == 'dev'
Description-Content-Type: text/markdown

# MCP X

MCP-сервер для для чтения и анализа X (Twitter). Доступ к профилям, ленте твитов и метрикам вовлечённости — без авторизации X API, на основе публичного web-GraphQL с guest-токеном.

[![FastMCP](https://img.shields.io/badge/FastMCP-1.28.1-000000)](https://github.com/modelcontextprotocol/python-sdk)
[![httpx](https://img.shields.io/badge/httpx-0.28.1-2A6DB2)](https://github.com/encode/httpx)

## 📑 Содержание

- [Возможности](#-возможности)
- [Быстрый старт](#-быстрый-старт)
- [Стек](#-стек)
- [Инструменты](#-инструменты)
- [Структура](#-структура)
- [Архитектура](#-архитектура)
- [Команды](#-команды)
- [Автор](#-автор)
- [Лицензия](#-лицензия)

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

- Доступ к публичным данным X через web-GraphQL `x.com/i/api/graphql` с guest-токеном — без OAuth и ключей разработчика
- Профиль пользователя, детали твита, лента (highlights), топ по вовлечённости, свежие и медиа-твиты, треды, сравнение аккаунтов
- Аналитика вовлечённости: снимок средних метрик, engagement/hour для свежих твитов, классификация сигналов (вопросы, жалобы, анонсы)
- Информирование о полноте: везде, где данные режутся, в ответе присутствуют поля `returned`/`total`/`incomplete`
- Авто-продление guest-токена по TTL и перевыпуск при 403/429
- Диагностика актуальности queryId — инструмент `validate_endpoints` проверяет, не устарели ли endpoint'ы

## ⚡ Быстрый старт

Регистрация сервера в Claude Code:

```bash
claude mcp add x -s user -- uvx --from st-mcp-x --index https://forgejo.emptyvessel.ru/api/packages/st/pypi/simple st-mcp-x
```

Подключение к opencode — секция `mcp` в `opencode.json`:

```jsonc
{
  "mcp": {
    "x": {
      "type": "local",
      "command": [
        "uvx",
        "--from",
        "st-mcp-x",
        "--index",
        "https://forgejo.emptyvessel.ru/api/packages/st/pypi/simple",
        "st-mcp-x",
      ],
      "enabled": true,
    },
  },
}
```

`uvx` скачивает пакет из forgejo registry. В Claude Code инструменты доступны как `mcp__x__*`, в opencode — `x_*`. Авторизация не требуется.

## 🛠️ Стек

| Технология | Версия | Назначение                                |
| ---------- | ------ | ----------------------------------------- |
| Python     | 3.13+  | Язык разработки                           |
| mcp[cli]   | 1.28.1 | FastMCP, транспорт stdio                  |
| httpx      | 0.28.1 | HTTP-клиент к GraphQL X и guest-активации |

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

### Базовые

| Инструмент        | Назначение                                                      |
| ----------------- | --------------------------------------------------------------- |
| `get_user`        | Профиль: bio, подписчики, верификация, дата регистрации         |
| `get_tweet`       | Детали твита по ID или URL: текст, автор, метрики, медиа        |
| `get_user_tweets` | Лента твитов (highlights на guest-токене) с ограничением лимита |
| `top_tweets`      | Топ твитов по вовлечённости (favorites + retweets)              |
| `recent_tweets`   | Свежие твиты за окно (hour/day/week/month/year/all)             |
| `media_tweets`    | Только твиты с медиа (фото/видео/GIF)                           |
| `thread_by_user`  | Твиты одного треда по conversation_id                           |
| `compare_users`   | Сравнение аккаунтов: подписчики, твиты, средний engagement      |

### Аналитика

| Инструмент                 | Назначение                                                    |
| -------------------------- | ------------------------------------------------------------- |
| `user_engagement_snapshot` | Снимок вовлечённости: средние метрики, engagement/hour, топ-3 |
| `trend_radar`              | Свежие твиты, ранжированные по вовлечённости в час            |
| `find_signals`             | Твиты с признаками вопросов, жалоб или анонсов                |

### Диагностика

| Инструмент           | Назначение                                           |
| -------------------- | ---------------------------------------------------- |
| `validate_endpoints` | Проверка актуальности queryId всех GraphQL-endpoints |

## 📁 Структура

```
mcp.x/
├── src/st_mcp_x/
│   ├── main.py          Точка входа: запуск сервера
│   ├── server.py        FastMCP и регистрация инструментов
│   ├── client.py        XClient, GuestToken и Guard (retry/backoff)
│   ├── config.py        Bearer-токен, пул User-Agents, TTL, таймауты
│   ├── endpoints.py     Таблица queryId GraphQL и флаги features
│   ├── format.py        Нормализация legacy-структур в плоский dict
│   ├── tools.py         Базовые инструменты чтения
│   └── analyze.py       Аналитика вовлечённости
├── scripts/
│   └── check.py         E2E-прогон инструментов через MCP-клиент
├── tests/
│   └── test_endpoints.py  Проверка актуальности queryId
├── .env.example
├── Makefile
└── pyproject.toml
```

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

Сервер обращается к web-GraphQL X с публичным bearer-токеном (захардкожен в JS-бандле веб-клиента) и одноразовым guest-токеном. Поток запроса:

```
Инструмент ──► Guard (retry/backoff) ──► XClient.gql ──► GraphQL X
                    │                         │
                    │                         ├─ Authorization: Bearer <public>
                    │                         └─ x-guest-token: <одноразовый>
                    │
                    └─ 403/429 → GuestToken.reset() + повтор
```

- **Guest-токен** получается через `POST /1.1/guest/activate.json`, живёт ~30 минут. Класс `GuestToken` хранит токен с TTL и лениво обновляет; при 403/429 `Guard` сбрасывает его и повторяет запрос.
- **QueryId** меняются при деплоях X. Таблица в `endpoints.py` — единственное место для обновления. При 404 инструмент `validate_endpoints` показывает, какие endpoint'ы устарели.
- **Highlights**: на guest-токене `UserTweets` отдаёт подборку топ-твитов пользователя (~99, разных периодов) вместо хронологической ленты. Для аналитики вовлечённости этого достаточно; для свежих твитов применяется `recent_tweets` с фильтром по временному окну.

## 🔧 Команды

```bash

# Приложение

make install      Установка зависимостей
make start        Запуск MCP-сервера

# Разработка

make e2e          Прогон инструментов через MCP-клиент
make lint         Проверка линтером
make fix          Автоисправление и проверка типов
make format       Форматирование кода
make clean        Очистка кэша
make purge        Удаление окружения и кэшей

# Релиз

make build        Сборка wheel и sdist
make publish      Публикация в forgejo registry
```

## 👤 Автор

**Станислав Байков** ([@st.rnd](mailto:st.rnd@mail.ru))

## 📄 Лицензия

Распространяется под лицензией MIT. Подробности в [LICENSE](LICENSE).
