Elyra 0.9.45: open a stranger's repo without holding your breath
Elyra 0.9.45 gates project configuration that can run code behind an explicit trust decision, and teaches Elyra to speak MCP in both directions.
You find a repository. Somebody's side project, a bug report with a reproduction attached, a library you're thinking of depending on. You type the three lines everyone types:
git clone https://example.com/someone/project
cd project
elyra
Here's the part we rarely say out loud: that's a slightly brave thing to do.
Nothing in your clone is supposed to run. But an agent harness reads configuration, and some configuration is code in a trench coat. A list of packages to install on startup. An extension file. A server definition that says "start this process." A setting that changes the shell every command goes through. Elyra 0.9.45 is built around one idea, and I think it's the right one: a repository you've just cloned shouldn't be able to make your machine run anything until you've said it may.
And because we were already in there, it also teaches Elyra to speak MCP, in both directions. The two belong together, and I'll explain why.
Part one: project trust
What's gated, and why
Five kinds of project configuration can now only take effect once you've trusted the directory. The docs give a reason for each, and the reasons are the interesting bit:
In the project Why it waits packages in .elyra/settings.json npm and git packages are installed on startup, which runs their install scripts extensions, and files in .elyra/extensions/ extensions are loaded as code .mcp.json, .elyra/mcp.json, .cursor/mcp.json, .vscode/mcp.json MCP server definitions start processes shellPath, shellCommandPrefix, npmCommand they change how every command runs autoExtensions, autoSkills they remove approval prompts
What isn't gated is just as deliberate. AGENTS.md, CLAUDE.md, skills, prompt templates, themes and every other setting work exactly as before, trusted or not. The docs put it plainly: those things are read by the model and can't run anything without going through the agent's own tools. A project that has none of the gated configuration never asks you anything at all.
So this isn't a wall around the repo. It's a short list of doors that execute things, and a lock on each.
The prompt
Open a project that has one of those doors and Elyra doesn't quietly pick a side. It lists exactly what would run, and offers four choices:
Trust this folder, remembered for this directory and everything below it.
Trust parent folder, remembered for the parent, so it covers every project inside. That's the one for a
~/Codethat only holds your own repositories.Trust for this session only. Nothing is saved.
Continue without project code. Elyra runs normally, skips the gated items, and says so.
That last option matters more than it looks. An untrusted project still works. You can read it, ask questions about it, let the agent explore it. It just doesn't get to start processes on your behalf. "No" is a perfectly good answer, and it doesn't cost you the session.
Changing your mind
Trust shouldn't be a decision you can't revisit. Inside Elyra:
/trust review what the project loads, and trust it (reloads in place)
/trust revoke stop trusting this project
/trust list list trusted directories
And from the shell:
elyra trust # trust the current directory
elyra trust ~/Code # trust a directory and everything below it
elyra trust --status # show the decision and what the project would load
elyra trust --revoke [path]
Trusted directories live in ~/.elyra/agent/trusted-projects.json, a plain file you can read. One small courtesy: elyra install -l <source> trusts the current project automatically, since installing a project package yourself is about as explicit a decision as there is.
Scripts and CI, where nobody's there to click
An obvious question: what happens when there's no human? Print mode, JSON mode, RPC mode and MCP server mode never prompt. In an untrusted project they run without the gated configuration and print a warning. Quietly hanging on a prompt nobody can answer would be worse.
If you do want a CI job to use the project's own configuration, you say so, for that one run:
elyra --trust-project -p "run the checks"
ELYRA_TRUST_PROJECT=1 elyra -p "run the checks"
I like that the secure path is also the default one. You opt in to trust, in the open, in the command line.
Child agents
If you use @elyracode/swarm, stages run as child Elyra processes, sometimes in a temporary git worktree. They'd be surprised to find themselves in an "untrusted" project you've already trusted, so the parent's decision is passed down through ctx.getChildAgentEnv(). The child strips that variable from its own environment at startup, so the commands the agent runs never inherit it. The decision is handed to the child, but not to whatever the child runs.
Part two: MCP, both ways
Why: schemas are expensive
The Model Context Protocol has become the common plug between agents and tools. You may already have servers configured for Claude Code, Cursor or VS Code: GitHub, a database, Linear.
The usual way to give an agent those tools is to put every tool's schema into every request. With a few servers that's a lot of tokens, resent every turn, and it changes whenever a server adds a tool, which means your prompt cache goes cold.
How: two stable tools
Elyra's bundled @elyracode/mcp takes a different route. It adds exactly two tools:
mcp_searchfinds tools by keyword and returns their names and input schemas.mcp_callcalls a tool by server and name.
The docs state the consequence: the tools block stays the same no matter how many servers and tools you have, which keeps the context small and the prompt cache warm. The agent asks "what can do X?" when it needs to, rather than carrying every answer around.
Servers start lazily, the first time a tool list or tool is needed, and tool lists are cached in ~/.elyra/agent/mcp-cache.json, so searching usually needs no running server at all.
You probably don't need to configure anything
Elyra reads what you already have. ~/.claude.json, ~/.cursor/mcp.json, .vscode/mcp.json, .cursor/mcp.json, .mcp.json, and Elyra's own ~/.elyra/agent/mcp.json and .elyra/mcp.json. Later entries win when two define the same server.
If you do write one, it looks like this:
{
"mcpServers": {
"github": { "type": "http", "url": "https://api.githubcopilot.com/mcp/" },
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres", "${DATABASE_URL}"]
},
"linear": { "url": "https://mcp.linear.app/sse", "directTools": true }
}
}
A few details I'm fond of:
${VAR}and${VAR:-default}expand from your environment, and a server that references an unset variable is skipped with a message instead of starting half-configured.A local server gets a minimal environment,
PATH,HOMEand the like, plus what you list inenv. Your shell's API keys aren't passed on unless you say so.directTools: trueis the escape hatch: it also exposes each of that server's tools under its own name,mcp__<server>__<tool>, for the one server you use constantly.
For remote servers that want OAuth, the flow is one command:
/mcp login linear
Elyra registers itself with the server's authorization server, opens your browser, and catches the redirect on http://127.0.0.1:53687/mcp/callback. Tokens are stored in ~/.elyra/agent/extension-credentials.json with 0600 permissions and refresh on their own. /mcp on its own shows the status of every server, including skipped files and config problems, which is where I'd start when something's quiet.
And if you'd rather not have it at all: "mcp": false in ~/.elyra/agent/settings.json. With no servers configured it registers nothing anyway.
The other direction: Elyra as a server
Now flip it around. elyra --mode mcp serves Elyra over stdio, so another MCP host, such as Claude Desktop, Cursor or another agent, can delegate work to it:
{
"mcpServers": {
"elyra": { "command": "elyra", "args": ["--mode", "mcp"], "cwd": "/path/to/project" }
}
}
It exposes three tools:
elyra_taskruns the agent on a task in the project directory. The default is read-only: it can read and search, nothing more. You ask foreditif the host should be allowed to change files and run commands. You get back the answer, the changed files, the cost, and a session id you can pick up later withelyra --session <id>.elyra_reviewreviews your uncommitted changes, by default with a model from a different vendor than Elyra's current one. A second opinion that doesn't share the first one's blind spots.elyra_decisionslists the project's recorded architecture decisions.
Two behaviours show the care that went into it. Tasks run one at a time, each in a fresh session, and tool activity is reported as progress notifications, which stops hosts with request timeouts from giving up on a long task. And Elyra never loads its own MCP server back into itself: a configured server that runs elyra --mode mcp is skipped with a message. Nobody wants to debug a hall of mirrors.
Why these two arrived together
Look back at the gated table. MCP server definitions start processes. A .mcp.json in a cloned repo is exactly the kind of "configuration that's actually code" that trust exists for. Shipping an MCP client without project trust would have meant shipping a new way for a repository to run commands on your machine. So project MCP files load only in trusted projects, while your own user-level servers load as always.
It's a good pairing in practice, too. Ship the integrations you want, and make the gate for what a stranger can ask of you the first thing you built.
For extension authors
If you write extensions, 0.9.45 adds some tools worth knowing about, each born from the work above:
ctx.isProjectTrusted(): if your extension executes configuration found in the project (MCP servers, workflow commands, hooks), check it and refuse while it'sfalse, telling the user to run/trust.elyra.credentials(namespace)stores JSON credentials for services other than model providers, in a0600file with cross-process locking, plusgetFreshOAuthTokens()so an expiring token is refreshed exactly once across concurrent Elyra processes.elyra.openBrowser(url)opens an http(s) URL without a shell.registerTool(tool, { defer: true })holds a tool added mid-session back while the prompt cache is warm, and activates it at the next cache boundary, so adding a tool doesn't throw away your cache.For SDK hosts,
createAgentSessionServices({ resolveProjectTrust })applies a trust decision before any resource loads. Without a resolver the SDK trusts the project, as before.
What to know before you upgrade
The first start in a project with gated configuration will ask. That's the feature working. Choose "trust parent folder" for the directory that holds your own repositories and you'll mostly never see it again.
Scripts in untrusted projects now run without the gated pieces. If a CI job relied on a repo's
.elyra/settings.jsonpackages or extensions, add--trust-projectto it. The warning in the log will tell you.The standalone binary builds can't load bundled packages yet, so if you use one, run
elyra install npm:@elyracode/mcponce. The npm install has MCP out of the box.Also in this release:
/reviewandelyra_reviewnow share the same code, and a provider error during a review is reported as "Review failed" rather than the misleading "The reviewer returned no findings". And the Together default moved to Kimi K3, after Together retired the old one.
The short version
Clone it. Open it. Read it, question it, let the agent explore. Nothing in it runs until you decide it may, and deciding is one keypress you can take back with /trust revoke. And when you want Elyra to reach your tools, it speaks MCP already, with two tools instead of two hundred schemas. Or when another tool wants to reach Elyra, elyra --mode mcp will answer, read-only unless you say otherwise.
Update, and open someone else's repo. It's a lot less brave than it used to be.