Repository navigation
Description
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 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.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 anoutputSchema: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, runtools.search({ query: "<app-slug>" })and read the output type of any tool. - Call that tool and return the raw result. It has
contentandstructuredContentat the top level, and the fields from step 2 sit understructuredContent.
Diagnostics / logs
None. The workaround is to read r.structuredContent instead of following the signature.
Before you submit
- I searched the open issues for a duplicate.
- I removed all keys, tokens, and credentials from this report.
Activity