xiaohongshu-mcp-integration
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesexiaohongshu-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 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.
xiaohongshu-mcpCore 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核心功能:
- 登录及会话管理
- 发布图片笔记(标题最多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
undefined1. 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
undefinedbash
undefinedPull 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
--name xiaohongshu-mcp
-p 8080:8080
-v $(pwd)/data:/app/data
xpzouying/xiaohongshu-mcp:latest
undefineddocker run -d
--name xiaohongshu-mcp
-p 8080:8080
-v $(pwd)/data:/app/data
xpzouying/xiaohongshu-mcp:latest
--name xiaohongshu-mcp
-p 8080:8080
-v $(pwd)/data:/app/data
xpzouying/xiaohongshu-mcp:latest
undefinedMethod 3: Build from Source
方法3:从源码构建
bash
undefinedbash
undefinedClone the repository
Clone the repository
git clone https://github.com/xpzouying/xiaohongshu-mcp.git
cd xiaohongshu-mcp
git clone https://github.com/xpzouying/xiaohongshu-mcp.git
cd xiaohongshu-mcp
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
undefinedConfiguration
配置
The MCP server can be configured for Claude Desktop or other MCP clients:
Claude Desktop Configuration ():
claude_desktop_config.jsonjson
{
"mcpServers": {
"xiaohongshu": {
"command": "/path/to/xiaohongshu-mcp",
"args": [],
"env": {}
}
}
}Environment Variables:
- : Directory for storing session data (default:
XHS_DATA_DIR)./data - : HTTP server port (default:
XHS_PORT)8080 - : Enable debug logging (default:
XHS_DEBUG)false
MCP服务器可配置用于Claude Desktop或其他MCP客户端:
Claude Desktop配置 ():
claude_desktop_config.jsonjson
{
"mcpServers": {
"xiaohongshu": {
"command": "/path/to/xiaohongshu-mcp",
"args": [],
"env": {}
}
}
}环境变量:
- : 会话数据存储目录(默认:
XHS_DATA_DIR)./data - : HTTP服务器端口(默认:
XHS_PORT)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: and are obtained from search results or feed lists.
feed_idxsec_tokenxhs_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_idxsec_token4. 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 env var
PLAYWRIGHT_BROWSERS_PATH
**症状:**首次运行时挂起或下载浏览器失败
解决方案:
- 确保稳定的网络连接
- 检查防火墙/代理设置
- 手动下载浏览器并设置环境变量
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
最佳实践
- Respect platform limits: Max 50 posts/day per account
- Avoid spam behavior: Add delays between automated actions
- Use quality content: Platform penalizes low-quality/duplicate content
- Monitor account health: Watch for verification requests or restrictions
- Use local files: More reliable than URL-based image/video uploads
- Validate content: Check title/content length before posting
- Handle errors gracefully: Implement retry logic with exponential backoff
- Keep sessions alive: Re-authenticate when sessions expire
- Single web session: Don't log in on multiple web browsers simultaneously
- Avoid prohibited content: Use content screening tools to check for violations
- **遵守平台限制:**每个账号每日最多发布50篇笔记
- **避免垃圾行为:**在自动化操作之间添加延迟
- **使用优质内容:**平台会惩罚低质量/重复内容
- **监控账号健康:**关注验证请求或限制通知
- **使用本地文件:**比基于URL的图片/视频上传更可靠
- **验证内容:**发布前检查标题/内容长度
- **优雅处理错误:**实现带指数退避的重试逻辑
- **保持会话活跃:**会话过期时重新认证
- **单一网页会话:**不要同时在多个网页浏览器登录
- **避免违规内容:**使用内容筛查工具检查是否违反规定