Add explicit app and account targets to MCP resource reads (#47248)

## What changed

Allow `mcpServer/resource/read` to specify `target: {connectorId, linkId}` for direct hosted app reads without tool discovery, when supported by the backend. Require an explicit `linkId`: a string selects an account, while `null` requests no-auth access subject to backend policy.

Restrict direct targets to `codex_apps` and reject empty connector IDs, empty link IDs, and synthetic link IDs. Preserve originating app/account scope when `originCallId` and `threadId` are supplied, and retain discovery when `target` is omitted.

Update protocol schemas and TypeScript and Python models, preserving required-but-nullable `linkId` semantics in Python code generation.

## Testing

Extend resource-read tests to check target metadata with and without a thread, including explicit no-auth targets and omitted targets. Add Python model tests for string and null `linkId` values and rejection of a missing `linkId`.

GitOrigin-RevId: 8cf5595fbdd937193aeb529901fc95299f6e18ad
This commit is contained in:
victor-openai
2026-09-22 10:42:50 +00:00
committed by copyberry
parent c46aa58a7b
commit 3b50349e1a
19 changed files with 324 additions and 60 deletions
+38 -20
View File
@@ -2512,21 +2512,18 @@ class McpAuthStatus(Enum):
o_auth = "oAuth"
class McpResourceReadParams(BaseModel):
class McpResourceReadTarget(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
)
connector_id: Annotated[str | None, Field(alias="connectorId")] = None
origin_call_id: Annotated[
connector_id: Annotated[str, Field(alias="connectorId")]
link_id: Annotated[
str | None,
Field(
alias="originCallId",
description="Originating MCP tool call used to select the resource's app.",
alias="linkId",
description="Null explicitly requests no-auth access, subject to the app's resource policy.",
),
] = None
server: str
thread_id: Annotated[str | None, Field(alias="threadId")] = None
uri: str
]
class McpServerConnectionStatus(Enum):
@@ -7380,17 +7377,6 @@ class ConfigMcpServerReloadRequest(BaseModel):
params: None = None
class McpServerResourceReadRequest(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
)
id: RequestId
method: Annotated[
Literal["mcpServer/resource/read"], Field(title="McpServer/resource/readRequestMethod")
]
params: McpResourceReadParams
class McpServerToolCallRequest(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
@@ -8492,6 +8478,27 @@ class LoginAccountParams(
]
class McpResourceReadParams(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
)
connector_id: Annotated[str | None, Field(alias="connectorId")] = None
origin_call_id: Annotated[
str | None,
Field(
alias="originCallId",
description="Originating MCP tool call used to select the resource's app.",
),
] = None
server: str
target: Annotated[
McpResourceReadTarget | None,
Field(description="Explicit hosted app/account. Omit to retain legacy resource discovery."),
] = None
thread_id: Annotated[str | None, Field(alias="threadId")] = None
uri: str
class McpResourceReadResponse(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
@@ -10473,6 +10480,17 @@ class McpServerStatusListRequest(BaseModel):
params: ListMcpServerStatusParams
class McpServerResourceReadRequest(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
)
id: RequestId
method: Annotated[
Literal["mcpServer/resource/read"], Field(title="McpServer/resource/readRequestMethod")
]
params: McpResourceReadParams
class AccountLoginStartRequest(BaseModel):
model_config = ConfigDict(
populate_by_name=True,