{"url_pattern":"^https?://(www\\.)?zhihu\\.com/.*$","site_name":"zhihu","allowed_domains":["example.com","zhihu.com","zhuanlan.zhihu.com"],"tools":[{"name":"insert_article","description":"Insert content into Zhihu article editor (must be on zhuanlan.zhihu.com/write)","inputSchema":{"type":"object","properties":{"title":{"type":"string","description":"Article title"},"content":{"type":"string","description":"Article content (HTML)"}},"required":["content"]},"handler":"(params) => {\n  // Find editor\n  const editor = document.querySelector('.public-DraftEditor-content') || document.querySelector('[data-slate-editor]') || document.querySelector('[contenteditable=\"true\"]');\n  if (!editor) {\n    return { success: false, message: 'Editor not found. Open zhihu.com/write or zhuanlan.zhihu.com/write first' };\n  }\n  // Set title\n  if (params.title) {\n    const titleInput = document.querySelector('textarea[placeholder*=\"标题\"]') || document.querySelector('.WriteIndex-titleInput textarea');\n    if (titleInput) {\n      const setter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, 'value').set;\n      setter.call(titleInput, params.title);\n      titleInput.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n  }\n  // Insert content\n  editor.focus();\n  editor.innerHTML = params.content;\n  editor.dispatchEvent(new Event('input', { bubbles: true }));\n  return { success: true, message: 'Content inserted into Zhihu editor' };\n}"},{"name":"open_write_page","description":"Navigate to Zhihu article writing page","inputSchema":{"type":"object","properties":{},"required":null},"handler":"() => {\n  window.location.href = 'https://zhuanlan.zhihu.com/write';\n  return { success: true, message: 'Opening Zhihu write page...' };\n}"},{"name":"zhihu_hot","description":"Get Zhihu hot list (trending topics)","inputSchema":{"type":"object","properties":{"count":{"type":"string","description":"Number of items to return (default: 20, max: 50)"}},"required":null},"handler":"(params) => {\n  const run = async function(args) {\n\n      const count = Math.min(parseInt(args.count) || 20, 50);\n      const resp = await fetch('https://www.zhihu.com/api/v3/feed/topstory/hot-lists/total?limit=50', {credentials: 'include'});\n      if (!resp.ok) return {error: 'HTTP ' + resp.status, hint: 'Not logged in?'};\n      const d = await resp.json();\n      const items = (d.data || []).slice(0, count).map((item, i) => {\n        const t = item.target || {};\n        return {\n          rank: i + 1,\n          id: t.id,\n          title: t.title,\n          url: 'https://www.zhihu.com/question/' + t.id,\n          excerpt: t.excerpt || '',\n          answer_count: t.answer_count,\n          follower_count: t.follower_count,\n          heat: item.detail_text || '',\n          trend: item.trend === 0 ? 'stable' : item.trend > 0 ? 'up' : 'down',\n          is_new: item.debut || false\n        };\n      });\n      return {count: items.length, items};\n  };\n  return run(params || {});\n}"},{"name":"zhihu_me","description":"Get current logged-in Zhihu user info","inputSchema":{"type":"object","properties":{},"required":null},"handler":"(params) => {\n  const run = async function(args) {\n\n      const resp = await fetch('https://www.zhihu.com/api/v4/me', {credentials: 'include'});\n      if (!resp.ok) return {error: 'HTTP ' + resp.status, hint: 'Not logged in?'};\n      const u = await resp.json();\n      return {\n        id: u.id,\n        uid: u.uid,\n        name: u.name,\n        url: 'https://www.zhihu.com/people/' + u.url_token,\n        url_token: u.url_token,\n        headline: u.headline,\n        gender: u.gender === 1 ? 'male' : u.gender === 0 ? 'female' : 'unknown',\n        ip_info: u.ip_info,\n        avatar_url: u.avatar_url,\n        is_vip: u.vip_info?.is_vip || false,\n        answer_count: u.answer_count,\n        question_count: u.question_count,\n        articles_count: u.articles_count,\n        columns_count: u.columns_count,\n        favorite_count: u.favorite_count,\n        voteup_count: u.voteup_count,\n        thanked_count: u.thanked_count,\n        creation_count: u.creation_count,\n        notifications: {\n          default: u.default_notifications_count,\n          follow: u.follow_notifications_count,\n          vote_thank: u.vote_thank_notifications_count,\n          messages: u.messages_count\n        }\n      };\n  };\n  return run(params || {});\n}"},{"name":"zhihu_question","description":"Get a Zhihu question and its top answers","inputSchema":{"type":"object","properties":{"id":{"type":"string","description":"Question ID (numeric)"},"count":{"type":"string","description":"Number of answers to fetch (default: 5, max: 20)"}},"required":["id"]},"handler":"(params) => {\n  const run = async function(args) {\n\n      if (!args.id) return {error: 'Missing argument: id'};\n      const qid = args.id;\n      const count = Math.min(parseInt(args.count) || 5, 20);\n\n      // Fetch question detail and answers in parallel\n      const [qResp, aResp] = await Promise.all([\n        fetch('https://www.zhihu.com/api/v4/questions/' + qid + '?include=data[*].detail,excerpt,answer_count,follower_count,visit_count,comment_count,topics', {credentials: 'include'}),\n        fetch('https://www.zhihu.com/api/v4/questions/' + qid + '/answers?limit=' + count + '&offset=0&sort_by=default&include=data[*].content,voteup_count,comment_count,author', {credentials: 'include'})\n      ]);\n\n      if (!qResp.ok) return {error: 'HTTP ' + qResp.status + ' fetching question', hint: qResp.status === 404 ? 'Question not found' : 'Not logged in?'};\n      if (!aResp.ok) return {error: 'HTTP ' + aResp.status + ' fetching answers', hint: 'Not logged in?'};\n\n      const q = await qResp.json();\n      const aData = await aResp.json();\n\n      // Strip HTML tags helper\n      const strip = (html) => (html || '').replace(/<[^>]+>/g, '').replace(/&nbsp;/g, ' ').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&').trim();\n\n      const answers = (aData.data || []).map((a, i) => ({\n        rank: i + 1,\n        id: a.id,\n        author: a.author?.name || 'anonymous',\n        author_headline: a.author?.headline || '',\n        voteup_count: a.voteup_count,\n        comment_count: a.comment_count,\n        content: strip(a.content).substring(0, 800),\n        created_time: a.created_time,\n        updated_time: a.updated_time\n      }));\n\n      return {\n        id: q.id,\n        title: q.title,\n        url: 'https://www.zhihu.com/question/' + qid,\n        detail: strip(q.detail) || '',\n        excerpt: q.excerpt || '',\n        answer_count: q.answer_count,\n        follower_count: q.follower_count,\n        visit_count: q.visit_count,\n        comment_count: q.comment_count,\n        topics: (q.topics || []).map(t => t.name),\n        answers_total: aData.paging?.totals || answers.length,\n        answers\n      };\n  };\n  return run(params || {});\n}"},{"name":"zhihu_search","description":"Search Zhihu for questions and answers","inputSchema":{"type":"object","properties":{"keyword":{"type":"string","description":"Search keyword"},"count":{"type":"string","description":"Number of results (default: 10, max: 20)"}},"required":["keyword"]},"handler":"(params) => {\n  const run = async function(args) {\n\n      if (!args.keyword) return {error: 'Missing argument: keyword'};\n      const count = Math.min(parseInt(args.count) || 10, 20);\n      const resp = await fetch('https://www.zhihu.com/api/v4/search_v3?q=' + encodeURIComponent(args.keyword) + '&t=general&offset=0&limit=' + count, {credentials: 'include'});\n      if (!resp.ok) return {error: 'HTTP ' + resp.status, hint: 'Not logged in?'};\n      const d = await resp.json();\n\n      // Strip HTML tags helper\n      const strip = (html) => (html || '').replace(/<[^>]+>/g, '').replace(/&nbsp;/g, ' ').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&').replace(/<em>/g, '').replace(/<\\/em>/g, '').trim();\n\n      const results = (d.data || [])\n        .filter(item => item.type === 'search_result')\n        .map((item, i) => {\n          const obj = item.object || {};\n          const q = obj.question || {};\n          return {\n            rank: i + 1,\n            type: obj.type,\n            id: obj.id,\n            title: strip(obj.title || q.name || ''),\n            excerpt: strip(obj.excerpt || ''),\n            url: obj.type === 'answer'\n              ? 'https://www.zhihu.com/question/' + q.id + '/answer/' + obj.id\n              : obj.type === 'article'\n              ? 'https://zhuanlan.zhihu.com/p/' + obj.id\n              : 'https://www.zhihu.com/question/' + obj.id,\n            author: obj.author?.name || '',\n            voteup_count: obj.voteup_count || 0,\n            comment_count: obj.comment_count || 0,\n            question_id: q.id || null,\n            question_title: strip(q.name || ''),\n            created_time: obj.created_time,\n            updated_time: obj.updated_time\n          };\n        });\n\n      return {\n        keyword: args.keyword,\n        count: results.length,\n        has_more: !d.paging?.is_end,\n        results\n      };\n  };\n  return run(params || {});\n}"}]}