kaxil opened a new pull request, #69225:
URL: https://github.com/apache/airflow/pull/69225
`MCPHook`'s `stdio` transport built `StdioTransport` without ever passing an
`env` argument, so a local MCP server subprocess had no way to receive
configuration or credentials except by inheriting the worker's ambient
environment. This adds:
- **`Extra.env`** — a static `dict[str, str]` in the connection's `extra`,
now passed through to the subprocess.
- **`env_provider`** — a zero-argument callable returning `dict[str, str]`,
mirroring the existing `token_provider` for HTTP/SSE. Its return value is
merged over `Extra.env` (`env_provider` wins on key conflicts), and every value
it returns is registered with secret masking regardless of key name.
## Why `env_provider`, not just `Extra.env`?
`Extra.env` is fine for a value that genuinely belongs to this connection.
`env_provider` exists for the same reason `token_provider` does on HTTP/SSE:
the credential has no stable static form to store here at all — either because
it lives in a different Airflow connection (avoiding two places to rotate the
same secret), or because it's minted fresh per call (an OAuth token, a Vault
lease) with nothing fixed to store anywhere.
## Usage
```python
from airflow.providers.common.ai.toolsets.mcp import MCPToolset
def mint_env() -> dict[str, str]:
from airflow.providers.common.compat.sdk import BaseHook
return {"API_KEY": BaseHook.get_connection("my_other_conn").password}
toolset = MCPToolset(mcp_conn_id="my_stdio_mcp", env_provider=mint_env)
```
## Gotchas
- `Extra.env` is Fernet-encrypted at rest like the rest of the connection's
`extra`, but it's only masked in the Connections UI/API and task logs if a
key's name happens to match a fixed set of sensitive-looking names (`api_key`,
`token`, `secret`, `password`, etc.). `env_provider` values are always masked
regardless of key name.
- Both `token_provider` and `env_provider` are invoked once, the first time
a given hook/toolset instance establishes a connection — not on every reconnect
of that same instance.
- Passing `env=None` (no static `Extra.env` and no `env_provider`) does not
inherit the full parent process environment; the MCP stdio client falls back to
a small allowlist of variables (see the `mcp` package's
`get_default_environment()`).
- Both the static `Extra.env` values and `env_provider`'s return value are
validated (non-empty string keys/values) at connection-build time, so a
misconfigured connection fails with a clear, attributed error instead of a bare
`TypeError` deep inside `subprocess.Popen`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]