Scenario D of the Embr × Foundry POC. The first sample where Embr is the thing being driven, not the thing hosting the driver.
An MCP server hosted on Embr that exposes Embr Global API operations as tools, so a Foundry / Claude Desktop / VS Code agent can answer questions like:
- "What's deployed in my
embr-foundry-chat-sampleproduction environment right now?" - "Show me the last failed build for the
embr-multiservice-apiproject." - "List all environment variables on my staging environment."
…by calling Embr's own control-plane.
This is the inverse of every other sample in this POC. Other samples ask "how does an Embr-hosted app talk to Foundry?" — this one asks "how does a Foundry agent talk to Embr?"
embr-mcp-control-plane/
├── app/
│ ├── embr_client.py # thin httpx wrapper around the Embr Global API
│ ├── mcp_server.py # FastMCP server registering the tools
│ └── main.py # FastAPI shell that mounts MCP under /mcp/
├── embr.yaml
├── requirements.txt
└── README.md
| Tool | Purpose |
|---|---|
embr_whoami |
Confirm the token is valid; returns API URL and a probe result |
list_projects |
Enumerate projects the user has access to |
get_project |
Project details by id |
get_project_by_repo |
Project details by GitHub owner/repo |
list_environments |
Environments under a project |
get_environment |
Environment details (incl. activeDeploymentId) |
list_deployments |
Recent deployments for an environment |
get_deployment |
Deployment details (status, url, error) |
list_builds |
Recent builds for an environment |
get_build |
Build details (status, error, imageRef) |
list_variable_keys |
Variable keys (NOT values — values may be secret) |
Mutating tools (create deployment, set env var, delete env) are intentionally not exposed in v1 — adding them is trivial code-wise, but the auth-scoping problem (see Findings below) means a write tool would inherit the human's full Embr permission. We surface that as a finding rather than ship the unsafe pattern.
-
Install deps
pip install -r requirements.txt
-
Get an Embr token. The MCP server uses the same bearer token your
embrCLI uses.# find it in ~/.config/embr-cli/config.json (or %APPDATA%\embr-cli\config.json on Windows) cat ~/.config/embr-cli/config.json | jq -r '.token'
-
Set env vars (
.envworks thanks to python-dotenv)export EMBR_TOKEN="<that token>" export EMBR_API_URL="https://api.embr.azure" # default; override for local API. Note: no /api suffix — Embr's Global API serves routes at root (/projects, /environments, …).
-
Run
uvicorn app.main:app --reload --port 8000
-
Smoke-test the MCP handshake
curl -s -X POST http://localhost:8000/mcp/ \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl","version":"0.0"}}}' -
Or point Claude Desktop / VS Code at it
embr quickstart deploy embr-devs/embr-mcp-control-plane -i 120233234After deploy:
embr config context -p prj_<id> -e env_<id>
embr variables set EMBR_TOKEN=<token> --secret
embr variables set EMBR_API_URL https://api.embr.azureThen the MCP endpoint is at https://<deployment-url>/mcp/.
To register from a Foundry agent: add an MCP project connection in the Foundry portal pointing at that URL, attach it as an MCP tool to your agent.
This sample exists to surface platform gaps, not to ship a production pattern. Specifically:
- The MCP server holds one
EMBR_TOKEN. That token is the human user's full bearer credential — same one theembrCLI uses. - Anyone (or any agent) with that token can: list every project, create / cancel / delete deployments, set env vars (including secrets), delete environments, delete projects.
- There is no way today to mint a token scoped to:
- a single project (
scope: project:prj_xxx) - read-only operations (
scope: read) - specific resource verbs (
scope: deployments:read environments:read) - a time window (
expires: 1h)
- a single project (
- The agent runs with the human's full permission, and the human has no way to constrain that.
Platform feature ask: scoped, short-lived tokens with an MCP-friendly minting flow — embr tokens issue --scope read --project prj_xxx --ttl 24h returning a token the agent can use.
- A real agent caller can't rotate its own token. If the human revokes, the agent silently 401s. There's no "heartbeat token" pattern.
- Platform ask: distinct credential class for agents with a refresh-token flow.
- There's no
embr.yaml: expose_as: control-plane-mcporembr mcp publishto make this kind of MCP server a first-class affordance. - Today the developer has to hand-write the
httpxwrapper, theFastMCPregistration, theembr.yaml, and the deploy + variable-setting dance for every control-plane MCP they want. - Platform ask: an
embrsubcommand or curated template that scaffolds a control-plane MCP server with a chosen subset of read/write capabilities.
- Embr's audit/activity log records the user that owns the token, not "this token was used by an agent named X via MCP server Y."
- For the "agent driving Embr" pattern to be a viable production posture, audit needs to record the agent identity alongside the user identity (think AWS IAM "AssumedRole" identity).
- Platform ask: agent identity threaded through to activity log entries.
- Same MCP-mount-path trailing-slash bug as
embr-foundry-tool-sample: the in-app middleware works around it, but the underlying ingress 307 leak (perFINDINGS.md) is unchanged.
- An agent can call
embr_whoamito see who it is, but there's no scopes-introspection endpoint (/auth/scopes,/.well-known/oauth-authorization-server, etc.). - Platform ask: an introspection endpoint so an agent can self-report capabilities to its model in-context.
A platform that wants to be the answer to "where do AI agents do their work?" has to be operable by agents, not just operable to host them. Today Embr is highly operable to host. The control-plane gaps above are exactly what a customer would hit the moment they ask "can my Foundry agent run a deploy when CI is green?" — and the answer is "yes, but you'd be giving it your full personal token."
That's the central finding this sample makes concrete.