{"url_pattern":"^https?://(www\\.)?v2ex\\.com(/.*)?$","site_name":"v2ex","allowed_domains":["example.com","v2ex.com"],"tools":[{"name":"v2ex_hot","description":"获取 V2EX 最热主题","inputSchema":{"type":"object","properties":{},"required":null},"handler":"(params) => {\n  const run = async function(args) {\n\n      const resp = await fetch('https://www.v2ex.com/api/topics/hot.json');\n      if (!resp.ok) return {error: 'HTTP ' + resp.status};\n      const topics = await resp.json();\n      return {count: topics.length, topics: topics.map(t => ({\n        id: t.id, title: t.title, content: (t.content || '').substring(0, 300),\n        node: t.node?.title, nodeSlug: t.node?.name,\n        author: t.member?.username, replies: t.replies,\n        created: t.created, url: t.url\n      }))};\n  };\n  return run(params || {});\n}"},{"name":"v2ex_latest","description":"获取 V2EX 最新主题","inputSchema":{"type":"object","properties":{},"required":null},"handler":"(params) => {\n  const run = async function(args) {\n\n      const resp = await fetch('https://www.v2ex.com/api/topics/latest.json');\n      if (!resp.ok) return {error: 'HTTP ' + resp.status};\n      const topics = await resp.json();\n      return {count: topics.length, topics: topics.map(t => ({\n        id: t.id, title: t.title, content: (t.content || '').substring(0, 300),\n        node: t.node?.title, nodeSlug: t.node?.name,\n        author: t.member?.username, replies: t.replies,\n        created: t.created, url: t.url\n      }))};\n  };\n  return run(params || {});\n}"},{"name":"v2ex_member","description":"V2EX 用户资料","inputSchema":{"type":"object","properties":{"username":{"type":"string","description":"Username"}},"required":["username"]},"handler":"(params) => {\n  const args = Object.assign({}, params || {});\n  let data = null;\n  let __wbContextUrl = globalThis.location?.href || '';\n  let __wbContextDocument = globalThis.document || null;\n    const __wbDefault = (value, fallback) => (value === undefined || value === null || value === '' ? fallback : value);\n    const __wbJoin = (value, separator) => Array.isArray(value) ? value.join(separator) : (value ?? '');\n    const __wbGet = (value, path) => {\n      if (!path) return value;\n      return String(path).split('.').reduce((acc, part) => (acc == null ? undefined : acc[part]), value);\n    };\n    const __wbBaseUrl = () => (__wbContextUrl || globalThis.location?.href || 'https://example.com/');\n    const __wbResolve = (target, base) => {\n      if (target == null) return '';\n      const text = String(target);\n      try {\n        return /^https?:/i.test(text) ? text : new URL(text, base || __wbBaseUrl()).toString();\n      } catch (_error) {\n        return text;\n      }\n    };\n    const __wbFetch = async (target, options) => {\n      const url = __wbResolve(target, __wbBaseUrl());\n      const resp = await globalThis.fetch(url, Object.assign({ credentials: 'include' }, options || {}));\n      if (!resp.ok) {\n        throw new Error(`HTTP ${resp.status} for ${url}`);\n      }\n      const text = await resp.text();\n      try {\n        return { url, text, data: JSON.parse(text) };\n      } catch (_error) {\n        return { url, text, data: text };\n      }\n    };\n  return (async () => {\n    {\n      const __wbResp = await __wbFetch(\"https://www.v2ex.com/api/members/show.json\");\n      data = __wbResp.data;\n    }\n    {\n      const source = Array.isArray(data) ? data : (data == null ? [] : [data]);\n      data = source.map((item, index) => ({\n        \"username\": item.username,\n        \"tagline\": item.tagline,\n        \"website\": item.website,\n        \"github\": item.github,\n        \"twitter\": item.twitter,\n        \"location\": item.location,\n      }));\n    }\n    return data;\n  })();\n}"},{"name":"v2ex_node","description":"V2EX 节点话题列表","inputSchema":{"type":"object","properties":{"name":{"type":"string","description":"Node name (e.g. python, javascript, apple)"},"limit":{"type":"number","description":"Number of topics (API returns max 20)","default":10}},"required":["name"]},"handler":"(params) => {\n  const args = Object.assign({\"limit\": 10}, params || {});\n  let data = null;\n  let __wbContextUrl = globalThis.location?.href || '';\n  let __wbContextDocument = globalThis.document || null;\n    const __wbDefault = (value, fallback) => (value === undefined || value === null || value === '' ? fallback : value);\n    const __wbJoin = (value, separator) => Array.isArray(value) ? value.join(separator) : (value ?? '');\n    const __wbGet = (value, path) => {\n      if (!path) return value;\n      return String(path).split('.').reduce((acc, part) => (acc == null ? undefined : acc[part]), value);\n    };\n    const __wbBaseUrl = () => (__wbContextUrl || globalThis.location?.href || 'https://example.com/');\n    const __wbResolve = (target, base) => {\n      if (target == null) return '';\n      const text = String(target);\n      try {\n        return /^https?:/i.test(text) ? text : new URL(text, base || __wbBaseUrl()).toString();\n      } catch (_error) {\n        return text;\n      }\n    };\n    const __wbFetch = async (target, options) => {\n      const url = __wbResolve(target, __wbBaseUrl());\n      const resp = await globalThis.fetch(url, Object.assign({ credentials: 'include' }, options || {}));\n      if (!resp.ok) {\n        throw new Error(`HTTP ${resp.status} for ${url}`);\n      }\n      const text = await resp.text();\n      try {\n        return { url, text, data: JSON.parse(text) };\n      } catch (_error) {\n        return { url, text, data: text };\n      }\n    };\n  return (async () => {\n    {\n      const __wbResp = await __wbFetch(\"https://www.v2ex.com/api/topics/show.json\");\n      data = __wbResp.data;\n    }\n    {\n      const source = Array.isArray(data) ? data : (data == null ? [] : [data]);\n      data = source.map((item, index) => ({\n        \"rank\": index + 1,\n        \"title\": item.title,\n        \"author\": item.member.username,\n        \"replies\": item.replies,\n        \"url\": item.url,\n      }));\n    }\n    if (Array.isArray(data)) data = data.slice(0, Number(args.limit) || 0);\n    return data;\n  })();\n}"},{"name":"v2ex_nodes","description":"V2EX 所有节点列表","inputSchema":{"type":"object","properties":{"limit":{"type":"number","description":"Number of nodes","default":30}},"required":null},"handler":"(params) => {\n  const args = Object.assign({\"limit\": 30}, params || {});\n  let data = null;\n  let __wbContextUrl = globalThis.location?.href || '';\n  let __wbContextDocument = globalThis.document || null;\n    const __wbDefault = (value, fallback) => (value === undefined || value === null || value === '' ? fallback : value);\n    const __wbJoin = (value, separator) => Array.isArray(value) ? value.join(separator) : (value ?? '');\n    const __wbGet = (value, path) => {\n      if (!path) return value;\n      return String(path).split('.').reduce((acc, part) => (acc == null ? undefined : acc[part]), value);\n    };\n    const __wbBaseUrl = () => (__wbContextUrl || globalThis.location?.href || 'https://example.com/');\n    const __wbResolve = (target, base) => {\n      if (target == null) return '';\n      const text = String(target);\n      try {\n        return /^https?:/i.test(text) ? text : new URL(text, base || __wbBaseUrl()).toString();\n      } catch (_error) {\n        return text;\n      }\n    };\n    const __wbFetch = async (target, options) => {\n      const url = __wbResolve(target, __wbBaseUrl());\n      const resp = await globalThis.fetch(url, Object.assign({ credentials: 'include' }, options || {}));\n      if (!resp.ok) {\n        throw new Error(`HTTP ${resp.status} for ${url}`);\n      }\n      const text = await resp.text();\n      try {\n        return { url, text, data: JSON.parse(text) };\n      } catch (_error) {\n        return { url, text, data: text };\n      }\n    };\n  return (async () => {\n    {\n      const __wbResp = await __wbFetch(\"https://www.v2ex.com/api/nodes/all.json\");\n      data = __wbResp.data;\n    }\n    {\n      const source = Array.isArray(data) ? [...data] : (data == null ? [] : [data]);\n      const by = \"topics\";\n      const desc = true;\n      source.sort((left, right) => {\n        const a = __wbGet(left, by);\n        const b = __wbGet(right, by);\n        if (a === b) return 0;\n        if (a == null) return desc ? 1 : -1;\n        if (b == null) return desc ? -1 : 1;\n        return desc ? (a < b ? 1 : -1) : (a > b ? 1 : -1);\n      });\n      data = source;\n    }\n    {\n      const source = Array.isArray(data) ? data : (data == null ? [] : [data]);\n      data = source.map((item, index) => ({\n        \"rank\": index + 1,\n        \"name\": item.name,\n        \"title\": item.title,\n        \"topics\": item.topics,\n        \"stars\": item.stars,\n      }));\n    }\n    if (Array.isArray(data)) data = data.slice(0, Number(args.limit) || 0);\n    return data;\n  })();\n}"},{"name":"v2ex_replies","description":"V2EX 主题回复列表","inputSchema":{"type":"object","properties":{"id":{"type":"string","description":"Topic ID"},"limit":{"type":"number","description":"Number of replies","default":20}},"required":["id"]},"handler":"(params) => {\n  const args = Object.assign({\"limit\": 20}, params || {});\n  let data = null;\n  let __wbContextUrl = globalThis.location?.href || '';\n  let __wbContextDocument = globalThis.document || null;\n    const __wbDefault = (value, fallback) => (value === undefined || value === null || value === '' ? fallback : value);\n    const __wbJoin = (value, separator) => Array.isArray(value) ? value.join(separator) : (value ?? '');\n    const __wbGet = (value, path) => {\n      if (!path) return value;\n      return String(path).split('.').reduce((acc, part) => (acc == null ? undefined : acc[part]), value);\n    };\n    const __wbBaseUrl = () => (__wbContextUrl || globalThis.location?.href || 'https://example.com/');\n    const __wbResolve = (target, base) => {\n      if (target == null) return '';\n      const text = String(target);\n      try {\n        return /^https?:/i.test(text) ? text : new URL(text, base || __wbBaseUrl()).toString();\n      } catch (_error) {\n        return text;\n      }\n    };\n    const __wbFetch = async (target, options) => {\n      const url = __wbResolve(target, __wbBaseUrl());\n      const resp = await globalThis.fetch(url, Object.assign({ credentials: 'include' }, options || {}));\n      if (!resp.ok) {\n        throw new Error(`HTTP ${resp.status} for ${url}`);\n      }\n      const text = await resp.text();\n      try {\n        return { url, text, data: JSON.parse(text) };\n      } catch (_error) {\n        return { url, text, data: text };\n      }\n    };\n  return (async () => {\n    {\n      const __wbResp = await __wbFetch(\"https://www.v2ex.com/api/replies/show.json\");\n      data = __wbResp.data;\n    }\n    {\n      const source = Array.isArray(data) ? data : (data == null ? [] : [data]);\n      data = source.map((item, index) => ({\n        \"floor\": index + 1,\n        \"author\": item.member.username,\n        \"content\": item.content,\n      }));\n    }\n    if (Array.isArray(data)) data = data.slice(0, Number(args.limit) || 0);\n    return data;\n  })();\n}"},{"name":"v2ex_topic","description":"获取 V2EX 主题详情和回复","inputSchema":{"type":"object","properties":{"id":{"type":"string","description":"Topic ID"}},"required":["id"]},"handler":"(params) => {\n  const run = async function(args) {\n\n      if (!args.id) return {error: 'Missing argument: id', hint: 'Provide a topic ID'};\n      const [topicResp, repliesResp] = await Promise.all([\n        fetch('https://www.v2ex.com/api/topics/show.json?id=' + args.id),\n        fetch('https://www.v2ex.com/api/replies/show.json?topic_id=' + args.id)\n      ]);\n      if (!topicResp.ok) return {error: 'HTTP ' + topicResp.status};\n      const topics = await topicResp.json();\n      const replies = repliesResp.ok ? await repliesResp.json() : [];\n      const t = topics[0];\n      if (!t) return {error: 'Topic not found'};\n      return {\n        id: t.id, title: t.title, content: t.content,\n        node: t.node?.title, author: t.member?.username,\n        replies: t.replies, created: t.created, url: t.url,\n        comments: replies.map(r => ({\n          author: r.member?.username, content: r.content, created: r.created\n        }))\n      };\n  };\n  return run(params || {});\n}"},{"name":"v2ex_user","description":"V2EX 用户发帖列表","inputSchema":{"type":"object","properties":{"username":{"type":"string","description":"Username"},"limit":{"type":"number","description":"Number of topics (API returns max 20)","default":10}},"required":["username"]},"handler":"(params) => {\n  const args = Object.assign({\"limit\": 10}, params || {});\n  let data = null;\n  let __wbContextUrl = globalThis.location?.href || '';\n  let __wbContextDocument = globalThis.document || null;\n    const __wbDefault = (value, fallback) => (value === undefined || value === null || value === '' ? fallback : value);\n    const __wbJoin = (value, separator) => Array.isArray(value) ? value.join(separator) : (value ?? '');\n    const __wbGet = (value, path) => {\n      if (!path) return value;\n      return String(path).split('.').reduce((acc, part) => (acc == null ? undefined : acc[part]), value);\n    };\n    const __wbBaseUrl = () => (__wbContextUrl || globalThis.location?.href || 'https://example.com/');\n    const __wbResolve = (target, base) => {\n      if (target == null) return '';\n      const text = String(target);\n      try {\n        return /^https?:/i.test(text) ? text : new URL(text, base || __wbBaseUrl()).toString();\n      } catch (_error) {\n        return text;\n      }\n    };\n    const __wbFetch = async (target, options) => {\n      const url = __wbResolve(target, __wbBaseUrl());\n      const resp = await globalThis.fetch(url, Object.assign({ credentials: 'include' }, options || {}));\n      if (!resp.ok) {\n        throw new Error(`HTTP ${resp.status} for ${url}`);\n      }\n      const text = await resp.text();\n      try {\n        return { url, text, data: JSON.parse(text) };\n      } catch (_error) {\n        return { url, text, data: text };\n      }\n    };\n  return (async () => {\n    {\n      const __wbResp = await __wbFetch(\"https://www.v2ex.com/api/topics/show.json\");\n      data = __wbResp.data;\n    }\n    {\n      const source = Array.isArray(data) ? data : (data == null ? [] : [data]);\n      data = source.map((item, index) => ({\n        \"rank\": index + 1,\n        \"title\": item.title,\n        \"node\": item.node.title,\n        \"replies\": item.replies,\n        \"url\": item.url,\n      }));\n    }\n    if (Array.isArray(data)) data = data.slice(0, Number(args.limit) || 0);\n    return data;\n  })();\n}"}]}