@@ -2154,18 +2154,14 @@ describe("structuredContent", () => {
21542154 ) ;
21552155 }
21562156
2157- function payloadOf ( result : unknown ) : Record < string , any > {
2158- expect ( result ) . toHaveProperty ( "structuredContent" ) ;
2159- return ( result as { structuredContent : Record < string , any > } )
2160- . structuredContent ;
2161- }
2162-
21632157 it ( "returns a structured payload in experimental mode" , async ( ) => {
21642158 mockLatestEvent ( ) ;
21652159
2166- const payload = payloadOf (
2167- await getIssueDetails . handler ( params , experimentalContext ) ,
2168- ) ;
2160+ const result = await getIssueDetails . handler ( params , experimentalContext ) ;
2161+
2162+ expect ( result ) . toHaveProperty ( "structuredContent" ) ;
2163+ const payload = ( result as { structuredContent : Record < string , any > } )
2164+ . structuredContent ;
21692165
21702166 // the issue level fields the markdown used to assemble
21712167 expect ( payload . issue . shortId ) . toBe ( "CLOUDFLARE-MCP-41" ) ;
@@ -2186,9 +2182,9 @@ describe("structuredContent", () => {
21862182 it ( "renders the event body itself rather than asking the api for one" , async ( ) => {
21872183 mockLatestEvent ( ) ;
21882184
2189- const payload = payloadOf (
2190- await getIssueDetails . handler ( params , experimentalContext ) ,
2191- ) ;
2185+ const result = await getIssueDetails . handler ( params , experimentalContext ) ;
2186+ const payload = ( result as { structuredContent : Record < string , any > } )
2187+ . structuredContent ;
21922188
21932189 expect ( typeof payload . event . body ) . toBe ( "string" ) ;
21942190 expect ( payload . event . body ) . toContain ( "### Error" ) ;
@@ -2199,9 +2195,9 @@ describe("structuredContent", () => {
21992195 it ( "produces a payload that satisfies the schema" , async ( ) => {
22002196 mockLatestEvent ( ) ;
22012197
2202- const payload = payloadOf (
2203- await getIssueDetails . handler ( params , experimentalContext ) ,
2204- ) ;
2198+ const result = await getIssueDetails . handler ( params , experimentalContext ) ;
2199+ const payload = ( result as { structuredContent : Record < string , any > } )
2200+ . structuredContent ;
22052201
22062202 // a tool that advertises a schema has to return something that satisfies it
22072203 expect ( ( ) => getIssueDetailsOutputSchema . parse ( payload ) ) . not . toThrow ( ) ;
@@ -2210,9 +2206,9 @@ describe("structuredContent", () => {
22102206 it ( "carries the response notes, which say which tool to call next" , async ( ) => {
22112207 mockLatestEvent ( ) ;
22122208
2213- const payload = payloadOf (
2214- await getIssueDetails . handler ( params , experimentalContext ) ,
2215- ) ;
2209+ const result = await getIssueDetails . handler ( params , experimentalContext ) ;
2210+ const payload = ( result as { structuredContent : Record < string , any > } )
2211+ . structuredContent ;
22162212
22172213 expect ( payload . responseNotes . length ) . toBeGreaterThan ( 0 ) ;
22182214 const notes = payload . responseNotes . join ( "\n" ) ;
@@ -2223,9 +2219,9 @@ describe("structuredContent", () => {
22232219 it ( "carries the top level message, which the body does not render" , async ( ) => {
22242220 mockLatestEvent ( { message : "TOP-LEVEL-MESSAGE" , entries : [ ] } ) ;
22252221
2226- const payload = payloadOf (
2227- await getIssueDetails . handler ( params , experimentalContext ) ,
2228- ) ;
2222+ const result = await getIssueDetails . handler ( params , experimentalContext ) ;
2223+ const payload = ( result as { structuredContent : Record < string , any > } )
2224+ . structuredContent ;
22292225
22302226 expect ( payload . event . message ) . toBe ( "TOP-LEVEL-MESSAGE" ) ;
22312227 } ) ;
@@ -2263,18 +2259,19 @@ describe("structuredContent", () => {
22632259 ) ,
22642260 ) ;
22652261
2266- const payload = payloadOf (
2267- await getIssueDetails . handler (
2268- { ...params , issueId : "PERF-N1-001" } ,
2269- experimentalContext ,
2270- ) ,
2262+ const result = await getIssueDetails . handler (
2263+ { ...params , issueId : "PERF-N1-001" } ,
2264+ experimentalContext ,
22712265 ) ;
2266+ const payload = ( result as { structuredContent : Record < string , any > } )
2267+ . structuredContent ;
22722268
22732269 expect ( payload . event . type ) . toBe ( "transaction" ) ;
22742270 expect ( payload . event . body ) . toContain ( "Span" ) ;
22752271 } ) ;
22762272
22772273 it ( "keeps the attached replay, which lives on the event not the related list" , async ( ) => {
2274+ // an issue whose only replay is attached would otherwise report no replays at all
22782275 mockLatestEvent ( {
22792276 contexts : {
22802277 replay : {
@@ -2284,9 +2281,9 @@ describe("structuredContent", () => {
22842281 } ,
22852282 } ) ;
22862283
2287- const payload = payloadOf (
2288- await getIssueDetails . handler ( params , experimentalContext ) ,
2289- ) ;
2284+ const result = await getIssueDetails . handler ( params , experimentalContext ) ;
2285+ const payload = ( result as { structuredContent : Record < string , any > } )
2286+ . structuredContent ;
22902287
22912288 expect ( payload . replays ?. attached ) . toBe ( "1234567890abcdef1234567890abcdef" ) ;
22922289 // and the attached id is not repeated in the related list
@@ -2301,14 +2298,16 @@ describe("structuredContent", () => {
23012298 it ( "reports no replays when there are none" , async ( ) => {
23022299 mockLatestEvent ( ) ;
23032300
2304- const payload = payloadOf (
2305- await getIssueDetails . handler ( params , experimentalContext ) ,
2306- ) ;
2301+ const result = await getIssueDetails . handler ( params , experimentalContext ) ;
2302+ const payload = ( result as { structuredContent : Record < string , any > } )
2303+ . structuredContent ;
23072304
23082305 expect ( payload . replays ) . toBeNull ( ) ;
23092306 } ) ;
23102307
23112308 it ( "maps external issues field by field so upstream extras cannot leak" , async ( ) => {
2309+ // structuredContent is a product contract, not a view of the api response: several
2310+ // upstream schemas are passthrough, so anything not mapped must not appear
23122311 mockLatestEvent ( ) ;
23132312 mswServer . use (
23142313 http . get (
@@ -2327,20 +2326,22 @@ describe("structuredContent", () => {
23272326 ) ,
23282327 ) ;
23292328
2330- const payload = payloadOf (
2331- await getIssueDetails . handler ( params , experimentalContext ) ,
2332- ) ;
2329+ const result = await getIssueDetails . handler ( params , experimentalContext ) ;
2330+ const payload = ( result as { structuredContent : Record < string , any > } )
2331+ . structuredContent ;
23332332
23342333 expect ( JSON . stringify ( payload ) ) . not . toContain ( "internalOnlyToken" ) ;
23352334 expect ( JSON . stringify ( payload ) ) . not . toContain ( "must-not-leak" ) ;
23362335 } ) ;
23372336
23382337 it ( "carries every field the markdown output surfaces" , async ( ) => {
2338+ // greg's bar for this migration is "roughly the same content": anything the markdown
2339+ // renders and the payload drops is a regression for every MCP user
23392340 mockLatestEvent ( { dateCreated : "2026-09-03T12:00:00.000Z" } ) ;
23402341
2341- const payload = payloadOf (
2342- await getIssueDetails . handler ( params , experimentalContext ) ,
2343- ) ;
2342+ const result = await getIssueDetails . handler ( params , experimentalContext ) ;
2343+ const payload = ( result as { structuredContent : Record < string , any > } )
2344+ . structuredContent ;
23442345
23452346 // the issue header markdown builds before the event body
23462347 for ( const field of [
@@ -2365,6 +2366,8 @@ describe("structuredContent", () => {
23652366 } ) ;
23662367
23672368 it ( "does not label an error's exception message as a query pattern" , async ( ) => {
2369+ // metadata.value is a query pattern for a performance issue and the exception message for
2370+ // an error, so reading it unconditionally puts error text under the wrong name
23682371 mswServer . use (
23692372 http . get (
23702373 "https://sentry.io/api/0/organizations/sentry-mcp-evals/issues/CLOUDFLARE-MCP-41/" ,
@@ -2383,12 +2386,15 @@ describe("structuredContent", () => {
23832386 issueCategory : "error" ,
23842387 } ) ,
23852388 ) ,
2389+ http . get (
2390+ "https://sentry.io/api/0/organizations/sentry-mcp-evals/issues/7890123456/events/latest/" ,
2391+ ( ) => HttpResponse . json ( createDefaultEvent ( ) ) ,
2392+ ) ,
23862393 ) ;
2387- mockLatestEvent ( ) ;
23882394
2389- const payload = payloadOf (
2390- await getIssueDetails . handler ( params , experimentalContext ) ,
2391- ) ;
2395+ const result = await getIssueDetails . handler ( params , experimentalContext ) ;
2396+ const payload = ( result as { structuredContent : Record < string , any > } )
2397+ . structuredContent ;
23922398
23932399 expect ( payload . issue . queryPattern ) . toBeNull ( ) ;
23942400 expect ( payload . issue . location ) . toBeNull ( ) ;
@@ -2401,8 +2407,8 @@ describe("structuredContent", () => {
24012407 http . get (
24022408 "https://sentry.io/api/0/organizations/sentry-mcp-evals/issues/CLOUDFLARE-MCP-41/" ,
24032409 ( ) =>
2404- HttpResponse . json (
2405- createPerformanceIssue ( {
2410+ HttpResponse . json ( {
2411+ ... createPerformanceIssue ( {
24062412 shortId : "CLOUDFLARE-MCP-41" ,
24072413 issueType : "performance_n_plus_one_db_queries" ,
24082414 issueCategory : "performance" ,
@@ -2412,14 +2418,17 @@ describe("structuredContent", () => {
24122418 location : "/api/checkout" ,
24132419 } ,
24142420 } ) ,
2415- ) ,
2421+ } ) ,
2422+ ) ,
2423+ http . get (
2424+ "https://sentry.io/api/0/organizations/sentry-mcp-evals/issues/7890123456/events/latest/" ,
2425+ ( ) => HttpResponse . json ( createDefaultEvent ( ) ) ,
24162426 ) ,
24172427 ) ;
2418- mockLatestEvent ( ) ;
24192428
2420- const payload = payloadOf (
2421- await getIssueDetails . handler ( params , experimentalContext ) ,
2422- ) ;
2429+ const result = await getIssueDetails . handler ( params , experimentalContext ) ;
2430+ const payload = ( result as { structuredContent : Record < string , any > } )
2431+ . structuredContent ;
24232432
24242433 expect ( payload . issue . title ) . toBe ( "N+1 Query" ) ;
24252434 expect ( payload . issue . queryPattern ) . toBe ( "SELECT * FROM users WHERE id = ?" ) ;
@@ -2433,7 +2442,8 @@ describe("structuredContent", () => {
24332442 ) ;
24342443 mockLatestEvent ( ) ;
24352444 mswServer . use (
2436- // echo back whichever issue id was asked for
2445+ // related ids come from replay-count, keyed by numeric issue id. Echo back whichever
2446+ // id was asked for: a preceding test can leave a different issue fixture registered.
24372447 http . get (
24382448 "https://sentry.io/api/0/organizations/sentry-mcp-evals/replay-count/" ,
24392449 ( { request } ) => {
@@ -2444,9 +2454,9 @@ describe("structuredContent", () => {
24442454 ) ,
24452455 ) ;
24462456
2447- const payload = payloadOf (
2448- await getIssueDetails . handler ( params , experimentalContext ) ,
2449- ) ;
2457+ const result = await getIssueDetails . handler ( params , experimentalContext ) ;
2458+ const payload = ( result as { structuredContent : Record < string , any > } )
2459+ . structuredContent ;
24502460
24512461 expect ( payload . replays ) . not . toBeNull ( ) ;
24522462 expect ( payload . replays . relatedCount ) . toBe ( 51 ) ;
0 commit comments