Skip to content
PDF

MCP

Integrate Model Context Protocol in your workflow

Introduction

The Model Context Protocol (MCP) is a standardized protocol that enables AI models to access external tools and resources through a secure, capability-based negotiation system. This protocol bridges the gap between AI models and external systems, allowing for dynamic tool discovery, execution, and integration.

Module Suite plays a crucial role in seamlessly incorporating MCP into your enterprise content management ecosystem. By bridging the gap between your organization's content repositories and MCP-compatible servers, Module Suite empowers you to:

  1. Extend AI capabilities: Leverage external tools and services through MCP servers, expanding the functionality available to AI models.

  2. Standardize tool integration: Use a consistent protocol for connecting AI models with external resources, simplifying integration complexity.

  3. Enable dynamic tool discovery: Automatically discover and utilize tools available on MCP servers without hardcoding integrations.

  4. Enhance AI workflows: Integrate MCP tools with OpenAI function calling, allowing AI models to automatically execute external tools based on user requests.

  5. Maintain security: Implement secure authentication mechanisms (OAuth2 or custom) to protect access to external tools and resources.

  6. Support flexible authentication: Choose between OAuth2 automatic authentication or custom authorization mechanisms based on your security requirements.

By integrating MCP through Module Suite, organizations can harness the power of standardized tool integration to transform their AI-powered workflows, leading to increased flexibility, reduced integration complexity, and improved overall productivity.

MCP Integration Considerations

While MCP offers significant benefits, it's important to consider factors such as authentication requirements, server compatibility, and network access when integrating MCP servers into your workflow. Module Suite provides the necessary tools and interfaces to address these considerations effectively.

Architecture and Networking

Module Suite acts as a central hub for communication between Extended ECM (xECM), MCP-compatible servers, and AI services.

Here's an overview of how the networking and communication work:

flowchart TD
    subgraph ECM["Extended ECM (xECM)"]
        MS[Module Suite]
    end

    MCP[MCP Server]
    OAuth[OAuth Provider]
    OpenAI[OpenAI Service]

    MS <--> |Internal APIs| ECM
    MS <--> |MCP Protocol| MCP
    MS <--> |OAuth 2.0| OAuth
    MS <--> |Function Calling| OpenAI

    style ECM fill:#f9f,stroke:#333,stroke-width:2px
    style MS fill:#bbf,stroke:#333,stroke-width:2px
    style MCP fill:#bfb,stroke:#333,stroke-width:2px
    style OAuth fill:#fbb,stroke:#333,stroke-width:2px
    style OpenAI fill:#fbb,stroke:#333,stroke-width:2px

Integration with xECM

Module Suite runs directly on xECM, providing seamless access to all xECM APIs. This tight integration allows for efficient data exchange and leveraging of xECM's content management capabilities.

MCP Server Communication

Module Suite implements communication channels to MCP-compatible servers, which can be: - Public internet services - VPN-accessible services - On-premises solutions

The mcp Content Script service includes methods to programmatically connect to MCP servers, list available tools, execute tools, and convert MCP tools to OpenAI function calling format to be used with the openai service directly.

MCP Protocol Support

Module Suite features comprehensive support for the Model Context Protocol specification, enabling flexible integration with various MCP-compatible servers. This allows for standardized tool integration while maintaining a consistent interface.

Authentication Mechanisms

Module Suite supports two authentication modes for MCP integration:

  1. OAuth2 Authentication (automatic): Full OAuth2 flow with automatic token management
  2. Custom Authorization (manual): Flexible authentication using custom headers or tokens
Typical Communication Sequence

Below is a diagram illustrating a typical communication sequence when using Module Suite with xECM, an MCP server, and OpenAI:

sequenceDiagram
    participant User
    participant xECM
    participant Module Suite
    participant MCP Server
    participant OAuth Provider
    participant OpenAI

    User->>xECM: Request AI operation
    xECM->>Module Suite: Pass request
    Module Suite->>Module Suite: Check authentication
    alt Authentication required
        Module Suite->>OAuth Provider: Request authorization
        OAuth Provider-->>Module Suite: Return tokens
    end
    Module Suite->>MCP Server: List available tools
    MCP Server-->>Module Suite: Return tool definitions
    Module Suite->>OpenAI: Send request with MCP tools
    OpenAI-->>Module Suite: Request tool execution
    Module Suite->>MCP Server: Execute tool
    MCP Server-->>Module Suite: Return tool result
    Module Suite->>OpenAI: Return tool result
    OpenAI-->>Module Suite: Return final response
    Module Suite->>xECM: Process and format response
    xECM->>User: Display result

Components of the MCP Service Integration

Module Suite provides a comprehensive set of components to enable seamless integration with MCP services. These components work together to offer a robust and flexible MCP-enhanced experience within the Extended ECM environment.

Content Script Service

MCP Extension Package Service

The MCP service is a dedicated Content Script extension package service specifically designed for Model Context Protocol integrations. Key features include:

  • Multi-profile support for flexible configuration
  • Comprehensive implementation of MCP protocol features
  • OAuth2 and custom authorization support
  • Tool discovery and execution capabilities
  • OpenAI function calling integration
graph TD
    A[Module Suite] --> B[MCP Service]
    B --> C[Tool Discovery]
    B --> D[Tool Execution]
    B --> E[OpenAI Integration]
    B --> F[Authentication]
    F --> G[OAuth2]
    F --> H[Custom Authorization]

    style A fill:#f9f,stroke:#333,stroke-width:2px
    style B fill:#bbf,stroke:#333,stroke-width:2px

Integration Use Cases

Module Suite offers various capabilities for integrating MCP-powered functionalities into your Extended ECM environment. Let's explore common use cases and how to implement them.

Tool Discovery

Tool discovery allows you to explore and understand the capabilities available on an MCP server. This functionality is valuable for implementing:

  • Dynamic tool integration without hardcoding
  • Capability-based feature negotiation
  • Tool documentation and schema inspection
  • Integration planning and development

Example: Listing Available Tools

Here's a simple example of how to discover tools available on an MCP server:

try {
    mcp.validateProfile("mcp-profile")
    def toolsResult = mcp.listTools("mcp-profile")

    toolsResult.tools.each { tool ->
        out << "<p><b>${tool.name}</b>: ${tool.description}</p>"
    }
} catch (Exception e) {
    log.error("Error listing tools: ${e.message}", e)
    out << "An error occurred: " + e.getMessage()
}

This code validates the MCP profile configuration, retrieves the list of available tools from the MCP server, and displays each tool's name and description.

The listTools method returns a result object containing all tools available on the MCP server. Each tool includes metadata such as name, description, and parameter schemas.

Use Autocompletion

Remember to use the auto-completion feature of the editor (CTRL+Space) to explore available configuration options when working with the MCP service.

Tool Execution

Tool execution allows the AI to interact directly with external systems through MCP servers, performing actions or retrieving information as needed. This powerful feature enables the AI to manipulate content and execute operations within external systems.

Example: Executing a Tool

In this example, we'll demonstrate how to execute a tool on an MCP server:

try {
    mcp.validateProfile("mcp-profile")

    def result = mcp.executeTool(
        "search_documents",
        [
            query: "contract",
            limit: 10
        ],
        "mcp-profile"
    )

    result.content.each { content ->
        if (content.type == "text") {
            out << "<p>${content.text}</p>"
        }
    }
} catch (Exception e) {
    log.error("Error executing tool: ${e.message}", e)
    out << "An error occurred: " + e.getMessage()
}

This example demonstrates several key concepts:

  • Profile Validation: The validateProfile method ensures the MCP profile is properly configured and authenticated.

  • Tool Execution: The executeTool method takes the tool name, parameters, and profile ID to execute the tool on the MCP server.

  • Result Processing: The method returns a CSMcpCallToolResult object that contains:

    • content: List of content items returned by the tool (text, image, audio, resource, or resource_link)
    • isError: Boolean indicating if the tool execution resulted in an error
    • structuredContent: Optional JSON object representing the structured result of the tool call
    • meta: Map containing metadata for the result
  • Error Handling: The implementation includes error handling to manage potential issues during tool execution.

Tool Parameter Validation

Ensure that tool parameters match the schema defined by the MCP server. Invalid parameters will result in tool execution failures.

MCP Tools with OpenAI Integration

MCP tools can be seamlessly integrated with OpenAI function calling, allowing AI models to automatically discover and execute external tools based on user requests. This integration enables powerful workflows where AI models can leverage external capabilities dynamically.

Example: Using MCP Tools with OpenAI

def profileId = 'mcp-profile'

try {
    // Validate profile
    mcp.validateProfile(profileId)

    // Get all MCP tools as OpenAI response functions
    def tools = mcp.listToolsAsOpenAIResponseTools(profileId)

    // Build OpenAI response request with all tools
    def responseBuilder = openai.newResponseRequestBuilder()
        .model("gpt-4o")
        .instructions("You are a helpful assistant.")
        .input("Write a file and list all files in the directory")
        .toolChoiceMode("auto")

    // Add all tools as function tools
    tools.each { tool -> responseBuilder.addFunctionTool(tool) }

    def request = responseBuilder.build()
    def result = openai.createResponse(request)

    // Process response types
    def responseTypes = result.getResponseType()

    responseTypes.eachWithIndex { type, index ->
        if (type == "function_call") {
            // Handle function call - executor automatically executes MCP tool
            result.handleFunctionCall({ functionCallId, callId, status, name, arguments ->
                def selectedTool = tools.find { it.name == name }
                def functionResult = selectedTool?.executor(arguments)
                return functionResult
            }, index)
        }
    }
} catch (Exception e) {
    log.error("Error in OpenAI integration: ${e.message}", e)
    out << "An error occurred: " + e.getMessage()
}

This example demonstrates the powerful integration between MCP and OpenAI:

  • Tool Conversion: The listToolsAsOpenAIResponseTools method converts MCP tools into OpenAI function calling format, making them available to AI models.

  • Automatic Tool Discovery: All available MCP tools are automatically added to the OpenAI request, allowing the AI to choose which tools to use based on the user's request.

  • Automatic Execution: When the AI decides to call a function, the executor automatically executes the corresponding MCP tool, handling the complexity of tool invocation.

  • Seamless Integration: The integration is transparent to the AI model, which simply sees function calling capabilities without needing to know about the underlying MCP protocol.

Benefits of MCP-OpenAI Integration

This integration offers several advantages:

  1. Dynamic Tool Discovery: AI models can automatically discover and use new tools as they become available on MCP servers.

  2. Standardized Interface: MCP provides a standardized way to expose tools, making integration consistent across different services.

  3. Flexible Execution: Tools can be executed automatically based on AI decisions, reducing the need for manual intervention.

  4. Extensibility: New tools can be added to MCP servers without requiring changes to the AI integration code.

Tool Configuration

When creating a new MCP tool execution, it is possible to provide the tool configuration in the form of a Map object. The structure of this map is compatible with the JSON format MCP uses to define tool calls. This is the best approach to handle complex tool executions.

Core Concepts

Capability-Based Negotiation

The Model Context Protocol uses a capability-based negotiation system where clients and servers explicitly declare their supported features during initialization. Capabilities determine which protocol features and primitives are available during a session.

  • Servers declare capabilities like tool support
  • Clients declare capabilities for tool invocation and execution
  • Both parties must respect declared capabilities throughout the session
  • Additional capabilities can be negotiated through extensions to the protocol

The following diagram illustrates the MCP session lifecycle with tool listing and execution:

sequenceDiagram
    participant Client as Client
    participant Server as Server

    Client->>Server: Initialize client
    Server->>Client: Initialize session with capabilities
    Client->>Server: Respond with supported capabilities

    Client->>Server: List tools
    Server->>Client: Return available tools

    loop Tool Execution
        Client->>Server: Execute tool with parameters
        Server->>Client: Return tool result
    end

    Client->>Server: Terminate
    Server->>Client: End session

Each capability unlocks specific protocol features for use during the session. For example:

  • Implemented server features must be advertised in the server's capabilities
  • Tool invocation requires the server to declare tool capabilities
  • Tool listing requires the server to declare tool support in its capabilities

This capability negotiation ensures clients and servers have a clear understanding of supported functionality while maintaining protocol extensibility.

Tools

One of the core concepts when working with MCP is the "Tool", which represents a callable function that can be executed on the MCP server.

When defining a tool execution, you will be able to provide the tool name and parameters. The tool execution returns results that can contain text, images, resources, or other content types.

MCP tools can also be converted to OpenAI function calling format, allowing AI models to automatically execute tools through the MCP service.

Configuration

Base Configuration parameters description, default and purpose.

MCP Service Configuration Overview

The Module Suite Extension for MCP supports two authentication modes:

  1. OAuth2 Authentication (automatic): Requires full OAuth configuration
  2. Custom Authorization (manual): Only requires the MCP base URI, OAuth can be bypassed

OAuth2 Configuration

If you want to use OAuth2 automatic authentication, it is mandatory to set an mcp profile in the Module Suite Base Configuration with the following properties:

Property Description Example Value
mcp_uri MCP server base URI https://mcp.example.com/mcp
client_id OAuth2 client ID your-client-id
client_secret OAuth2 client secret your-secret-key
auth_uri OAuth2 authorization endpoint https://auth.example.com/oauth/authorize
token_uri OAuth2 token endpoint https://auth.example.com/oauth/token
refresh_uri OAuth2 refresh token endpoint https://auth.example.com/oauth/refresh
redirect_uri Content Server redirect URL https://your-domain:8443/otcs/cs
scope OAuth2 scope read write or empty
additional_props Additional properties specific for MCP additional_key@additional_value

OAuth2 Flow

The extension handles the OAuth authentication flow to MCP but the first time an mcp profile is used, it is necessary to authenticate the application on the MCP server website.

Redirect URI Configuration

The redirect_uri should point to your Content Server instance and will be used during the OAuth authorization flow. Ensure this URL is accessible and properly configured in your OAuth provider.

Custom Authorization Configuration

OAuth can be bypassed by providing an authorization closure to the validateProfile method. This allows authentication with any server using custom headers or authentication mechanisms. When using custom authorization, the minimum required configuration is:

Property Description Example Value
mcp_uri MCP server base URI https://mcp.example.com/mcp

All other OAuth-related properties (client_id, client_secret, auth_uri, etc.) are only required for OAuth automatic authentication and are not used when using custom authorization.

Security Considerations

When using custom authorization, ensure that your authentication mechanism is secure and follows your organization's security policies. API keys and tokens should be stored securely and not exposed in logs or public configurations.

Authentication

The extension supports two authentication modes: OAuth2 automatic authentication and custom authorization via closure.

OAuth2 Authentication

The MCP integration uses OAuth 2.0 for secure authentication. The following sequence diagram illustrates the complete authentication flow:

sequenceDiagram
    participant User as User
    participant CS as Content Server
    participant OAuth as OAuth Provider
    participant MCP as MCP Server

    User->>CS: Request MCP operation
    CS->>CS: Check for valid access token
    alt No valid access token
        CS->>CS: Check for refresh token
        alt No refresh token
            CS->>User: Redirect to authorization
            User->>OAuth: Authorize application
            OAuth->>CS: Return authorization code
            CS->>OAuth: Exchange code for tokens
            OAuth->>CS: Return access & refresh tokens
            CS->>CS: Store tokens securely
        else Refresh token exists
            CS->>OAuth: Request new access token
            OAuth->>CS: Return new access token
            CS->>CS: Store updated token
        end
        CS->>MCP: Make API request with token
        MCP->>CS: Return response
        CS->>User: Return result
    else Valid access token exists
        CS->>MCP: Make API request with token
        MCP->>CS: Return response
        CS->>User: Return result
    end

Token Management

The extension automatically handles token refresh:

  • Access tokens are refreshed automatically when expired
  • Refresh tokens are used to obtain new access tokens
  • Tokens are stored securely in Content Server's system data
  • Automatic refresh occurs transparently during API calls

Custom Authorization

OAuth can be bypassed by providing an authorization closure to the validateProfile method. This allows authentication with any server using custom headers, API keys, or other authentication mechanisms. When using custom authorization, only the mcp_uri configuration property is required.

EXAMPLE: Authorizing the application on the MCP endpoint
def profileId = 'mcp-profile'

try {
    mcp.validateProfile(profileId)
    out << "Successfully logged on MCP with the profile <b>${profileId}</b>"
} catch(AuthenticationException e) {
    def redirectUrl = "${url}/runcs/${self.ID}"
    def authURL = mcp.getAuthorizationUrl(redirectUrl, profileId)
    redirect authURL
}

The script invokes the Module Suite Extension for MCP validateProfile method which checks the configuration properties for the provided profile ID, checks the authorization code and, if it doesn't exists in the system, throws an AuthenticationException to indicate that the login to MCP is required. This exception is designed to be caught so that the authorization process can be initiated by redirecting the user to the OAuth authorization URL.

EXAMPLE: Using custom authorization
def profileId = 'mcp-profile'

// Define custom authorization closure
Closure authorizationClosure = { builder ->
    builder.header("OTCSTicket", "xxx-token-here")
}

// Validate profile with custom authorization (OAuth is bypassed)
mcp.validateProfile(profileId, authorizationClosure)

out << "Successfully authenticated with custom authorization"

The authorization closure receives a request builder that can be customized with headers, authentication tokens, or any other HTTP request modifications needed for your MCP server. This approach allows you to authenticate with servers that use non-OAuth authentication mechanisms such as API keys, custom tokens, or Content Server tickets.

Choosing the Right Authentication Method

When selecting an authentication method for your MCP integration, consider the following factors:

  • OAuth2: Use when the MCP server supports OAuth2 and you want automatic token management
  • Custom Authorization: Use when you need to integrate with servers using non-standard authentication or when you want more control over the authentication process

Troubleshooting

Common Issues

Authentication Errors

Problem: AuthenticationException when calling MCP methods

Solution: Verify profile configuration and ensure user has completed OAuth flow

try {
    mcp.validateProfile("mcp-profile")
} catch (AuthenticationException e) {
    def authURL = mcp.getAuthorizationUrl("${url}/runcs/${self.ID}", "mcp-profile")
    redirect authURL
}

Configuration Errors

Problem: ConfigurationException when validating profile

Solution: Check all required properties are set and property names match exactly

try {
    mcp.validateProfile("mcp-profile")
} catch (ConfigurationException e) {
    log.error("Configuration error: ${e.message}")
    out << "Please check your profile configuration: ${e.message}"
}

Tool Execution Failures

Problem: Tools fail to execute or return errors

Solution: Validate tool parameters match schema and check MCP server connectivity

try {
    def result = mcp.executeTool("tool_name", [param: "value"], "mcp-profile")
    if (result.isError) {
        log.error("Tool execution failed")
        result.content.each { content ->
            log.error("Error: ${content.text}")
        }
    }
} catch (CSMcpServiceException e) {
    log.error("Service error: ${e.message}", e)
}

Additional Resources