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

# Endor Labs MCP server in OpenCode

> Learn how to deploy and run the Endor Labs MCP server in OpenCode.

export const BadgeTabs = ({children}) => {
  const DEFAULT_BADGE_COLOR = 'gray';
  const FALLBACK_TAB_PREFIX = 'Tab ';
  const ARIA_ID_PREFIX = 'bt-tab-';
  const ACCENT_GREEN = '#26D07C';
  const BADGE_COLOR_CLASS = {
    green: 'bt-badge--green',
    blue: 'bt-badge--blue',
    orange: 'bt-badge--orange',
    red: 'bt-badge--red',
    purple: 'bt-badge--purple',
    yellow: 'bt-badge--yellow',
    gray: 'bt-badge--gray'
  };
  const readDataAttr = (props, kebabName) => {
    if (!props || typeof props !== 'object') return undefined;
    const direct = props[kebabName];
    if (direct !== undefined && direct !== null) return String(direct);
    return undefined;
  };
  const normalizeBadgeColor = raw => {
    if (!raw) return DEFAULT_BADGE_COLOR;
    const c = String(raw).toLowerCase().trim();
    return BADGE_COLOR_CLASS[c] ? c : DEFAULT_BADGE_COLOR;
  };
  const flattenChildren = (node, out) => {
    if (node === null || node === undefined) return;
    if (Array.isArray(node)) {
      for (const item of node) flattenChildren(item, out);
      return;
    }
    out.push(node);
  };
  const childToTabItem = (child, index, itemCount) => {
    if (child === null || child === undefined) return null;
    if (typeof child === 'string' || typeof child === 'number') {
      const text = String(child).trim();
      if (!text) return null;
      return {
        key: `text-${index}`,
        title: `${FALLBACK_TAB_PREFIX}${itemCount + 1}`,
        badgeText: '',
        badgeColor: DEFAULT_BADGE_COLOR,
        node: <span>{child}</span>
      };
    }
    if (typeof child !== 'object' || !child.props) return null;
    const p = child.props;
    const title = readDataAttr(p, 'data-title')?.trim() || `${FALLBACK_TAB_PREFIX}${itemCount + 1}`;
    const badgeText = readDataAttr(p, 'data-badge')?.trim() || '';
    const badgeColor = normalizeBadgeColor(readDataAttr(p, 'data-badge-color'));
    return {
      key: child.key == null ? `tab-${index}` : String(child.key),
      title,
      badgeText,
      badgeColor,
      node: child
    };
  };
  const tabItems = useMemo(() => {
    const arr = [];
    flattenChildren(children, arr);
    const items = [];
    for (const [i, child] of arr.entries()) {
      const item = childToTabItem(child, i, items.length);
      if (item) items.push(item);
    }
    return items;
  }, [children]);
  const [activeIndex, setActiveIndex] = useState(0);
  const [isDark, setIsDark] = useState(false);
  const [baseId] = useState(() => `${ARIA_ID_PREFIX}${Math.random().toString(36).slice(2, 11)}`);
  useEffect(() => {
    const check = () => {
      const r = document.documentElement;
      setIsDark(r.dataset.theme === 'dark' || r.classList.contains('dark'));
    };
    check();
    const obs = new MutationObserver(check);
    obs.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ['data-theme', 'class']
    });
    return () => obs.disconnect();
  }, []);
  useEffect(() => {
    if (activeIndex >= tabItems.length && tabItems.length > 0) setActiveIndex(0);
  }, [activeIndex, tabItems.length]);
  const safeIndex = tabItems.length === 0 ? 0 : Math.min(activeIndex, tabItems.length - 1);
  const focusTabAt = nextIndex => {
    if (tabItems.length === 0) return;
    const wrapped = (nextIndex % tabItems.length + tabItems.length) % tabItems.length;
    setActiveIndex(wrapped);
    const btn = document.getElementById(`${baseId}-tab-${wrapped}`);
    if (btn && typeof btn.focus === 'function') btn.focus();
  };
  const onKeyDownTabList = event => {
    if (tabItems.length === 0) return;
    const key = event.key;
    if (key === 'ArrowRight' || key === 'ArrowDown') {
      event.preventDefault();
      focusTabAt(safeIndex + 1);
    } else if (key === 'ArrowLeft' || key === 'ArrowUp') {
      event.preventDefault();
      focusTabAt(safeIndex - 1);
    } else if (key === 'Home') {
      event.preventDefault();
      focusTabAt(0);
    } else if (key === 'End') {
      event.preventDefault();
      focusTabAt(tabItems.length - 1);
    }
  };
  if (tabItems.length === 0) return null;
  const containerStyle = {
    borderRadius: '0.5rem',
    overflow: 'hidden',
    border: isDark ? '1px solid rgba(38,208,124,0.2)' : '1px solid #a7e8c8',
    margin: '1rem 0'
  };
  const navStyle = {
    display: 'flex',
    flexWrap: 'wrap',
    gap: 0,
    background: isDark ? 'rgba(38,208,124,0.1)' : '#e6f9f0',
    borderBottom: isDark ? '1px solid rgba(38,208,124,0.2)' : '1px solid #a7e8c8',
    padding: '0 0.75rem'
  };
  const btnStyle = selected => ({
    display: 'inline-flex',
    alignItems: 'center',
    gap: '0.35rem',
    padding: '0.6rem 0.75rem',
    border: 'none',
    borderBottom: selected ? `2px solid ${ACCENT_GREEN}` : '2px solid transparent',
    background: 'transparent',
    color: isDark ? selected ? '#e6edf3' : 'rgba(255,255,255,0.6)' : selected ? '#111827' : '#4b5563',
    cursor: 'pointer',
    fontSize: '0.85rem',
    fontWeight: selected ? 600 : 400
  });
  const panelStyle = {
    padding: '1rem 1.25rem'
  };
  return <div className="bt-root" style={containerStyle}>
      <div className="not-prose bt-tablist" role="tablist" aria-orientation="horizontal" tabIndex={-1} onKeyDown={onKeyDownTabList} style={navStyle}>
        {tabItems.map((tab, index) => {
    const selected = index === safeIndex;
    const tabId = `${baseId}-tab-${index}`;
    const panelId = `${baseId}-panel-${index}`;
    const badgeClass = BADGE_COLOR_CLASS[tab.badgeColor] || BADGE_COLOR_CLASS.gray;
    return <button key={tab.key} type="button" id={tabId} role="tab" aria-selected={selected} aria-controls={panelId} tabIndex={selected ? 0 : -1} className={`bt-tab-btn${selected ? ' bt-tab-btn--active' : ''}`} style={btnStyle(selected)} onClick={() => setActiveIndex(index)}>
              <span className="bt-tab-title">{tab.title}</span>
              {tab.badgeText ? <span className={`bt-badge ${badgeClass}`}>{tab.badgeText}</span> : null}
            </button>;
  })}
      </div>
      {tabItems.map((tab, index) => {
    const panelId = `${baseId}-panel-${index}`;
    const tabId = `${baseId}-tab-${index}`;
    const hidden = index !== safeIndex;
    return <div key={`${tab.key}-panel`} id={panelId} role="tabpanel" aria-labelledby={tabId} hidden={hidden} className="bt-tabpanel" style={{
      display: hidden ? 'none' : 'block',
      ...panelStyle
    }}>
            {tab.node}
          </div>;
  })}
    </div>;
};

Scan dependencies, detect vulnerabilities, find leaked secrets, and review code for security issues directly inside OpenCode, powered by your AI agent.

<Tip>
  You can also connect the [Endor Labs documentation MCP server](/introduction/docs-mcp-server) to get accurate, real-time answers about Endor Labs directly in your AI tools.
</Tip>

The Endor Labs MCP server runs locally on your machine as a lightweight process. Your IDE or CLI launches it through `npx` or a system-installed `endorctl` and communicates with it over stdio. When the AI agent needs security context, the server calls the Endor Labs cloud platform and returns the results. The server uses the stdio transport only, so configure it with a `command` and `args` entry rather than an HTTP (`type: http`) URL.

## What you can do

With the Endor Labs MCP server, you can:

* **Check dependency safety** before adding a new package
* **Scan for vulnerabilities and malware** in your open source dependencies
* **Find leaked secrets** accidentally committed in your Git history
* **Run static analysis (SAST)** on your code with the `scan` tool
* **Run AI security reviews** on your code changes (Enterprise Edition)

The MCP server returns the full set of findings for the dependency, package, or code you ask about. It does not perform function-level reachability analysis and does not filter findings by an action policy. For reachability and policy-based findings, run a full Endor Labs scan or use the Endor Labs platform.

<Note>
  **Node.js: 18 or later required, 24 LTS recommended**

  The Endor Labs MCP server runs `endorctl` through `npx`, which requires Node.js 18 or later. npm is included with Node.js, so no separate npm installation or version is required. On Node.js versions older than 24, you may see a harmless warning printed before scan output.

  ```text theme={null}
  (node:NNNNN) ExperimentalWarning: CommonJS module .../debug/src/node.js is loading ES Module .../supports-color/index.js using require().
  ```

  This is a Node.js runtime notice, not an error from `endorctl` or the MCP server, and it does not affect scan results. To silence it, upgrade Node.js to 24 LTS or later, then restart your IDE or CLI. Verify with `node --version`.
</Note>

## Install the MCP server

OpenCode reads MCP server definitions from an `opencode.json` (or `opencode.jsonc`) configuration file. Add the file to your project root to scope the server to that project, or to `~/.config/opencode/opencode.json` to make it available across all projects.

<BadgeTabs>
  <div data-title="Developer Edition" data-badge="FREE" data-badge-color="green">
    The Developer Edition is free and uses default security policies from Endor Labs. You do not need an Endor Labs account. When you use the MCP server for the first time, a browser window opens for authentication through GitHub, GitLab, or Google.

    <br />

    Add the following configuration to your `opencode.json` file.

    ```json theme={null}
    {
      "$schema": "https://opencode.ai/config.json",
      "mcp": {
        "endor-cli-tools": {
          "type": "local",
          "command": ["npx", "-y", "endorctl", "ai-tools", "mcp-server"]
        }
      }
    }
    ```

    <Note>
      Have questions? Email us at [community-support@endor.ai](mailto:community-support@endor.ai).
    </Note>
  </div>

  <div data-title="Enterprise Edition" data-badge="PAID" data-badge-color="blue">
    The Enterprise Edition enforces your organization's specific security policies. You need your Endor Labs namespace and an authentication method. Ensure that your developers have Read-Only permissions to Endor Labs. See [Authorization policies](/platform-administration/rbac/authorization-policies) for more details.

    Add the following configuration to your `opencode.json` file, replacing the placeholder values with your organization's values.

    ```json theme={null}
    {
      "$schema": "https://opencode.ai/config.json",
      "mcp": {
        "endor-cli-tools": {
          "type": "local",
          "command": ["npx", "-y", "endorctl", "ai-tools", "mcp-server"],
          "environment": {
            "ENDOR_NAMESPACE": "<your-namespace>",
            "ENDOR_MCP_SERVER_AUTH_MODE": "<your-auth-mode>"
          }
        }
      }
    }
    ```

    The following parameters are used to configure the MCP server. All parameters are optional.

    * `ENDOR_MCP_SERVER_AUTH_MODE`: The authentication mode to use for the MCP server. You can use the following authentication modes: `github`, `gitlab`, `google`, `sso`. If you choose `sso`, you must add `ENDOR_MCP_SERVER_AUTH_TENANT` as an additional parameter. If not specified, the MCP server defaults to browser authentication for the Developer Edition.
    * `ENDOR_NAMESPACE`: The namespace to use for the MCP server. Required for Enterprise Edition to access your organization's specific policies. Not needed for Developer Edition.
    * `ENDOR_MCP_SERVER_AUTH_TENANT`: The tenant name for SSO authentication. Required when `ENDOR_MCP_SERVER_AUTH_MODE` is set to `sso` for Enterprise Edition access.

    <Note>
      **Advanced:** You can set scan environment variables in the server's `env` block and the MCP server passes them through to scans. For example, set `SECRETS_RULES_PATH` to point the secret scanner at a custom ruleset. See [Manage secret rules](/scan/secrets/secret-rules/).
    </Note>
  </div>
</BadgeTabs>

## Verify the installation

```bash theme={null}
opencode mcp list
```

Confirm that **endor-cli-tools** appears in the list with a connected status.

### Try a test prompt

After installing the MCP server, try the following prompt in your AI chat or CLI to verify that the tools are working.

```text theme={null}
Check if the npm package lodash version 4.17.20 has any vulnerabilities
```

The MCP server uses the `check_dependency_for_vulnerabilities` tool to check for known vulnerabilities and return the results. If you see a response with vulnerability details, the MCP server is working correctly.

The following video shows the Endor Labs MCP server in action.

<video autoPlay muted loop playsInline style={{width: '100%'}}>
  <source src="https://mintcdn.com/endorlabs-b4795f4f/ClD-_arjCT08cSHI/images/setup-deployment/mcp/opencode/opencode-mcp.mp4?fit=max&auto=format&n=ClD-_arjCT08cSHI&q=85&s=aaef56687b0d00438e17c604a58cf31d" type="video/mp4" data-path="images/setup-deployment/mcp/opencode/opencode-mcp.mp4" />
</video>

## Manage MCP server tools

Use `opencode mcp list` to view your configured servers and their connection status. To temporarily disable the Endor Labs MCP server without removing it from your configuration, set `"enabled": false` on its entry in `opencode.json`.

To disable specific tools instead of the entire server, add a `tools` key to `opencode.json`. Tool names are prefixed with the server name.

```json theme={null}
{
  "mcp": {
    "endor-cli-tools": {
      "type": "local",
      "command": ["npx", "-y", "endorctl", "ai-tools", "mcp-server"]
    }
  },
  "tools": {
    "endor-cli-tools_check_dependency_for_vulnerabilities": false
  }
}
```

## How to use the Endor Labs MCP server

The Endor Labs MCP server provides the following tools:

* `check_dependency_for_vulnerabilities`: Check if a dependency in your project is vulnerable.
* `check_dependency_for_risks`: Check a dependency for security risks including vulnerabilities and malware.
* `get_endor_vulnerability`: Get the details of a specific vulnerability from the Endor Labs vulnerability database.
* `get_resource`: Retrieve additional context from commonly used Endor Labs resources about your software, such as findings, vulnerabilities, and projects.
* `scan`: Run an Endor Labs security scan to detect risks in your open source dependencies, find common security issues, and spot any credentials accidentally exposed in your Git repository.
* `security_review`: Perform security review analysis on code diffs. Analyzes local uncommitted changes (both staged and unstaged) compared to HEAD, or diffs between the main branch and the last commit. The tool sets the [`--diff-scope`](/scan/ai-sast#ai-sast-diff-scans) scan option automatically based on the review type. Requires the Enterprise Edition. You must specify your namespace in the MCP server configuration. You must also enable AI security code review for your namespace in the Endor Labs platform. See [AI security code review](/secure-ai-coding/ai-security-review/) for setup instructions.

After you set up the MCP server, you can choose to disable the tools that you do not want to use.

## Configure AGENTS.md

To enhance the MCP server integration, you can add instructions in `AGENTS.md` at the root of your repository. OpenCode reads `AGENTS.md` files to guide AI development with your project-specific instructions.

1. Navigate to the root of your repository.

2. Create or edit the `AGENTS.md` file in the root of your repository.

3. Add appropriate rules for your project. For example, you can add a rule to check if the code is free from vulnerabilities.

### Example AGENTS.md instructions

You can use the following `AGENTS.md` instructions as a quick start for the Endor Labs MCP server. Modify the instructions to meet your specific organization's needs. For more information, refer to the [OpenCode rules documentation](https://opencode.ai/docs/rules/).

<Tabs>
  <Tab title="SCA Rule Example">
    ```markdown theme={null}
    # Software Composition Analysis (SCA) Rule (Endor Labs via MCP)

    This project uses Endor Labs for automated dependency (SCA) scanning, integrated through the MCP server.

    ## Workflow

    Every time a manifest or lockfile (package.json, requirements.txt, go.mod, pom.xml, etc.) is created or modified in any way, immediately do the following prior to performing your next task.

    **Important**: Do not proceed after creating or modifying a manifest file without running this first.

    - Run `endor-cli-tools` using the `check_dependency_for_vulnerabilities` tool via the MCP server.
    - Provide the **ecosystem**, **dependency name**, and **version** always when making this tool call.
    - If a vulnerability or error is identified:
      - Upgrade to the suggested safe version, or
      - Replace the dependency with a non-vulnerable alternative.
    - Re-run the check using `endor-cli-tools` to confirm the issue is resolved.

    ## Notes
    - All scans must be performed using the MCP server integration (`endor-cli-tools`). Do not invoke `endorctl` directly.
    ```
  </Tab>

  <Tab title="Secrets Rule Example">
    ```markdown theme={null}
    # Leaked Secrets Detection Rule (Endor Labs via MCP)

    This project uses [Endor Labs](https://docs.endorlabs.com/) for automated security scanning, integrated through the MCP server.

    ## Workflow

    Whenever a file is modified in the repository, and before the end of an agent session:

    - Run `endor-cli-tools` using the `scan` tool via the MCP server to check for leaked secrets.
    - If any secrets or errors are detected:
      - Remove the exposed secret or correct the error immediately.
      - Re-run the scan to verify the secret has been properly removed.
    - Save scan results and remediation steps in a security log or as comments for audit purposes.

    ## Notes
    - All scans must be performed using the MCP server integration (`endor-cli-tools`). Do not invoke `endorctl` directly.
    - This scan must use the path of the directory from which the changed files are in. Use absolute paths.
    ```
  </Tab>

  <Tab title="SAST Rule Example">
    ```markdown theme={null}
    # Static Application Security Testing (SAST) Rule (Endor Labs via MCP)

    This project uses [Endor Labs](https://docs.endorlabs.com/) for automated SAST, integrated through the MCP server.

    ## Workflow

    Whenever a file is modified in the repository, and before the end of an agent session:

    - Run `endor-cli-tools` using the `scan` tool via the MCP server to perform SAST scans.
    - If any vulnerabilities or errors are found:
      - Present the issues to the user.
      - Recommend and apply appropriate fixes (e.g., input sanitization, validation, escaping, secure APIs).
    - Save scan results and remediation steps in a security log or as comments for audit purposes.

    ## Notes
    - All scans must be performed using the MCP server integration (`endor-cli-tools`). Do not invoke `endorctl` directly.
    - Do not invoke Opengrep directly.
    - This scan must use the path of the directory from which the changed files are in. Use absolute paths.
    ```
  </Tab>
</Tabs>

## Keep endorctl up to date

The default configuration runs `npx -y endorctl`, which downloads the latest published endorctl into the npx cache (`~/.npm/_npx/`) and reuses it on later runs. If you are not getting the latest version, do one of the following:

* Clear the npx cache (`~/.npm/_npx/`), then restart your IDE or CLI so the next run downloads the current endorctl.
* Pin a specific version by changing `endorctl` to `endorctl@<version>` in your `args`.
* Install endorctl yourself and call it directly, with `command` set to `endorctl` and `args` set to `["ai-tools", "mcp-server"]`. Updates are then managed by your package manager, for example `brew upgrade endorctl`. See [Install endorctl](/setup-deployment/cli/).

## Troubleshooting

Use the following troubleshooting steps to resolve common issues with the Endor Labs MCP server.

<AccordionGroup>
  <Accordion title="MCP server shows disconnected">
    Run `npx --version` in your terminal. If the command fails, install [Node.js](https://nodejs.org/) version 18 or later (Node.js 24 LTS recommended). After installing, restart your IDE or CLI to reload the MCP server configuration.
  </Accordion>

  <Accordion title="Browser auth window does not open">
    Ensure your IDE or CLI can open a browser. Check firewall or security software that might block browser launch. For Enterprise Edition with SSO, verify that `ENDOR_MCP_SERVER_AUTH_MODE` and `ENDOR_MCP_SERVER_AUTH_TENANT` are set correctly in your MCP configuration.
  </Accordion>

  <Accordion title="npx times out behind a corporate proxy">
    Install endorctl using your preferred method and configure the MCP server to call it directly instead of using npx. In the Enterprise Edition install wizard, select **No** under **Using npx?** to generate the correct configuration. Alternatively, replace the `command` and `args` entries in your MCP configuration manually, using your client's configuration format.

    <CodeGroup>
      ```json JSON theme={null}
      "command": "endorctl",
      "args": ["ai-tools", "mcp-server"]
      ```

      ```toml Codex config.toml theme={null}
      command = "endorctl"
      args = ["ai-tools", "mcp-server"]
      ```
    </CodeGroup>

    For installation options, see [Install endorctl](/setup-deployment/cli/). For more details on how npx and a system-installed endorctl differ, see the FAQ entry below.
  </Accordion>

  <Accordion title="Understanding npx vs. a system-installed endorctl">
    The default MCP server configuration uses `npx -y endorctl` to run endorctl. This command downloads endorctl from the npm registry into a temporary cache (`~/.npm/_npx/`) and runs it from there. It does **not** install endorctl globally and does **not** interact with any existing endorctl binary on your system.

    If you have endorctl installed separately (for example, through Homebrew or a direct download), the `npx` command runs its own copy and ignores the system-installed version. These two copies are completely independent.

    To use your existing endorctl installation instead of npx, select **No** under **Using npx?** in the Enterprise Edition install wizard. This generates a configuration that calls `endorctl` directly, in your client's configuration format.

    <CodeGroup>
      ```json JSON theme={null}
      "command": "endorctl",
      "args": ["ai-tools", "mcp-server"]
      ```

      ```toml Codex config.toml theme={null}
      command = "endorctl"
      args = ["ai-tools", "mcp-server"]
      ```
    </CodeGroup>

    With this approach, updates are managed by your existing package manager (for example, `brew upgrade endorctl`).
  </Accordion>

  <Accordion title="Tools return errors (Enterprise)">
    Verify your namespace is correct and your user has `Read-Only` permissions in Endor Labs. See [Authorization policies](/platform-administration/rbac/authorization-policies/) for details. Also ensure endorctl is on your PATH if you installed it globally instead of using npx.
  </Accordion>

  <Accordion title="MCP server fails to start on Windows">
    On Windows, ensure the following prerequisites are met:

    * Node.js is installed
    * npm global bin directory is in your PATH

    #### Install Node.js

    If Node.js is not installed, download and install the **LTS version** from [nodejs.org](https://nodejs.org/). During installation, ensure the option to add Node.js to PATH is selected.

    #### Configure the PATH environment variable

    After installing Node.js, verify that the npm global bin directory is in your PATH:

    1. Run the following command in the command line.

       ```powershell theme={null}
       npm config get prefix
       ```

       This returns the npm global directory path, typically `C:\Users\<YourUsername>\AppData\Roaming\npm`.

    2. Add the npm global directory path to the **Path** variable under **User variables** in your system's environment variables settings.

    3. Restart for the PATH changes to take effect.

    #### Verify the setup

    Run the following command in your terminal.

    ```powershell theme={null}
    npx --version
    ```

    If this returns a version number, your Windows setup is complete and the MCP server can use `npx` to run endorctl.
  </Accordion>
</AccordionGroup>
