APC MCP Hints Should Name Secrets, Not Store Them
A project can tell tools which MCP servers it expects.
That does not mean the repository should carry the credentials.
This is one of the clearest APC and APX boundaries: APC should name the MCP contract, while APX should supply and use secrets at runtime.
APC is the portable context layer. It gives a repository one stable place to declare project-owned agent context, rules, skills, and MCP expectations. For MCP, that place is .apc/mcps.json.
APX is the daily-use runtime and tooling layer. It reads APC files, merges them with local runtime config, audits conflicts, starts servers, and exposes tools through commands like apx mcp list, apx mcp run, and apx mcp check.
Once you keep those jobs separate, the rule gets simple:
.apc/mcps.json should describe what the project expects.
It should not contain the secret values needed to satisfy that expectation.
What belongs in .apc/mcps.json
The APC MCP config spec is specific about allowed content. The file may include:
- server names
- commands and non-secret arguments
- remote MCP URLs when the endpoint itself is part of the project contract
- environment variable names a user must provide locally
- enabled or disabled state when a consumer supports it
That makes the file portable and reviewable.
A repository can say, "this project expects a GitHub MCP server" or "this project uses a filesystem MCP rooted here," without leaking anyone's account or machine-local state.
A safe example looks like this:
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${env:GITHUB_TOKEN}"
}
}
}
}
That tells every compatible consumer what to wire up, but leaves the actual credential outside the repository.
What should stay out
The same APC spec also draws a hard line around unsafe content. Do not commit:
- API keys
- bearer tokens
- OAuth refresh tokens
- personal account IDs
- private headers
- credentials embedded in URLs
- generated session IDs
- machine-local absolute paths unless the path itself is intentionally part of the contract
The reason is bigger than secret hygiene.
If a repository stores literal credentials in .apc/mcps.json, APC stops being portable context and starts becoming a private runtime dump. That breaks the whole point of APC.
A clone-safe contract should survive a new laptop, a new teammate, or a different compatible runtime. A real token does not travel safely across any of those boundaries.
Where APX fits
This is where APX becomes useful instead of redundant.
APX does not need APC to hold the secret itself. It needs APC to hold the portable hint. Then APX can merge that hint with local runtime state and do the operational work.
That is why the APX CLI has a dedicated MCP layer:
apx mcp list
apx mcp check
apx mcp run github search_repositories '{"query":"org:agentprojectcontext"}'
apx mcp check is especially relevant here because it audits MCP source files, merge order, and conflicts. In practice, that means APC can stay commit-safe while APX verifies whether the local machine has supplied the missing pieces correctly.
So the workflow becomes clean:
- The repo declares the expected MCP server in
.apc/mcps.json. - The user provides credentials locally through environment variables or runtime-owned config.
- APX reads both layers, audits them, and runs the server.
That is a better split than pushing everything into one file.
Why naming env vars is enough
Teams sometimes assume that if the repo already names a secret like GITHUB_TOKEN, they may as well paste the value too.
That is the wrong conclusion.
Naming the variable is enough because it preserves the contract without hardcoding ownership.
The project can say:
- which variable must exist
- which server consumes it
- which command uses that server
and still let each developer, CI runner, or local daemon provide the value in its own safe way.
That is exactly how portable context should behave.
APC keeps the shared project expectation visible in Git.
APX keeps runtime credentials and execution local.
Small rule, big payoff.
When .apc/mcps.json names secrets instead of storing them, the repository stays portable, review stays sane, and runtimes like APX can still wire the full MCP stack without leaking private state into the project.
Top comments (0)