Implement MCP client that uses Gitlab MCP server
What does this MR do and why?
MCP client is implemented in Workhorse. Workhorse is a proxy in front of Gitlab Rails and it already implements communication with Duo Workflow Service:
- Workhorse: Act as a proxy to Duo Workflow (!193149 - merged)
- [Workflow] Handle runHttpRequest action from Du... (!196891 - merged)
Diagram
sequenceDiagram
participant User
participant Workhorse
participant GitLabRails as GitLab Rails
participant DuoWorkflowService as Duo Workflow Service
%% Initial Setup Phase
User->>Workhorse: Establish WebSocket connection
Note over Workhorse,User: Bidirectional communication
Workhorse->>GitLabRails: Auth request
GitLabRails->>Workhorse: DWS and MCP server configurations
%% Service Connections
Workhorse->>GitLabRails: Init session with MCP Server
GitLabRails->>Workhorse: List of available tools
Workhorse->>DuoWorkflowService: Establish gRPC connection
Note over Workhorse,DuoWorkflowService: Bidirectional communication
%% Tool Execution Flow
User->>Workhorse: Input that may require MCP tool call
Workhorse->>DuoWorkflowService: Propagate message
DuoWorkflowService->>Workhorse: RunMCPTool action
Workhorse->>GitLabRails: Handle action and call MCP tool
GitLabRails->>Workhorse: Response
Workhorse->>DuoWorkflowService: Send MCP tool response
DuoWorkflowService->>Workhorse: Agent response
Workhorse->>User: Agent response
Why
- It enables support for self managed customers
- It enables support for customers with IP restrictions
- It enables support for airgapped customers
If we implement an MCP client in Duo Workflow Service, we'll likely encounter the issues we used to have with direct http requests from DWS to Rails:
- Self-managed customers may have closed networks or .com customers may have IP restrictions configured: in this case, a request from DWS is rejected and it's not easy to specify an IP in allowlist because DWS IP is dynamic.
- With Workhorse proxy we establish a gRPC connection with DWS and due to bidirectional communication over the established channel, the issue with incoming requests is solved.
MCP Server Configuration
It's implemented in a way that Gitlab Rails may specify configuration for any number of Streamable HTTP MCP servers:
{
server_name: {
URL: <server-url>,
Headers: <headers-send-on-each-request>,
Tools: <list-of-supported-tools> # empty means that all tools will be listed
}
}
GitLab configuration is hard-coded, while the list may also contain other server configurations For example,
{
gitlab: {
# URL is skipped and automatically resolved in Workhorse
Headers: {
Authorization: "Bearer #{gitlab_token}"
},
Tools: GITLAB_ENABLED_TOOLS
},
context7: {
URL: "https://mcp.context7.com/mcp",
}
}
Or the list can be extended by user provided configurations on instance/namespace/project/user levels. Enabling such feature .com will require AppSec review, but one of the very likely use cases: instance admins of self-managed instances can configure access to their own closed MCP servers. Enabling such feature is out of scope of this MR, we just initially design the feature in a way that it's possible in the future.
Additionally, Tools
version is available: it filters the list of available tools.
Migration plan
Currently, Gitlab server configuration narrows the list to a single tool (get_issue
). Additionally, the list is sent as x-gitlab-enabled-mcp-server-tools
header. The idea is:
- Extend the list of
Tools
and now they are passed as MCP tools to Duo Workflow Service and inx-gitlab-enabled-mcp-server-tools
header - Duo Workflow Service reads
x-gitlab-enabled-mcp-server-tools
header and excludes the specified tools from the list of its own defined tools, so the specified MCP tools can be used instead - We gradually extend the list with more tools with/without a feature flag to eventually mostly use MCP Server tools
A problem that is not yet solved in this MR: some of the tools should be pre-approved and some of them should require approval. We can have an additional PreApprovedTools
option in MCP server configuration to mark some tools as pre-approved.
How to test it
The implementation is behind mcp_client
feature flag.
- Enable
mcp_client
feature flag - Compile Workhorse. From
gitlab
folder:cd workhorse && make && gdk restart gitlab-workhorse && gdk tail -f gitlab-workhorse
- In Duo Workflow Service, manually remove
get_issue
(or any other) tool from the list:duo_workflow_service/workflows/chat/workflow.py
and run it aspoetry run duo-workflow-service
. In gitlab folder make sure thatconfig/gitlab.yml
contains:
development:
...
duo_workflow:
service_url: 0.0.0.0:50052
secure: false
- Visit
gdk.test:3333
(instead ofgdk.test:3000
) to have Web Agentic Chat available - Ask Agentic Chat to explain some issue
- An MCP tool
get_issue
should be called
Relates to #561296