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]

Reply via email to