MCP Provider Architecture#
The MCP provider stack uses a three-layer pattern to separate persistence, domain logic, and presentation:
MCPToolProvider (SQLAlchemy)
β .to_entity()
MCPProviderEntity (Pydantic)
β MCPToolProviderController.from_entity()
MCPToolProviderController
Layer 1 β MCPToolProvider (Persistence)#
MCPToolProvider is the SQLAlchemy model backing the tool_mcp_providers table. It stores:
server_urlβ encrypted URL, with a separateserver_url_hashfor uniqueness enforcementencrypted_credentialsandencrypted_headersβ JSON-encoded blobs of encrypted valuesauthedβ boolean flag indicating whether OAuth is completetoolsβ JSON-serialized list of MCP tool definitions fetched from the remote servertimeout/sse_read_timeoutβ connection timeouts (defaults: 30s / 300s)identity_modeβ controls end-user identity forwarding ("off"or"idp_token")
The .credentials, .headers, and .tool_dict properties deserialize the raw JSON columns . The .to_entity() method delegates to MCPProviderEntity.from_db_model() .
Layer 2 β MCPProviderEntity (Domain)#
MCPProviderEntity is a Pydantic BaseModel that adds business logic on top of the raw database columns. It is the authoritative object passed around the service layer. Key responsibilities:
Decryption helpers β decrypt_server_url(), decrypt_headers(), and decrypt_credentials() all delegate to _decrypt_dict(), which dynamically builds an encrypter config for only the string fields, skipping nested dicts (e.g., client_information) that are not themselves encrypted.
Credential masking β The _mask_value() helper exposes only the first 2 and last 2 characters of long secrets (using "*" for the rest); values shorter than 6 characters are fully masked . Three public methods apply this:
masked_server_url()β strips the URL path to/******masked_headers()β masks every header valuemasked_credentials()β masksclient_idandclient_secretfrom nested OAuthclient_information
API serialization β to_api_response() produces the JSON object returned by the REST API. It accepts an include_sensitive flag: when False (used for list views), expensive decryption is skipped and masked_headers is returned as {} .
OAuth helpers β retrieve_tokens() returns OAuthTokens if the provider is authed (returns None on empty access_token to avoid sending an invalid Authorization header). retrieve_client_information() reconstructs an OAuthClientInformation from nested credentials, decrypting encrypted_client_secret inline. client_metadata builds OAuthClientMetadata for dynamic registration, selecting authorization_code vs client_credentials grant type from the stored client_information. decrypt_authentication() assembles the final headers dict to send to the MCP server β using explicit headers if present, otherwise injecting a Bearer token from retrieve_tokens().
IdentityMode enum β IdentityMode has two values: OFF (no forwarding, default) and IDP_TOKEN (forward an SSO access token from dify-enterprise). This is stored in MCPToolProvider.identity_mode and surfaced through the entity.
Layer 3 β MCPToolProviderController (Presentation)#
MCPToolProviderController wraps an MCPProviderEntity (or DB model) into a ToolProviderController, making the MCP provider consumable by the same tool invocation pipeline used by built-in and API tools.
from_db()β convenience classmethod that callsdb_provider.to_entity()thenfrom_entity()from_entity()β converts each raw tool dict inMCPProviderEntity.toolsto aToolEntityusingToolTransformService.convert_mcp_schema_to_parameter(), wraps them in aToolProviderEntityWithPlugin, and returns a fully initialized controllerget_tool()/get_tools()β instantiateMCPToolobjects on demand
Author fields at both tool and provider level are intentionally set to "Anonymous" because per-tool authorship is not persisted .
Service Layer Entry Point#
MCPToolManageService is the primary service that orchestrates CRUD operations on MCP providers. It queries MCPToolProvider rows, calls .to_entity() to get MCPProviderEntity objects, and uses MCPToolProviderController.from_db() when a controller is needed for tool invocation or credential management .
Key Source Files#
| File | Role |
|---|---|
api/models/tools.py | MCPToolProvider β SQLAlchemy DB model |
api/core/entities/mcp_provider.py | MCPProviderEntity β domain entity with decryption & masking |
api/core/tools/mcp_tool/provider.py | MCPToolProviderController β presentation/tool-invocation layer |
api/services/tools/mcp_tools_manage_service.py | MCPToolManageService β service layer orchestration |