@tool contract (see
Build an integration). Connecting an MCP
server is the lighter-weight path: you point ModuleX at a server URL, it lists
the server’s tools, and it stores them on a credential your organization can use.
There is no in-app builder for authoring integrations today. You add your
own tools either by publishing a package to the
modulex-integrations catalog
(code) or by connecting an external MCP server (this page). Both paths are
code/configuration only.How it works
When you register an MCP server, ModuleX connects to it once, lists its tools, and persists the connection plus the discovered tool definitions as a single credential. At run time, a Tool node that references that credential reconnects to the server, loads the live tools, and invokes the one you named.Register the server
Call
POST /credentials/mcp-server with the server URL (and any auth
headers). ModuleX connects, discovers the tools, and stores them on a new
credential whose integration_name is the literal mcp_server and whose
auth_type is custom.Inspect the discovered tools
The create response includes the discovered tools in
credentials_metadata. You can also read them any time with
GET /credentials/{credential_id}/mcp-tools.Use a tool in a workflow
In a Tool node, set
tool.integration_name to mcp_server, set tool.credential_id to your
MCP credential, and set tool.service_name to the MCP tool’s name.🎬 MEDIA PLACEHOLDER · MX-MEDIA-4200 · [IMAGE]
[IMAGE_DESCRIPTION]: Diagram of the MCP credential lifecycle in ModuleX.
[IMAGE_DETAILS]: Three-stage flow — (1)
POST /credentials/mcp-server → ModuleX connects to the external MCP server and discovers tools; (2) tools stored on an mcp_server credential (auth_type: custom) in the organization; (3) a Tool node references the credential by credential_id and service_name, ModuleX reconnects at run time and invokes the tool. Show the server URL masked. Light theme, 16:9, labelled arrows.What a discovered tool looks like
Each tool ModuleX discovers is reduced to three fields, captured at discovery time and stored on the credential:The MCP tool’s name, as advertised by the server. This is the value you put in
a Tool node’s
service_name.The tool’s human/LLM-facing description (empty string if the server provides
none).
The tool’s input parameters as a JSON Schema object (typically
{type, properties, required}). ModuleX reads this from the tool’s
args_schema (or args / tool_call_schema fallbacks); if the server
advertises no schema, this is an empty object {}.TextContent response — a shape like
[{"type": "text", "text": "{...}"}] — and decodes the stringified JSON so that
an MCP tool returns structured data just like a built-in tool. This parsing is
handled internally by MCPToolWrapper; you do not configure it.
Transport and protocol
ModuleX connects to the server with thelangchain-mcp-adapters client over a
configurable transport. Two transports exist in the protocol — sse and
streamable_http — but the REST route does not expose a transport field: a
server registered through POST /credentials/mcp-server always uses the default
streamable_http transport. The discovered server_info.protocol_version
ModuleX records is 2024-11-05.
Authentication
Every ModuleX API request authenticates with your API key as a bearer token plus your organization context header. See API authentication for the full model.Request headers
member role cannot register or refresh MCP servers. See
Roles & permissions.
The MCP server itself is authenticated separately, with the headers you supply
on registration. ModuleX sends those headers to the server on every connection —
for example a bearer token the server expects:
headers field
The server URL and headers can carry secrets (some hosted MCP servers encode a
per-user token in the URL path or query). ModuleX encrypts them at rest on
the credential and masks the URL in logs to scheme and host only — for
example
https://mcp.example.com. The full URL is never logged.Register an MCP server
POST /credentials/mcp-server connects to the server, discovers its tools, and
creates one mcp_server credential.
Request body
The MCP server endpoint URL, for example
https://mcp.example.com/mcp.
ModuleX connects to this URL during discovery and again on every run.Optional HTTP headers sent to the MCP server on every request, including auth —
for example
{"Authorization": "Bearer token"}. Keys and values are strings.
Omit for an unauthenticated server.Optional label for the credential. If omitted, ModuleX generates one from the
server’s reported name and tool count, for example
MCP Server - example (8 tools).Whether to make this the default credential for the
mcp_server integration in
this organization. A Tool node that omits credential_id cannot resolve an MCP
server, so for MCP this mostly affects which credential the app preselects.There is no
transport_type field on this request — the route always registers
the server with the streamable_http transport (see
Transport and protocol).Response
A successful call returns201-style credential data shaped as
MCPServerCredentialResponse. This is a narrower shape than the standard
credential response — it omits updated_at, integration_type, last_used_at,
and expires_at.
The new credential’s ID. Use it as
tool.credential_id in a Tool node and as
the path parameter for refresh and list calls.Always
mcp_server.The label, either the one you supplied or the generated default.
Always
custom for MCP server credentials.Whether this is the default
mcp_server credential for the organization.ISO 8601 creation timestamp.
The discovery metadata, including the discovered tools.
Example response
List discovered tools
GET /credentials/{credential_id}/mcp-tools returns the tools currently stored
on the credential. It reads the persisted credentials_metadata.tools — it does
not reconnect to the server (use refresh for that).
The MCP server credential’s ID.
Response
The credential queried.
The discovered tool descriptors, each
{name, description, input_schema}.The number of tools returned.
Refresh tool discovery
POST /credentials/{credential_id}/refresh-discovery reconnects to the server,
re-lists its tools, updates the stored credentials_metadata, and returns a
summary of what changed. Run it after the server adds or removes tools. It is
valid only for mcp_server credentials; any other credential returns 400.
The MCP server credential to refresh.
Response
The credential refreshed.
ISO 8601 timestamp of this refresh.
A diff against the previous tool set.
The tool count after the refresh.
Whether the refresh completed.
Example response
Use an MCP tool in a workflow
A Tool node calls an MCP tool the same way it calls a catalog action, with three differences:integration_name is the literal
mcp_server, credential_id is required (the URL, headers, and transport
live on the credential, not the catalog), and service_name is the MCP tool’s
name.
Tool node — MCP tool definition
service_name, and invokes it with the mapped
inputs. The output is parsed back into structured data, so you reference it like
any other node output. See the Tool node
reference for input_mapping, parameter defaults and overrides, and the output
shape.
Errors
These routes use the standard{detail} HTTPException envelope (a string or, for
the org rate limit, an object) — not the flat billing DenialEnvelope. The
MCP credential routes are CRUD-style and have no per-call credit gate (the
credit gate applies to modulex_key resolution at execution time, not to these
routes). For the complete error model, see
Errors & status codes.
| Status | When | Detail |
|---|---|---|
400 | Connection or discovery failed; or refresh called on a non-mcp_server credential | CredentialValidationError message |
401 / 403 | Missing/invalid API key, or caller is not an owner/admin | auth dependency message |
404 | Credential not found in this organization (refresh / list) | CredentialNotFoundError message |
429 | Organization-class API rate limit (fail-open; includes X-RateLimit-* headers) | rate-limit object |
500 | Internal failure persisting the credential | CredentialServiceError message |
SDK reference
Every operation maps to a method in both official SDKs.| REST route | Python (modulex-python) | JavaScript (modulex-js) |
|---|---|---|
POST /credentials/mcp-server | credentials.create_mcp_server(...) | credentials.mcpServer(...) |
POST /credentials/{id}/refresh-discovery | credentials.refresh_mcp_discovery(id) | credentials.refreshDiscovery(id) |
GET /credentials/{id}/mcp-tools | credentials.mcp_tools(id) | credentials.mcpTools(id) |
Parity note: the JS
MCPServerCredentialResponse mirrors the backend’s narrower
MCP shape (it omits updated_at, integration_type, last_used_at, and
expires_at relative to a standard credential response). For the full
cross-language matrix, see the SDK ⇄ API parity matrix.Limitations
No transport choice on the public route
No transport choice on the public route
POST /credentials/mcp-server always registers a server with the
streamable_http transport; the sse transport is not selectable through
the request body. (TBD: a public way to choose the transport.)Discovery is a snapshot
Discovery is a snapshot
The tool list is captured at registration and persisted on the credential. A
GET .../mcp-tools call reads that snapshot; it does not reconnect. Run
refresh to pick up tools the server has added or
removed.Resources and prompts are not exposed
Resources and prompts are not exposed
MCP
resources and prompts are recorded as empty arrays; only tools are
discovered and usable today.Owner/admin only
Owner/admin only
Registering, refreshing, and listing MCP servers require the owner or admin
role. The
member role is retired and cannot perform these actions — see
Roles & permissions.Related
Tool node
Wire an MCP tool into a workflow with
integration_name: mcp_server.Build an integration
The code path: author a package integration with the
@tool contract.Credentials & OAuth2
How ModuleX stores and resolves credentials, including
custom types.Managing credentials
Create, scope, and rotate credentials in the app and via API.