xiaohongshu-mcp-integration

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

xiaohongshu-mcp-integration

xiaohongshu-mcp-integration

Skill by ara.so — MCP Skills collection.
This skill enables AI coding agents to integrate with Xiaohongshu (Little Red Book / 小红书) through an MCP server. It provides capabilities for login management, content publishing (text/image/video), searching, retrieving recommendations, managing interactions (like, favorite, comment), and accessing user profiles.
Skill by ara.so — MCP Skills collection.
该Skill支持AI编码Agent通过MCP服务器与小红书集成,提供登录管理、内容发布(文字/图片/视频)、搜索、获取推荐内容、管理互动(点赞、收藏、评论)以及访问用户资料等功能。

What It Does

功能介绍

The
xiaohongshu-mcp
project is a Model Context Protocol (MCP) server that provides programmatic access to Xiaohongshu's platform. It uses browser automation to interact with the platform and exposes tools through the MCP interface.
Core capabilities:
  • Login and session management
  • Publish image posts (up to 20 characters title, 1000 characters content)
  • Publish video posts (local files only)
  • Search content by keywords
  • Get recommendation feed
  • Retrieve post details (including engagement metrics and comments)
  • Post comments and reply to comments
  • Like/unlike posts
  • Favorite/unfavorite posts
  • Get user profile information
Important constraints:
  • Titles must be ≤20 characters
  • Content must be ≤1000 characters
  • Daily posting limit is ~50 posts per account
  • Cannot log in on multiple web sessions simultaneously (mobile app is OK)
  • Requires login before using most features
xiaohongshu-mcp
项目是一个模型上下文协议(MCP)服务器,提供对小红书平台的程序化访问能力。它通过浏览器自动化与平台交互,并通过MCP接口对外提供工具。
核心功能:
  • 登录及会话管理
  • 发布图片笔记(标题最多20字符,内容最多1000字符)
  • 发布视频笔记(仅支持本地文件)
  • 按关键词搜索内容
  • 获取推荐信息流
  • 获取笔记详情(包含互动数据及评论)
  • 发布评论及回复评论
  • 点赞/取消点赞笔记
  • 收藏/取消收藏笔记
  • 获取用户资料信息
重要限制:
  • 标题长度不得超过20字符
  • 内容长度不得超过1000字符
  • 每个账号每日发布上限约为50篇笔记
  • 不可同时在多个网页会话登录(移动端APP不受影响)
  • 使用大部分功能前需先完成登录

Installation

安装方法

Method 1: Pre-compiled Binaries (Recommended)

方法1:预编译二进制文件(推荐)

Download from GitHub Releases:
Main MCP Server:
  • macOS Apple Silicon:
    xiaohongshu-mcp-darwin-arm64
  • macOS Intel:
    xiaohongshu-mcp-darwin-amd64
  • Windows x64:
    xiaohongshu-mcp-windows-amd64.exe
  • Linux x64:
    xiaohongshu-mcp-linux-amd64
Login Tool:
  • macOS Apple Silicon:
    xiaohongshu-login-darwin-arm64
  • macOS Intel:
    xiaohongshu-login-darwin-amd64
  • Windows x64:
    xiaohongshu-login-windows-amd64.exe
  • Linux x64:
    xiaohongshu-login-linux-amd64
bash
undefined
GitHub Releases下载:
主MCP服务器:
  • macOS Apple Silicon:
    xiaohongshu-mcp-darwin-arm64
  • macOS Intel:
    xiaohongshu-mcp-darwin-amd64
  • Windows x64:
    xiaohongshu-mcp-windows-amd64.exe
  • Linux x64:
    xiaohongshu-mcp-linux-amd64
登录工具:
  • macOS Apple Silicon:
    xiaohongshu-login-darwin-arm64
  • macOS Intel:
    xiaohongshu-login-darwin-amd64
  • Windows x64:
    xiaohongshu-login-windows-amd64.exe
  • Linux x64:
    xiaohongshu-login-linux-amd64
bash
undefined

1. First run the login tool

1. First run the login tool

chmod +x xiaohongshu-login-darwin-arm64 ./xiaohongshu-login-darwin-arm64
chmod +x xiaohongshu-login-darwin-arm64 ./xiaohongshu-login-darwin-arm64

2. Start the MCP server

2. Start the MCP server

chmod +x xiaohongshu-mcp-darwin-arm64 ./xiaohongshu-mcp-darwin-arm64

**Note:** First run downloads a headless browser (~150MB).
chmod +x xiaohongshu-mcp-darwin-arm64 ./xiaohongshu-mcp-darwin-arm64

**注意:**首次运行会下载一个无头浏览器(约150MB)。

Method 2: Docker

方法2:Docker

bash
undefined
bash
undefined

Pull the image

Pull the image

docker pull xpzouying/xiaohongshu-mcp:latest
docker pull xpzouying/xiaohongshu-mcp:latest

Run the container

Run the container

docker run -d
--name xiaohongshu-mcp
-p 8080:8080
-v $(pwd)/data:/app/data
xpzouying/xiaohongshu-mcp:latest
undefined
docker run -d
--name xiaohongshu-mcp
-p 8080:8080
-v $(pwd)/data:/app/data
xpzouying/xiaohongshu-mcp:latest
undefined

Method 3: Build from Source

方法3:从源码构建

bash
undefined
bash
undefined

Clone the repository

Clone the repository

Build

Build

go build -o xiaohongshu-mcp ./cmd/mcp go build -o xiaohongshu-login ./cmd/login
go build -o xiaohongshu-mcp ./cmd/mcp go build -o xiaohongshu-login ./cmd/login

Run

Run

./xiaohongshu-login # First time setup ./xiaohongshu-mcp # Start server
undefined
./xiaohongshu-login # First time setup ./xiaohongshu-mcp # Start server
undefined

Configuration

配置

The MCP server can be configured for Claude Desktop or other MCP clients:
Claude Desktop Configuration (
claude_desktop_config.json
):
json
{
  "mcpServers": {
    "xiaohongshu": {
      "command": "/path/to/xiaohongshu-mcp",
      "args": [],
      "env": {}
    }
  }
}
Environment Variables:
  • XHS_DATA_DIR
    : Directory for storing session data (default:
    ./data
    )
  • XHS_PORT
    : HTTP server port (default:
    8080
    )
  • XHS_DEBUG
    : Enable debug logging (default:
    false
    )
MCP服务器可配置用于Claude Desktop或其他MCP客户端:
Claude Desktop配置 (
claude_desktop_config.json
):
json
{
  "mcpServers": {
    "xiaohongshu": {
      "command": "/path/to/xiaohongshu-mcp",
      "args": [],
      "env": {}
    }
  }
}
环境变量:
  • XHS_DATA_DIR
    : 会话数据存储目录(默认:
    ./data
  • XHS_PORT
    : HTTP服务器端口(默认:
    8080
  • XHS_DEBUG
    : 启用调试日志(默认:
    false

MCP Tools

MCP工具

1. Login Management

1. 登录管理

xhs_login: Open login page for manual authentication
json
{
  "name": "xhs_login",
  "arguments": {}
}
xhs_check_login_status: Check if currently logged in
json
{
  "name": "xhs_check_login_status",
  "arguments": {}
}
xhs_login: 打开登录页面进行手动认证
json
{
  "name": "xhs_login",
  "arguments": {}
}
xhs_check_login_status: 检查当前登录状态
json
{
  "name": "xhs_check_login_status",
  "arguments": {}
}

2. Content Publishing

2. 内容发布

xhs_create_image_note: Publish image post
json
{
  "name": "xhs_create_image_note",
  "arguments": {
    "title": "美食分享",
    "desc": "今天做的菜真好吃!\n#美食 #家常菜",
    "images": [
      "/Users/username/Pictures/food1.jpg",
      "/Users/username/Pictures/food2.jpg"
    ],
    "post_time": "",
    "privacy": "public",
    "tags": ["美食", "家常菜"]
  }
}
Image sources supported:
  • Local absolute paths (recommended):
    /path/to/image.jpg
  • HTTP/HTTPS URLs:
    https://example.com/image.jpg
xhs_create_video_note: Publish video post
json
{
  "name": "xhs_create_video_note",
  "arguments": {
    "title": "旅行Vlog",
    "desc": "记录美好时光\n#旅行 #Vlog",
    "video": "/Users/username/Videos/trip.mp4",
    "cover": "/Users/username/Videos/cover.jpg",
    "post_time": "",
    "privacy": "public",
    "tags": ["旅行", "Vlog"]
  }
}
Note: Only local video files are supported (no HTTP URLs).
xhs_create_image_note: 发布图片笔记
json
{
  "name": "xhs_create_image_note",
  "arguments": {
    "title": "美食分享",
    "desc": "今天做的菜真好吃!\n#美食 #家常菜",
    "images": [
      "/Users/username/Pictures/food1.jpg",
      "/Users/username/Pictures/food2.jpg"
    ],
    "post_time": "",
    "privacy": "public",
    "tags": ["美食", "家常菜"]
  }
}
支持的图片来源:
  • 本地绝对路径(推荐):
    /path/to/image.jpg
  • HTTP/HTTPS URL:
    https://example.com/image.jpg
xhs_create_video_note: 发布视频笔记
json
{
  "name": "xhs_create_video_note",
  "arguments": {
    "title": "旅行Vlog",
    "desc": "记录美好时光\n#旅行 #Vlog",
    "video": "/Users/username/Videos/trip.mp4",
    "cover": "/Users/username/Videos/cover.jpg",
    "post_time": "",
    "privacy": "public",
    "tags": ["旅行", "Vlog"]
  }
}
**注意:**仅支持本地视频文件(不支持HTTP URL)。

3. Content Discovery

3. 内容发现

xhs_search: Search for content
json
{
  "name": "xhs_search",
  "arguments": {
    "keyword": "美食",
    "page": 1,
    "page_size": 20,
    "sort": "general"
  }
}
xhs_get_recommend_feeds: Get recommendation feed
json
{
  "name": "xhs_get_recommend_feeds",
  "arguments": {
    "page_size": 10
  }
}
xhs_get_note_detail: Get post details with engagement data
json
{
  "name": "xhs_get_note_detail",
  "arguments": {
    "feed_id": "64f1a2b3c4d5e6f7a8b9c0d1",
    "xsec_token": "ABCdef123456..."
  }
}
Note:
feed_id
and
xsec_token
are obtained from search results or feed lists.
xhs_search: 搜索内容
json
{
  "name": "xhs_search",
  "arguments": {
    "keyword": "美食",
    "page": 1,
    "page_size": 20,
    "sort": "general"
  }
}
xhs_get_recommend_feeds: 获取推荐信息流
json
{
  "name": "xhs_get_recommend_feeds",
  "arguments": {
    "page_size": 10
  }
}
xhs_get_note_detail: 获取包含互动数据的笔记详情
json
{
  "name": "xhs_get_note_detail",
  "arguments": {
    "feed_id": "64f1a2b3c4d5e6f7a8b9c0d1",
    "xsec_token": "ABCdef123456..."
  }
}
注意:
feed_id
xsec_token
可从搜索结果或信息流列表中获取。

4. Interactions

4. 互动管理

xhs_comment_note: Post a comment
json
{
  "name": "xhs_comment_note",
  "arguments": {
    "feed_id": "64f1a2b3c4d5e6f7a8b9c0d1",
    "xsec_token": "ABCdef123456...",
    "content": "写得真好!"
  }
}
xhs_reply_comment: Reply to a comment
json
{
  "name": "xhs_reply_comment",
  "arguments": {
    "feed_id": "64f1a2b3c4d5e6f7a8b9c0d1",
    "xsec_token": "ABCdef123456...",
    "comment_id": "comment_123",
    "content": "谢谢你的支持!"
  }
}
xhs_like_note: Like a post
json
{
  "name": "xhs_like_note",
  "arguments": {
    "feed_id": "64f1a2b3c4d5e6f7a8b9c0d1",
    "xsec_token": "ABCdef123456...",
    "unlike": false
  }
}
xhs_favorite_note: Favorite a post
json
{
  "name": "xhs_favorite_note",
  "arguments": {
    "feed_id": "64f1a2b3c4d5e6f7a8b9c0d1",
    "xsec_token": "ABCdef123456...",
    "unfavorite": false
  }
}
xhs_comment_note: 发布评论
json
{
  "name": "xhs_comment_note",
  "arguments": {
    "feed_id": "64f1a2b3c4d5e6f7a8b9c0d1",
    "xsec_token": "ABCdef123456...",
    "content": "写得真好!"
  }
}
xhs_reply_comment: 回复评论
json
{
  "name": "xhs_reply_comment",
  "arguments": {
    "feed_id": "64f1a2b3c4d5e6f7a8b9c0d1",
    "xsec_token": "ABCdef123456...",
    "comment_id": "comment_123",
    "content": "谢谢你的支持!"
  }
}
xhs_like_note: 点赞笔记
json
{
  "name": "xhs_like_note",
  "arguments": {
    "feed_id": "64f1a2b3c4d5e6f7a8b9c0d1",
    "xsec_token": "ABCdef123456...",
    "unlike": false
  }
}
xhs_favorite_note: 收藏笔记
json
{
  "name": "xhs_favorite_note",
  "arguments": {
    "feed_id": "64f1a2b3c4d5e6f7a8b9c0d1",
    "xsec_token": "ABCdef123456...",
    "unfavorite": false
  }
}

5. User Profiles

5. 用户资料

xhs_get_user_profile: Get user profile and posts
json
{
  "name": "xhs_get_user_profile",
  "arguments": {
    "user_id": "5f9e8d7c6b5a4e3d2c1b0a9",
    "xsec_token": "ABCdef123456..."
  }
}
xhs_get_user_profile: 获取用户资料及笔记
json
{
  "name": "xhs_get_user_profile",
  "arguments": {
    "user_id": "5f9e8d7c6b5a4e3d2c1b0a9",
    "xsec_token": "ABCdef123456..."
  }
}

Code Examples

代码示例

Go: Programmatic Usage

Go: 程序化调用

go
package main

import (
    "context"
    "fmt"
    "log"
    
    "github.com/xpzouying/xiaohongshu-mcp/pkg/xhs"
)

func main() {
    // Initialize client
    client, err := xhs.NewClient(xhs.Config{
        DataDir: "./data",
        Debug:   false,
    })
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()
    
    ctx := context.Background()
    
    // Check login status
    loggedIn, err := client.CheckLoginStatus(ctx)
    if err != nil {
        log.Fatal(err)
    }
    
    if !loggedIn {
        // Trigger login flow
        if err := client.Login(ctx); err != nil {
            log.Fatal(err)
        }
    }
    
    // Search for content
    results, err := client.Search(ctx, xhs.SearchParams{
        Keyword:  "美食",
        Page:     1,
        PageSize: 10,
    })
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("Found %d results\n", len(results.Items))
    
    // Publish an image post
    note, err := client.CreateImageNote(ctx, xhs.ImageNoteParams{
        Title: "美食分享",
        Desc:  "今天做的菜真好吃!\n#美食 #家常菜",
        Images: []string{
            "/path/to/image1.jpg",
            "/path/to/image2.jpg",
        },
        Tags: []string{"美食", "家常菜"},
    })
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("Published note: %s\n", note.ID)
    
    // Like a post
    if len(results.Items) > 0 {
        item := results.Items[0]
        err = client.LikeNote(ctx, xhs.LikeParams{
            FeedID:    item.FeedID,
            XsecToken: item.XsecToken,
        })
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println("Liked post successfully")
    }
}
go
package main

import (
    "context"
    "fmt"
    "log"
    
    "github.com/xpzouying/xiaohongshu-mcp/pkg/xhs"
)

func main() {
    // Initialize client
    client, err := xhs.NewClient(xhs.Config{
        DataDir: "./data",
        Debug:   false,
    })
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()
    
    ctx := context.Background()
    
    // Check login status
    loggedIn, err := client.CheckLoginStatus(ctx)
    if err != nil {
        log.Fatal(err)
    }
    
    if !loggedIn {
        // Trigger login flow
        if err := client.Login(ctx); err != nil {
            log.Fatal(err)
        }
    }
    
    // Search for content
    results, err := client.Search(ctx, xhs.SearchParams{
        Keyword:  "美食",
        Page:     1,
        PageSize: 10,
    })
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("Found %d results\n", len(results.Items))
    
    // Publish an image post
    note, err := client.CreateImageNote(ctx, xhs.ImageNoteParams{
        Title: "美食分享",
        Desc:  "今天做的菜真好吃!\n#美食 #家常菜",
        Images: []string{
            "/path/to/image1.jpg",
            "/path/to/image2.jpg",
        },
        Tags: []string{"美食", "家常菜"},
    })
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("Published note: %s\n", note.ID)
    
    // Like a post
    if len(results.Items) > 0 {
        item := results.Items[0]
        err = client.LikeNote(ctx, xhs.LikeParams{
            FeedID:    item.FeedID,
            XsecToken: item.XsecToken,
        })
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println("Liked post successfully")
    }
}

Go: HTTP API Usage

Go: HTTP API调用

go
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
)

func main() {
    baseURL := "http://localhost:8080"
    
    // Check login status
    resp, err := http.Get(baseURL + "/api/check_login_status")
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    
    var loginStatus struct {
        LoggedIn bool `json:"logged_in"`
    }
    json.NewDecoder(resp.Body).Decode(&loginStatus)
    fmt.Printf("Logged in: %v\n", loginStatus.LoggedIn)
    
    // Search
    searchReq := map[string]interface{}{
        "keyword":   "美食",
        "page":      1,
        "page_size": 10,
    }
    body, _ := json.Marshal(searchReq)
    resp, err = http.Post(
        baseURL+"/api/search",
        "application/json",
        bytes.NewBuffer(body),
    )
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    
    var searchResult map[string]interface{}
    json.NewDecoder(resp.Body).Decode(&searchResult)
    fmt.Printf("Search results: %+v\n", searchResult)
    
    // Publish image post
    publishReq := map[string]interface{}{
        "title": "美食分享",
        "desc":  "今天做的菜真好吃!\n#美食 #家常菜",
        "images": []string{
            "/path/to/image1.jpg",
            "/path/to/image2.jpg",
        },
        "tags": []string{"美食", "家常菜"},
    }
    body, _ = json.Marshal(publishReq)
    resp, err = http.Post(
        baseURL+"/api/create_image_note",
        "application/json",
        bytes.NewBuffer(body),
    )
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    
    result, _ := io.ReadAll(resp.Body)
    fmt.Printf("Published: %s\n", result)
}
go
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
)

func main() {
    baseURL := "http://localhost:8080"
    
    // Check login status
    resp, err := http.Get(baseURL + "/api/check_login_status")
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    
    var loginStatus struct {
        LoggedIn bool `json:"logged_in"`
    }
    json.NewDecoder(resp.Body).Decode(&loginStatus)
    fmt.Printf("Logged in: %v\n", loginStatus.LoggedIn)
    
    // Search
    searchReq := map[string]interface{}{
        "keyword":   "美食",
        "page":      1,
        "page_size": 10,
    }
    body, _ := json.Marshal(searchReq)
    resp, err = http.Post(
        baseURL+"/api/search",
        "application/json",
        bytes.NewBuffer(body),
    )
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    
    var searchResult map[string]interface{}
    json.NewDecoder(resp.Body).Decode(&searchResult)
    fmt.Printf("Search results: %+v\n", searchResult)
    
    // Publish image post
    publishReq := map[string]interface{}{
        "title": "美食分享",
        "desc":  "今天做的菜真好吃!\n#美食 #家常菜",
        "images": []string{
            "/path/to/image1.jpg",
            "/path/to/image2.jpg",
        },
        "tags": []string{"美食", "家常菜"},
    }
    body, _ = json.Marshal(publishReq)
    resp, err = http.Post(
        baseURL+"/api/create_image_note",
        "application/json",
        bytes.NewBuffer(body),
    )
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    
    result, _ := io.ReadAll(resp.Body)
    fmt.Printf("Published: %s\n", result)
}

Python: MCP Client Integration

Python: MCP客户端集成

python
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

async def main():
    server_params = StdioServerParameters(
        command="/path/to/xiaohongshu-mcp",
        args=[],
        env={}
    )
    
    async with stdio_client(server_params) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()
            
            # Check login status
            result = await session.call_tool(
                "xhs_check_login_status",
                arguments={}
            )
            print(f"Login status: {result}")
            
            # Search
            result = await session.call_tool(
                "xhs_search",
                arguments={
                    "keyword": "美食",
                    "page": 1,
                    "page_size": 10
                }
            )
            print(f"Search results: {result}")
            
            # Publish post
            result = await session.call_tool(
                "xhs_create_image_note",
                arguments={
                    "title": "美食分享",
                    "desc": "今天做的菜真好吃!\n#美食 #家常菜",
                    "images": [
                        "/path/to/image1.jpg",
                        "/path/to/image2.jpg"
                    ],
                    "tags": ["美食", "家常菜"]
                }
            )
            print(f"Published: {result}")

if __name__ == "__main__":
    asyncio.run(main())
python
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

async def main():
    server_params = StdioServerParameters(
        command="/path/to/xiaohongshu-mcp",
        args=[],
        env={}
    )
    
    async with stdio_client(server_params) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()
            
            # Check login status
            result = await session.call_tool(
                "xhs_check_login_status",
                arguments={}
            )
            print(f"Login status: {result}")
            
            # Search
            result = await session.call_tool(
                "xhs_search",
                arguments={
                    "keyword": "美食",
                    "page": 1,
                    "page_size": 10
                }
            )
            print(f"Search results: {result}")
            
            # Publish post
            result = await session.call_tool(
                "xhs_create_image_note",
                arguments={
                    "title": "美食分享",
                    "desc": "今天做的菜真好吃!\n#美食 #家常菜",
                    "images": [
                        "/path/to/image1.jpg",
                        "/path/to/image2.jpg"
                    ],
                    "tags": ["美食", "家常菜"]
                }
            )
            print(f"Published: {result}")

if __name__ == "__main__":
    asyncio.run(main())

Common Patterns

常见模式

Pattern 1: Content Automation Workflow

模式1:内容自动化工作流

go
// 1. Check login
loggedIn, _ := client.CheckLoginStatus(ctx)
if !loggedIn {
    client.Login(ctx)
}

// 2. Search for trending topics
results, _ := client.Search(ctx, xhs.SearchParams{
    Keyword:  "trending_topic",
    Page:     1,
    PageSize: 20,
})

// 3. Analyze top posts
for _, item := range results.Items[:5] {
    detail, _ := client.GetNoteDetail(ctx, xhs.NoteDetailParams{
        FeedID:    item.FeedID,
        XsecToken: item.XsecToken,
    })
    // Analyze engagement metrics
    fmt.Printf("Likes: %d, Comments: %d\n", 
        detail.LikeCount, detail.CommentCount)
}

// 4. Publish optimized content
client.CreateImageNote(ctx, xhs.ImageNoteParams{
    Title:  "Title ≤20 chars",
    Desc:   "Optimized content based on analysis\n#trending",
    Images: []string{"/path/to/image.jpg"},
    Tags:   []string{"trending", "topic"},
})
go
// 1. Check login
loggedIn, _ := client.CheckLoginStatus(ctx)
if !loggedIn {
    client.Login(ctx)
}

// 2. Search for trending topics
results, _ := client.Search(ctx, xhs.SearchParams{
    Keyword:  "trending_topic",
    Page:     1,
    PageSize: 20,
})

// 3. Analyze top posts
for _, item := range results.Items[:5] {
    detail, _ := client.GetNoteDetail(ctx, xhs.NoteDetailParams{
        FeedID:    item.FeedID,
        XsecToken: item.XsecToken,
    })
    // Analyze engagement metrics
    fmt.Printf("Likes: %d, Comments: %d\n", 
        detail.LikeCount, detail.CommentCount)
}

// 4. Publish optimized content
client.CreateImageNote(ctx, xhs.ImageNoteParams{
    Title:  "Title ≤20 chars",
    Desc:   "Optimized content based on analysis\n#trending",
    Images: []string{"/path/to/image.jpg"},
    Tags:   []string{"trending", "topic"},
})

Pattern 2: Engagement Automation

模式2:互动自动化

go
// Get recommendations
feeds, _ := client.GetRecommendFeeds(ctx, xhs.FeedParams{
    PageSize: 20,
})

// Engage with relevant content
for _, feed := range feeds.Items {
    // Like posts in your niche
    if isRelevant(feed.Title, feed.Desc) {
        client.LikeNote(ctx, xhs.LikeParams{
            FeedID:    feed.FeedID,
            XsecToken: feed.XsecToken,
        })
        
        // Add thoughtful comment
        client.CommentNote(ctx, xhs.CommentParams{
            FeedID:    feed.FeedID,
            XsecToken: feed.XsecToken,
            Content:   generateComment(feed),
        })
    }
}
go
// Get recommendations
feeds, _ := client.GetRecommendFeeds(ctx, xhs.FeedParams{
    PageSize: 20,
})

// Engage with relevant content
for _, feed := range feeds.Items {
    // Like posts in your niche
    if isRelevant(feed.Title, feed.Desc) {
        client.LikeNote(ctx, xhs.LikeParams{
            FeedID:    feed.FeedID,
            XsecToken: feed.XsecToken,
        })
        
        // Add thoughtful comment
        client.CommentNote(ctx, xhs.CommentParams{
            FeedID:    feed.FeedID,
            XsecToken: feed.XsecToken,
            Content:   generateComment(feed),
        })
    }
}

Pattern 3: Scheduled Publishing

模式3:定时发布

go
// Prepare content queue
posts := []xhs.ImageNoteParams{
    {
        Title:  "Morning Post",
        Desc:   "Content 1\n#tag1",
        Images: []string{"/images/1.jpg"},
    },
    {
        Title:  "Evening Post",
        Desc:   "Content 2\n#tag2",
        Images: []string{"/images/2.jpg"},
    },
}

// Schedule publishing (respect 50 posts/day limit)
for i, post := range posts {
    if i >= 50 {
        break // Daily limit
    }
    
    client.CreateImageNote(ctx, post)
    
    // Wait between posts (avoid rate limiting)
    time.Sleep(5 * time.Minute)
}
go
// Prepare content queue
posts := []xhs.ImageNoteParams{
    {
        Title:  "Morning Post",
        Desc:   "Content 1\n#tag1",
        Images: []string{"/images/1.jpg"},
    },
    {
        Title:  "Evening Post",
        Desc:   "Content 2\n#tag2",
        Images: []string{"/images/2.jpg"},
    },
}

// Schedule publishing (respect 50 posts/day limit)
for i, post := range posts {
    if i >= 50 {
        break // Daily limit
    }
    
    client.CreateImageNote(ctx, post)
    
    // Wait between posts (avoid rate limiting)
    time.Sleep(5 * time.Minute)
}

Troubleshooting

故障排除

Issue: Login Session Expired

问题:登录会话过期

Symptom: API calls return "not logged in" errors
Solution:
go
// Re-authenticate
err := client.Login(ctx)
if err != nil {
    log.Fatal("Login failed:", err)
}
**症状:**API调用返回“未登录”错误
解决方案:
go
// Re-authenticate
err := client.Login(ctx)
if err != nil {
    log.Fatal("Login failed:", err)
}

Issue: Title/Content Length Violations

问题:标题/内容长度违规

Symptom: Post creation fails with validation error
Solution:
go
func validatePost(title, content string) error {
    if len([]rune(title)) > 20 {
        return fmt.Errorf("title too long: %d characters (max 20)", 
            len([]rune(title)))
    }
    if len([]rune(content)) > 1000 {
        return fmt.Errorf("content too long: %d characters (max 1000)", 
            len([]rune(content)))
    }
    return nil
}
**症状:**发布笔记时返回验证错误
解决方案:
go
func validatePost(title, content string) error {
    if len([]rune(title)) > 20 {
        return fmt.Errorf("title too long: %d characters (max 20)", 
            len([]rune(title)))
    }
    if len([]rune(content)) > 1000 {
        return fmt.Errorf("content too long: %d characters (max 1000)", 
            len([]rune(content)))
    }
    return nil
}

Issue: Multiple Web Sessions

问题:多个网页会话

Symptom: Account gets logged out unexpectedly
Solution: Ensure only one web session is active. Use mobile app for manual checks while MCP is running.
**症状:**账号意外登出
**解决方案:**确保仅一个网页会话处于活跃状态。在MCP运行期间,使用移动端APP进行手动检查。

Issue: Image Upload Fails

问题:图片上传失败

Symptom: Image post creation returns error
Solution: Use local absolute paths instead of URLs:
go
// ❌ Avoid
images := []string{"https://example.com/image.jpg"}

// ✅ Prefer
images := []string{"/Users/username/Pictures/image.jpg"}
**症状:**发布图片笔记时返回错误
**解决方案:**使用本地绝对路径而非URL:
go
// ❌ Avoid
images := []string{"https://example.com/image.jpg"}

// ✅ Prefer
images := []string{"/Users/username/Pictures/image.jpg"}

Issue: Rate Limiting

问题:速率限制

Symptom: Actions fail with rate limit errors
Solution: Add delays between operations:
go
const (
    postDelay    = 5 * time.Minute  // Between posts
    likeDelay    = 2 * time.Second  // Between likes
    commentDelay = 10 * time.Second // Between comments
)

time.Sleep(postDelay)
**症状:**操作因速率限制失败
**解决方案:**在操作之间添加延迟:
go
const (
    postDelay    = 5 * time.Minute  // Between posts
    likeDelay    = 2 * time.Second  // Between likes
    commentDelay = 10 * time.Second // Between comments
)

time.Sleep(postDelay)

Issue: Browser Download Fails

问题:浏览器下载失败

Symptom: First run hangs or fails downloading browser
Solution:
  • Ensure stable internet connection
  • Check firewall/proxy settings
  • Manually download browser and set
    PLAYWRIGHT_BROWSERS_PATH
    env var
**症状:**首次运行时挂起或下载浏览器失败
解决方案:
  • 确保稳定的网络连接
  • 检查防火墙/代理设置
  • 手动下载浏览器并设置
    PLAYWRIGHT_BROWSERS_PATH
    环境变量

Issue: Account Verification Required

问题:需要账号验证

Symptom: Platform requests identity verification
Solution: This is normal for new/unverified accounts. Complete identity verification through the mobile app, then retry.
**症状:**平台要求身份验证
**解决方案:**这对于新账号或未验证账号是正常现象。通过移动端APP完成身份验证后重试。

Best Practices

最佳实践

  1. Respect platform limits: Max 50 posts/day per account
  2. Avoid spam behavior: Add delays between automated actions
  3. Use quality content: Platform penalizes low-quality/duplicate content
  4. Monitor account health: Watch for verification requests or restrictions
  5. Use local files: More reliable than URL-based image/video uploads
  6. Validate content: Check title/content length before posting
  7. Handle errors gracefully: Implement retry logic with exponential backoff
  8. Keep sessions alive: Re-authenticate when sessions expire
  9. Single web session: Don't log in on multiple web browsers simultaneously
  10. Avoid prohibited content: Use content screening tools to check for violations
  1. **遵守平台限制:**每个账号每日最多发布50篇笔记
  2. **避免垃圾行为:**在自动化操作之间添加延迟
  3. **使用优质内容:**平台会惩罚低质量/重复内容
  4. **监控账号健康:**关注验证请求或限制通知
  5. **使用本地文件:**比基于URL的图片/视频上传更可靠
  6. **验证内容:**发布前检查标题/内容长度
  7. **优雅处理错误:**实现带指数退避的重试逻辑
  8. **保持会话活跃:**会话过期时重新认证
  9. **单一网页会话:**不要同时在多个网页浏览器登录
  10. **避免违规内容:**使用内容筛查工具检查是否违反规定