# How r-nacos Implements MCP Server Functionality for Exposing HTTP Services as MCP Tools

> Discover how r-nacos models HTTP services as versioned tools in Raft-backed servers, using REST APIs and import/export contexts for MCP server functionality.

- Repository: [Nacos Group/r-nacos](https://github.com/nacos-group/r-nacos)
- Tags: internals
- Published: 2026-03-07

---

**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`](https://github.com/nacos-group/r-nacos/blob/main/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`](https://github.com/nacos-group/r-nacos/blob/main/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`](https://github.com/nacos-group/r-nacos/blob/main/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:

```bash
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:

```bash
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:

```bash
curl -O "http://localhost:8848/api/v2/mcp/server/download?namespace=production"

```

Import servers from a ZIP file using Python:

```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.rs`](https://github.com/nacos-group/r-nacos/blob/main/src/mcp/model/mcp.rs) define servers, values, and tool specifications that serialize to protobuf DTOs for Raft persistence.
- **Import/export safety** through `McpImportContext` ensures collision-free ID generation using `SEQ_MCP_SERVER_ID` and `SEQ_TOOL_SPEC_VERSION` sequences.
- **RESTful control plane** endpoints in [`src/console/v2/mcp_server_api.rs`](https://github.com/nacos-group/r-nacos/blob/main/src/console/v2/mcp_server_api.rs) translate HTTP requests into `McpManagerRaftReq` commands 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`](https://github.com/nacos-group/r-nacos/blob/main/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`.