different-ai/openwork · error · McpAppHostError
unsupported_resource_permissions
unsupported_resource_permissions
Error message
This OpenWork host slice does not grant device permissions or dedicated sandbox origins.
What it means
resourcePresentationMeta reads ui.permissions and ui.domain from an MCP App resource's _meta. This OpenWork host slice intentionally does not implement device-permission grants or dedicated sandbox origins, so if an app requests either, the host throws unsupported_resource_permissions instead of silently ignoring the request.
Source
Thrown at apps/server/src/mcp-app-host.ts:129
function domainList(value: unknown): string[] {
if (!Array.isArray(value) || value.length > 16) {
if (value === undefined) return [];
throw new McpAppHostError("invalid_resource_csp", "MCP App CSP domain lists must contain at most 16 origins.");
}
const domains = value.map(safeDomain);
if (domains.some((domain) => domain === null)) {
throw new McpAppHostError("invalid_resource_csp", "MCP App CSP domains must be HTTPS origins (or loopback HTTP origins).");
}
return Array.from(new Set(domains as string[]));
}
function resourcePresentationMeta(value: unknown): { csp: McpAppCsp; prefersBorder: boolean } {
const meta = isRecord(value) ? value : {};
const ui = isRecord(meta.ui) ? meta.ui : {};
const csp = isRecord(ui.csp) ? ui.csp : {};
const permissions = isRecord(ui.permissions) ? ui.permissions : {};
if (Object.keys(permissions).length > 0 || ui.domain !== undefined) {
throw new McpAppHostError(
"unsupported_resource_permissions",
"This OpenWork host slice does not grant device permissions or dedicated sandbox origins.",
);
}
return {
csp: {
connectDomains: domainList(csp.connectDomains),
resourceDomains: domainList(csp.resourceDomains),
frameDomains: domainList(csp.frameDomains),
baseUriDomains: domainList(csp.baseUriDomains),
},
prefersBorder: ui.prefersBorder !== false,
};
}
function remoteUrl(config: Record<string, unknown>): URL | null {
if (config.enabled === false || typeof config.url !== "string") return null;
try {View on GitHub (pinned to 2b7df46e8a)
Solutions
- Remove ui.permissions and ui.domain from the app's _meta so it runs in the shared host sandbox.
- Redesign the app to not require device permissions; do privileged work in the MCP server instead of the UI.
- Use a different MCP host that supports permissions if device access is essential.
- Ask the OpenWork maintainers about permission support before relying on it.
Example fix
// before
'"ui": { "permissions": { "camera": {} }, "domain": "app.example.com" }'
// after
'"ui": {}' Defensive patterns
Strategy: validation
Validate before calling
const ui = (tool?._meta as any)?.ui ?? {}
const requested = Object.keys(ui.permissions ?? {}).length > 0 || ui.domain !== undefined
if (requested) throw new Error('app requests permissions/dedicated origin — unsupported on this host') Type guard
function isHostCompatibleUi(ui: unknown): ui is { csp?: unknown } {
const u = ui as { permissions?: Record<string, unknown>; domain?: unknown } | undefined
return !!u && Object.keys(u.permissions ?? {}).length === 0 && u.domain === undefined
} Try / catch
try {
const presentation = host.presentation(resource)
} catch (e) {
if (e instanceof McpAppHostError && e.code === 'unsupported_resource_permissions') {
hideApp(resource.name); notify('app requires permissions this host does not grant')
} else throw e
} Prevention
- Do not set ui.permissions or ui.domain in tool _meta unless targeting a supporting host
- Perform privileged operations in the MCP server, not the app UI
- Audit app templates for leftover permissions blocks
- Feature-detect host capability docs before shipping permission-requiring apps
When it happens
Trigger: Connecting to an MCP App whose tool _meta sets ui.permissions (any keys, e.g. camera/microphone/geolocation grants) or ui.domain (requesting a dedicated sandbox origin).
Common situations: App built for hosts that support permissions/dedicated origins (e.g. full MCP App hosts) being loaded in OpenWork; server template left the permissions block in; author requesting camera/mic for a widget.
Related errors
- invalid_resource_uri
- invalid_resource_csp
- unsupported_transport
- MCP_PROVIDER_HTTP_403
- invalid_mcp_token_payload
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/06ee53ea0fbd0332.
Report an issue: GitHub.