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

# ModuleX MCP overview

> Publish your live ModuleX workflows, Files, and Knowledge as tools an external AI client can call over the Model Context Protocol (MCP). What ModuleX MCP is, how it differs from connecting a custom MCP server, what it exposes, and what it requires.

export const MediaEmbed = ({id, type = 'screenshot', caption = '', ext, ratio = '16 / 9'}) => {
  const isVideo = type === 'video' || type === 'app_video';
  const resolvedExt = ext || (isVideo ? 'mp4' : type === 'screenshot' ? 'webp' : 'svg');
  const src = 'https://media.modulex.dev/' + id + '.' + resolvedExt;
  const [status, setStatus] = useState('loading');
  const [isDev, setIsDev] = useState(false);
  const [inView, setInView] = useState(false);
  const boxRef = useRef(null);
  useEffect(() => {
    if (typeof window === 'undefined') return;
    const h = window.location.hostname;
    setIsDev(h === 'localhost' || h === '127.0.0.1' || h.endsWith('.mintlify.app'));
  }, []);
  useEffect(() => {
    if (inView) return;
    if (typeof IntersectionObserver === 'undefined') {
      setInView(true);
      return;
    }
    const el = boxRef.current;
    if (!el) return;
    const io = new IntersectionObserver(entries => {
      if (entries.some(e => e.isIntersecting)) {
        setInView(true);
        io.disconnect();
      }
    }, {
      rootMargin: '300px'
    });
    io.observe(el);
    return () => io.disconnect();
  }, [inView]);
  if (status === 'missing') {
    if (!isDev) return null;
    return <div style={{
      display: 'flex',
      flexDirection: 'column',
      justifyContent: 'center',
      gap: '0.4rem',
      padding: '1rem 1.25rem',
      margin: '1.25rem 0',
      width: '100%',
      aspectRatio: ratio,
      boxSizing: 'border-box',
      border: '1px dashed rgba(128,128,128,0.45)',
      borderRadius: '0.75rem',
      background: 'rgba(128,128,128,0.06)',
      color: 'currentColor',
      fontSize: '0.85rem',
      lineHeight: 1.45
    }}>
        <div style={{
      display: 'flex',
      alignItems: 'center',
      gap: '0.5rem',
      opacity: 0.75
    }}>
          <span aria-hidden="true">🎬</span>
          <code style={{
      fontSize: '0.75rem'
    }}>{id}</code>
          <span style={{
      fontSize: '0.65rem',
      textTransform: 'uppercase',
      letterSpacing: '0.04em',
      padding: '0.1rem 0.4rem',
      borderRadius: '0.4rem',
      background: 'rgba(128,128,128,0.18)'
    }}>
            {type}
          </span>
        </div>
        <div style={{
      opacity: 0.9
    }}>{caption || 'Media not uploaded yet.'}</div>
        <div style={{
      fontSize: '0.7rem',
      opacity: 0.5
    }}>
          Upload to R2 as <code>{id}.{resolvedExt}</code> — preview only, hidden in production.
        </div>
      </div>;
  }
  const mediaStyle = {
    display: status === 'loaded' ? 'block' : 'none',
    width: '100%',
    height: 'auto',
    borderRadius: '0.75rem'
  };
  const media = isVideo ? <video src={inView ? src : undefined} autoPlay loop muted playsInline preload="metadata" onLoadedData={() => setStatus('loaded')} onError={() => setStatus('missing')} style={mediaStyle} /> : <img src={inView ? src : undefined} alt={caption} onLoad={() => setStatus('loaded')} onError={() => setStatus('missing')} style={mediaStyle} />;
  return <figure style={{
    margin: '1.25rem 0'
  }}>
      <div ref={boxRef} style={status === 'loaded' ? {
    width: '100%'
  } : {
    width: '100%',
    aspectRatio: ratio,
    borderRadius: '0.75rem',
    background: 'rgba(128,128,128,0.06)'
  }}>
        {media}
      </div>
      {status === 'loaded' && caption ? <figcaption style={{
    marginTop: '0.5rem',
    textAlign: 'center',
    fontSize: '0.85rem',
    opacity: 0.7
  }}>
          {caption}
        </figcaption> : null}
    </figure>;
};

**ModuleX MCP** turns your organization into a **Model Context Protocol (MCP) server**. You publish a private endpoint that external AI clients — Claude Code, Cursor, Codex, or any MCP-capable app — connect to, and they can then call your live [workflows](/concepts/workflows-and-runs), read and write your organization's **Files**, and search your [Knowledge bases](/concepts/knowledge-rag), all as MCP tools.

You set it up entirely in the app: create a logical MCP server, choose which tools it exposes, and generate a key. The client connects over HTTP with that key and sees your tools alongside its own.

<CardGroup cols={3}>
  <Card title="Workflows" icon="workflow" href="/api-reference/mcp/connect-a-client#workflow-tools">
    Each deployed workflow becomes a callable tool. The client runs it with the workflow's published inputs and gets the result back.
  </Card>

  <Card title="Files" icon="file-text" href="/api-reference/mcp/connect-a-client#built-in-tools">
    List, read, write, and append your organization's Files from the client, subject to your existing quotas.
  </Card>

  <Card title="Knowledge" icon="book-open" href="/api-reference/mcp/connect-a-client#built-in-tools">
    List your Knowledge bases and run retrieval over them, so the client can ground its answers in your data.
  </Card>
</CardGroup>

<MediaEmbed id="MX-MEDIA-4700" type="image" caption={"A direction diagram: external AI clients (Claude Code, Cursor, Codex) connect over Streamable HTTP to a private ModuleX MCP endpoint that exposes the organization's workflow, Files, and Knowledge tools."} />

## Which MCP page do you want?

ModuleX touches MCP in **two opposite directions**. They are separate features — do not confuse them.

<CardGroup cols={2}>
  <Card title="ModuleX as the MCP server" icon="upload" href="/api-reference/mcp/overview">
    **This page.** ModuleX *publishes* an MCP endpoint; an external client connects *to ModuleX* and calls your workflows, Files, and Knowledge. The client is the consumer; ModuleX provides the tools.
  </Card>

  <Card title="ModuleX as the MCP client" icon="download" href="/integrations/building/custom-mcp">
    The reverse: you connect an *external* MCP server *to ModuleX* as a credential, and ModuleX calls its tools from a [Tool node](/workflow-builder/nodes/tool). ModuleX is the consumer. See [Custom MCP servers](/integrations/building/custom-mcp).
  </Card>
</CardGroup>

<Note>
  A quick test: if you want **Claude Code or Cursor to use ModuleX**, you are on the right page. If you want **a ModuleX workflow to use some other tool server**, you want [Custom MCP servers](/integrations/building/custom-mcp).
</Note>

## How it works

<Steps>
  <Step title="Create a server in the app">
    In **Settings → ModuleX MCP**, create a private MCP server for your organization. See [Publish an MCP server](/api-reference/mcp/publish-a-server).
  </Step>

  <Step title="Choose what it exposes">
    Select which built-in tools (Files, Knowledge) and which deployed [workflows](/workflow-builder/execution/deploy) the server publishes.
  </Step>

  <Step title="Generate a key">
    Create a server key. ModuleX shows the key once — copy it then. Clients send it on every request.
  </Step>

  <Step title="Connect a client">
    Paste the endpoint URL and key into your MCP client's config. Your tools appear in the client. See [Connect an MCP client](/api-reference/mcp/connect-a-client).
  </Step>
</Steps>

## What it exposes

A published server exposes **tools** in two groups:

* **Built-in tools** — a fixed set for your organization's Files and Knowledge: list workflows, list/read/write/append Files, and list/search Knowledge. Enable the ones you want per server.
* **Workflow tools** — each deployed workflow you publish, exposed with its published name, description, and input schema. Calling the tool runs the workflow.

The [Connect an MCP client](/api-reference/mcp/connect-a-client#the-published-tools) page lists every built-in tool and explains how workflow tools are named and called.

<Info>
  ModuleX MCP publishes your **workflows, Files, and Knowledge** — not the third-party [integration catalog](/integrations/catalog). To give a client access to a catalog action (Slack, GitHub, and so on), wrap it in a workflow and publish that workflow.
</Info>

## Requirements

<CardGroup cols={3}>
  <Card title="A paid plan" icon="credit-card" href="/billing/plans">
    Publishing requires an organization on a paid plan. See [Plans & pricing](/billing/plans).
  </Card>

  <Card title="Owner or admin" icon="shield" href="/security/roles-permissions">
    Only an organization owner or admin can create and manage MCP servers and keys.
  </Card>

  <Card title="A private endpoint" icon="lock" href="/api-reference/mcp/publish-a-server">
    Each server is private to your organization and reached only with an active key.
  </Card>
</CardGroup>

## Billing

Connecting a client and listing tools are free. Calling a tool that **runs a workflow** or **searches Knowledge** consumes [credits](/billing/credits), metered exactly as if you ran it in the app — the client is just another way to trigger the same managed usage. If your organization is out of credits or its plan does not permit the usage, the tool call comes back as an error result rather than running. See [Usage gating & limits](/billing/usage-gating).

## Next steps

<CardGroup cols={2}>
  <Card title="Publish an MCP server" icon="upload" href="/api-reference/mcp/publish-a-server">
    Create a server in the app, choose its tools, and generate a key.
  </Card>

  <Card title="Connect an MCP client" icon="plug" href="/api-reference/mcp/connect-a-client">
    Endpoint, transport, auth, and ready-to-paste configs for Claude Code, Cursor, Codex, and generic HTTP clients.
  </Card>

  <Card title="Custom MCP servers" icon="download" href="/integrations/building/custom-mcp">
    The reverse direction: use an external MCP server's tools inside a ModuleX workflow.
  </Card>

  <Card title="Deploy a workflow" icon="rocket" href="/workflow-builder/execution/deploy">
    A workflow must be deployed before it can be published as an MCP tool.
  </Card>
</CardGroup>
