WORLDBOOK

Worldbooks | WebMCP | Search | Submit WebMCP

v2ex WebMCP

Browser tool configuration for v2ex

URL Pattern: ^https?://(www\.)?v2ex\.com(/.*)?$
Allowed Extra Domains: example.com, v2ex.com

Tools (8)

v2ex_hot()

获取 V2EX 最热主题

Parameters

No parameters

JavaScript Handler

(params) => {
  const run = async function(args) {

      const resp = await fetch('https://www.v2ex.com/api/topics/hot.json');
      if (!resp.ok) return {error: 'HTTP ' + resp.status};
      const topics = await resp.json();
      return {count: topics.length, topics: topics.map(t => ({
        id: t.id, title: t.title, content: (t.content || '').substring(0, 300),
        node: t.node?.title, nodeSlug: t.node?.name,
        author: t.member?.username, replies: t.replies,
        created: t.created, url: t.url
      }))};
  };
  return run(params || {});
}

v2ex_latest()

获取 V2EX 最新主题

Parameters

No parameters

JavaScript Handler

(params) => {
  const run = async function(args) {

      const resp = await fetch('https://www.v2ex.com/api/topics/latest.json');
      if (!resp.ok) return {error: 'HTTP ' + resp.status};
      const topics = await resp.json();
      return {count: topics.length, topics: topics.map(t => ({
        id: t.id, title: t.title, content: (t.content || '').substring(0, 300),
        node: t.node?.title, nodeSlug: t.node?.name,
        author: t.member?.username, replies: t.replies,
        created: t.created, url: t.url
      }))};
  };
  return run(params || {});
}

v2ex_member()

V2EX 用户资料

Parameters

username string required - Username

JavaScript Handler

(params) => {
  const args = Object.assign({}, 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://www.v2ex.com/api/members/show.json");
      data = __wbResp.data;
    }
    {
      const source = Array.isArray(data) ? data : (data == null ? [] : [data]);
      data = source.map((item, index) => ({
        "username": item.username,
        "tagline": item.tagline,
        "website": item.website,
        "github": item.github,
        "twitter": item.twitter,
        "location": item.location,
      }));
    }
    return data;
  })();
}

v2ex_node()

V2EX 节点话题列表

Parameters

name string required - Node name (e.g. python, javascript, apple)
limit number - Number of topics (API returns max 20)

JavaScript Handler

(params) => {
  const args = Object.assign({"limit": 10}, 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://www.v2ex.com/api/topics/show.json");
      data = __wbResp.data;
    }
    {
      const source = Array.isArray(data) ? data : (data == null ? [] : [data]);
      data = source.map((item, index) => ({
        "rank": index + 1,
        "title": item.title,
        "author": item.member.username,
        "replies": item.replies,
        "url": item.url,
      }));
    }
    if (Array.isArray(data)) data = data.slice(0, Number(args.limit) || 0);
    return data;
  })();
}

v2ex_nodes()

V2EX 所有节点列表

Parameters

limit number - Number of nodes

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://www.v2ex.com/api/nodes/all.json");
      data = __wbResp.data;
    }
    {
      const source = Array.isArray(data) ? [...data] : (data == null ? [] : [data]);
      const by = "topics";
      const desc = true;
      source.sort((left, right) => {
        const a = __wbGet(left, by);
        const b = __wbGet(right, by);
        if (a === b) return 0;
        if (a == null) return desc ? 1 : -1;
        if (b == null) return desc ? -1 : 1;
        return desc ? (a < b ? 1 : -1) : (a > b ? 1 : -1);
      });
      data = source;
    }
    {
      const source = Array.isArray(data) ? data : (data == null ? [] : [data]);
      data = source.map((item, index) => ({
        "rank": index + 1,
        "name": item.name,
        "title": item.title,
        "topics": item.topics,
        "stars": item.stars,
      }));
    }
    if (Array.isArray(data)) data = data.slice(0, Number(args.limit) || 0);
    return data;
  })();
}

v2ex_replies()

V2EX 主题回复列表

Parameters

id string required - Topic ID
limit number - Number of replies

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://www.v2ex.com/api/replies/show.json");
      data = __wbResp.data;
    }
    {
      const source = Array.isArray(data) ? data : (data == null ? [] : [data]);
      data = source.map((item, index) => ({
        "floor": index + 1,
        "author": item.member.username,
        "content": item.content,
      }));
    }
    if (Array.isArray(data)) data = data.slice(0, Number(args.limit) || 0);
    return data;
  })();
}

v2ex_topic()

获取 V2EX 主题详情和回复

Parameters

id string required - Topic ID

JavaScript Handler

(params) => {
  const run = async function(args) {

      if (!args.id) return {error: 'Missing argument: id', hint: 'Provide a topic ID'};
      const [topicResp, repliesResp] = await Promise.all([
        fetch('https://www.v2ex.com/api/topics/show.json?id=' + args.id),
        fetch('https://www.v2ex.com/api/replies/show.json?topic_id=' + args.id)
      ]);
      if (!topicResp.ok) return {error: 'HTTP ' + topicResp.status};
      const topics = await topicResp.json();
      const replies = repliesResp.ok ? await repliesResp.json() : [];
      const t = topics[0];
      if (!t) return {error: 'Topic not found'};
      return {
        id: t.id, title: t.title, content: t.content,
        node: t.node?.title, author: t.member?.username,
        replies: t.replies, created: t.created, url: t.url,
        comments: replies.map(r => ({
          author: r.member?.username, content: r.content, created: r.created
        }))
      };
  };
  return run(params || {});
}

v2ex_user()

V2EX 用户发帖列表

Parameters

username string required - Username
limit number - Number of topics (API returns max 20)

JavaScript Handler

(params) => {
  const args = Object.assign({"limit": 10}, 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://www.v2ex.com/api/topics/show.json");
      data = __wbResp.data;
    }
    {
      const source = Array.isArray(data) ? data : (data == null ? [] : [data]);
      data = source.map((item, index) => ({
        "rank": index + 1,
        "title": item.title,
        "node": item.node.title,
        "replies": item.replies,
        "url": item.url,
      }));
    }
    if (Array.isArray(data)) data = data.slice(0, Number(args.limit) || 0);
    return data;
  })();
}

🔌 Chrome MCP Server Extension

Use these tools with Claude, ChatGPT, and other AI assistants.

Get Extension →

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.v2ex.com/...