MCP Control Plane (Beta)¶
Status: beta. The MCP server ships in beta. Tools, schemas, and response envelopes can change in a future minor release until the interface is marked stable. Feedback is welcome through GitHub issues.
Py Env Studio (PES) exposes a local, read-only MCP (Model Context Protocol) server so AI coding agents can consume authoritative Python environment state instead of guessing it from files.
PES is not an AI model. The client (VS Code Copilot, Copilot CLI, Claude Desktop, Cursor, …) does the reasoning; PES supplies environment, package, dependency, security, runtime, and project facts from its own services, database, and caches.
MCP client (reasoning) ──stdio──▶ PES MCP server ──▶ PES Core services
environment · packages
security · runtime
project · database
Beta scope and guarantees¶
Property |
Value |
|---|---|
Transport |
Local stdio only (no HTTP, no sockets, no network) |
Access |
Read-only — no tool mutates environments, packages, or projects |
Scans |
Never triggered by MCP; |
Tools |
8 read-only tools (see the table below) |
Default state |
Enabled, but it runs only when a client launches |
Logging |
Diagnostics go to stderr; stdout is reserved for protocol traffic |
Protocol |
MCP JSON-RPC 2.0, newline-delimited messages, protocol version |
Requirements¶
Python 3.12+
Py Env Studio 2.1.0+ installed so the
py-env-studiocommand is onPATHAn MCP-capable client (VS Code with Copilot Chat, GitHub Copilot CLI, Claude Desktop, Cursor, …)
Step 1 — Verify the PES CLI works¶
py-env-studio --help # flags, subcommands, and output options
py-env-studio --list # environments PES knows about
pes and pyenvstudio are equivalent aliases installed alongside
py-env-studio, so pes --help, pes --list, and pes mcp all work the same
way (see the CLI reference).
The installed version is reported by the initialize handshake shown below, by
Help → About in the GUI, and by pip show py-env-studio (which reads the
same 2.1.0 value as pyproject.toml and py_env_studio/config.ini).
If py-env-studio is not found, either use the full path to the executable
(for example
C:\Users\<you>\AppData\Local\Programs\Python\Python312\Scripts\py-env-studio.exe)
or invoke the module form python -m py_env_studio mcp.
Confirm the server starts and speaks JSON-RPC. Send an initialize message:
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' | py-env-studio mcp
On PowerShell the same one-liner works with single quotes; if your shell mangles
the braces, save the line to a file and redirect it
(py-env-studio mcp < request.jsonl).
Expected response (single line):
{"jsonrpc": "2.0", "id": 1, "result": {"protocolVersion": "2024-11-05",
"capabilities": {"tools": {}},
"serverInfo": {"name": "py-env-studio", "version": "2.1.0"}}}
Press Ctrl+C to stop a manually started server.
Step 2 — Register the server in your MCP client¶
VS Code with Copilot Chat (recommended: the guided flow)¶
Open the Command Palette (
Ctrl+Shift+P).Run MCP: Add Server.
Choose stdio as the server type.
Enter the command
py-env-studioand the argumentmcp.Save the server to Workspace (
.vscode/mcp.json) or to your User profile.
VS Code with Copilot Chat (manual .vscode/mcp.json)¶
Create .vscode/mcp.json in the workspace (or open your user configuration with
the MCP: Open User Configuration command) and add:
{
"servers": {
"py-env-studio": {
"type": "stdio",
"command": "py-env-studio",
"args": ["mcp"]
}
}
}
When the command is not on PATH, point command at the interpreter and pass
the module as the first argument:
{
"servers": {
"py-env-studio": {
"type": "stdio",
"command": "C:\\Python312\\python.exe",
"args": ["-m", "py_env_studio", "mcp"],
"cwd": "${workspaceFolder}"
}
}
}
Portable format (Copilot CLI, Agent Host, other clients)¶
Clients that use the portable format read a top-level mcpServers object from
.mcp.json at the workspace root or ~/.copilot/mcp-config.json:
{
"mcpServers": {
"py-env-studio": {
"command": "py-env-studio",
"args": ["mcp"]
}
}
}
Claude Desktop uses claude_desktop_config.json in the platform-specific
%APPDATA%\Claude (Windows), ~/Library/Application Support/Claude (macOS), or
~/.config/Claude (Linux) directory with the same mcpServers shape, and
Cursor uses ~/.cursor/mcp.json (global) or <workspace>/.cursor/mcp.json.
Step 3 — Start and trust the server¶
In VS Code, run MCP: List Servers from the Command Palette.
Select
py-env-studioand choose Start (or Restart after a config change).Approve the MCP server trust prompt. Workspace servers inherit Workspace Trust; user-level servers show a separate trust dialog on first start or after their configuration changes.
Open Copilot Chat and use Configure Tools to confirm the eight
pyenv_*tools are listed, and toggle off any tool you do not want the agent to use.
VS Code can also start configured servers automatically when you send a chat
message; the chat.mcp.autostart setting controls that behaviour
(never, onlyNew, newAndOutdated).
Step 4 — Ask the agent something¶
Once the tools are available, prompts such as these resolve from PES state instead of guesswork:
“Which Python environments does PES manage, and which one is the current project using?”
“List the packages installed in environment
<environment_id>.”“Analyze this project with PES and report the Python version, package manager, outdated packages, and any cached vulnerabilities.”
To call a tool directly for debugging:
{"jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": {"name": "pyenv_get_project_context", "arguments": {}}}
Step 5 — (Optional) Tune the MCP settings¶
The server reads the [mcp] section of the PES config.ini (the packaged
default lives in py_env_studio/config.ini; the active copy lives in the
platform user-data directory):
[mcp]
enabled = true
server_name = py-env-studio
transport = stdio
log_level = INFO
Setting |
Default |
Purpose |
|---|---|---|
|
|
Set to |
|
|
Name reported in the |
|
|
Reserved for future transports; stdio is the only supported value in beta |
|
|
Logging verbosity for MCP diagnostics (stderr only) |
When the server is disabled, startup exits with
MCP server is disabled (config [mcp] enabled=false). on stderr.
Tools (beta, read-only)¶
Tool |
Input |
Source |
|---|---|---|
|
— |
|
|
|
|
|
|
environment + package count + runtime registry |
|
|
|
|
|
|
|
|
|
|
|
cached scan via |
|
|
|
pyenv_analyze_project is the aggregate tool: one call returns the PES project
configuration, resolved environment, Python runtime, package manager,
dependencies, outdated packages, cached vulnerabilities, and runtime state.
Response envelope¶
Successful calls return the payload inside structuredContent (and the same
JSON as text content):
{"success": true, "data": {"..." : "..."},
"metadata": {"source": "pes", "cached": true, "timestamp": "2026-09-23T12:00:00+00:00"}}
Failures use a structured error and set isError on the MCP content envelope:
{"success": false,
"error": {"code": "ENVIRONMENT_NOT_FOUND", "message": "...", "details": {}}}
Error codes: ENVIRONMENT_NOT_FOUND, PROJECT_NOT_FOUND, AMBIGUOUS_PROJECT,
INVALID_INPUT, SERVICE_UNAVAILABLE, SCAN_UNAVAILABLE.
An environment with no cached scan returns success: true with
"scan_available": false and "findings": [] — PES never performs a network
lookup on behalf of MCP.
Security and privacy¶
The transport is local stdio: nothing is exposed on a port and no MCP tool makes a network request.
Vulnerability data is read from the cache PES already produced; use Tools → Scan Now in the GUI (or refresh the dashboard) to update it.
MCP returns environment, package, dependency, and project metadata. A project analysis can include installed package names and versions, so treat tool output like any other repository metadata.
Like every MCP server,
py-env-studio mcpis a local process started by your client: only register it from configuration you control.
Troubleshooting¶
Symptom |
Resolution |
|---|---|
Server missing in MCP: List Servers |
Re-check |
|
|
Tools list is empty |
Start/restart the server, then run MCP: Reset Cached Tools and reload the chat |
Tools return |
Call |
|
Pass an explicit |
|
Run a PES vulnerability scan for that environment first; MCP only reads cached results |
Output shows nothing but chat cannot reach the server |
Read the server log via MCP: List Servers → Show Output; PES writes diagnostics to stderr only |
Startup says the server is disabled |
Set |
Disable or remove¶
Add
enabled = falseto the[mcp]section ofconfig.inito refuse startup for every client.Or remove the
py-env-studioentry from.vscode/mcp.json,~/.copilot/mcp-config.json, or the equivalent client configuration.