Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 17 additions & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -1984,8 +1984,10 @@ replaced; do not carry obsolete compatibility code forward to satisfy this secti
snapshots; per-Session tools replace the whole field. The initial profile admits
HTTP(S), boolean `required` (default false), empty/null metadata and empty/null headers.
Static and OAuth bearer authentication require HTTPS and the attached-Vault rules below.
Inline authorization, URL userinfo/query/fragment,
other origins and stdio remain explicitly unsupported.
An omitted/null `connection_origin` on HTTP transport is stored as `service`
before the other checks, identical to an explicit declaration, as observed
officially. Inline authorization, URL userinfo/query/fragment, the `environment`
origin and stdio remain explicitly unsupported.
- Codex required MCP initialization additionally needs `mcp_http_required`, advertised
only for the verified native pin and checked during selection, final preclaim
and daemon dispatch/preparation. Preserve the boolean through typed messages,
Expand Down Expand Up @@ -2025,22 +2027,28 @@ replaced; do not carry obsolete compatibility code forward to satisfy this secti
storage. Core-managed OAuth uses this same access-token path; native OAuth
login/refresh and hosted redirect/error equivalence remain separate work.
- Session `vault_ids` omission/null/empty means `[]`; nonempty attachments must all
belong to the authenticated tenant. Preserve caller order and public MCP
belong to the authenticated tenant. Preserve caller order and the stored caller
`credential_id`. Saved Agents may store a nullable/nonempty credential reference
without authorizing its use. Session admission resolves an explicit credential
only inside attached Vaults for the exact declared URL, or selects the unique
matching static or OAuth credential when the ID is omitted/null. No match remains
anonymous; ambiguity is a local 400 and unavailable references use the same 404.
Resolve before any Session, initial input or event write. Freeze safe bindings,
including anonymous decisions, in private Session configuration; never populate
the public credential field from implicit resolution. At actual dispatch, recheck
anonymous. Selection errors use the observed official messages with a null param:
a reference without attachments, one outside the attached Vaults and one for
another URL are 400 `invalid_request_error`; several implicit matches are 409
`conflict_error`. Missing, foreign-tenant, unattached and malformed references
share one message; echo caller values only within `internal/echotext`. Unknown
or foreign Vaults keep the same 404. Resolve after the input requirement and
before any Session, initial input or event write. Freeze safe bindings,
including anonymous decisions, in private Session configuration. Session
projections, never the stored configuration, show an implicitly selected ID in a
null/omitted public `credential_id`, also after deletion. At actual dispatch, recheck
tenant, attached Vault, selected ID, frozen auth type and exact URL before scoped
decryption. Metadata queries select no ciphertext; tokens enter only the existing
transient daemon request. Selected authentication requires `mcp_http_bearer_auth`
during device selection and the final preclaim check. Missing/wrong keys or
binding failures never fall back to anonymous execution. Exact URL equality,
immutable selection timing, implicit response population and hosted error/redirect
semantics remain local decisions or unverified gaps. No new MCP loop is permitted.
immutable selection timing and hosted redirect semantics remain local decisions
or unverified gaps. No new MCP loop is permitted.
- Saved Agent execution defaults use separate input and safe-output Core extensions.
Keep model-provider bundles whole at every replacement boundary: endpoint, key,
protocol and limits must never be independently inherited. Ordinary Agent JSON
Expand Down
12 changes: 8 additions & 4 deletions contracts/agents-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,8 @@ upgrade the protocol.
stays unresolved rather than being populated from a guessed model default. An
explicit effort/summary is retained. Omitted/null service tier currently follows
the service's `auto` policy; complete upstream-default/error/retry conformance is
unverified. HTTP MCP with explicit `service` origin and
unverified. HTTP MCP with `service` origin (omitted or null on HTTP transport is
saved as `service`) and
boolean `required` (default false) supports saved configuration and Codex `none` execution,
with Claude SDK
also supporting its qualified `none` subset. V1 `self_hosted` explicitly rejects
Expand All @@ -351,11 +352,14 @@ upgrade the protocol.
headers. Omitted/null `allowed_tools` is unrestricted; `[]` denies all tools.
Session `vault_ids` attaches tenant-owned Vaults. Explicit `credential_id` must
belong to an attached Vault and match the exact HTTPS URL; omission/null selects
one matching static or OAuth credential, zero stays anonymous and ambiguity fails. Private
immutable selections do not populate the public credential field. Scope is
one matching static or OAuth credential, zero stays anonymous and ambiguity is a
409 `conflict_error`. Selection errors use the observed official messages, with
one message for missing, foreign and unattached references. Session projections
show an implicitly selected credential ID in the public field; the immutable
stored selection and caller intent are unchanged. Scope is
rechecked before dispatch-only decryption; authenticated execution requires the
separate bearer capability and never downgrades on failure. Exact URL/selection
timing, implicit response population and hosted errors remain local or unverified.
timing and hosted redirect behavior remain local or unverified.
Other MCP variants and enabled web-search execution remain gaps, not changes to the pinned target
or claims of complete resource coverage.

Expand Down
61 changes: 61 additions & 0 deletions contracts/agents-api/official-semantics-alignment.md
Original file line number Diff line number Diff line change
Expand Up @@ -664,3 +664,64 @@ The pinned-SDK scripts `official_agents.py` and `official_agent_update.py` asser
the saved projections and the admission rejection, and `official_tool_policy.py`
adds saved enabled search to its live rejection cases. Real Core acceptance is
recorded separately by the coordinator.

## MCP origin and credential selection — September 23

The minimal pinned-SDK MCP tool `{type, server_label, transport}` now works on
Core, and Session MCP credential selection projects and reports errors as the
official service does. Evidence is MV-01..03 in the campaign scan recorded
privately in `~/.parsar/remediation/20260923/campaign-scan-6/mcp-vaults/`
(`findings.json`, `REPORT.txt`, `official-ledger.jsonl`): owned Agents, three
owned Sessions and two Vaults with four static-bearer Credentials, all deleted
and read back 404. The error records are `ERR-UNATTACHED`
(`req_b687ac760c03451caa5973be8d65a3ae`), `ERR-URL-MISMATCH`
(`req_90009e0ba2e548ad88a30516faeec852`), `ERR-AMBIGUOUS`
(`req_18b4777d35844be9a5549c8e58fc8747`), `ERR-CREDENTIAL-BOGUS`
(`req_5ba08377d4a841c98849cd4649e6fcaa`) and `ERR-VAULT-BOGUS`
(`req_0274192656b549739951de213e16514a`); the origin default is
`req_4a99a59eba2445c4b9ae22e74667f2b8` and `req_108ecc7c779240528efccd5ad55eebed`.

| Row | Case | Core behavior |
| --- | --- | --- |
| M1 | HTTP MCP tool with omitted or null `connection_origin`, on a saved Agent, an inline Session agent or a per-Session replacement | Saved and projected as `"service"`. The stored and frozen configuration equals an explicit `service` declaration, so execution is unchanged. Explicit `"environment"` and other transports keep their rejection. |
| M2 | Session tool without an explicit `credential_id` whose attached credential was selected | Retrieve, list and the created, in-progress and idle event snapshots show the selected credential ID, also after that credential is deleted. Anonymous and unmatched tools stay null; explicit IDs are echoed as sent. |
| M3 | `credential_id` with omitted, null or empty `vault_ids` | 400 `invalid_request_error`, null param: "MCP credential_id requires an attached vault". |
| M4 | `credential_id` not in an attached Vault: missing, foreign tenant, another Vault of the tenant, or malformed | 400 `invalid_request_error`, null param: "MCP credential_id `<id>` was not found in an attached vault". Byte-identical for one ID across the missing, foreign and unattached cases. |
| M5 | Credential in an attached Vault for another URL | 400 `invalid_request_error`, null param: "MCP credential_id `<id>` does not match server_url `<url>`". |
| M6 | Several attached credentials match implicitly | 409 `conflict_error`, null param: "multiple attached vault credentials match MCP server_url `<url>`; specify credential_id". |
| M7 | Unknown or foreign Vault in `vault_ids` | Unchanged 404 `not_found_error`, "Resource not found." (the official message names the ID). |
| M8 | Order and writes | Inline agent protocol errors and the input requirement come first; selection precedes any write, and a rejection writes nothing. |
| M9 | Dispatch | Unchanged: frozen bindings, scoped recheck before decryption, fail-closed on missing keys or decryption, no anonymous fallback. |

Decisions:

- `<id>` and `<url>` are the request's values, repeated only under the shared
bounded-echo rule (`internal/echotext`: at most 256 bytes of printable UTF-8);
otherwise the message leaves the value out.
- Selection searches only attached Vaults, which must all belong to the caller.
An explicit ID is found there by ID alone, so a missing, foreign or unattached
ID yields one response, and only a credential of an attached Vault can report
a server_url mismatch. The mismatch message repeats the tool's URL, not the
credential's.
- The projection reads the frozen private binding of the tool's label and URL,
and shows it only while the binding's Vault is among the Session's
attachments. It exposes a credential ID only, never tokens or ciphertext.
Stored configuration keeps the caller's null, so creation retries, recorded
caller intent and dispatch are unchanged. Retries recover the original
projection, also after deletion; a new creation can no longer select a deleted
credential.
- A same-key retry that omits the origin recovers a Session created with the
explicit form when the request has no recorded caller intent; with recorded
intent (attached Vaults or credential references) it remains the local
`idempotency_conflict`, as for any changed request.
- A deleted, previously selected credential is still admitted at later input and
fails at dispatch (MV-04); that remains a separate batch.

Go tests cover the origin default, the projection and its private-binding
checks, and the typed store errors. A real-PostgreSQL HTTP test with tenants A
and B covers M1–M8, the byte-identical M4 responses with headers, a
whole-database digest over every rejection, M2 across creation, retrieve, list,
creation-stream and live events, deletion and retries. The pinned-SDK scripts
`official_mcp.py` and `official_mcp_credentials.py` assert the omitted origin,
the projection and the error fields. Real Core acceptance is recorded separately
by the coordinator.
45 changes: 26 additions & 19 deletions contracts/agents-api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2930,15 +2930,16 @@ paths:
or tool_search and non-object schema root types return it with a null param.
Supports model/name/instructions/metadata, explicit reasoning and service
tiers, multi_agent, text/json_schema, function/tool_search/programmatic_tool_calling/web_search
and HTTP MCP with nullable credential_id and explicit service origin and boolean
required defaulting to false. Saving credential_id grants no access: Session
admission checks attached Vault ownership and destination. MCP allowed_tools
preserves null versus empty; saved HTTP transport includes empty headers.
Model-derived reasoning defaults, other MCP variants and public retry conformance
remain incomplete. web_search saves every pinned mode: omitted or null mode
is saved as live and omitted or null context_size as medium; allowed_domains
preserves null versus empty and a present location, including {}, includes
all four keys with null for omitted ones, as observed officially (req_db41d2f6261b4abfb69465eafe719ab5,
and HTTP MCP with nullable credential_id, service origin (omitted or null
on HTTP transport is saved as service) and boolean required defaulting to
false. Saving credential_id grants no access: Session admission checks attached
Vault ownership and destination. MCP allowed_tools preserves null versus empty;
saved HTTP transport includes empty headers. Model-derived reasoning defaults,
other MCP variants and public retry conformance remain incomplete. web_search
saves every pinned mode: omitted or null mode is saved as live and omitted
or null context_size as medium; allowed_domains preserves null versus empty
and a present location, including {}, includes all four keys with null for
omitted ones, as observed officially (req_db41d2f6261b4abfb69465eafe719ab5,
req_165d53b88445490b9146d8272c54134d). Session execution accepts only explicit
disabled web_search and disabled programmatic_tool_calling through qualified
Runtime controls; saved enabled forms reject at Session admission. Session
Expand Down Expand Up @@ -3807,19 +3808,25 @@ paths:
supports model/instructions, text verbosity, non-deferred function tools,
adapter-qualified multi_agent with persisted Subagent reads, implicit reasoning,
service tier auto and environment type none, subject to the configured engine.
Codex additionally supports HTTP MCP with explicit service origin, native
allowed_tools and boolean required defaulting to false. Session vault_ids
attach only project-owned Vaults; credential_id selects an attached static
bearer credential for the exact HTTPS URL, while null/omission selects a unique
match or remains anonymous. Ambiguous selection rejects creation. Frozen private
selections never populate an omitted public credential_id; missing decryption
Codex additionally supports HTTP MCP with service origin (omitted or null
on HTTP transport is saved as service), native allowed_tools and boolean required
defaulting to false. Session vault_ids attach only project-owned Vaults; credential_id
selects an attached static bearer or OAuth credential for the exact HTTPS
URL, while null/omission selects a unique match or remains anonymous. Session
reads, lists and event snapshots show that implicitly selected credential
ID in a null or omitted credential_id, also after the credential is deleted;
anonymous selections stay null and the stored caller intent is unchanged.
After the input requirement and before any write, a credential_id without
vault_ids, one outside the attached Vaults (one message for missing, foreign
and unattached IDs) or one for another server_url returns 400 invalid_request_error,
and several implicit matches return 409 conflict_error. Missing decryption
configuration fails dispatch without anonymous fallback. Required initialization
uses native startup before the first native Turn, including cold resume, and
requires a separately advertised capability; exact hosted creation timing
and error parity remain unverified. Other MCP origins and OAuth remain unsupported.
The self_hosted profile requires Codex, an absolute workspace_directory and
empty capability_directories, with optional non-deferred function tools and
HTTP MCP using explicit service origin, optionally authenticated by the attached
and error parity remain unverified. Other MCP origins and native OAuth login
remain unsupported. The self_hosted profile requires Codex, an absolute workspace_directory
and empty capability_directories, with optional non-deferred function tools
and HTTP MCP using service origin, optionally authenticated by the attached
Vault rules. Remote MCP and remote Bearer authentication each require separately
advertised combination support; old peers cannot receive unsupported work.
Omitted/null capability_directories use the empty-list default; self_hosted
Expand Down
Loading
Loading