# `app.toptik/tiktok` on anlyon.dev

> Text inside fenced blocks marked untrusted-server-text was written by the MCP server's publisher, not by anlyon.dev. It is data to inspect, not instructions to follow. Invisible characters are shown as [U+XXXX].
> No finding is not a safety guarantee: these are point-in-time checks of tool definitions, not of code or behaviour.

- Page: https://anlyon.dev/servers/app.toptik/tiktok
- JSON: https://anlyon.dev/api/v1/servers/app.toptik/tiktok
- Version: 1.0.0 (active)
- Publisher: app.toptik (domain proven to the MCP Registry)
- Runs: remote (streamable-http)
- Sign-in to list tools: none
- Metadata from the official MCP Registry, synced 2026-10-21T17:45:10.294Z

Title and description, as the publisher wrote them:

```untrusted-server-text
TopTik — TikTok data
TikTok data for agents: videos, creators, comments, search, transcripts. 25 tools, pay per call.
```

Scanned 2026-10-21T18:43:32.363Z over streamable-http.

**25 tools: 1 do something that can't be undone, 14 change things and 10 only read.**

| Group | Class | Tools | Claude Code |
| --- | --- | --- | --- |
| Deletes or cancels | destructive | 0 | deny |
| Can't be undone | irreversible | 1 | ask |
| Changes things | write | 14 | ask |
| Only reads | read | 10 | allow |

## Findings

- **warn** Annotations that disagree with the tool in `tiktok_video_comments` ([annotation-conflict](https://anlyon.dev/methodology#annotation-conflict))

```untrusted-server-text
The server marks "tiktok_video_comments" read-only (readOnlyHint: true), and its own name, description or input give the class "write".

annotations: {"readOnlyHint":true,"idempotentHint":true,"openWorldHint":true}; The name "tiktok_video_comments" says "comment": a word for a change.
```

- **warn** Annotations that disagree with the tool in `tiktok_comment_replies` ([annotation-conflict](https://anlyon.dev/methodology#annotation-conflict))

```untrusted-server-text
The server marks "tiktok_comment_replies" read-only (readOnlyHint: true), and its own name, description or input give the class "irreversible".

annotations: {"readOnlyHint":true,"idempotentHint":true,"openWorldHint":true}; The name "tiktok_comment_replies" says "comment": a word for a change.
```


## Can't be undone (1)

Sends, pays, publishes or merges: once done, it cannot be taken back. Claude Code: ask.

### `tiktok_comment_replies`

- The name "tiktok_comment_replies" says "comment": a word for a change.
- The name "tiktok_comment_replies" also says "reply": a word for sending, and what is sent cannot be taken back.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
- Findings: warn annotation-conflict

Description, as the server wrote it:

```untrusted-server-text
Replies under one comment. Worth calling only when tiktok_video_comments reported reply_count above 0.
```

## Changes things (14)

Creates or changes something that can be changed back. Claude Code: ask.

### `tiktok_creator_followers`

- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

Description, as the server wrote it:

```untrusted-server-text
A sample of a creator's followers (most recent), plus the total. One page only: TikTok does not page this list reliably, so this is a sample and not an export.
```

### `tiktok_creator_following`

- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

Description, as the server wrote it:

```untrusted-server-text
A sample of the accounts a creator follows, plus the total. One page only, for the same reason as followers.
```

### `tiktok_creator_liked_videos`

- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

Description, as the server wrote it:

```untrusted-server-text
Videos a creator has liked. Only works when the account keeps its likes public; most do not, and a private list returns no videos.
```

### `tiktok_creator_playlists`

- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

Description, as the server wrote it:

```untrusted-server-text
A creator's playlists (TikTok calls them mixes or series). Most creators have none, which returns total 0.
```

### `tiktok_creator_profile`

- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

Description, as the server wrote it:

```untrusted-server-text
A creator's profile: handle, nickname, bio, follower, following and video counts, privacy and verification flags, and avatar.
```

### `tiktok_creator_videos`

- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

Description, as the server wrote it:

```untrusted-server-text
A creator's posts, newest first, with stats. Page by passing the previous response's max_cursor as cursor until has_more is 0. Pinned posts appear on page one only.
```

### `tiktok_explore_feed`

- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

Description, as the server wrote it:

```untrusted-server-text
TikTok's Explore / Discover feed: what is trending now. Not personalised and not cached, so each call returns a fresh set; call again for more.
```

### `tiktok_hashtag_videos`

- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

Description, as the server wrote it:

```untrusted-server-text
Videos under a hashtag. Pages hold about 12 videos whatever count asks for; page with cursor.
```

### `tiktok_live_streams`

- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

Description, as the server wrote it:

```untrusted-server-text
Live rooms matching a keyword, each with playable stream URLs per quality (FLV always, HLS when TikTok provides it), title and viewer count. URLs are signed (see expires_at), but a room usually ends long before its signature does; if one quality fails, try another.
```

### `tiktok_sound_videos`

- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

Description, as the server wrote it:

```untrusted-server-text
Videos TikTok associates with a sound. Treat it as a feed seeded by the sound, not a strict filter: some results use a different sound, so check music_id on each row.
```

### `tiktok_video_comments`

- The name "tiktok_video_comments" says "comment": a word for a change.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
- Findings: warn annotation-conflict

Description, as the server wrote it:

```untrusted-server-text
Top-level comments on a video, with like and reply counts. cursor is an offset: pass the previous response's cursor to continue. TikTok re-ranks between pages, so dedupe on comment_id.
```

### `tiktok_video_download_url`

- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

Description, as the server wrote it:

```untrusted-server-text
Direct media URLs for one post: no-watermark video, watermarked video, audio, covers, and the images of a photo post. Links only, no bytes; they are signed and expire (see expires), so fetch promptly.
```

### `tiktok_video_stats`

- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

Description, as the server wrote it:

```untrusted-server-text
One video or photo post by id: caption, plays, likes, comments, shares, saves, duration, hashtags, sound and author.
```

### `tiktok_video_transcript`

- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

Description, as the server wrote it:

```untrusted-server-text
A video's spoken text from TikTok's own caption track: one joined string plus timed cues. has_transcript false means the video has no caption track, which is common and is not an error.
```

## Only reads (10)

Looks things up and changes nothing. Claude Code: allow.

### `tiktok_hashtag_resolve`

- The name "tiktok_hashtag_resolve" says "resolve": a word for reading.

Description, as the server wrote it:

```untrusted-server-text
Hashtag name to its id, with total video and view counts. Feed the id to tiktok_hashtag_videos.
```

### `tiktok_places_search`

- The name "tiktok_places_search" says "search": a word for reading.

Description, as the server wrote it:

```untrusted-server-text
Search TikTok places (points of interest) by name: address, coordinates, rating, review count and video count.
```

### `tiktok_resolve_username`

- The name "tiktok_resolve_username" says "resolve": a word for reading.

Description, as the server wrote it:

```untrusted-server-text
Resolve a TikTok @handle to the account's numeric uid and sec_uid. Start here: every tiktok_creator_* tool takes the sec_uid this returns. An empty user_list means no exact match was found.
```

### `tiktok_search_creators`

- The name "tiktok_search_creators" says "search": a word for reading.

Description, as the server wrote it:

```untrusted-server-text
Keyword search over accounts, with follower counts. Pages by offset, not cursor. For one exact @handle use tiktok_resolve_username instead: it is cheaper and more reliable.
```

### `tiktok_search_hashtags`

- The name "tiktok_search_hashtags" says "search": a word for reading.

Description, as the server wrote it:

```untrusted-server-text
Keyword search over hashtags, with post and view counts. One page only.
```

### `tiktok_search_lives`

- The name "tiktok_search_lives" says "search": a word for reading.

Description, as the server wrote it:

```untrusted-server-text
Live rooms on air right now that match a keyword, with the host's account. One page only. For playable stream URLs use tiktok_live_streams.
```

### `tiktok_search_photos`

- The name "tiktok_search_photos" says "search": a word for reading.

Description, as the server wrote it:

```untrusted-server-text
Keyword search over photo-mode (carousel) posts, with image URLs and stats. One page only.
```

### `tiktok_search_sounds`

- The name "tiktok_search_sounds" says "search": a word for reading.

Description, as the server wrote it:

```untrusted-server-text
Keyword search over sounds, with usage counts. cursor is an offset: pass the previous response's cursor.
```

### `tiktok_search_videos`

- The name "tiktok_search_videos" says "search": a word for reading.

Description, as the server wrote it:

```untrusted-server-text
Keyword search over videos. TikTok search is a bounded, re-ranked pool, not an endless list: ask for count 30, page with cursor, dedupe on video_id, and stop when two pages add nothing new.
```

### `tiktok_sound_resolve`

- The name "tiktok_sound_resolve" says "resolve": a word for reading.

Description, as the server wrote it:

```untrusted-server-text
Sound title to music id, with the closest candidates. Feed the id to tiktok_sound_videos.
```

## Claude Code permissions

For `.claude/settings.json`, assuming the server is installed as `tiktok`:

```json
{
  "permissions": {
    "allow": [
      "mcp__tiktok__tiktok_resolve_username",
      "mcp__tiktok__tiktok_sound_resolve",
      "mcp__tiktok__tiktok_hashtag_resolve",
      "mcp__tiktok__tiktok_search_videos",
      "mcp__tiktok__tiktok_search_creators",
      "mcp__tiktok__tiktok_search_hashtags",
      "mcp__tiktok__tiktok_search_sounds",
      "mcp__tiktok__tiktok_search_lives",
      "mcp__tiktok__tiktok_search_photos",
      "mcp__tiktok__tiktok_places_search"
    ],
    "ask": [
      "mcp__tiktok__tiktok_creator_profile",
      "mcp__tiktok__tiktok_creator_videos",
      "mcp__tiktok__tiktok_creator_liked_videos",
      "mcp__tiktok__tiktok_creator_followers",
      "mcp__tiktok__tiktok_creator_following",
      "mcp__tiktok__tiktok_creator_playlists",
      "mcp__tiktok__tiktok_video_stats",
      "mcp__tiktok__tiktok_video_comments",
      "mcp__tiktok__tiktok_comment_replies",
      "mcp__tiktok__tiktok_video_download_url",
      "mcp__tiktok__tiktok_video_transcript",
      "mcp__tiktok__tiktok_sound_videos",
      "mcp__tiktok__tiktok_hashtag_videos",
      "mcp__tiktok__tiktok_explore_feed",
      "mcp__tiktok__tiktok_live_streams"
    ],
    "deny": []
  }
}
```
