feat: MCP app sampling support via stock SDK types (alt to #477) (#530)

* feat: MCP app sampling support via stock SDK types

Alternative to #477. Instead of forking a stripped-down sampling schema,
this reuses the stock `CreateMessageRequest` / `CreateMessageResult` /
`CreateMessageResultWithTools` types from `@modelcontextprotocol/sdk`
directly — same pattern already used for `tools/call`.

- Spec: `sampling/createMessage` listed under `### Standard MCP Messages`,
  `sampling?: { tools?: {} }` added to `HostCapabilities` (mirrors MCP
  `ClientCapabilities.sampling` shape for easy pass-through).
- SDK: `App.createSamplingMessage()` with overloads that narrow the return
  type based on whether `params.tools` is set; `AppBridge.oncreatesamplingmessage`
  setter; `CreateMessageRequest`/`CreateMessageResult*` added to the
  `AppRequest`/`AppResult` unions.
- Picks up SEP-1577 tool-calling support (`tools`, `toolChoice`, `tool_use`
  content blocks, `stopReason: "toolUse"`, array content) for free — unblocks
  the "nested agents" use case motivated by the original PR.

https://claude.ai/code/session_01ENGWTtsfcyP4S6fTWtUMAh

* feat(app): guard createSamplingMessage before handshake completes

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Olivier Chafik 2026-04-21 13:29:09 +01:00 • committed by GitHub
commit 926dcb4fe9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 323 additions and 1 deletions

View file

@ -501,6 +501,19 @@
}
},
"additionalProperties": false
},
"sampling": {
"description": "Host supports LLM sampling (sampling/createMessage) from the view.\nMirrors the MCP `ClientCapabilities.sampling` shape so hosts can pass it through.",
"type": "object",
"properties": {
"tools": {
"description": "Host supports tool use via `tools` and `toolChoice` parameters.",
"type": "object",
"properties": {},
"additionalProperties": false
}
},
"additionalProperties": false
}
},
"additionalProperties": false
@ -2841,6 +2854,19 @@
}
},
"additionalProperties": false
},
"sampling": {
"description": "Host supports LLM sampling (sampling/createMessage) from the view.\nMirrors the MCP `ClientCapabilities.sampling` shape so hosts can pass it through.",
"type": "object",
"properties": {
"tools": {
"description": "Host supports tool use via `tools` and `toolChoice` parameters.",
"type": "object",
"properties": {},
"additionalProperties": false
}
},
"additionalProperties": false
}
},
"additionalProperties": false,

View file

@ -558,6 +558,24 @@ export const McpUiHostCapabilitiesSchema = z.object({
message: McpUiSupportedContentBlockModalitiesSchema.optional().describe(
"Host supports receiving content messages (ui/message) from the view.",
),
/**
* @description Host supports LLM sampling (sampling/createMessage) from the view.
* Mirrors the MCP `ClientCapabilities.sampling` shape so hosts can pass it through.
*/
sampling: z
.object({
/** @description Host supports tool use via `tools` and `toolChoice` parameters. */
tools: z
.object({})
.optional()
.describe(
"Host supports tool use via `tools` and `toolChoice` parameters.",
),
})
.optional()
.describe(
"Host supports LLM sampling (sampling/createMessage) from the view.\nMirrors the MCP `ClientCapabilities.sampling` shape so hosts can pass it through.",
),
});
/**