spring-nacos-mcp
# spring-nacos-mcp
[中文文档](README.zh-CN.md)
**A project-aware, read-only Nacos MCP server for Spring Cloud repositories.**
Point it at your Spring Cloud repo. It reads your own `application-*` / `bootstrap-*`
files, discovers every environment (dev / test / pre / prod / ...), and gives your AI
assistant read-only Nacos tools across **all** of them — no host, port, namespace or
token to configure.
```text
You: "Is sso.server.productCode consistent between dev and test?"
Claude: → nacos_search_config(env=dev, keyword=sso.server.productCode)
→ nacos_diff_config(env_a=dev, env_b=test, data_id=sso.properties)
"Yes — the value is identical in both environments (`PC-1001`).
One related key differs though: sso.server.url points to
dev-sso.corp.com in dev and test-sso.corp.com in test."
```
## Why not the official `nacos-mcp-server`?
The official [nacos-group/nacos-mcp-server](https://github.com/nacos-group/nacos-mcp-server)
connects to **one cluster** that you configure by hand (`--host`, `--port`, `--access_token`).
That's the right tool for operating a Nacos cluster.
This project answers a different question: *"what does **my project's** config look
like across environments?"*
| | official nacos-mcp-server | spring-nacos-mcp |
|---|---|---|
| Setup | manual host/port/token per cluster | **zero-config**: parsed from your repo |
| Environments | one per server instance | all profiles, `env` param on every tool |
| Cross-env diff | not possible (single cluster) | built-in `nacos_diff_config` |
| Spring awareness | none | shared-configs, file-extension, app config |
| Write operations | planned | **never** (read-only by design) |
## Quickstart
### The easy way: let your AI agent install it
Paste this into Cursor / Claude Code / Codex / Trae:
> Install the MCP server from https://github.com/kestiny18/spring-nacos-mcp
> into this project and verify it works.
The repo ships an [llms-install.md](llms-install.md) with exact steps per client,
so the agent can do the whole thing — download, config, verification — by itself.
### Manual, option A: copy one file (no PyPI, no dependencies)
The whole server is a single, zero-dependency, standard-library-only Python file.
Drop it into your repo:
```bash
curl -sfL -o tools/nacos_mcp.py https://raw.githubusercontent.com/kestiny18/spring-nacos-mcp/main/src/spring_nacos_mcp/server.py
```
```jsonc
// .cursor/mcp.json or .mcp.json (Claude Code), at the repo root
{
"mcpServers": {
"spring-nacos-mcp": { "command": "python", "args": ["tools/nacos_mcp.py"] }
}
}
```
Works on intranet machines too — copy the file over however you like.
### Manual, option B: uv / pip straight from git
```jsonc
{
"mcpServers": {
"spring-nacos-mcp": {
"command": "uvx",
"args": ["--from", "git+https://github.com/kestiny18/spring-nacos-mcp", "spring-nacos-mcp"]
}
}
}
```
Or `pip install git+https://github.com/kestiny18/spring-nacos-mcp` and use the
`spring-nacos-mcp` command.
The server auto-detects the repo root from its working directory (your editor's
workspace). For clients that don't launch servers in the workspace (e.g. Claude
Desktop), pin it: `"args": [..., "--repo", "/path/to/repo"]`.
### Verify your setup
```bash
python tools/nacos_mcp.py --check # or: spring-nacos-mcp --check
```
Prints every discovered environment, where it came from, and whether the Nacos
server is reachable. Exit codes: `0` all reachable · `1` nothing discovered ·
`2` discovered but some unreachable (usually VPN/network, not setup).
## Tools
| Tool | What it does |
|---|---|
| `nacos_list_envs` | List discovered environments with address/namespace/groups |
| `nacos_get_config` | Read one config's raw content by dataId |
| `nacos_get_app_config` | App config + the shared/extension configs your project declares |
| `nacos_list_configs` | List dataIds in a namespace (optional fuzzy filter) |
| `nacos_search_config` | Full-text search across all config contents |
| `nacos_diff_config` | **Key-level diff of one config between two environments** |
| `nacos_list_services` | List services in the discovery registry |
| `nacos_list_instances` | List online instances (IP/port/health) of a service |
## How discovery works
1. Find the repo root (`.git`, `pom.xml`, `build.gradle`, `mvnw`, `gradlew`, ...).
2. Scan every `*/src/main/resources/` for
`application[-<profile>].{yml,yaml,properties}` and `bootstrap[-<profile>].{yml,yaml,properties}`.
Multi-document YAML with `spring.config.activate.on-profile` (or legacy
`spring.profiles`) is supported.
3. For each profile, merge sources in priority order:
`bootstrap-<profile>` → `application-<profile>` → base `bootstrap` → base `application`.
4. Extract `spring.cloud.nacos.*`: server-addr, namespace, username/password, config
group (also from `spring.config.import: nacos:...?group=X`), discovery group,
`file-extension`, `shared-configs` / `extension-configs` / legacy `shared-dataids`.
Relaxed binding (`server-addr` / `serverAddr` / `server_addr`) is handled.
5. `${...}` placeholders are resolved from environment variables
(`${nacos.addr}` also tries `NACOS_ADDR`); `${name:default}` uses the default.
Environments with unresolved placeholders are skipped with a clear log line.
### Overrides
Environment variables (highest precedence), `<ENV>` is the upper-cased profile name:
```bash
NACOS_DEV_SERVER_ADDR / NACOS_DEV_NAMESPACE / NACOS_DEV_USERNAME /
NACOS_DEV_PASSWORD / NACOS_DEV_GROUP / NACOS_DEV_CONTEXT_PATH
NACOS_USERNAME / NACOS_PASSWORD # global fallback credentials
```
Or a `.spring-nacos-mcp.yml` at the repo root — patch discovered environments or
define ones that aren't in the repo at all:
```yaml
envs:
staging:
server-addr: nacos-staging.corp.com:8848
namespace: ns-staging
username: readonly
password: ${STAGING_NACOS_PASSWORD} # resolved from env var
```
## Security notes
- **Read-only by construction**: the only endpoints ever called are config/service
GET queries and the login endpoint. There is no code path that writes to Nacos.
- **Config content reaches the LLM.** If your configs contain secrets, enable
masking: `SPRING_NACOS_MCP_MASK=1` masks values whose keys contain
`password/secret/token/credential/...`, or provide your own list:
`SPRING_NACOS_MCP_MASK=password,apikey`. Masking is off by default.
- Prefer a read-only Nacos account (via `NACOS_USERNAME` / `NACOS_PASSWORD`) over
credentials committed in config files.
## Compatibility
- Python ≥ 3.9, zero runtime dependencies.
- Nacos 1.x / 2.x via the v1 OpenAPI; auth via `/v1/auth/login` with automatic
fallback to `/v3/auth/user/login` (Nacos 3.x). `https://` server addresses and
comma-separated cluster address lists are supported.
- Nacos 3.x keeps v1 OpenAPI compatibility in current releases; if your deployment
disables it, please open an issue — a v3 API backend is on the roadmap.
## Limitations
- The built-in YAML parser covers the subset used by Spring config files
(nested maps, lists, multi-document). Anchors and flow collections are ignored.
- Placeholders that come from Maven profile filtering (`@...@`) are not resolved;
use the override file for those repos.
## License
[Apache-2.0](LICENSE)
TDQS
Scored across 8 tools
Each tool targets a distinct resource and action: diff config, get config (raw or app-level), list configs, list environments, list instances, list services, search config. No two tools have overlapping purposes, making selection unambiguous.
All tool names follow the consistent pattern 'nacos_verb_noun' in snake_case (e.g., nacos_diff_config, nacos_list_services). Verbs and nouns are clear and uniform, with no mixing of conventions.
With 8 tools covering both configuration and service discovery, the count is well-scoped for the domain. Each tool serves a distinct purpose without bloat or insufficiency.
The toolset provides comprehensive read and comparison capabilities for Nacos configs and services, including diff, search, and app-level config resolution. It lacks write operations (create/update/delete), but given the diagnostic focus, this is a minor gap.