Problem
Every tool returns a single text block holding pretty-printed JSON, and no tool declares an outputSchema or returns structuredContent. Neither identifier appears anywhere in packages/.
Representative: packages/mcp/src/tools/orgs.ts:24-50, and the same shape in all ~90 handlers.
Why it matters
The result is already structured data — apiRequest<T> returns a typed object, which the handler then stringifies. The client has to re-parse a text blob to get back what the server already had, with no schema to validate against and no way to tell a JSON payload from a human-readable message. Since SDK 1.10 a tool can declare outputSchema and return structuredContent alongside the text block, and clients that support it get typed results while older clients keep reading the text.
Proposed approach
- Derive the output schemas from the existing response interfaces (
UserProfile, ApiTokenResponse, and the per-product equivalents) rather than restating the shapes — a zod schema per response type, with the TS type inferred from it.
- Return both
structuredContent and the text block, so no client regresses.
- Start with the high-traffic read tools (
list_orgs, list_projects, get_me, list_issues, list_sites) and extend from there; this does not need to be one PR.
Acceptance criteria
- Tools converted so far advertise an
outputSchema in tools/list and return matching structuredContent.
- The text block is unchanged for clients that ignore structured output.
- Response types have one definition, not a type plus a hand-written schema that can drift.
Problem
Every tool returns a single text block holding pretty-printed JSON, and no tool declares an
outputSchemaor returnsstructuredContent. Neither identifier appears anywhere inpackages/.Representative:
packages/mcp/src/tools/orgs.ts:24-50, and the same shape in all ~90 handlers.Why it matters
The result is already structured data —
apiRequest<T>returns a typed object, which the handler then stringifies. The client has to re-parse a text blob to get back what the server already had, with no schema to validate against and no way to tell a JSON payload from a human-readable message. Since SDK 1.10 a tool can declareoutputSchemaand returnstructuredContentalongside the text block, and clients that support it get typed results while older clients keep reading the text.Proposed approach
UserProfile,ApiTokenResponse, and the per-product equivalents) rather than restating the shapes — a zod schema per response type, with the TS type inferred from it.structuredContentand the text block, so no client regresses.list_orgs,list_projects,get_me,list_issues,list_sites) and extend from there; this does not need to be one PR.Acceptance criteria
outputSchemaintools/listand return matchingstructuredContent.