UnitySVC MCP server starter
Project description
UnitySVC MCP Server
Exposes the UnitySVC catalog and account operations to MCP clients — Claude Code, Claude Desktop, Codex, claude.ai — so an agent can discover services, explain how to call them, and (when you supply credentials) operate your account.
It is deliberately thin: it adapts MCP calls to the UnitySVC APIs through the official
unitysvc-py and unitysvc-sellers SDKs. Business rules, visibility, billing, and
authorization stay in the UnitySVC backend.
Status. Prototype. The table below marks what runs today versus what is designed but not yet built. See unitysvc/unitysvc#1492 for the full design.
Status Market + seller listing tools via the official SDKs ✅ implemented Anonymous marketplace browsing (no credentials) ✅ implemented stdio transport (default) and HTTP (opt-in) ✅ implemented Credentials from UNITYSVC_API_KEY/UNITYSVC_SELLER_API_KEY✅ implemented Tools split by mode, advertised on credentials present ✅ implemented Published to PyPI ✅ v0.1.0 mcp.unitysvc.comdeployed⏳ not yet deployed how_to_callcode-generation tool⏳ planned The earlier role-inference bug — where a valid seller key resolved to a customer principal and seller tools rejected it — is fixed by removing role inference entirely.
Two modes
The same package runs in two shapes. They differ only in transport and where credentials come from — the tools themselves are identical.
| Local (stdio) | Hosted (HTTP) | |
|---|---|---|
| Runs as | a subprocess of your MCP client, on your machine | a service at mcp.unitysvc.com |
| Credentials | your own API keys, from the process environment | none — by design |
| Offers | everything: the market view, plus your customer and seller operations | market discovery and how-to guidance only |
| Reaches | Claude Code, Claude Desktop, Codex | any client, including claude.ai in a browser |
| Needs | a local Python runtime | nothing |
Why the hosted instance holds no credentials. The valuable question — "which service should I use, and how do I call it?" — does not require your key. The catalog is public, and the actual invocation goes from your machine to the gateway with your key, never through us. So the hosted server answers questions and returns copy-pasteable commands; it never acts on your behalf, and there is no credential for it to hold, log, or leak.
It is not a different program. It is this same package running with nothing in its environment, so only the tools that need no credentials are advertised.
Credentials: where they live, and what is never sent
This is the part worth reading carefully.
Local (stdio)
your MCP client config
│ populates the child process environment at spawn
▼
unitysvc-mcp-server (subprocess on your machine)
│ UNITYSVC_API_KEY / UNITYSVC_SELLER_API_KEY
▼ HTTPS, directly
api.unitysvc.com / seller.unitysvc.com
- Your key lives in your MCP client's configuration and in the environment of a process on your own machine. Nowhere else.
- It is sent only to the UnitySVC API, over HTTPS, by the SDK — the same destination
the
usvcCLI uses. There is no intermediary. - It is never sent to
mcp.unitysvc.com, and never appears in tool arguments, so it does not enter the model's context, the conversation transcript, or your client's logs.
Exporting the variable in your shell is not enough. MCP clients pass only a safelist
of variables to a spawned server — HOME, LOGNAME, PATH, SHELL, TERM, USER — so
UNITYSVC_API_KEY from your shell profile will not reach the process. You must declare
it in the MCP configuration. Use variable expansion so the value stays in your shell rather
than being written into a file:
"env": { "UNITYSVC_API_KEY": "${UNITYSVC_API_KEY}" }
Which key you provide decides what you can do:
| You set | You get |
|---|---|
| nothing | marketplace browsing |
UNITYSVC_SELLER_API_KEY |
marketplace browsing + your seller listings |
UNITYSVC_API_KEY |
marketplace browsing — no additional tools yet |
UNITYSVC_API_KEY currently unlocks nothing: the customer-side tools
(enrollments, invoke) are not built, and marketplace browsing does not vary by
customer — the backend serves that listing from a fixed active + public
filter and ignores caller identity. The variable is recognised so it is ready
when those tools land; until then, only a seller key changes what you can do.
There is no role to configure. The API key already encodes whether it is a customer or a seller key, and the backend enforces it.
Hosted (HTTP)
No credentials are configured, sent, or held. If you find yourself pasting an API key to
use mcp.unitysvc.com, something is wrong — it does not accept one.
Installation
Claude Code — local, with your keys
claude mcp add unitysvc \
--env UNITYSVC_API_KEY="${UNITYSVC_API_KEY}" \
--env UNITYSVC_SELLER_API_KEY="${UNITYSVC_SELLER_API_KEY}" \
-- uvx --prerelease=allow --from unitysvc-mcp-server unitysvc-mcp-server
Note on
--prerelease=allow. This package pinsmcp[cli]==2.0.0b1, the MCP Python SDK v2 beta.uvrefuses to resolve pre-release dependencies unless told to, souvxneeds that flag.pip install unitysvc-mcp-serverneeds nothing extra. The flag goes away once MCP SDK v2 ships stable and the pin moves off the beta.
Or project-scoped, in .mcp.json — safe to commit, since the values are expanded from your
environment at launch and never written into the file:
{
"mcpServers": {
"unitysvc": {
"type": "stdio",
"command": "uvx",
"args": ["--prerelease=allow", "--from", "unitysvc-mcp-server", "unitysvc-mcp-server"],
"env": {
"UNITYSVC_API_KEY": "${UNITYSVC_API_KEY}",
"UNITYSVC_SELLER_API_KEY": "${UNITYSVC_SELLER_API_KEY}"
}
}
}
}
Omit either variable to run without that role's tools; omit both for anonymous browsing.
Claude Desktop — local, with your keys
~/Library/Application Support/Claude/claude_desktop_config.json (macOS):
{
"mcpServers": {
"unitysvc": {
"type": "stdio",
"command": "uvx",
"args": ["--prerelease=allow", "--from", "unitysvc-mcp-server", "unitysvc-mcp-server"],
"env": { "UNITYSVC_API_KEY": "svcpass_..." }
}
}
}
Claude Desktop is a GUI application and does not read your shell startup files, so ${VAR}
expansion has nothing to expand from — the literal value is required here. That file is not
in a repository, but treat it as a secret. Restart Claude Desktop after editing, and note
that a JSON syntax error silently disables all configured servers.
Codex — local, with your keys
Codex takes an equivalent stdio entry in ~/.codex/config.toml with command, args, and
env. Check the current Codex documentation for the exact key names before relying on it —
we have not verified them against a recent release.
claude.ai — hosted, no credentials
Add https://mcp.unitysvc.com/mcp as a custom connector. There is nothing to authenticate
and no key to supply. You get catalog discovery and how-to guidance; to act on your account,
use one of the local setups above.
Tools
Named for the side of the marketplace they belong to, so it is unambiguous which one answers a given request:
Tools are named for the credential they need, and grouped into one module per requirement — the prefix is the access rule:
| Prefix | Requires | Registered | Today |
|---|---|---|---|
market_ |
nothing | always | market_list_services(group, limit, cursor) |
customer_ |
UNITYSVC_API_KEY |
when set | — (enrollments, invoke: planned) |
seller_ |
UNITYSVC_SELLER_API_KEY |
when set | seller_list_services(status, limit, cursor) |
So a prefixed tool needs that role's key and market_ is free — a rule an agent can apply
without reading descriptions, and one that keeps same-verb pairs unambiguous
(customer_get_usage = your spend, seller_get_usage = your revenue).
The hosted deployment runs with an empty environment, so it registers market_ only.
Each description also states explicitly what the tool is not and points at its counterpart, since those descriptions are all a model has when choosing.
Tools are advertised, not just gated. With no seller key, seller_list_services does
not appear in tools/list at all, so an agent never sees an option it cannot use and never
burns a turn discovering that. The hosted deployment runs with an empty environment, so it
advertises exactly the first row.
The previous role-aware list_services has been removed. It existed to paper over an agent
not knowing which mode it was in; conditional advertisement answers that directly, and the
tool was redundant with the two explicit ones in both modes.
Configuration
| Variable | Purpose | Default |
|---|---|---|
UNITYSVC_API_KEY |
customer API key — recognised, but unlocks no tools yet | unset |
UNITYSVC_SELLER_API_KEY |
seller API key | unset → seller tools unavailable |
UNITYSVC_API_URL |
customer API base | https://api.unitysvc.com/v1 |
UNITYSVC_SELLER_API_URL |
seller API base | https://seller.unitysvc.com/v1 |
UNITYSVC_MCP_TRANSPORT |
stdio or http |
stdio |
UNITYSVC_MCP_HOST / UNITYSVC_MCP_PORT |
bind address — HTTP mode only | 127.0.0.1 / 8000 |
The key and URL variables are the SDKs' own, so if you already use the usvc CLI you have
them set and need no new values.
Anonymous catalog browsing requires the customer API to serve unauthenticated catalog reads (unitysvc/unitysvc#1610) — merged, but not yet deployed in every environment.
Development
uv sync --dev
uv run pytest
uv run ruff check src/ tests/
Run it:
uv run unitysvc-mcp-server # stdio (default)
UNITYSVC_MCP_TRANSPORT=http uv run unitysvc-mcp-server # HTTP, binds HOST:PORT
The startup log line reports which mode you got — transport, whether any credentials were found, and the tools registered.
The MCP SDK v2 beta is pinned in pyproject.toml; revisit the pin when v2 stabilises.
Design
See unitysvc/unitysvc#1492 for the full design: the two deployment modes, credential handling, MCP specification conformance, and phasing.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file unitysvc_mcp_server-0.1.2.tar.gz.
File metadata
- Download URL: unitysvc_mcp_server-0.1.2.tar.gz
- Upload date:
- Size: 74.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8437c47db38c9c10ac9928faa45d46e45cba17880813c66b1261acfd3cdf31d0
|
|
| MD5 |
5ab2144adea6a102b9842ee766aab7a7
|
|
| BLAKE2b-256 |
ba21b7654b6272aad48759f51afb6a78cb4e29c38b548fb60e82b6efb75c51d7
|
Provenance
The following attestation bundles were made for unitysvc_mcp_server-0.1.2.tar.gz:
Publisher:
publish.yml on unitysvc/unitysvc-mcp-server
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
unitysvc_mcp_server-0.1.2.tar.gz -
Subject digest:
8437c47db38c9c10ac9928faa45d46e45cba17880813c66b1261acfd3cdf31d0 - Sigstore transparency entry: 2195133779
- Sigstore integration time:
-
Permalink:
unitysvc/unitysvc-mcp-server@50ec77ef91ce42b9903e05dfedbc51df2f0d43db -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/unitysvc
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@50ec77ef91ce42b9903e05dfedbc51df2f0d43db -
Trigger Event:
release
-
Statement type:
File details
Details for the file unitysvc_mcp_server-0.1.2-py3-none-any.whl.
File metadata
- Download URL: unitysvc_mcp_server-0.1.2-py3-none-any.whl
- Upload date:
- Size: 16.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
200fe3d3d3625be9dc76d0e8eb0861eafd4e46e1902065ea41d13968874c84ec
|
|
| MD5 |
203e688fe71aeb15e3e97ab9b23a7b9b
|
|
| BLAKE2b-256 |
3e6dc60278f096a20eca2ed497b2e22858699144e6c2e2d224d1343bfd61eb2f
|
Provenance
The following attestation bundles were made for unitysvc_mcp_server-0.1.2-py3-none-any.whl:
Publisher:
publish.yml on unitysvc/unitysvc-mcp-server
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
unitysvc_mcp_server-0.1.2-py3-none-any.whl -
Subject digest:
200fe3d3d3625be9dc76d0e8eb0861eafd4e46e1902065ea41d13968874c84ec - Sigstore transparency entry: 2195133783
- Sigstore integration time:
-
Permalink:
unitysvc/unitysvc-mcp-server@50ec77ef91ce42b9903e05dfedbc51df2f0d43db -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/unitysvc
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@50ec77ef91ce42b9903e05dfedbc51df2f0d43db -
Trigger Event:
release
-
Statement type: