Skip to main content
Glama
README.md

# linuxdo-mcp

#### 本帖使用社区公益推广,符合推广要求。我申明并遵循社区要求的以下内容:
* **我的项目是免费使用的,无收费(变相收费、赞助)部分:** 是 
* **我的帖子已经打上 #公益推广 标签:** 是 
* **我的项目属于个人项目,与公司或商业机构无关:** 是 
* **我的项目不存在QQ、TG等群组引流:** 是 
* **我的项目不存在非运营必要的网站引流:** 是 
* **我的项目不存在为他人推广、AFF:** 是 
* **我的项目无关联的商业项目:** 是 
* **我的站点存在登录,并已接入 LINUX DO Connect:** 否
* **我帖子内的项目介绍,AI生成、润色内容部分已截图发出:** 是 
* **以上选择我承诺是永久有效的,接受社区和佬友监督:** 是 

  
搜索 / 阅读 [linux.do](https://linux.do)(Discourse 论坛)的 MCP 服务器。
用 [curl_cffi](https://github.com/lexiforest/curl_cffi) 模拟 Chrome TLS 指纹绕过 Cloudflare,
凭登录 cookie 访问受信任等级限制的内容。

## 工具

| 工具 | 返回 | 说明 |
|------|------|------|
| `whoami()` | JSON | 当前 cookie 对应的登录用户与信任等级 |
| `search(query, page=1, pages=1)` | JSON | 全量搜索,`query` 支持 Discourse 高级语法 |
| `get_topic(topic_id, posts=5)` | JSON | 话题详情 + 前 N 楼正文 |
| `list_categories()` | JSON | 所有板块,含各自话题数 `topic_count`、帖子数 `post_count` |
| `category_topics(category_id, page=1)` | JSON | 指定类别下的话题列表(每页约 30),含该类别总话题数 |
| `list_tags()` | JSON | 所有标签及各自话题数 `count` |
| `tag_topics(tag, page=1)` | JSON | 指定标签下的话题列表 |
| `user_info(username)` | JSON | 用户资料:信任等级、头衔、发帖数、获赞数、注册/在线时间 |
| `latest_topics(page=1)` | JSON | 首页「最新」话题 |
| `top_topics(period="weekly", page=1)` | JSON | 「热门」话题,period: daily/weekly/monthly/quarterly/yearly/all |
| `user_actions(username, limit=20)` | JSON | 某用户的发帖/回复活动(含摘要与链接) |
| `format_search(query, page=1, pages=1)` | Markdown | 同 search,直接返回成品 Markdown(标题+URL+摘要) |
| `format_topic(topic_id, posts=20)` | Markdown | 同 get_topic,直接返回成品 Markdown(出处头+逐楼表格) |

- `format_*` 工具返回拼好的 Markdown 字符串,客户端可原样展示;其余返回结构化 JSON。
- `get_topic` / `format_topic` 的 `topic_id` 可直接传话题 URL(如 `https://linux.do/t/xxx/2885565`),自动解析出 id。
- 搜索高级语法:`order:latest`、`#分类`、`@用户`、`tags:标签`、`after:2025-01-01`、`in:title` 等。

## 前置

- 安装 [uv](https://docs.astral.sh/uv/)(提供 `uvx`)。
- 准备一个 linux.do 的登录 cookie(`_t`),给法见下方「登录配置」。只需 `_t`,**不需要** `cf_clearance`。

## 配置(复制到你的 MCP 客户端)

`uvx` 会自动拉取并运行,无需下载代码。基础配置:

```json
{
  "mcpServers": {
    "linuxdo": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/mrsxs/linuxdo-mcp", "linuxdo-mcp"]
    }
  }
}
```

再按下面「登录配置」二选一填 `env`。

- **Claude Code**:`claude mcp add-json linuxdo '<上面的内容>'`,或写进 `.mcp.json` / 设置。
- **Cursor / Claude Desktop / Cline**:粘进各自的 MCP 配置文件即可。

## 登录配置(两种方式,二选一)

> 为什么不直接读你平时用的浏览器?因为工具和主浏览器**共用同一个 `_t`** 时,
> Discourse 的 token 轮换会判定异常、把会话作废,导致**主浏览器被顶下线**。
> 所以默认 `LINUXDO_READ_BROWSER=0`(不读浏览器),请用下面任一「独立身份」。

### 方式一:独立 token(任何平台通用,最省心)

在**隐身窗口**或另一个浏览器登录 linux.do,F12 → Application → Cookies → `https://linux.do`
→ 复制 `_t` 的值,填进 `env`:

```json
"env": { "LINUXDO_COOKIE": "_t=你复制的值" }
```

只需填一次:工具之后自动接收 Discourse 轮换、写回缓存**自续期**,长期免维护,且与主浏览器互不影响。

### 方式二:专用 Chrome profile 自动读(macOS/Linux,免手工复制)

在 Chrome 右上角头像 →「添加」新建一个 profile(例:显示名 `linuxdo`),在其中登录 linux.do,然后:

```json
"env": {
  "LINUXDO_READ_BROWSER": "1",
  "LINUXDO_CHROME_PROFILE": "linuxdo"
}
```

`LINUXDO_CHROME_PROFILE` 可填**显示名**(Chrome 菜单里看到的,如 `linuxdo`)或**目录名**(如 `Profile 1`);
填错会列出所有可用 profile 供对照。工具首次自动读该 profile 做 bootstrap,之后同样走缓存自续期。
你日常用的主 profile(`Default`)完全不受影响——只要不在这个专用 profile 里刷 linux.do 就永不冲突。

## cookie 获取顺序与续期

1. 缓存文件 `~/.cache/linuxdo-mcp/cookie.json`(权限 600,工具自维护、含轮换续期,最新);
2. 环境变量 `LINUXDO_COOKIE`(方式一,首次 bootstrap 后写入缓存);
3. 浏览器 cookie 库(方式二,仅当 `LINUXDO_READ_BROWSER=1`)。

`_t` 是 Discourse 的滚动 token,工具每次请求都会接收服务器轮换回来的新值写回缓存,
所以配一次通常长期有效;遇 401/403 会清缓存并提示更新。

方式二各平台授权差异:

| 平台 | Chrome/Chromium/Brave | Firefox |
|---|---|---|
| macOS | 首次弹一次钥匙串授权框,选「始终允许」;uv 缓存重建致解释器路径变化时会再弹一次 | 免授权 |
| Linux | 一般免授权(cookie 若在已上锁的 gnome-keyring/kwallet 则需解锁) | 免授权 |
| Windows | **不支持**(pycookiecheat 只支持 macOS/Linux),请用方式一或 `LINUXDO_BROWSER=firefox` | 免授权 |

## 环境变量一览

| 变量 | 说明 |
|---|---|
| `LINUXDO_COOKIE` | 方式一:手工指定 cookie,形如 `_t=xxx`(裸 token 也可) |
| `LINUXDO_READ_BROWSER` | 方式二:置 `1` 才允许读浏览器(默认 `0`,防止与主浏览器互顶) |
| `LINUXDO_CHROME_PROFILE` | 方式二:Chrome 系 profile 的显示名或目录名(如 `linuxdo` / `Profile 1`) |
| `LINUXDO_BROWSER` | `chrome`(默认)/`chromium`/`brave`/`slack`/`firefox` |
| `LINUXDO_COOKIE_TTL` | 缓存有效期秒数,默认 `2592000`(30 天,配合自续期) |
| `LINUXDO_CACHE_DIR` | 缓存目录,默认 `~/.cache/linuxdo-mcp` |
| `LINUXDO_IMPERSONATE` | TLS 指纹,默认 `chrome` |

> ⚠️ `_t` 等于你的 linux.do 登录凭证,只填进自己的本地配置,**切勿分享给他人**。


## 本地运行(开发)

```bash
uvx --from . linuxdo-mcp        # 或 uv run src/linuxdo_mcp/server.py
```

## 备注

- cookie 过期返回 401/403 时会清缓存并提示更新;按你选的方式重配一次即可(方式二一般不会到期,浏览器保持登录时会自动续期)。
- 读取浏览器 cookie 依赖 [pycookiecheat](https://github.com/n8henrie/pycookiecheat),只读取 linux.do 一个域名下的 cookie。
- 偶发被 Cloudflare 拦截时会自动重试 3 次;仍失败可设 `LINUXDO_IMPERSONATE=chrome131`(或 `chrome124`)换指纹。
- 所有请求为只读 GET,不做任何写操作。

TDQS

B3.4/5.0

Scored across 13 tools

Disambiguation3/5

Most tools map to distinct resources or filters, but search/format_search and get_topic/format_topic are essentially the same operations differing only in output formatting. The descriptions make the distinction explicit, so confusion is possible but not severe.

Naming Consistency3/5

Names mix bare verbs (search), verb_noun patterns (get_topic, list_categories), noun_topics forms (category_topics, latest_topics), and standalone words (whoami). All names are lowercase snake_case and readable, but they do not follow a single predictable convention.

Tool Count4/5

At 13 tools the count is within a reasonable range for a forum reader, but format_search and format_topic are redundant with search and get_topic, slightly padding the surface. The remaining tools each contribute meaningfully to searching and browsing the forum.

Completeness4/5

For a read-oriented forum browsing/searching server, the coverage is solid: search, topic detail, categories, tags, users, and topic feeds are all present. Obvious gaps like posting or replying would matter only if write access was expected, which is not suggested by the tool set.

Maintenance

ActivityMaintained
ResponsivenessNo issues