Skip to content

mcp-client-agent: a third copy of the credential premise #14311 removed, latent because the spec carries no @stable #1371

Description

@rafaelgiln

Found while working #1334. Same dead premise, a second copy — not currently red, because the spec never runs anywhere that would tell us.

What it is

tests/tests-automations/regression/mcp/client/mcp-client-agent.spec.ts:86 carries its own local copy of the #751 credential-settle guard:

// #751: the model selection rebinds `api_key` via a debounced autosave — running the
// Playground before it lands builds with the wrong provider's key.
async function waitForAgentCredentialSettled(page, flowId, expectedCredential) {
  ...
  expect(agent?.data?.node?.template?.api_key?.value).toBe(expectedCredential);
  }).toPass({ timeout: 20000, intervals: [500, 1000, 2000] });
}

Upstream #14311 ("stop automatic provider field binding", on the 1.12 line since 2026-08-04) deleted the block that wrote the credential variable name into api_key. Measured on 1.12.0.dev18/dev19 while working #1334: the field reads {value: "", load_from_db: false} on every build, from mount onward, for the OpenAI Compatible provider and for the plain OpenAI provider — build-wide, not provider-specific. So the transition this guard waits for cannot happen; it can only burn its 20 s and fail.

Why the earlier sweeps missed it

#1274 migrated the shared helper tests/helpers/flows/agent-credential-settle.ts off this axis and 19 @stable specs came with it. #1334 migrated the remaining inline copy in openai-compatible-provider-setup.spec.ts, and its grep — for credential: — reported that as the last one. This copy spells the same read api_key?.value, so that grep could not see it. It is the third instance of the same premise and the first that no sweep has touched.

Why it is not red today, which is the actual problem

The spec is tagged @mcp @agents @regressionno @stable — so daily-stable.yml never runs it, and pr-validation.yml only selects it for a PR that touches its import graph. It is latently broken: whoever runs it next, or whoever promotes it, pays. That is the #945/#940 shape — a spec with no @stable is an invisible red — and it is why this is worth an issue rather than a note.

The fix is already written twice

agent-credential-settle.ts (#1274) is the reference: the credential is no longer stored but is still determined, by the provider of the selected model, so the guard settles on model.value[0].provider instead. #1334 proved that causally on the run path — instantiation.py reads that field and calls get_api_key_for_provider, which with an empty api_key resolves get_provider_secret_variable_key(provider); dropping only the provider's own credential turns the run into 401 Incorrect API key provided: EMPTY while the binding is unchanged.

Note the local guard also predates the shared helper — the first question is whether it should be replaced by agent-credential-settle.ts outright rather than re-pointed in place, which would delete the divergence instead of updating it.

Deliverables (Done when)

  • The guard no longer asserts api_key.value, by adopting the shared helper or by re-pointing onto the provider axis with the same verdict taxonomy.
  • The spec is run and passes reliably (multiple clean --retries=0 runs) — it has no @stable, so "it compiles" is not evidence.
  • A grep records that no further copy of the premise survives, searching the read (api_key) and not one spelling of it.
  • Decide whether this spec should carry @stable, or state why not — a spec nothing runs cannot report a regression.

Metadata

Metadata

Assignees

Labels

area:mcpModel Context Protocolfollow-upApproved exception: follow-up of merged work (ROADMAP Intake)

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions