linux-do WebMCP
Browser tool configuration for linux-do
Tools (6)
linux_do_categories()
linux.do 分类列表
Parameters
JavaScript Handler
(params) => {
const args = Object.assign({"subcategories": false, "limit": 20}, params || {});
let data = null;
let __wbContextUrl = globalThis.location?.href || '';
let __wbContextDocument = globalThis.document || null;
const __wbDefault = (value, fallback) => (value === undefined || value === null || value === '' ? fallback : value);
const __wbJoin = (value, separator) => Array.isArray(value) ? value.join(separator) : (value ?? '');
const __wbGet = (value, path) => {
if (!path) return value;
return String(path).split('.').reduce((acc, part) => (acc == null ? undefined : acc[part]), value);
};
const __wbBaseUrl = () => (__wbContextUrl || globalThis.location?.href || 'https://example.com/');
const __wbResolve = (target, base) => {
if (target == null) return '';
const text = String(target);
try {
return /^https?:/i.test(text) ? text : new URL(text, base || __wbBaseUrl()).toString();
} catch (_error) {
return text;
}
};
const __wbFetch = async (target, options) => {
const url = __wbResolve(target, __wbBaseUrl());
const resp = await globalThis.fetch(url, Object.assign({ credentials: 'include' }, options || {}));
if (!resp.ok) {
throw new Error(`HTTP ${resp.status} for ${url}`);
}
const text = await resp.text();
try {
return { url, text, data: JSON.parse(text) };
} catch (_error) {
return { url, text, data: text };
}
};
return (async () => {
{
const __wbResp = await __wbFetch("https://linux.do");
__wbContextUrl = __wbResp.url;
__wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');
data = __wbContextDocument;
}
{
const document = __wbContextDocument || globalThis.document;
const location = new URL(__wbBaseUrl());
const window = { document, location };
const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));
data = await (((async () => {
const res = await fetch('/categories.json', { credentials: 'include' });
if (!res.ok) throw new Error('HTTP ' + res.status + ' - 请先登录 linux.do');
let data;
try { data = await res.json(); } catch { throw new Error('响应不是有效 JSON - 请先登录 linux.do'); }
const cats = data?.category_list?.categories || [];
const showSub = (args.subcategories);
const results = [];
const limit = (args.limit);
for (const c of cats.slice(0, (args.limit))) {
results.push({
name: c.name,
slug: c.slug,
id: c.id,
topics: c.topic_count,
description: (c.description_text || '').slice(0, 80),
});
if (results.length >= limit) break;
if (showSub && c.subcategory_ids && c.subcategory_ids.length > 0) {
const subRes = await fetch('/categories.json?parent_category_id=' + c.id, { credentials: 'include' });
if (subRes.ok) {
let subData;
try { subData = await subRes.json(); } catch { continue; }
const subCats = subData?.category_list?.categories || [];
for (const sc of subCats) {
results.push({
name: c.name + ' / ' + sc.name,
slug: sc.slug,
id: sc.id,
topics: sc.topic_count,
description: (sc.description_text || '').slice(0, 80),
});
if (results.length >= limit) break;
}
}
}
if (results.length >= limit) break;
}
return results;
})())());
}
{
const source = Array.isArray(data) ? data : (data == null ? [] : [data]);
data = source.map((item, index) => ({
"name": item.name,
"slug": item.slug,
"id": item.id,
"topics": item.topics,
"description": item.description,
}));
}
return data;
})();
}
linux_do_search()
搜索 linux.do
Parameters
JavaScript Handler
(params) => {
const args = Object.assign({"limit": 20}, params || {});
let data = null;
let __wbContextUrl = globalThis.location?.href || '';
let __wbContextDocument = globalThis.document || null;
const __wbDefault = (value, fallback) => (value === undefined || value === null || value === '' ? fallback : value);
const __wbJoin = (value, separator) => Array.isArray(value) ? value.join(separator) : (value ?? '');
const __wbGet = (value, path) => {
if (!path) return value;
return String(path).split('.').reduce((acc, part) => (acc == null ? undefined : acc[part]), value);
};
const __wbBaseUrl = () => (__wbContextUrl || globalThis.location?.href || 'https://example.com/');
const __wbResolve = (target, base) => {
if (target == null) return '';
const text = String(target);
try {
return /^https?:/i.test(text) ? text : new URL(text, base || __wbBaseUrl()).toString();
} catch (_error) {
return text;
}
};
const __wbFetch = async (target, options) => {
const url = __wbResolve(target, __wbBaseUrl());
const resp = await globalThis.fetch(url, Object.assign({ credentials: 'include' }, options || {}));
if (!resp.ok) {
throw new Error(`HTTP ${resp.status} for ${url}`);
}
const text = await resp.text();
try {
return { url, text, data: JSON.parse(text) };
} catch (_error) {
return { url, text, data: text };
}
};
return (async () => {
{
const __wbResp = await __wbFetch("https://linux.do");
__wbContextUrl = __wbResp.url;
__wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');
data = __wbContextDocument;
}
{
const document = __wbContextDocument || globalThis.document;
const location = new URL(__wbBaseUrl());
const window = { document, location };
const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));
data = await (((async () => {
const keyword = ((args.query));
const res = await fetch('/search.json?q=' + encodeURIComponent(keyword), { credentials: 'include' });
if (!res.ok) throw new Error('HTTP ' + res.status + ' - 请先登录 linux.do');
let data;
try { data = await res.json(); } catch { throw new Error('响应不是有效 JSON - 请先登录 linux.do'); }
const topics = data?.topics || [];
return topics.slice(0, (args.limit)).map(t => ({
title: t.title,
views: t.views,
likes: t.like_count,
replies: (t.posts_count || 1) - 1,
url: 'https://linux.do/t/topic/' + t.id,
}));
})())());
}
{
const source = Array.isArray(data) ? data : (data == null ? [] : [data]);
data = source.map((item, index) => ({
"rank": index + 1,
"title": item.title,
"views": item.views,
"likes": item.likes,
"replies": item.replies,
"url": item.url,
}));
}
if (Array.isArray(data)) data = data.slice(0, Number(args.limit) || 0);
return data;
})();
}
linux_do_tags()
linux.do 标签列表
Parameters
JavaScript Handler
(params) => {
const args = Object.assign({"limit": 30}, params || {});
let data = null;
let __wbContextUrl = globalThis.location?.href || '';
let __wbContextDocument = globalThis.document || null;
const __wbDefault = (value, fallback) => (value === undefined || value === null || value === '' ? fallback : value);
const __wbJoin = (value, separator) => Array.isArray(value) ? value.join(separator) : (value ?? '');
const __wbGet = (value, path) => {
if (!path) return value;
return String(path).split('.').reduce((acc, part) => (acc == null ? undefined : acc[part]), value);
};
const __wbBaseUrl = () => (__wbContextUrl || globalThis.location?.href || 'https://example.com/');
const __wbResolve = (target, base) => {
if (target == null) return '';
const text = String(target);
try {
return /^https?:/i.test(text) ? text : new URL(text, base || __wbBaseUrl()).toString();
} catch (_error) {
return text;
}
};
const __wbFetch = async (target, options) => {
const url = __wbResolve(target, __wbBaseUrl());
const resp = await globalThis.fetch(url, Object.assign({ credentials: 'include' }, options || {}));
if (!resp.ok) {
throw new Error(`HTTP ${resp.status} for ${url}`);
}
const text = await resp.text();
try {
return { url, text, data: JSON.parse(text) };
} catch (_error) {
return { url, text, data: text };
}
};
return (async () => {
{
const __wbResp = await __wbFetch("https://linux.do");
__wbContextUrl = __wbResp.url;
__wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');
data = __wbContextDocument;
}
{
const document = __wbContextDocument || globalThis.document;
const location = new URL(__wbBaseUrl());
const window = { document, location };
const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));
data = await (((async () => {
const res = await fetch('/tags.json', { credentials: 'include' });
if (!res.ok) throw new Error('HTTP ' + res.status + ' - 请先登录 linux.do');
let data;
try { data = await res.json(); } catch { throw new Error('响应不是有效 JSON - 请先登录 linux.do'); }
let tags = data?.tags || [];
tags.sort((a, b) => (b.count || 0) - (a.count || 0));
return tags.slice(0, (args.limit)).map(t => ({
id: t.id,
name: t.name || t.id,
slug: t.slug,
count: t.count || 0,
}));
})())());
}
{
const source = Array.isArray(data) ? data : (data == null ? [] : [data]);
data = source.map((item, index) => ({
"rank": index + 1,
"name": item.name,
"count": item.count,
"slug": item.slug,
"id": item.id,
"url": `https://linux.do/tag/${item.slug}`,
}));
}
return data;
})();
}
linux_do_topic()
linux.do 帖子详情和回复(首页)
Parameters
JavaScript Handler
(params) => {
const args = Object.assign({"limit": 20, "main_only": false}, params || {});
let data = null;
let __wbContextUrl = globalThis.location?.href || '';
let __wbContextDocument = globalThis.document || null;
const __wbDefault = (value, fallback) => (value === undefined || value === null || value === '' ? fallback : value);
const __wbJoin = (value, separator) => Array.isArray(value) ? value.join(separator) : (value ?? '');
const __wbGet = (value, path) => {
if (!path) return value;
return String(path).split('.').reduce((acc, part) => (acc == null ? undefined : acc[part]), value);
};
const __wbBaseUrl = () => (__wbContextUrl || globalThis.location?.href || 'https://example.com/');
const __wbResolve = (target, base) => {
if (target == null) return '';
const text = String(target);
try {
return /^https?:/i.test(text) ? text : new URL(text, base || __wbBaseUrl()).toString();
} catch (_error) {
return text;
}
};
const __wbFetch = async (target, options) => {
const url = __wbResolve(target, __wbBaseUrl());
const resp = await globalThis.fetch(url, Object.assign({ credentials: 'include' }, options || {}));
if (!resp.ok) {
throw new Error(`HTTP ${resp.status} for ${url}`);
}
const text = await resp.text();
try {
return { url, text, data: JSON.parse(text) };
} catch (_error) {
return { url, text, data: text };
}
};
return (async () => {
{
const __wbResp = await __wbFetch("https://linux.do");
__wbContextUrl = __wbResp.url;
__wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');
data = __wbContextDocument;
}
{
const document = __wbContextDocument || globalThis.document;
const location = new URL(__wbBaseUrl());
const window = { document, location };
const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));
data = await (((async () => {
const mainOnly = (args.main_only);
const toLocalTime = (utcStr) => {
if (!utcStr) return '';
const date = new Date(utcStr);
return Number.isNaN(date.getTime()) ? utcStr : date.toLocaleString();
};
const res = await fetch('/t/(args.id).json', { credentials: 'include' });
if (!res.ok) throw new Error('HTTP ' + res.status + ' - 请先登录 linux.do');
let data;
try { data = await res.json(); } catch { throw new Error('响应不是有效 JSON - 请先登录 linux.do'); }
const strip = (html) => (html || '')
.replace(/<br\s*\/?>/gi, ' ')
.replace(/<\/(p|div|li|blockquote|h[1-6])>/gi, ' ')
.replace(/<[^>]+>/g, '')
.replace(/ /g, ' ')
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/&#(?:(\d+)|x([0-9a-fA-F]+));/g, (_, dec, hex) => {
try { return String.fromCodePoint(dec !== undefined ? Number(dec) : parseInt(hex, 16)); } catch { return ''; }
})
.replace(/\s+/g, ' ')
.trim();
const posts = data?.post_stream?.posts || [];
if (mainOnly) {
const mainPost = posts.find(p => p.post_number === 1);
if (!mainPost) return [];
return [{
author: mainPost.username || '',
content: mainPost.cooked || '',
likes: mainPost.like_count || 0,
created_at: toLocalTime(mainPost.created_at),
}];
}
return posts.slice(0, (args.limit)).map(p => ({
author: p.username,
content: strip(p.cooked).slice(0, 200),
likes: p.like_count,
created_at: toLocalTime(p.created_at),
}));
})())());
}
{
const source = Array.isArray(data) ? data : (data == null ? [] : [data]);
data = source.map((item, index) => ({
"author": item.author,
"content": item.content,
"likes": item.likes,
"created_at": item.created_at,
}));
}
return data;
})();
}
linux_do_user_posts()
linux.do 用户的帖子
Parameters
JavaScript Handler
(params) => {
const args = Object.assign({"limit": 20}, params || {});
let data = null;
let __wbContextUrl = globalThis.location?.href || '';
let __wbContextDocument = globalThis.document || null;
const __wbDefault = (value, fallback) => (value === undefined || value === null || value === '' ? fallback : value);
const __wbJoin = (value, separator) => Array.isArray(value) ? value.join(separator) : (value ?? '');
const __wbGet = (value, path) => {
if (!path) return value;
return String(path).split('.').reduce((acc, part) => (acc == null ? undefined : acc[part]), value);
};
const __wbBaseUrl = () => (__wbContextUrl || globalThis.location?.href || 'https://example.com/');
const __wbResolve = (target, base) => {
if (target == null) return '';
const text = String(target);
try {
return /^https?:/i.test(text) ? text : new URL(text, base || __wbBaseUrl()).toString();
} catch (_error) {
return text;
}
};
const __wbFetch = async (target, options) => {
const url = __wbResolve(target, __wbBaseUrl());
const resp = await globalThis.fetch(url, Object.assign({ credentials: 'include' }, options || {}));
if (!resp.ok) {
throw new Error(`HTTP ${resp.status} for ${url}`);
}
const text = await resp.text();
try {
return { url, text, data: JSON.parse(text) };
} catch (_error) {
return { url, text, data: text };
}
};
return (async () => {
{
const __wbResp = await __wbFetch("https://linux.do");
__wbContextUrl = __wbResp.url;
__wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');
data = __wbContextDocument;
}
{
const document = __wbContextDocument || globalThis.document;
const location = new URL(__wbBaseUrl());
const window = { document, location };
const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));
data = await (((async () => {
const username = ((args.username));
const toLocalTime = (utcStr) => {
if (!utcStr) return '';
const date = new Date(utcStr);
return Number.isNaN(date.getTime()) ? utcStr : date.toLocaleString();
};
const strip = (html) => (html || '')
.replace(/<br\s*\/?>/gi, ' ')
.replace(/<\/(p|div|li|blockquote|h[1-6])>/gi, ' ')
.replace(/<[^>]+>/g, '')
.replace(/ /g, ' ')
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/&#(?:(\d+)|x([0-9a-fA-F]+));/g, (_, dec, hex) => {
try { return String.fromCodePoint(dec !== undefined ? Number(dec) : parseInt(hex, 16)); } catch { return ''; }
})
.replace(/\s+/g, ' ')
.trim();
const limit = (__wbDefault((args.limit), 20));
const res = await fetch('/user_actions.json?username=' + encodeURIComponent(username) + '&filter=5&offset=0&limit=' + limit, { credentials: 'include' });
if (!res.ok) throw new Error('HTTP ' + res.status + ' - 请先登录 linux.do');
let data;
try { data = await res.json(); } catch { throw new Error('响应不是有效 JSON - 请先登录 linux.do'); }
const actions = data?.user_actions || [];
return actions.slice(0, limit).map(a => ({
author: a.acting_username || a.username || '',
title: a.title || '',
content: strip(a.excerpt).slice(0, 200),
created_at: toLocalTime(a.created_at),
url: 'https://linux.do/t/topic/' + a.topic_id + '/' + a.post_number,
}));
})())());
}
{
const source = Array.isArray(data) ? data : (data == null ? [] : [data]);
data = source.map((item, index) => ({
"index": index + 1,
"topic_user": item.author,
"topic": item.title,
"reply": item.content,
"time": item.created_at,
"url": item.url,
}));
}
return data;
})();
}
linux_do_user_topics()
linux.do 用户创建的话题
Parameters
JavaScript Handler
(params) => {
const args = Object.assign({"limit": 20}, params || {});
let data = null;
let __wbContextUrl = globalThis.location?.href || '';
let __wbContextDocument = globalThis.document || null;
const __wbDefault = (value, fallback) => (value === undefined || value === null || value === '' ? fallback : value);
const __wbJoin = (value, separator) => Array.isArray(value) ? value.join(separator) : (value ?? '');
const __wbGet = (value, path) => {
if (!path) return value;
return String(path).split('.').reduce((acc, part) => (acc == null ? undefined : acc[part]), value);
};
const __wbBaseUrl = () => (__wbContextUrl || globalThis.location?.href || 'https://example.com/');
const __wbResolve = (target, base) => {
if (target == null) return '';
const text = String(target);
try {
return /^https?:/i.test(text) ? text : new URL(text, base || __wbBaseUrl()).toString();
} catch (_error) {
return text;
}
};
const __wbFetch = async (target, options) => {
const url = __wbResolve(target, __wbBaseUrl());
const resp = await globalThis.fetch(url, Object.assign({ credentials: 'include' }, options || {}));
if (!resp.ok) {
throw new Error(`HTTP ${resp.status} for ${url}`);
}
const text = await resp.text();
try {
return { url, text, data: JSON.parse(text) };
} catch (_error) {
return { url, text, data: text };
}
};
return (async () => {
{
const __wbResp = await __wbFetch("https://linux.do");
__wbContextUrl = __wbResp.url;
__wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');
data = __wbContextDocument;
}
{
const document = __wbContextDocument || globalThis.document;
const location = new URL(__wbBaseUrl());
const window = { document, location };
const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));
data = await (((async () => {
const username = ((args.username));
const toLocalTime = (utcStr) => {
if (!utcStr) return '';
const date = new Date(utcStr);
return Number.isNaN(date.getTime()) ? utcStr : date.toLocaleString();
};
const res = await fetch('/topics/created-by/' + encodeURIComponent(username) + '.json', { credentials: 'include' });
if (!res.ok) throw new Error('HTTP ' + res.status + ' - 请先登录 linux.do');
let data;
try { data = await res.json(); } catch { throw new Error('响应不是有效 JSON - 请先登录 linux.do'); }
const topics = data?.topic_list?.topics || [];
return topics.slice(0, (args.limit)).map(t => ({
title: t.fancy_title || t.title || '',
replies: t.posts_count || 0,
created_at: toLocalTime(t.created_at),
likes: t.like_count || 0,
views: t.views || 0,
url: 'https://linux.do/t/topic/' + t.id,
}));
})())());
}
{
const source = Array.isArray(data) ? data : (data == null ? [] : [data]);
data = source.map((item, index) => ({
"rank": index + 1,
"title": item.title,
"replies": item.replies,
"created_at": item.created_at,
"likes": item.likes,
"views": item.views,
"url": item.url,
}));
}
return data;
})();
}
🔌 Chrome MCP Server Extension
Use these tools with Claude, ChatGPT, and other AI assistants.
How to Use WebMCP
WebMCP tools are designed for browser extensions or automation frameworks. The browser extension matches the current URL against the pattern and executes the JavaScript handler when the tool is invoked.
API Endpoint:
GET /api/webmcp/match?url=https://www.linux-do.com/...