{"url_pattern":"^https?://(www\\.)?facebook\\.com(/.*)?$","site_name":"facebook","allowed_domains":["example.com","facebook.com"],"tools":[{"name":"facebook_events","description":"Browse Facebook event categories","inputSchema":{"type":"object","properties":{"limit":{"type":"number","description":"Number of categories","default":15}},"required":null},"handler":"(params) => {\n  const args = Object.assign({\"limit\": 15}, 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.facebook.com/events\");\n      __wbContextUrl = __wbResp.url;\n      __wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');\n      data = __wbContextDocument;\n    }\n    {\n      const document = __wbContextDocument || globalThis.document;\n      const location = new URL(__wbBaseUrl());\n      const window = { document, location };\n      const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));\n      data = await (((() => {\n  const limit = (args.limit);\n  // Try actual event items first\n  const articles = document.querySelectorAll('[role=\"article\"]');\n  if (articles.length > 0) {\n    return Array.from(articles).slice(0, limit).map((el, i) => ({\n      index: i + 1,\n      name: el.textContent.trim().replace(/\\s+/g, ' ').substring(0, 120),\n    }));\n  }\n\n  // List event categories from sidebar navigation\n  const links = Array.from(document.querySelectorAll('[role=\"navigation\"] a'))\n    .filter(a => {\n      const href = a.href || '';\n      const text = a.textContent.trim();\n      return href.includes('/events/') && text.length > 1 && text.length < 60 &&\n        !href.includes('create');\n    });\n\n  return links.slice(0, limit).map((a, i) => ({\n    index: i + 1,\n    name: a.textContent.trim(),\n  }));\n})())());\n    }\n    return data;\n  })();\n}"},{"name":"facebook_feed","description":"Get your Facebook news feed","inputSchema":{"type":"object","properties":{"limit":{"type":"number","description":"Number of posts","default":10}},"required":null},"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.facebook.com/\");\n      __wbContextUrl = __wbResp.url;\n      __wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');\n      data = __wbContextDocument;\n    }\n    {\n      const document = __wbContextDocument || globalThis.document;\n      const location = new URL(__wbBaseUrl());\n      const window = { document, location };\n      const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));\n      data = await (((() => {\n  const limit = (args.limit);\n  const posts = document.querySelectorAll('[role=\"article\"]');\n  return Array.from(posts)\n    .filter(el => {\n      const text = el.textContent.trim();\n      // Filter out \"People you may know\" suggestions (both CN and EN)\n      return text.length > 30 &&\n        !text.startsWith('可能认识') &&\n        !text.startsWith('People you may know') &&\n        !text.startsWith('People You May Know');\n    })\n    .slice(0, limit)\n    .map((el, i) => {\n      // Author from header link\n      const headerLink = el.querySelector('h2 a, h3 a, h4 a, strong a');\n      const author = headerLink ? headerLink.textContent.trim() : '';\n\n      // Post text: grab visible spans, filter noise\n      const spans = Array.from(el.querySelectorAll('div[dir=\"auto\"]'))\n        .map(s => s.textContent.trim())\n        .filter(t => t.length > 10 && t.length < 500);\n      const content = spans.length > 0 ? spans[0] : '';\n\n      // Engagement: find like/comment/share counts (CN + EN)\n      const allText = el.textContent;\n      const likesMatch = allText.match(/所有心情：([\\d,.\\s]*[\\d万亿KMk]+)/) ||\n                         allText.match(/All:\\s*([\\d,.KMk]+)/) ||\n                         allText.match(/([\\d,.KMk]+)\\s*(?:likes?|reactions?)/i);\n      const commentsMatch = allText.match(/([\\d,.]+\\s*[万亿]?)\\s*条评论/) ||\n                            allText.match(/([\\d,.KMk]+)\\s*comments?/i);\n      const sharesMatch = allText.match(/([\\d,.]+\\s*[万亿]?)\\s*次分享/) ||\n                          allText.match(/([\\d,.KMk]+)\\s*shares?/i);\n\n      return {\n        index: i + 1,\n        author: author.substring(0, 50),\n        content: content.replace(/\\n/g, ' ').substring(0, 120),\n        likes: likesMatch ? likesMatch[1] : '-',\n        comments: commentsMatch ? commentsMatch[1] : '-',\n        shares: sharesMatch ? sharesMatch[1] : '-',\n      };\n    });\n})())());\n    }\n    return data;\n  })();\n}"},{"name":"facebook_friends","description":"Get Facebook friend suggestions","inputSchema":{"type":"object","properties":{"limit":{"type":"number","description":"Number of friend suggestions","default":10}},"required":null},"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.facebook.com/friends\");\n      __wbContextUrl = __wbResp.url;\n      __wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');\n      data = __wbContextDocument;\n    }\n    {\n      const document = __wbContextDocument || globalThis.document;\n      const location = new URL(__wbBaseUrl());\n      const window = { document, location };\n      const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));\n      data = await (((() => {\n  const limit = (args.limit);\n  const items = document.querySelectorAll('[role=\"listitem\"]');\n  return Array.from(items)\n    .slice(0, limit)\n    .map((el, i) => {\n      const text = el.textContent.trim().replace(/\\s+/g, ' ');\n      // Extract mutual info if present (before name extraction to avoid pollution)\n      const mutualMatch = text.match(/([\\d,]+)\\s*位.*(?:关注|共同|mutual)/);\n      // Extract name: remove mutual info, action buttons, etc.\n      let name = text\n        .replace(/[\\d,]+\\s*位.*(?:关注了|共同好友|mutual friends?)/, '')\n        .replace(/加好友.*/, '').replace(/Add [Ff]riend.*/, '')\n        .replace(/移除$/, '').replace(/Remove$/, '')\n        .trim();\n      return {\n        index: i + 1,\n        name: name.substring(0, 50),\n        mutual: mutualMatch ? mutualMatch[1] : '-',\n      };\n    })\n    .filter(item => item.name.length > 0);\n})())());\n    }\n    return data;\n  })();\n}"},{"name":"facebook_groups","description":"List your Facebook groups","inputSchema":{"type":"object","properties":{"limit":{"type":"number","description":"Number of groups","default":20}},"required":null},"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.facebook.com/groups/feed/\");\n      __wbContextUrl = __wbResp.url;\n      __wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');\n      data = __wbContextDocument;\n    }\n    {\n      const document = __wbContextDocument || globalThis.document;\n      const location = new URL(__wbBaseUrl());\n      const window = { document, location };\n      const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));\n      data = await (((() => {\n  const limit = (args.limit);\n  const links = Array.from(document.querySelectorAll('a'))\n    .filter(a => {\n      const href = a.href || '';\n      return href.includes('/groups/') &&\n        !href.includes('/feed') &&\n        !href.includes('/discover') &&\n        !href.includes('/joins') &&\n        !href.includes('category=create') &&\n        a.textContent.trim().length > 2;\n    });\n\n  // Deduplicate by href\n  const seen = new Set();\n  const groups = [];\n  for (const a of links) {\n    const href = a.href.split('?')[0];\n    if (seen.has(href)) continue;\n    seen.add(href);\n    const raw = a.textContent.trim().replace(/\\s+/g, ' ');\n    // Split name from \"上次发帖\" info\n    const parts = raw.split(/上次发帖|Last post/);\n    groups.push({\n      name: (parts[0] || '').trim().substring(0, 60),\n      last_post: parts[1] ? parts[1].replace(/^[：:]/, '').trim() : '-',\n      url: href,\n    });\n  }\n  return groups.slice(0, limit).map((g, i) => ({ index: i + 1, ...g }));\n})())());\n    }\n    return data;\n  })();\n}"},{"name":"facebook_memories","description":"Get your Facebook memories (On This Day)","inputSchema":{"type":"object","properties":{"limit":{"type":"number","description":"Number of memories","default":10}},"required":null},"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.facebook.com/onthisday\");\n      __wbContextUrl = __wbResp.url;\n      __wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');\n      data = __wbContextDocument;\n    }\n    {\n      const document = __wbContextDocument || globalThis.document;\n      const location = new URL(__wbBaseUrl());\n      const window = { document, location };\n      const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));\n      data = await (((() => {\n  const limit = (args.limit);\n  const articles = document.querySelectorAll('[role=\"article\"]');\n  return Array.from(articles)\n    .slice(0, limit)\n    .map((el, i) => {\n      const headerLink = el.querySelector('h2 a, h3 a, h4 a, strong a');\n      const spans = Array.from(el.querySelectorAll('div[dir=\"auto\"]'))\n        .map(s => s.textContent.trim())\n        .filter(t => t.length > 5 && t.length < 500);\n      const timeEl = el.querySelector('a[href*=\"/posts/\"] span, a[href*=\"story_fbid\"] span');\n      return {\n        index: i + 1,\n        source: headerLink ? headerLink.textContent.trim().substring(0, 50) : '-',\n        content: (spans[0] || '').replace(/\\n/g, ' ').substring(0, 150),\n        time: timeEl ? timeEl.textContent.trim() : '-',\n      };\n    })\n    .filter(item => item.content.length > 0 || item.source !== '-');\n})())());\n    }\n    return data;\n  })();\n}"},{"name":"facebook_notifications","description":"Get recent Facebook notifications","inputSchema":{"type":"object","properties":{"limit":{"type":"number","description":"Number of notifications","default":15}},"required":null},"handler":"(params) => {\n  const args = Object.assign({\"limit\": 15}, 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.facebook.com/notifications\");\n      __wbContextUrl = __wbResp.url;\n      __wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');\n      data = __wbContextDocument;\n    }\n    {\n      const document = __wbContextDocument || globalThis.document;\n      const location = new URL(__wbBaseUrl());\n      const window = { document, location };\n      const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));\n      data = await (((() => {\n  const limit = (args.limit);\n  const items = document.querySelectorAll('[role=\"listitem\"]');\n  return Array.from(items)\n    .filter(el => el.querySelectorAll('a').length > 0)\n    .slice(0, limit)\n    .map((el, i) => {\n      const raw = el.textContent.trim().replace(/\\s+/g, ' ');\n      // Remove leading \"未读\" and trailing \"标记为已读\"\n      const cleaned = raw.replace(/^未读/, '').replace(/标记为已读$/, '').replace(/^Unread/, '').replace(/Mark as read$/, '').trim();\n      // Try to extract time (last segment like \"11小时\", \"5天\", \"1周\")\n      const timeMatch = cleaned.match(/(\\d+\\s*(?:分钟|小时|天|周|个月|minutes?|hours?|days?|weeks?|months?))\\s*$/);\n      const time = timeMatch ? timeMatch[1] : '';\n      const text = timeMatch ? cleaned.slice(0, -timeMatch[0].length).trim() : cleaned;\n      return {\n        index: i + 1,\n        text: text.substring(0, 150),\n        time: time || '-',\n      };\n    });\n})())());\n    }\n    return data;\n  })();\n}"},{"name":"facebook_profile","description":"Get Facebook user/page profile info","inputSchema":{"type":"object","properties":{"username":{"type":"string","description":"Facebook username or page name"}},"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.facebook.com/${args.username}`);\n      __wbContextUrl = __wbResp.url;\n      __wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');\n      data = __wbContextDocument;\n    }\n    {\n      const document = __wbContextDocument || globalThis.document;\n      const location = new URL(__wbBaseUrl());\n      const window = { document, location };\n      const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));\n      data = await (((() => {\n  const h1 = document.querySelector('h1');\n  let name = h1 ? h1.textContent.trim() : '';\n\n  // Find friends/followers links\n  const links = Array.from(document.querySelectorAll('a'));\n  const friendsLink = links.find(a => a.href && a.href.includes('/friends'));\n  const followersLink = links.find(a => a.href && a.href.includes('/followers'));\n\n  return [{\n    name: name,\n    username: ((args.username)),\n    friends: friendsLink ? friendsLink.textContent.trim() : '-',\n    followers: followersLink ? followersLink.textContent.trim() : '-',\n    url: window.location.href,\n  }];\n})())());\n    }\n    return data;\n  })();\n}"}]}