diff --git a/CHANGELOG.md b/CHANGELOG.md index b8016ce7..58555bfe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,14 @@ new version heading in the same commit. ## [Unreleased] +## [0.459.1] - 2026-10-12 +### Fixed +- **The "DataForSEO (v2 tools)" connector now authenticates.** The v2 server reads its login from + `DATAFORSEO_USERNAME`, not `DATAFORSEO_LOGIN`, so a connector added from the 0.458.0 catalog entry got + HTTP 401 on every call. The entry now sets `DATAFORSEO_USERNAME` from the same `secret:DATAFORSEO_LOGIN` + vault key, so one stored login serves both versions. The v3 entry was unaffected. + **For admins:** if you added "DataForSEO (v2 tools)" on 0.458.0, remove it and add it again with the same name. + ## [0.459.0] - 2026-10-12 ### Changed - **Picking an assignee on an Inbox proposal card accepts it.** The card's assignee picker now moves an diff --git a/docs/connectors/dataforseo.md b/docs/connectors/dataforseo.md index d809d6ff..908f3871 100644 --- a/docs/connectors/dataforseo.md +++ b/docs/connectors/dataforseo.md @@ -31,7 +31,9 @@ remote session to drop. skills already name those tools. 3. Fill both fields with `secret:DATAFORSEO_LOGIN` / `secret:DATAFORSEO_PASSWORD`. They are resolved from the vault at launch, and an unresolvable reference is blanked and audited as - `connector.secret.unresolved`. + `connector.secret.unresolved`. The login lands in a different env var per version: v3 reads + `DATAFORSEO_LOGIN`, v2 reads only `DATAFORSEO_USERNAME` and answers every call with HTTP 401 without it. + The catalog entries set the right one; a hand-built connector must too. **Keep the connector's NAME when replacing an old one.** The MCP server key is the connector id (a slug of its label), and tool names are `mcp____`. Replacing a `DataforSEO` connector with one labelled diff --git a/package-lock.json b/package-lock.json index d43843a3..d1a84805 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "agent-os", - "version": "0.459.0", + "version": "0.459.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "agent-os", - "version": "0.459.0", + "version": "0.459.1", "license": "MIT", "bin": { "agent-os": "bin/agent-os" diff --git a/package.json b/package.json index 207ba7f1..ea0c515b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "agent-os", - "version": "0.459.0", + "version": "0.459.1", "description": "A generic, governed operating system for running autonomous agents safely across brands. Ships with a local web console.", "license": "MIT", "type": "commonjs", diff --git a/scripts/connector-auth-stub-test.cjs b/scripts/connector-auth-stub-test.cjs index 1e75fc8d..30e1dae7 100644 --- a/scripts/connector-auth-stub-test.cjs +++ b/scripts/connector-auth-stub-test.cjs @@ -47,12 +47,13 @@ async function main() { assert(/catalog/.test(authStubRemedy({ url: 'https://mcp.dataforseo.com/mcp' })), 'the hosted-DataForSEO remedy points at the catalog entry'); console.log('\n\x1b[1m2) DataForSEO catalog entries run locally, pinned, with vault creds\x1b[0m'); - for (const [type, ver] of [['dataforseo', /^3\./], ['dataforseo-v2', /^2\./]]) { + // The login env var is per version: v2 only reads DATAFORSEO_USERNAME and 401s on every call without it. + for (const [type, ver, login] of [['dataforseo', /^3\./, 'DATAFORSEO_LOGIN'], ['dataforseo-v2', /^2\./, 'DATAFORSEO_USERNAME']]) { const e = CATALOG.find((c) => c.type === type); const spec = e && npxSpec({ transport: e.transport, command: e.command, args: e.args }); const m = spec && /^dataforseo-mcp-server@(\d+\.\d+\.\d+)$/.exec(spec); assert(e?.transport === 'stdio' && m && ver.test(m[1]), `${type}: stdio, exact pinned version (${spec})`); - assert(e?.fields.map((f) => f.key).join() === 'DATAFORSEO_LOGIN,DATAFORSEO_PASSWORD' && e.fields.every((f) => /secret:/.test(f.placeholder || '')), `${type}: API login + password fields, vault refs suggested`); + assert(e?.fields.map((f) => f.key).join() === `${login},DATAFORSEO_PASSWORD` && e.fields[0].placeholder === 'secret:DATAFORSEO_LOGIN' && e.fields.every((f) => /secret:/.test(f.placeholder || '')), `${type}: ${login} + password fields, both from the same vault keys`); } console.log('\n\x1b[1m3) npx pre-fetch\x1b[0m'); diff --git a/src/connectors/connectors.ts b/src/connectors/connectors.ts index 925fa20d..51f56bf0 100644 --- a/src/connectors/connectors.ts +++ b/src/connectors/connectors.ts @@ -155,9 +155,11 @@ export const CATALOG: CatalogEntry[] = [ transport: 'stdio', command: 'npx', args: ['-y', 'dataforseo-mcp-server@2.9.13'], + // v2 reads DATAFORSEO_USERNAME (v3 reads DATAFORSEO_LOGIN, falling back to USERNAME). The env var + // differs; the vault key does not, so one stored DATAFORSEO_LOGIN serves both versions. fields: [ { - key: 'DATAFORSEO_LOGIN', + key: 'DATAFORSEO_USERNAME', label: 'API login', placeholder: 'secret:DATAFORSEO_LOGIN', help: 'The API login from app.dataforseo.com/api-access (not your dashboard login). Store it in Settings → Secrets and enter secret:DATAFORSEO_LOGIN here.',