Skip to main content
Glama
skiddgoddamn

tgtrack-mcp

by skiddgoddamn
README.md
<div align="center">

# tgtrack-mcp

**Manage a [tgtrack](https://tgtrack.ru) / «Откуда Подписки» account from an AI agent — channels, ad-system integrations, tracking-script settings, goals and links — with no official API.**

![license](https://img.shields.io/badge/license-MIT-blue)
![MCP](https://img.shields.io/badge/MCP-server-6E56CF)
![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178C6?logo=typescript&logoColor=white)
![tests](https://img.shields.io/badge/tests-passing-34c759)
![PRs welcome](https://img.shields.io/badge/PRs-welcome-34c759)

**English** · [Русский](./README.ru.md)

</div>

## Why

tgtrack ("Откуда Подписки") tracks **where your Telegram subscribers come from** and feeds offline *"subscription"* conversions back to Yandex Metrika / Direct. All of it — channels, "advertising systems" (integrations), the landing tracking-script, goals, links, daily reports — lives only in the `settings.tgtrack.ru` panel. There is **no public API**.

**tgtrack-mcp** exposes that control plane as [MCP](https://modelcontextprotocol.io) tools. It talks to the same internal endpoints the panel uses and **signs every request exactly like the panel does** (a short-lived JWT plus an md5-based request signature), so an AI agent (Claude, etc.) can list channels, read and create integrations, tweak the script settings, goals and links — in one turn.

- 🔑 **Uses your panel token** — a JWT read from the `settings.tgtrack.ru` URL; nothing is scraped or hardcoded
- 🧩 **26 focused tools** — the settings control plane **plus the runtime Bot API** (start/stop events, deep goals, `get_user_info`); read + safe writes, destructive actions gated behind `confirm: true`
- 🧮 **Panel-accurate signing** — `H = md5(md5(JSON + T) + T)`, verified against a live sample
- 🪶 **TypeScript, ESM, strict** — thin, MIT, no account secrets in the repo

## How it works

Every call is a `POST` to `https://api.tgtrack.ru/API/settings/<endpoint>.php` with a `multipart/form-data` body of two fields:

```
JSON = JSON.stringify({ ...params, T, tn })   // T = unix seconds, tn = your JWT
H    = md5( md5(JSON + T) + T )               // request signature (T is the salt)
```

The response is a `{ S, D, M }` envelope: `S === 0` means success and the payload is `D.data`; otherwise the tool returns a typed error (`217/218` = bad/expired token → a clear "refresh your token" message).

## Requirements

1. **Node ≥ 18.**
2. A **tgtrack token** (`TGTRACK_TOKEN`): open [settings.tgtrack.ru](https://settings.tgtrack.ru), and copy the `t=` value from the address bar (or the `tgtrack_token` cookie). It is short-lived (~72 h); tgtrack has no working refresh endpoint, so re-paste it when it expires.

## Setup

```bash
npm install
npm run build
```

Register it with your MCP client (see [`.mcp.json.example`](./.mcp.json.example)):

```json
{
  "mcpServers": {
    "tgtrack": {
      "command": "node",
      "args": ["dist/index.js"],
      "env": { "TGTRACK_TOKEN": "<the ?t=... JWT from settings.tgtrack.ru>" }
    }
  }
}
```

## Tools

### Read

| Tool | Purpose |
|------|---------|
| `tgtrack_list_channels` | List all channels / groups / bots on the account. |
| `tgtrack_get_channel` | Full channel: integrations (ad systems), links, script & report settings. |
| `tgtrack_get_integration_script` | Build the ready `<script>` + `click.tgtrack.ru` link from `linkID` + `counterID` (no API call). |

### Integrations ("advertising systems")

| Tool | Purpose |
|------|---------|
| `tgtrack_create_integration` | Create an integration. For `yandex` returns `grantAccessUrl` + `webCreationCode` (finish the OAuth grant in a browser). |
| `tgtrack_set_script_settings` | Script settings of an integration (strict mode, conversion delay, auto-approve, goal flags…). |
| `tgtrack_update_goal` | Update a goal (name/value in Metrika), optionally create it. |
| `tgtrack_yandex_web_create_status` | Poll Yandex auto-goal creation by `webCreationCode`. |
| `tgtrack_get_restore_yandex_link` | Link to re-grant Yandex access for an integration. |

### Links & channel

| Tool | Purpose |
|------|---------|
| `tgtrack_get_landings` | Landings attached to a channel / integration. |
| `tgtrack_set_link_url` | Change a link's target URL. |
| `tgtrack_set_link_name` | Rename a link / integration. |
| `tgtrack_set_outbound_link_params` | Params of an under-post button link (target, button text, subscription check). |
| `tgtrack_set_channel_auto_approve` | Toggle auto-approval of join requests. |
| `tgtrack_set_report_settings` | Daily-report toggles (morning report, send-if-no-subs, traffic report). |

### Dangerous — require `confirm: true`

| Tool | Purpose |
|------|---------|
| `tgtrack_delete_invite_link` | ⚠️ Delete an invite link / integration (irreversible). |
| `tgtrack_delete_outbound_link` | ⚠️ Delete an outbound link (irreversible). |
| `tgtrack_new_api_token` | ⚠️ Mint a new API key — **invalidates the previous one**. |
| `tgtrack_new_report_key` | ⚠️ Mint a new report key — invalidates the previous one. |

Without `confirm: true` the dangerous tools return a description of what they *would* do and never touch the API.

### Bot API — runtime events (`bot-api.tgtrack.ru`)

A second contour, separate from the settings API: it is **not** JWT-signed — it `POST`s JSON to
`https://bot-api.tgtrack.ru/v1/<API_KEY>/<method>` (MAX: `https://max.tgtrack.ru/API/bot-api/v1/<API_KEY>/<method>`).
The `API_KEY` is the **per-bot/channel key** (`apiToken` in `tgtrack_get_channel`), not the panel JWT —
pass it as `apiKey` on each call, or set `TGTRACK_BOT_API_KEY`. Add `max: true` for MAX.

| Tool | Purpose |
|------|---------|
| `tgtrack_bot_event_url` | Build the webhook URL for a constructor (e.g. `my_bothelp_was_started`) — no API call; paste into BotHelp/SaleBot. |
| `tgtrack_bot_started` | `my_bot_was_started` — limited integration, send the `start_value` (or `auto_detect`). |
| `tgtrack_bot_user_started` | `user_did_start_bot` — start with user data (`user_id`, name, `start_value`). |
| `tgtrack_bot_stopped` | `my_bot_was_stopped` — user blocked/unsubscribed the bot. |
| `tgtrack_bot_on_telegram_webhook` | `on_telegram_webhook` — full integration: forward the raw Telegram update 1:1. |
| `tgtrack_bot_send_reach_goal` | `send_reach_goal` — push a funnel goal to the ad system the user came from (21-day window). |
| `tgtrack_bot_add_event` | `add_event` — lifecycle event / sale with `amount`, `conversion_target`, `labels`. |
| `tgtrack_bot_get_user_info` | `get_user_info` — utm tags, join/leave dates and first source for a `user_id`. |

## Usage

Run the MCP server over stdio, or call a tool directly for scripting:

```bash
node dist/index.js                                   # MCP (stdio)

TGTRACK_TOKEN=... npx tsx src/run.ts tgtrack_list_channels
TGTRACK_TOKEN=... npx tsx src/run.ts tgtrack_get_channel '{"chatID":"600334c8b9b9e"}'
TGTRACK_TOKEN=... npx tsx src/run.ts tgtrack_get_integration_script \
  '{"linkID":"5cd4255d831d9e","counterID":"110494105"}'

# Bot API (per-bot key, no JWT):
npx tsx src/run.ts tgtrack_bot_event_url '{"apiKey":"<API_KEY>","method":"my_bothelp_was_started"}'
npx tsx src/run.ts tgtrack_bot_get_user_info '{"apiKey":"<API_KEY>","userId":"123456789"}'
```

Streamable HTTP transport:

```bash
TGTRACK_TOKEN=... node dist/index.js --http --port 3001   # /mcp, /health
```

## Scope

**Included:** the full settings/management control plane — channels, integrations, script settings, goals, links, reports — **and the runtime Bot API** (start/stop events, deep goals, `add_event`, `get_user_info`).

**Not included yet:**
- **Analytics reports** (subscribers over time, source breakdown, conversions) — this lives behind a separate reporting API keyed by a report key (`tgtrack_new_report_key`). Planned for v2.
- **Admin tools** (`deleteChannel`, `changeUserAccess`, …) — planned behind a flag (v1.1).
- **MAX** (`max.tgtrack.ru`) parity — behind a `service` option.

## Security

The token lives only in your environment (`TGTRACK_TOKEN`) — never in the repo, never logged, never echoed in error messages. `.mcp.json` and `.env` are git-ignored; only `.mcp.json.example` (with a placeholder) is committed.

## Contributing

Contributions welcome — open an issue or a PR.

1. Fork and branch: `git checkout -b feature/my-change`
2. `npm install`; `npm run build` and `npm test` must pass
3. **Never commit secrets** (the JWT / `.env` / a real `.mcp.json`) or real account data
4. Open a PR describing what and why

## License

MIT

TDQS

A3.5/5.0

Scored across 18 tools

Disambiguation5/5

Each tool targets a distinct resource or action (e.g., create integration, delete link, get channel info), with no overlapping purposes. Descriptions further clarify unique roles.

Naming Consistency5/5

All tools follow a consistent 'tgtrack_verb_noun' pattern using snake_case, with verbs like create, delete, get, list, set, new, update. Only minor variation like 'new' vs 'create' but pattern is uniform.

Tool Count5/5

18 tools is well-scoped for managing integrations, channels, links, reports, and settings. Not excessive, and each tool serves a clear purpose within the domain.

Completeness5/5

The set covers CRUD-like operations for integrations, links, channels, and settings, plus specialized actions for Yandex OAuth, script generation, and goal updates. No obvious gaps for the server's scope.

Maintenance

ActivityMaintained
ResponsivenessNo issues