> ## Documentation Index
> Fetch the complete documentation index at: https://docs.thor.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Documents

> Use Notion and Google Docs as additional Thor context when answering questions, drafting issues, and checking alignment.

export const ChatLink = ({children}) => <span className="text-[#1264A3] dark:text-[#1D9BD1] underline underline-offset-2 decoration-[#1264A3]/40 dark:decoration-[#1D9BD1]/40 group-data-[chat=teams]:text-[#5B5FC7] group-data-[chat=teams]:dark:text-[#A6A7DC] group-data-[chat=teams]:decoration-[#5B5FC7]/40 group-data-[chat=mcp]:text-[#79c0ff] group-data-[chat=mcp]:decoration-[#79c0ff]/50 group-data-[chat=mcp]:no-underline font-medium break-all cursor-pointer">
    {children}
  </span>;

export const McpResult = ({children}) => <div className="hidden group-data-[chat=mcp]:block font-mono text-[13px] leading-relaxed mt-4">
    <div className="mb-1.5 flex items-center gap-2">
      <span className="rounded px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wide bg-[#1f6feb]/25 text-[#79c0ff] border border-[#1f6feb]/40">
        thor
      </span>
      <span className="text-[11px] text-[#8b949e]">response</span>
    </div>
    <div className="rounded-md border border-[#1f6feb]/35 bg-[#0d1117] px-3 py-2.5 border-l-[3px] border-l-[#1f6feb]">
      <div className="min-w-0 text-[#c9d1d9] whitespace-pre-wrap">{children}</div>
    </div>
  </div>;

export const McpPrompt = ({children}) => <div className="hidden group-data-[chat=mcp]:block font-mono text-[13px] leading-relaxed">
    <div className="mb-1.5 flex items-center gap-2">
      <span className="rounded px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wide bg-[#238636]/25 text-[#3fb950] border border-[#238636]/40">
        you
      </span>
      <span className="text-[11px] text-[#8b949e]">prompt</span>
    </div>
    <div className="rounded-md border border-[#30363d] bg-[#161b22] px-3 py-2.5">
      <div className="flex gap-2">
        <span className="shrink-0 select-none text-[#3fb950] font-bold">›</span>
        <div className="min-w-0 text-[#e6edf3]">{children}</div>
      </div>
    </div>
  </div>;

export const Mention = ({children}) => <>
    <span className="text-[#1264A3] dark:text-[#1D9BD1] font-medium group-data-[chat=teams]:hidden group-data-[chat=mcp]:hidden">
      @{children}
    </span>
    <span className="hidden group-data-[chat=teams]:inline-flex items-center rounded px-1 mx-0.5 text-[#5B5FC7] dark:text-[#A6A7DC] bg-[#5B5FC7]/10 dark:bg-[#5B5FC7]/20 font-medium">
      @{children}
    </span>
  </>;

export const Message = ({name, bot = false, self = false, time, color, avatar: avatarUrl, children}) => {
  const thorAvatar = "/images/thor-icon.svg";
  const youAvatar = "/images/you-avatar.jpg";
  const resolvedName = bot ? "Thor" : self ? "You" : name || "Alex";
  const resolvedColor = color || "#5095dd";
  const imageAvatar = avatarUrl || (bot ? thorAvatar : self ? youAvatar : null);
  const imagePad = bot && !avatarUrl;
  const avatarNode = () => {
    if (imageAvatar) {
      return <>
          <img src={imageAvatar} alt={resolvedName} className={`h-9 w-9 rounded-lg object-cover shrink-0 group-data-[chat=teams]:hidden ${imagePad ? "bg-[#D9E3E6] p-1.5 object-contain" : ""}`} />
          <img src={imageAvatar} alt={resolvedName} className={`hidden h-8 w-8 rounded-full object-cover shrink-0 group-data-[chat=teams]:block ${imagePad ? "bg-[#E8E8F0] dark:bg-[#2B2B36] p-1 object-contain" : ""}`} />
        </>;
    }
    return <>
        <div className="h-8 w-8 rounded-lg shrink-0 flex items-center justify-center text-white text-xs font-semibold group-data-[chat=teams]:hidden" style={{
      backgroundColor: resolvedColor
    }}>
          {resolvedName.slice(0, 1).toUpperCase()}
        </div>
        <div className="hidden h-8 w-8 rounded-full shrink-0 items-center justify-center text-white text-xs font-semibold group-data-[chat=teams]:flex" style={{
      backgroundColor: resolvedColor
    }}>
          {resolvedName.slice(0, 1).toUpperCase()}
        </div>
      </>;
  };
  return <>
      <div className="flex gap-2.5 items-start rounded-lg px-2 py-1.5 hover:bg-zinc-50 dark:hover:bg-white/5 group-data-[chat=teams]:hidden group-data-[chat=mcp]:hidden">
        {avatarNode()}
        <div className="min-w-0 flex-1">
          <div className="flex items-baseline gap-2 flex-wrap">
            <span className="text-[15px] font-bold text-zinc-900 dark:text-zinc-100">
              {resolvedName}
            </span>
            {bot ? <span className="rounded px-1 py-px text-[10px] font-bold uppercase tracking-wide bg-[#E8F5FA] text-[#1264A3] dark:bg-[#1D9BD1]/20 dark:text-[#1D9BD1]">
                App
              </span> : null}
            {time ? <span className="text-[12px] text-zinc-500">{time}</span> : null}
          </div>
          <div className="text-[15px] leading-relaxed text-zinc-800 dark:text-zinc-200 mt-0.5">
            {children}
          </div>
        </div>
      </div>

      <div className="hidden group-data-[chat=teams]:flex gap-2.5 items-start">
        {avatarNode()}
        <div className="min-w-0 max-w-[92%]">
          <div className="flex items-baseline gap-2 mb-1">
            <span className="text-[13px] font-semibold text-zinc-900 dark:text-zinc-100">
              {resolvedName}
            </span>
            {bot ? <span className="rounded px-1 py-px text-[10px] font-semibold uppercase tracking-wide bg-[#5B5FC7]/15 text-[#5B5FC7] dark:text-[#A6A7DC]">
                Bot
              </span> : null}
            {time ? <span className="text-[11px] text-zinc-500">{time}</span> : null}
          </div>
          <div className={`rounded-md px-3 py-2 text-[13px] leading-relaxed text-zinc-800 dark:text-zinc-100 shadow-sm ${bot ? "bg-white dark:bg-[#292929] border border-[#5B5FC7]/25" : "bg-white dark:bg-[#292929]"}`}>
            {children}
          </div>
        </div>
      </div>
    </>;
};

export const Conversation = ({channel = "general", type = "channel", defaultPlatform, platforms = "slack,teams,mcp", children}) => {
  const available = platforms.split(",").map(p => p.trim()).filter(Boolean);
  const initial = defaultPlatform && available.includes(defaultPlatform) ? defaultPlatform : available[0] || "slack";
  const [platform, setPlatform] = useState(initial);
  const thorAvatar = "/images/thor-icon.svg";
  const isDm = type === "dm";
  const title = isDm ? "Thor" : channel.replace(/^#/, "");
  const showTabs = available.length > 1;
  const tabClass = active => `inline-flex items-center gap-1.5 rounded-md px-2.5 py-1.5 text-xs font-medium transition-colors ${active ? "bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 shadow-sm" : "text-zinc-500 hover:text-zinc-800 dark:hover:text-zinc-200"}`;
  const slackIcon = () => <svg viewBox="0 0 20 20" className="h-3.5 w-3.5" aria-hidden="true">
      <path fill="currentColor" d="M4.5 12.7a1.6 1.6 0 1 1-1.6-1.6h1.6v1.6zm.8 0a1.6 1.6 0 1 1 3.2 0v4a1.6 1.6 0 1 1-3.2 0v-4zM7.3 4.5a1.6 1.6 0 1 1 1.6-1.6v1.6H7.3zm0 .8a1.6 1.6 0 1 1 0 3.2h-4a1.6 1.6 0 1 1 0-3.2h4zM15.5 7.3a1.6 1.6 0 1 1 1.6 1.6h-1.6V7.3zm-.8 0a1.6 1.6 0 1 1-3.2 0v-4a1.6 1.6 0 1 1 3.2 0v4zM12.7 15.5a1.6 1.6 0 1 1-1.6 1.6v-1.6h1.6zm0-.8a1.6 1.6 0 1 1 0-3.2h4a1.6 1.6 0 1 1 0 3.2h-4z" />
    </svg>;
  const teamsIcon = () => <svg viewBox="0 0 20 20" className="h-3.5 w-3.5" aria-hidden="true">
      <path fill="currentColor" d="M11.2 4.2a2.4 2.4 0 1 1 2.5 2.4h-.1a2.4 2.4 0 0 1-2.4-2.4zm-6.3.6a2.1 2.1 0 1 1 2.2 2h-.1a2.1 2.1 0 0 1-2.1-2zm6.5 3.4h4.2c.8 0 1.4.6 1.4 1.4v4.1a3.4 3.4 0 0 1-3.4 3.4h-.3A4.3 4.3 0 0 0 17 13.2V8.8c0-.9-.7-1.6-1.6-1.6h-4zm-6.6.3h4.6c.7 0 1.3.6 1.3 1.3v5.1A3.7 3.7 0 0 1 7 18.6H6.3A3.7 3.7 0 0 1 2.6 14.9V9.8c0-.7.6-1.3 1.3-1.3z" />
    </svg>;
  const mcpIcon = () => <svg viewBox="0 0 20 20" className="h-3.5 w-3.5" aria-hidden="true">
      <path fill="currentColor" d="M4 5.5A1.5 1.5 0 0 1 5.5 4h9A1.5 1.5 0 0 1 16 5.5v9a1.5 1.5 0 0 1-1.5 1.5h-9A1.5 1.5 0 0 1 4 14.5v-9zM6 7v1.5h1.75V7H6zm3.25 0v1.5H11V7H9.25zM12.5 7v1.5H14.25V7H12.5zM6 10v1.5h8.25V10H6zm0 3v1.5h5V13H6z" />
    </svg>;
  let frame;
  if (platform === "mcp") {
    frame = <div className="overflow-hidden rounded-xl border border-zinc-700 shadow-sm not-prose bg-[#0d1117]">
        <div className="flex items-center gap-2 border-b border-zinc-700/80 bg-[#161b22] px-3 py-2">
          <div className="flex items-center gap-1.5">
            <span className="h-2.5 w-2.5 rounded-full bg-[#ff5f56]" />
            <span className="h-2.5 w-2.5 rounded-full bg-[#ffbd2e]" />
            <span className="h-2.5 w-2.5 rounded-full bg-[#27c93f]" />
          </div>
          <div className="min-w-0 flex-1 text-center font-mono text-[11px] text-[#8b949e] truncate">
            thor mcp — cursor / claude
          </div>
          <div className="w-10" />
        </div>
        <div className="px-4 py-4 space-y-1 min-h-[7rem]">
          <div className="font-mono text-[11px] text-[#8b949e] mb-3">
            <span className="text-[#79c0ff]">mcp</span>
            <span className="text-[#8b949e]">:</span>
            <span className="text-[#a5d6ff]">thor</span>
            <span className="text-[#8b949e]">$ </span>
            <span className="text-[#c9d1d9]">ask</span>
          </div>
          {children}
          <div className="font-mono text-[13px] text-[#7ee787] mt-4 animate-pulse">
            ▍
          </div>
        </div>
      </div>;
  } else if (platform === "teams") {
    frame = <div className="overflow-hidden rounded-xl border border-zinc-200 dark:border-zinc-700 shadow-sm not-prose">
        <div className="flex items-center gap-2.5 bg-[#5B5FC7] px-3 py-2.5">
          {isDm ? <img src={thorAvatar} alt="" className="h-6 w-6 rounded-full bg-white/90 p-0.5 object-contain" /> : <div className="flex h-6 w-6 items-center justify-center rounded bg-white/15 text-white text-xs font-bold">
              #
            </div>}
          <div className="min-w-0">
            <div className="text-sm font-semibold text-white truncate">
              {title}
            </div>
            <div className="text-[11px] text-white/70">
              {isDm ? "Chat · Microsoft Teams" : "Microsoft Teams"}
            </div>
          </div>
        </div>
        <div className="bg-[#F5F5F5] dark:bg-[#1F1F1F] px-3 py-3 space-y-3">
          {children}
        </div>
      </div>;
  } else {
    frame = <div className="overflow-hidden rounded-xl border border-zinc-200 dark:border-zinc-700 shadow-sm not-prose">
        <div className="flex items-center gap-2 border-b border-zinc-200 dark:border-zinc-700 bg-white dark:bg-[#1A1D21] px-3 py-2.5">
          {isDm ? <img src={thorAvatar} alt="" className="h-5 w-5 rounded bg-[#D9E3E6] p-0.5 object-contain" /> : <span className="text-zinc-500 dark:text-zinc-400 text-lg leading-none">
              #
            </span>}
          <span className="text-sm font-bold text-zinc-900 dark:text-zinc-100">
            {title}
          </span>
        </div>
        <div className="bg-white dark:bg-[#1A1D21] px-2 py-3 space-y-1">
          {children}
        </div>
      </div>;
  }
  return <div className="my-4 not-prose group" data-chat={platform}>
      {showTabs ? <div className="mb-2 inline-flex flex-wrap items-center rounded-lg border border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-900 p-0.5">
          {available.includes("slack") ? <button type="button" onClick={() => setPlatform("slack")} className={tabClass(platform === "slack")}>
              {slackIcon()}
              Slack
            </button> : null}
          {available.includes("teams") ? <button type="button" onClick={() => setPlatform("teams")} className={tabClass(platform === "teams")}>
              {teamsIcon()}
              Teams
            </button> : null}
          {available.includes("mcp") ? <button type="button" onClick={() => setPlatform("mcp")} className={tabClass(platform === "mcp")}>
              {mcpIcon()}
              MCP
            </button> : null}
        </div> : null}

      {frame}

      {platform === "mcp" && showTabs ? <p className="mt-2 text-xs text-zinc-500 dark:text-zinc-400">
          Same workflows via Thor's{" "}
          <a href="/usecases/mcp" className="underline underline-offset-2">
            MCP server
          </a>{" "}
          in Cursor, Claude, or any MCP client.
        </p> : null}
    </div>;
};

# Pre-requisites

To use documents as Thor context, connect the platforms your team writes specs and decisions in. Thor supports **Notion** and **Google Docs** (via Google Drive).

Thor only has access to documents you explicitly share — not your entire Drive or Notion workspace.

<AccordionGroup>
  <Accordion icon="book" title="Notion">
    Open the Thor Slack app, go to the **Home** tab, and click **Your Connections**. Connect your **Notion** account and select the pages you want Thor to index during the OAuth flow.

    Indexed pages are added to **team shared context** — everyone in your organization can ask Thor about them, even if they have not connected their own Notion account.

    To add more pages later, reconnect Notion from **Your Connections** and update your page selection.
  </Accordion>

  <Accordion icon="google" title="Google Docs">
    Open the Thor Slack app, go to the **Home** tab, and click **Your Connections**. Connect your **Google** account.

    Thor only has access to Google Docs you have shared — not your full Google Drive.
  </Accordion>
</AccordionGroup>

## Manage documents in the webapp

<img src="https://mintcdn.com/thor/YYCrix9H3kEt1_oM/images/documents.png?fit=max&auto=format&n=YYCrix9H3kEt1_oM&q=85&s=9613b03974d2eef4b5fea3dfdda1bd5a" alt="documents" width="1024" height="687" data-path="images/documents.png" />

The **Documents** page shows every Notion page and Google Doc Thor can access — who shared it, when it last synced, and whether it's **shared with the team**. Search, filter by source or status, and spot connections that need attention after a reconnect.

# Use cases

## Check whether work aligns with a spec

Ask Thor to compare in-flight tasks against a product spec, PRD, or decision doc. Thor searches and reads the synced document, then cross-references your issues, threads, and meeting context from the [data layer](/why-thor/data-layer):

<Conversation type="dm">
  <Message self time="1:12 PM">
    Hey <Mention>Thor</Mention>, are our latest auth migration tasks aligned with this spec? <ChatLink>[https://www.notion.so/acme/Auth-Migration-Spec-8f3a2c1b9e0d4a67b2c5d8e1f0a3b6c9](https://www.notion.so/acme/Auth-Migration-Spec-8f3a2c1b9e0d4a67b2c5d8e1f0a3b6c9)</ChatLink> and our Q2 roadmap?
  </Message>

  <Message bot time="1:12 PM">
    Mostly — ENG-1842 and ENG-1849 match the spec. The rollback checklist the team discussed in the last meeting is entirely missing though. Want me to draft that issue?
  </Message>

  <McpPrompt>
    Use the Thor MCP to check whether our latest auth migration tasks are aligned with this Notion spec: <ChatLink>[https://www.notion.so/acme/Auth-Migration-Spec-8f3a2c1b9e0d4a67b2c5d8e1f0a3b6c9](https://www.notion.so/acme/Auth-Migration-Spec-8f3a2c1b9e0d4a67b2c5d8e1f0a3b6c9)</ChatLink>
  </McpPrompt>

  <McpResult>
    Mostly aligned — ENG-1842, ENG-1849 match.
    Gap: rollback checklist (spec §4) has no task yet.
  </McpResult>
</Conversation>

## Draft an issue from a document

Have Thor read a spec or design doc and turn it into a well-scoped GitHub or Linear issue:

<Conversation type="dm">
  <Message self time="2:05 PM">
    Hey <Mention>Thor</Mention>, go through this doc <ChatLink>[https://docs.google.com/document/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms](https://docs.google.com/document/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms)</ChatLink> and generate Linear issues for any work we didn't track yet.
  </Message>

  <Message bot time="2:05 PM">
    Drafted **ENG-1902: Add versioned /v2 endpoints for customer export**. That was the big missing piece. Includes the auth, pagination, and rate-limit notes from the doc. Want me to assign it?
  </Message>

  <McpPrompt>
    Use the Thor MCP to draft a Linear issue for the API changes in <ChatLink>[https://docs.google.com/document/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms](https://docs.google.com/document/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms)</ChatLink>
  </McpPrompt>

  <McpResult>
    Created ENG-1902: Add versioned /v2 endpoints for customer export
  </McpResult>
</Conversation>

## Summarize or answer questions about a document

Ask Thor to read a specific page or search across your team's shared documents:

<Conversation type="dm">
  <Message self time="3:30 PM">
    Hey <Mention>Thor</Mention>, what does our deployment runbook say about rollback?
  </Message>

  <Message bot time="3:30 PM">
    Rollback is done in two steps: revert the release tag, then run `make deploy-previous` from ops. If DB migrations ran, follow the "forward-fix" section instead of a hard rollback. Want the exact runbook section?
  </Message>

  <McpPrompt>
    Use the Thor MCP to check what our deployment runbook says about rollback.
  </McpPrompt>

  <McpResult>
    Revert release tag → make deploy-previous. If migrations ran: use forward-fix, not hard rollback
  </McpResult>
</Conversation>

## List documents Thor can use

See which Notion pages and Google Docs are registered for your team:

<Conversation type="dm">
  <Message self time="4:01 PM">
    Hey <Mention>Thor</Mention>, do we have any documents for the auth migration?
  </Message>

  <Message bot time="4:01 PM">
    Yes! Many. <ChatLink>Auth Migration Spec</ChatLink>, <ChatLink>Q2 Roadmap Decisions</ChatLink>, <ChatLink>Onboarding Spec</ChatLink>, <ChatLink>Deployment Runbook</ChatLink>, <ChatLink>Pricing v2</ChatLink>, and <ChatLink>API Export Design</ChatLink>. Want me to give me a synopsis of each?
  </Message>

  <McpPrompt>
    Use the Thor MCP to list which documents you have access to.
  </McpPrompt>

  <McpResult>
    Yes! Many. [https://www.notion.so/acme/Auth-Migration-Spec-8f3a2c1b9e0d4a67b2c5d8e1f0a3b6c9,https://www.notion.so/acme/Q2-Roadmap-Decisions-c4e91a7f2b384d0e9f1a6c8d5e2b0a47,https://www.notion.so/acme/Onboarding-Spec-1234567890abcdef1234567890abcdef,https://docs.google.com/document/d/3k9QmN2pLx7vRcYwE4tHsUaBdFgHjKlMnOpQrStUvWx,https://www.notion.so/acme/Pricing-v2-1234567890abcdef1234567890abcdef,https://docs.google.com/document/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms](https://www.notion.so/acme/Auth-Migration-Spec-8f3a2c1b9e0d4a67b2c5d8e1f0a3b6c9,https://www.notion.so/acme/Q2-Roadmap-Decisions-c4e91a7f2b384d0e9f1a6c8d5e2b0a47,https://www.notion.so/acme/Onboarding-Spec-1234567890abcdef1234567890abcdef,https://docs.google.com/document/d/3k9QmN2pLx7vRcYwE4tHsUaBdFgHjKlMnOpQrStUvWx,https://www.notion.so/acme/Pricing-v2-1234567890abcdef1234567890abcdef,https://docs.google.com/document/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms)
  </McpResult>
</Conversation>
