Executor version
apps framework 0.0.1-beta.0 (source references below are from the v2 branch at fd03c8a)
How do you run Executor?
Executor Cloud
Operating system
Windows
Integration involved
Remote MCP server (Metabase, https://<instance>.metabaseapp.com/api/metabase-mcp) imported with mcpOperations through accountOperations
What happened
For tools imported with mcpOperations, the output type in tools.search is the upstream MCP outputSchema. That schema describes structuredContent, but the call resolves to the full MCP result: { content, structuredContent, isError?, _meta? }.
tools.search signature for Metabase search:
Promise<{ data: Array<{ id: number, type: ..., name: string, ... }> }>
What the call actually returns:
{ content: [{ type: "text", text: "{\"data\":[...]}" }], structuredContent: { data: [...] } }
The same thing happens with every Metabase tool we called (search, read_resource, execute_sql).
Source:
packages/apps/src/implementation/mcp-tools.ts:55: the upstream output schema validates result.structuredContent
packages/apps/src/implementation/mcp-tools.ts:60: the full result is returned
packages/apps/src/implementation/protocol-operations.ts:42-46: the same upstream outputSchema is copied onto the operation unchanged, and that's what the signature is generated from
packages/app-templates/executor/skills/app-authoring/integrations.md:34: documents that results retain content, structuredContent, isError and _meta
apps/local/server/test/catalog.test.ts:861-880: asserts outputSchema is { account: string } and, in the same test, that the call result is { content, structuredContent: { account }, _meta }
What you expected
The type in tools.search matches what the call returns.
Related: #851 fixed this in v1 by declaring the output as the CallToolResult shape with the upstream schema nested under structuredContent. It also added typeCheckOutputTypeScript, which compiles the advertised output type against a real result. We didn't find an equivalent check in v2. #1769 (closed) returned structuredContent as the data.
Steps to reproduce
- Deploy an app using the authenticated remote MCP template from
integrations.md, pointed at an MCP server whose tools declare an outputSchema:
export default defineApp({ accounts: { service: provider.many() } }, async ({ accounts, signal }) =>
accountOperations(accounts.service, async (account) => mcpOperations({
url: "https://<instance>.metabaseapp.com/api/metabase-mcp",
headers: { Authorization: "Bearer " + account.fields.access_token },
signal,
}), { signal }),
)
- In
execute, run tools.search({ query: "<app-slug>" }) and read the output type of any tool.
- Call that tool and return the raw result. It has
content and structuredContent at the top level, and the fields from step 2 sit under structuredContent.
Diagnostics / logs
None. The workaround is to read r.structuredContent instead of following the signature.
Before you submit
Executor version
appsframework0.0.1-beta.0(source references below are from thev2branch atfd03c8a)How do you run Executor?
Executor Cloud
Operating system
Windows
Integration involved
Remote MCP server (Metabase,
https://<instance>.metabaseapp.com/api/metabase-mcp) imported withmcpOperationsthroughaccountOperationsWhat happened
For tools imported with
mcpOperations, the output type intools.searchis the upstream MCPoutputSchema. That schema describesstructuredContent, but the call resolves to the full MCP result:{ content, structuredContent, isError?, _meta? }.tools.searchsignature for Metabasesearch:What the call actually returns:
The same thing happens with every Metabase tool we called (
search,read_resource,execute_sql).Source:
packages/apps/src/implementation/mcp-tools.ts:55: the upstream output schema validatesresult.structuredContentpackages/apps/src/implementation/mcp-tools.ts:60: the fullresultis returnedpackages/apps/src/implementation/protocol-operations.ts:42-46: the same upstreamoutputSchemais copied onto the operation unchanged, and that's what the signature is generated frompackages/app-templates/executor/skills/app-authoring/integrations.md:34: documents that results retaincontent,structuredContent,isErrorand_metaapps/local/server/test/catalog.test.ts:861-880: assertsoutputSchemais{ account: string }and, in the same test, that the call result is{ content, structuredContent: { account }, _meta }What you expected
The type in
tools.searchmatches what the call returns.Related: #851 fixed this in v1 by declaring the output as the
CallToolResultshape with the upstream schema nested understructuredContent. It also addedtypeCheckOutputTypeScript, which compiles the advertised output type against a real result. We didn't find an equivalent check inv2. #1769 (closed) returnedstructuredContentas the data.Steps to reproduce
integrations.md, pointed at an MCP server whose tools declare anoutputSchema:execute, runtools.search({ query: "<app-slug>" })and read the output type of any tool.contentandstructuredContentat the top level, and the fields from step 2 sit understructuredContent.Diagnostics / logs
None. The workaround is to read
r.structuredContentinstead of following the signature.Before you submit