MCP Server for AI agents¶
The Update Factory MCP server lets an AI agent that speaks the Model Context Protocol (an MCP client, such as Claude Code or opencode) use the Management API of your tenant: list and create targets, inspect distributions, software modules and rollouts, manage tags, types and filters, and more.
Read-only tools are marked as such, so your client can allow them without asking. Operations that delete or invalidate do nothing until the agent repeats the call with an explicit confirm=true, which a well-behaved client asks you to approve. As a further precaution, the API clients that Kynetics provides for the MCP server are not allowed to delete anything: deletion operations are answered with HTTP 403 Forbidden.
The server is a Python package on a private package index: access is through your Kynetics contact.
Before you start¶
You need four things from Kynetics:
- An API client for your tenant (a name and a secret). To request one, open a ticket; see Bearer Token (OAuth 2 client credentials).
- The index URL of the private package index, ending in
/simple/(written<INDEX_URL>below). - A read-only index user and its password (
<INDEX_USER>,<INDEX_PASSWORD>). - The version of the server to install, written
<VERSION>below.
You also need uv, which runs the server (uvx) and downloads it from the index.
1. Give uv the index credentials¶
uv reads the credentials of the index from a netrc file. Create or extend it with this line:
machine <INDEX_HOST> login <INDEX_USER> password <INDEX_PASSWORD>
<INDEX_HOST> is only the host name of <INDEX_URL>: no https://, no path. Then make the file private:
The file is ~/.netrc.
chmod 600 ~/.netrc
The file is %USERPROFILE%\_netrc (%USERPROFILE%\.netrc also works). Windows has no chmod: keep the file in your user profile folder and do not share it.
On every system you can keep the file elsewhere and point uv to it with the NETRC environment variable. Do not put these credentials in the configuration of your MCP client.
2. Check the installation¶
uvx --index <INDEX_URL> updatefactory-mcp-server@<VERSION> --version
It must print updatefactory-mcp-server <VERSION>. The first run downloads the server and its dependencies and takes about ten seconds.
Warning
Keep a space between <INDEX_URL> and updatefactory-mcp-server. Without it uvx prints only its own version (uvx 0.x.y) and never contacts the index.
3. Save the API client credentials¶
Put the API client name and secret in a file that only you can read, so that the secret stays out of your MCP client configuration. Use the tier of your tenant (business or personal) and the tenant name:
{
"business": {
"<TENANT>": {
"client_id": "<API_CLIENT_NAME>",
"client_secret": "<API_CLIENT_SECRET>"
}
}
}
| System | File |
|---|---|
| Linux | ~/.config/updatefactory/credentials.json |
| macOS | ~/Library/Application Support/updatefactory/credentials.json |
| Windows | %APPDATA%\updatefactory\credentials.json |
On Linux and macOS run chmod 600 on the file. The file can hold several tiers and tenants; the server picks the entry that matches UF_ENV and UF_TENANT.
4. Configure your MCP client¶
Every client needs the same three things: the command uvx, the arguments --index <INDEX_URL> updatefactory-mcp-server@<VERSION>, and two environment variables: UF_ENV (business or personal) and UF_TENANT (your tenant name).
claude mcp add updatefactory --scope user \
--env UF_ENV=business --env UF_TENANT=<TENANT> \
-- uvx --index <INDEX_URL> updatefactory-mcp-server@<VERSION>
Keep the name updatefactory right after add: a name placed right after --env is read as another variable. --scope user makes the server available in all your projects and writes its configuration to ~/.claude.json. With --scope project the configuration goes to a .mcp.json file in the project, which can be committed and shared, and each user has to approve the server once (claude mcp list shows it as pending until then): never put a secret in that file. claude mcp list shows the configured servers.
Add the server to the opencode.json of the project (or to your global opencode configuration):
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"updatefactory": {
"type": "local",
"command": ["uvx", "--index", "<INDEX_URL>", "updatefactory-mcp-server@<VERSION>"],
"environment": {
"UF_ENV": "business",
"UF_TENANT": "<TENANT>"
},
"enabled": true
}
}
}
opencode mcp list shows the server as connected when it starts.
These clients read a mcpServers block from their MCP configuration file. Add:
{
"mcpServers": {
"updatefactory": {
"command": "uvx",
"args": ["--index", "<INDEX_URL>", "updatefactory-mcp-server@<VERSION>"],
"env": {
"UF_ENV": "business",
"UF_TENANT": "<TENANT>"
}
}
}
}
A desktop application may start the command with a shorter PATH than your terminal: if the client reports that uvx is not found, replace "uvx" with its full path (run which uvx, or where uvx on Windows).
Add the server to .vscode/mcp.json (or to your user MCP configuration):
{
"servers": {
"updatefactory": {
"type": "stdio",
"command": "uvx",
"args": ["--index", "<INDEX_URL>", "updatefactory-mcp-server@<VERSION>"],
"env": {
"UF_ENV": "business",
"UF_TENANT": "<TENANT>"
}
}
}
}
If you prefer not to keep the secret in a file, VS Code can ask for it when the server starts: declare an input with "type": "promptString" and "password": true, and reference it from the environment as "UF_CLIENT_SECRET": "${input:uf-secret}" together with "UF_CLIENT_ID": "<API_CLIENT_NAME>".
Add the server to ~/.codex/config.toml:
[mcp_servers.updatefactory]
command = "uvx"
args = ["--index", "<INDEX_URL>", "updatefactory-mcp-server@<VERSION>"]
[mcp_servers.updatefactory.env]
UF_ENV = "business"
UF_TENANT = "<TENANT>"
5. Make the first call¶
Restart the client and ask it:
List 5 targets of my Update Factory tenant.
The agent calls the targets_read tool. A list of targets, even an empty one, means that the server started and your API client credentials work.
Where the API client secret is stored¶
| Method | Where the secret is | Notes |
|---|---|---|
| Credentials file (step 3) | credentials.json, readable only by you |
Recommended. The client configuration holds only UF_ENV and UF_TENANT. |
| Client prompt | Asked by the client at start, not in a file | VS Code, see its tab. |
Environment variables UF_CLIENT_ID and UF_CLIENT_SECRET in the client configuration |
The client configuration file, in plaintext | Both must be set. They override the credentials file and ignore UF_ENV and UF_TENANT. Never in a file you share or commit. |
Pin and update¶
Always keep the version after @ in the arguments: it decides which release your client starts. To update, change the version number in the client configuration and restart the client.
uvx keeps the downloaded server in a cache, but it contacts the index at every start: the machine needs network access and a valid netrc file each time. With uvx --offline it starts from the cache without contacting the index.
Troubleshooting¶
401 Unauthorized from the index, in a message such as "An index URL ... could not be queried due to a lack of valid authentication credentials"
: The index user is missing from your netrc file, the host is wrong, or the password is. Check that the line in the netrc file names only the host, and that the client runs as the user who owns the file.
updatefactory-mcp-server: UF_ENV is required (UpdateFactory environment identifier)
: The environment variables are missing from the client configuration: add UF_ENV and UF_TENANT.
updatefactory-mcp-server: no API client credentials found for UF_ENV='...' UF_TENANT='...'
: The server found no API client credentials for that tier and tenant, and stops. The message lists where it looked, in order: the environment variables UF_CLIENT_ID and UF_CLIENT_SECRET, the credentials file (with its full path) and the system keyring (an optional extra). For the file it says why it did not match: the file does not exist, it is not valid JSON, it has no entry for that tier and tenant (it then names the tiers or tenants it does contain), it uses a flat layout instead of the nested one of step 3, or the entry lacks a client_id or a client_secret. Fix the file of step 3: its path, UF_ENV and UF_TENANT must match its keys.
HTTP 403 Forbidden from a tool, after the server started
: The credentials are accepted, but the API client has no permission for this operation. A 403 on a deletion is expected: the API clients that Kynetics provides for the MCP server are not allowed to delete. For any other operation contact Kynetics support.
The first start is slow : The server and its dependencies are downloaded once, about ten seconds on a regular connection. Later starts are faster.
The client says the server did not start : Run the command of step 2 in a terminal as the same user: the error is printed there.