English | 简体中文
A Python implementation of Nacos OpenAPI.
see: https://nacos.io/zh-cn/docs/open-API.html
Python 3.10+
Supported Nacos version over 3.x
Note: AI Client feature requires Nacos server version 3.1.0 or above.
pip install nacos-sdk-pythonfrom v2.nacos import NacosNamingService, NacosConfigService, NacosAIService, ClientConfigBuilder, GRPCConfig, \
Instance, SubscribeServiceParam, RegisterInstanceParam, DeregisterInstanceParam, \
BatchRegisterInstanceParam, GetServiceParam, ListServiceParam, ListInstanceParam, ConfigParam
from v2.nacos.ai.model.ai_param import GetPromptParam, SubscribePromptParam, DownloadSkillParam
client_config = (ClientConfigBuilder()
.access_key(os.getenv('NACOS_ACCESS_KEY'))
.secret_key(os.getenv('NACOS_SECRET_KEY'))
.server_address(os.getenv('NACOS_SERVER_ADDR', 'localhost:8848'))
.log_level('INFO')
.grpc_config(GRPCConfig(grpc_timeout=5000))
.build())- server_address - required - Nacos server address
- access_key - The aliyun accessKey to authenticate.
- secret_key - The aliyun secretKey to authenticate.
- credentials_provider - The custom access key manager.
- username - The username to authenticate.
- password - The password to authenticate.
- log_level - Log level | default:
logging.INFO - cache_dir - cache dir path. | default:
~/nacos/cache - log_dir - log dir path. | default:
~/logs/nacos - namespace_id - namespace id. | default: ``
- grpc_config - grpc config.
- max_receive_message_length - max receive message length in grpc. | default: 100 * 1024 * 1024
- max_keep_alive_ms - max keep alive ms in grpc. | default: 60 * 1000
- initial_window_size - initial window size in grpc. | default: 10 * 1024 * 1024
- initial_conn_window_size - initial connection window size in grpc. | default: 10 * 1024 * 1024
- grpc_timeout - grpc timeout in milliseconds. | default: 3000
- port_offset - gRPC port offset. The gRPC port = HTTP port + offset. | default: 1000
- capability_negotiation_timeout - timeout for capability negotiation in milliseconds. | default: 5000
- tls_config - tls config
- enabled - whether enable tls.
- ca_file - ca file path.
- cert_file - cert file path.
- key_file - key file path.
- kms_config - aliyun kms config
- enabled - whether enable aliyun kms.
- endpoint - aliyun kms endpoint.
- access_key - aliyun accessKey.
- secret_key - aliyun secretKey.
- password - aliyun kms password.
config_client = await NacosConfigService.create_config_service(client_config)
param: ConfigParam
paramdata_id Data id.paramgroup Group, useDEFAULT_GROUPif no group specified.paramcontent Config content.paramtag Config tag.paramapp_name Application name.parambeta_ips Beta test ip address.paramcas_md5 MD5 check code.paramtype Config type.paramsrc_user Source user.paramencrypted_data_key Encrypted data key.paramkms_key_id Kms encrypted data key id.paramusage_type Usage type.
content = await config_client.get_config(ConfigParam(
data_id=data_id,
group=group
))paramConfigParam config client common parameters. When getting configuration, it is necessary to specify the required data_id and group in param.returnConfig content if success or an exception will be raised.
Get value of one config item following priority:
-
Step 1 - Get from local failover dir.
-
Step 2 - Get from one server until value is got or all servers tried.
- Content will be saved to snapshot dir after got from server.
-
Step 3 - Get from snapshot dir.
async def config_listener(tenant, data_id, group, content):
print("listen, tenant:{} data_id:{} group:{} content:{}".format(tenant, data_id, group, content))
await config_client.add_listener(dataID, groupName, config_listener)paramConfigParam config client common parameters.listenerlistener Configure listener, defined by the namespace_id、group、data_id、content.return
Add Listener to a specified config item.
- Once changes or deletion of the item happened, callback functions will be invoked.
- If the item is already exists in server, callback functions will be invoked for once.
- Callback functions are invoked from current process.
await client.remove_listener(dataID, groupName, config_listener)paramConfigParam config client common parameters.returnTrue if success or an exception will be raised.
Remove watcher from specified key.
res = await client.publish_config(ConfigParam(
data_id=dataID,
group=groupName,
content="Hello world")
)paramConfigParam config client common parameters. When publishing configuration, it is necessary to specify the required data_id, group and content in param.returnTrue if success or an exception will be raised.
Publish one congfig data item to Nacos.
- If the data key is not exist, create one first.
- If the data key is exist, update to the content specified.
- Content can not be set to None, if there is need to delete config item, use function remove instead.
res = await client.remove_config(ConfigParam(
data_id=dataID,
group=groupName
))paramConfigParam config client common parameters.When removing configuration, it is necessary to specify the required data_id and group in param.returnTrue if success or an exception will be raised.
Remove one config data item from Nacos.
await client.shutdown()naming_client = await NacosNamingService.create_naming_service(client_config)response = await client.register_instance(
request=RegisterInstanceParam(service_name='nacos.test.1', group_name='DEFAULT_GROUP', ip='1.1.1.1',
port=7001, weight=1.0, cluster_name='c1', metadata={'a': 'b'},
enabled=True,
healthy=True, ephemeral=True))param1 = RegisterInstanceParam(service_name='nacos.test.1',
group_name='DEFAULT_GROUP',
ip='1.1.1.1',
port=7001,
weight=1.0,
cluster_name='c1',
metadata={'a': 'b'},
enabled=True,
healthy=True,
ephemeral=True
)
param2 = RegisterInstanceParam(service_name='nacos.test.1',
group_name='DEFAULT_GROUP',
ip='1.1.1.1',
port=7002,
weight=1.0,
cluster_name='c1',
metadata={'a': 'b'},
enabled=True,
healthy=True,
ephemeral=True
)
param3 = RegisterInstanceParam(service_name='nacos.test.1',
group_name='DEFAULT_GROUP',
ip='1.1.1.1',
port=7003,
weight=1.0,
cluster_name='c1',
metadata={'a': 'b'},
enabled=True,
healthy=False,
ephemeral=True
)
response = await client.batch_register_instances(
request=BatchRegisterInstanceParam(service_name='nacos.test.1', group_name='DEFAULT_GROUP',
instances=[param1, param2, param3]))response = await client.deregister_instance(
request=DeregisterInstanceParam(service_name='nacos.test.1', group_name='DEFAULT_GROUP', ip='1.1.1.1',
port=7001, cluster_name='c1', ephemeral=True)
)response = await client.update_instance(
request=RegisterInstanceParam(service_name='nacos.test.1', group_name='DEFAULT_GROUP', ip='1.1.1.1',
port=7001, weight=2.0, cluster_name='c1', metadata={'a': 'b'},
enabled=True,
healthy=True, ephemeral=True))service = await client.get_service(
GetServiceParam(service_name='nacos.test.1', group_name='DEFAULT_GROUP', cluster_name='c1'))service_list = await client.list_services(ListServiceParam())instance_list = await client.list_instances(ListInstanceParam(service_name='nacos.test.1', healthy_only=True))
instance_list = await client.list_instances(ListInstanceParam(service_name='nacos.test.1', healthy_only=False))
instance_list = await client.list_instances(ListInstanceParam(service_name='nacos.test.1', healthy_only=None))async def cb(instance_list: List[Instance]):
print('received subscribe callback', str(instance_list))
await client.subscribe(
SubscribeServiceParam(service_name='nacos.test.1', group_name='DEFAULT_GROUP', subscribe_callback=cb))async def cb(instance_list: List[Instance]):
print('received subscribe callback', str(instance_list))
await client.unsubscribe(
SubscribeServiceParam(service_name='nacos.test.1', group_name='DEFAULT_GROUP', subscribe_callback=cb))await client.shutdown()Important: AI Client feature requires Nacos server version 3.1.0 or above.
from v2.nacos import NacosAIService, ClientConfigBuilder
client_config = (ClientConfigBuilder()
.server_address(os.getenv('NACOS_SERVER_ADDR', 'localhost:8848'))
.build())
ai_client = await NacosAIService.create_ai_service(client_config)Transport Modes:
- Prompt supports both gRPC and HTTP transport. By default, gRPC is used. If the gRPC port is unreachable, the AI client will still start normally (gRPC reconnects asynchronously in the background), and Prompt operations can fall back to HTTP.
- Skill download always uses HTTP, regardless of gRPC availability.
- MCP Server / Agent Card management uses gRPC.
Nacos provides management capabilities for MCP (Model Context Protocol) Server, including registration, discovery, and subscription, supporting dynamic registration and service discovery of MCP servers.
from v2.nacos.ai.model.ai_param import GetMcpServerParam
mcp_server = await ai_client.get_mcp_server(
GetMcpServerParam(mcp_name='my-mcp-server', version='1.0.0')
)paramGetMcpServerParam Parameter for retrieving MCP server information.mcp_name- Name of the MCP server to query (required).version- Version of the MCP server to query (optional).
returnMcpServerDetailInfo if success or an exception will be raised.
from v2.nacos.ai.model.ai_param import ReleaseMcpServerParam
from v2.nacos.ai.model.mcp.mcp import McpServerBasicInfo, ServerVersionDetail
server_spec = McpServerBasicInfo(
name='my-mcp-server',
description='My MCP Server',
protocol='http',
versionDetail=ServerVersionDetail(version='1.0.0')
)
result = await ai_client.release_mcp_server(
ReleaseMcpServerParam(server_spec=server_spec)
)paramReleaseMcpServerParam Parameter for releasing/publishing MCP server.server_spec- Basic information specification for the MCP server (required).tool_spec- Tool specification defining the tools provided by MCP server (optional).mcp_endpoint_spec- Endpoint specification for MCP server network configuration (optional).
returnServer ID if success or an exception will be raised.
from v2.nacos.ai.model.ai_param import RegisterMcpServerEndpointParam
await ai_client.register_mcp_server_endpoint(
RegisterMcpServerEndpointParam(
mcp_name='my-mcp-server',
address='127.0.0.1',
port=8080,
version='1.0.0'
)
)paramRegisterMcpServerEndpointParam Parameter for registering MCP server endpoint.mcp_name- Name of the MCP server (required).address- IP address or hostname of the MCP server endpoint (required).port- Port number of the MCP server endpoint (required).version- Version of the MCP server (optional).
from v2.nacos.ai.model.ai_param import SubscribeMcpServerParam
async def mcp_listener(mcp_id, namespace_id, mcp_name, mcp_server_detail):
print(f"MCP Server changed: {mcp_name}, version: {mcp_server_detail.version}")
await ai_client.subscribe_mcp_server(
SubscribeMcpServerParam(
mcp_name='my-mcp-server',
version='1.0.0',
subscribe_callback=mcp_listener
)
)paramSubscribeMcpServerParam Parameter for subscribing to MCP server changes.mcp_name- Name of the MCP server to subscribe to (required).version- Version of the MCP server to subscribe to (optional).subscribe_callback- Callback function to handle MCP server changes (required).
await ai_client.unsubscribe_mcp_server(
SubscribeMcpServerParam(
mcp_name='my-mcp-server',
version='1.0.0',
subscribe_callback=mcp_listener
)
)Nacos provides management capabilities for AI Agent, including registration, discovery, and subscription, supporting dynamic registration and service discovery of Agent Card based on A2A protocol.
from v2.nacos.ai.model.ai_param import GetAgentCardParam
agent_card = await ai_client.get_agent_card(
GetAgentCardParam(agent_name='my-agent', version='1.0.0')
)paramGetAgentCardParam Parameter for retrieving agent card information.agent_name- Name of the agent card (required).version- Target version, if null or empty, get latest version (optional).registration_type- Registration type: 'url' or 'service' (optional).
returnAgentCardDetailInfo if success or an exception will be raised.
from v2.nacos.ai.model.ai_param import ReleaseAgentCardParam
from a2a.types import AgentCard
agent_card = AgentCard(
name='my-agent',
version='1.0.0',
protocol_version='1.0'
)
await ai_client.release_agent_card(
ReleaseAgentCardParam(
agent_card=agent_card,
registration_type='service',
set_as_latest=True
)
)paramReleaseAgentCardParam Parameter for releasing/publishing agent card.agent_card- Agent card information (required).registration_type- Registration type: 'url' or 'service' (optional, default: 'service').set_as_latest- Whether to set as the latest version (optional, default: False).
from v2.nacos.ai.model.ai_param import RegisterAgentEndpointParam
await ai_client.register_agent_endpoint(
RegisterAgentEndpointParam(
agent_name='my-agent',
address='127.0.0.1',
port=8080,
version='1.0.0',
transport='JSONRPC',
path='/agent',
support_tls=False
)
)paramRegisterAgentEndpointParam Parameter for registering agent endpoint.agent_name- Name of the agent (required).address- IP address or hostname of the agent endpoint (required).port- Port number of the agent endpoint (required).version- Version of the agent (required).transport- Transport protocol (optional, default: 'JSONRPC').path- URL path for the endpoint (optional).support_tls- Whether TLS is supported (optional, default: False).
from v2.nacos.ai.model.ai_param import DeregisterAgentEndpointParam
await ai_client.deregister_agent_endpoint(
DeregisterAgentEndpointParam(
agent_name='my-agent',
address='127.0.0.1',
port=8080,
version='1.0.0'
)
)paramDeregisterAgentEndpointParam Parameter for deregistering agent endpoint.agent_name- Name of the agent (required).address- IP address or hostname of the agent endpoint (required).port- Port number of the agent endpoint (required).version- Version of the agent (required).
from v2.nacos.ai.model.ai_param import SubscribeAgentCardParam
async def agent_listener(agent_name, agent_card_detail):
print(f"Agent card changed: {agent_name}, version: {agent_card_detail.version}")
await ai_client.subscribe_agent_card(
SubscribeAgentCardParam(
agent_name='my-agent',
version='1.0.0',
subscribe_callback=agent_listener
)
)paramSubscribeAgentCardParam Parameter for subscribing to agent card changes.agent_name- Name of the agent (required).version- Version of the agent (optional).subscribe_callback- Callback function to handle agent card changes (required).
await ai_client.unsubscribe_agent_card(
SubscribeAgentCardParam(
agent_name='my-agent',
version='1.0.0',
subscribe_callback=agent_listener
)
)Nacos provides prompt template management capabilities, including retrieval, subscription, and rendering with variable substitution.
from v2.nacos.ai.model.ai_param import GetPromptParam
prompt = await ai_client.get_prompt(
GetPromptParam(prompt_key='my-prompt', version='1.0.0')
)
print(prompt.template)paramGetPromptParam Parameter for retrieving prompt information.prompt_key- Key of the prompt to query (required).version- Version of the prompt (optional).label- Label of the prompt (optional).
returnPrompt if success or an exception will be raised.
The Prompt object supports template rendering with {{variableName}} placeholders. Variables defined in the prompt may include default values via PromptVariable.defaultValue. When rendering, default values are applied first, then overridden by user-provided values.
# Render the prompt template with variable substitution
result = prompt.render({"name": "Alice", "place": "Nacos"})
print(result) # e.g. "Hello Alice, welcome to Nacos!"
# Variables with defaultValue will be used automatically if not overridden
# For example, if the prompt has a variable: PromptVariable(name="lang", defaultValue="en")
# Calling render without providing "lang" will use "en" as the value
result = prompt.render({"name": "Alice"})paramvariables - A dict of variable name to value mappings (optional). Overrides default values defined inPromptVariable.defaultValue.returnRendered string with all{{variableName}}placeholders replaced.
from v2.nacos.ai.model.ai_param import SubscribePromptParam
async def prompt_listener(prompt_key, prompt):
print(f"Prompt changed: {prompt_key}, version: {prompt.version}")
prompt = await ai_client.subscribe_prompt(
SubscribePromptParam(
prompt_key='my-prompt',
version='1.0.0',
subscribe_callback=prompt_listener
)
)paramSubscribePromptParam Parameter for subscribing to prompt changes.prompt_key- Key of the prompt to subscribe to (required).version- Version of the prompt (optional).label- Label of the prompt (optional).subscribe_callback- Callback function to handle prompt changes (required).
returnCurrent Prompt if success or an exception will be raised.
await ai_client.unsubscribe_prompt(
SubscribePromptParam(
prompt_key='my-prompt',
version='1.0.0',
subscribe_callback=prompt_listener
)
)Nacos supports downloading skill packages as ZIP archives.
from v2.nacos.ai.model.ai_param import DownloadSkillParam
zip_bytes = await ai_client.download_skill_zip(
DownloadSkillParam(skill_name='my-skill', version='1.0.0')
)
# Save to file
with open('my-skill.zip', 'wb') as f:
f.write(zip_bytes)paramDownloadSkillParam Parameter for downloading a skill ZIP.skill_name- Name of the skill (required).version- Target skill version (optional, defaults to latest).label- Target skill label, e.g. "latest", "stable" (optional).
returnZIP file content as bytes if success or an exception will be raised.
await ai_client.shutdown()