How r-nacos Implements MCP Server Functionality for Exposing HTTP Services as MCP Tools
r-nacos implements MCP server functionality by modeling HTTP services as versioned tools within Raft-backed servers, providing REST APIs for CRUD operations, and using import/export contexts to remap IDs during data migration.
The r-nacos repository provides a Management Control Plane (MCP) that transforms HTTP endpoints into registered MCP tools. This architecture enables centralized discovery and invocation of services through a structured tool specification system backed by consensus-based storage.
Understanding the MCP Server Architecture in r-nacos
The implementation follows a three-layer architecture that separates data modeling, context management, and API exposure. The Data Model layer defines immutable protobuf DTOs and mutable Rust structs for servers and tools. The Import/Export Context layer handles ID generation and version remapping during data migration. The HTTP API layer exposes REST endpoints that translate client requests into Raft commands for the MCP manager.
Data Model Layer – Defining MCP Servers and Tools
The core data structures in src/mcp/model/mcp.rs establish the foundation for MCP server functionality.
McpServer Structure
The McpServer struct represents the top-level entity that groups tools under a unique key. It stores fields such as id, unique_key, namespace, name, auth_keys, current_value, release_value, and histories. The implementation provides conversion helpers to_do and from_do to translate between the Rust struct and the protobuf DTO (McpServerDo) used for Raft persistence.
McpServerValue and Tool Specifications
The mutable portion of a server is captured in McpServerValue, which holds description, a list of tools: Vec<McpTool>, the operator user, and timestamps. The update_param method merges a received McpServerParam into the existing value while tracking tool-version reference changes. Individual tools are represented by McpTool and McpSimpleTool, which link to a ToolSpec via tool_key and a specific version via tool_version.
Protobuf DTO Conversions
The model layer ensures seamless conversion between internal Rust structs and protobuf DTOs for distributed storage. These conversions preserve field mappings for route_rule, group, and namespace identifiers, ensuring that HTTP service metadata remains consistent across the Raft cluster.
Import and Export Context – ID Remapping and Version Management
When importing previously exported MCP servers, the system must remap IDs to avoid collisions with existing data. The McpImportContext in src/transfer/context/mcp.rs orchestrates this process.
Resetting Tool Specifications
The reset_tool_spec method creates new version IDs for a ToolSpec by calling next_tool_version_id—a Raft-backed sequence generator—for each old version. It updates the versions map and stores a tool_version_map that records the mapping from old version IDs to new ones for subsequent rewriting.
Building Servers with Unique IDs
The build_mcp_server method receives a persisted McpServerDo, deserializes it, and assigns a fresh server ID via next_server_id. It iterates through each historic McpServerValue and the current value, invoking reset_mcp_server_value to assign new server-value IDs and rewrite each tool's tool_version using the tool_version_map.
Raft-Backed Sequence Management
The context relies on the Raft SequenceManager to guarantee globally unique identifiers. It sends async messages with sequence keys SEQ_MCP_SERVER_ID, SEQ_MCP_SERVER_VALUE_ID, and SEQ_TOOL_SPEC_VERSION to obtain monotonic IDs that prevent conflicts during concurrent import operations.
HTTP API Layer – REST Endpoints for MCP Server Management
The console layer in src/console/v2/mcp_server_api.rs exposes HTTP endpoints that translate client requests into Raft commands. Each handler follows a consistent pattern: validate parameters, extract the operator from UserSession, generate missing IDs via SequenceManager, wrap the operation in a Raft request, and return an ApiResult.
Creating and Updating Servers
The do_add_mcp_server handler processes POST requests to /api/v2/mcp/server. It validates the McpServerParam, generates a server ID and initial value ID through the SequenceManager, and dispatches a McpManagerRaftReq::AddServer request to the MCP manager actor. The do_update_mcp_server handler follows a similar pattern for PUT requests, using McpManagerRaftReq::UpdateServer.
Publishing and Version Control
Publishing makes the current configuration active. The do_publish_current_mcp_server endpoint handles POST requests to /api/v2/mcp/server/publish by generating a new value ID and dispatching McpManagerRaftReq::PublishCurrentServer. The do_publish_history_mcp_server endpoint enables rollback to historic versions by accepting a specific history ID.
Import and Export Operations
The download_mcp_servers handler supports GET requests to /api/v2/mcp/server/download, querying all servers and converting each to YAML using generate_mcp_server_yaml before streaming a ZIP archive. The import_mcp_servers handler processes POST requests to /api/v2/mcp/server/import, extracting YAML files, deserializing them to McpServerImportDto, and invoking update_mcp_server_for_import which uses McpImportContext for ID remapping.
Practical Examples – Working with MCP Servers
Adding a New MCP Server
Use the REST API to register an HTTP service with multiple tools:
curl -X POST "http://localhost:8848/api/v2/mcp/server" \
-H "Content-Type: application/json" \
-d '{
"unique_key": "order-service",
"namespace": "production",
"name": "Order Service",
"description": "Expose order CRUD API",
"auth_keys": ["order-key-1","order-key-2"],
"tools": [
{
"tool_name": "CreateOrder",
"namespace": "production",
"group": "order",
"route_rule": "/order/create"
},
{
"tool_name": "GetOrder",
"namespace": "production",
"group": "order",
"route_rule": "/order/get"
}
]
}'
Publishing the Current Version
Activate the configured tools by publishing the server:
curl -X POST "http://localhost:8848/api/v2/mcp/server/publish" \
-H "Content-Type: application/json" \
-d '{"id": 12}'
Exporting and Importing Servers
Export all servers to a ZIP archive:
curl -O "http://localhost:8848/api/v2/mcp/server/download?namespace=production"
Import servers from a ZIP file using Python:
import requests
url = "http://localhost:8848/api/v2/mcp/server/import"
zip_bytes = open("servers_export.zip", "rb").read()
files = {"file": ("servers_export.zip", zip_bytes, "application/zip")}
resp = requests.post(url, files=files)
print(resp.json())
Summary
The r-nacos MCP server functionality combines consensus-based storage with structured tool definitions to expose HTTP services as manageable resources:
- Immutable data models in
src/mcp/model/mcp.rsdefine servers, values, and tool specifications that serialize to protobuf DTOs for Raft persistence. - Import/export safety through
McpImportContextensures collision-free ID generation usingSEQ_MCP_SERVER_IDandSEQ_TOOL_SPEC_VERSIONsequences. - RESTful control plane endpoints in
src/console/v2/mcp_server_api.rstranslate HTTP requests intoMcpManagerRaftReqcommands for atomic state changes. - Version management allows publishing current configurations or rolling back to historic server values via dedicated API endpoints.
Frequently Asked Questions
What is the MCP server functionality in r-nacos?
The MCP server functionality in r-nacos provides a Management Control Plane that registers HTTP services as MCP tools. Each tool binds to a ToolSpec that defines the HTTP endpoint, method, and schema, while the McpServer aggregates multiple tools under a unique key with authentication and routing rules.
How does r-nacos ensure unique IDs for MCP servers during import?
During import operations, the McpImportContext in src/transfer/context/mcp.rs generates fresh identifiers by querying the Raft-backed SequenceManager. It uses sequence keys SEQ_MCP_SERVER_ID, SEQ_MCP_SERVER_VALUE_ID, and SEQ_TOOL_SPEC_VERSION to obtain monotonic IDs, then remaps old tool version references through a tool_version_map to prevent collisions with existing data.
What file formats are supported for MCP server import and export?
The HTTP API supports YAML for individual server definitions and ZIP archives for bulk operations. The download_mcp_servers endpoint generates a ZIP containing one YAML file per server, while import_mcp_servers accepts a ZIP archive, extracts the YAML files, deserializes them into McpServerImportDto objects, and processes them through the import context.
How does the publishing mechanism work for MCP server versions?
Publishing activates the current server configuration by creating a new immutable version. The do_publish_current_mcp_server handler generates a fresh value ID via the SequenceManager, then dispatches a McpManagerRaftReq::PublishCurrentServer request to the MCP manager actor. This operation updates the release_value field, making the tools visible to downstream consumers while preserving the history for potential rollback via do_publish_history_mcp_server.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →