@claudinho/mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +68 -0
  3. package/dist/index.js +2881 -0
  4. package/package.json +54 -0
package/dist/index.js ADDED
@@ -0,0 +1,2881 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+
6
+ // src/server.ts
7
+ import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
8
+ import { z } from "zod";
9
+
10
+ // ../core/dist/index.js
11
+ var REGIONAL_INDICATOR_A = 127462;
12
+ var TAG_BASE = 917504;
13
+ var TAG_CANCEL = 917631;
14
+ var BLACK_FLAG = 127988;
15
+ var NEUTRAL = "\u{1F3F3}\uFE0F";
16
+ function norm(s) {
17
+ return s.toLowerCase().normalize("NFD").replace(/[̀-ͯ]/g, "").replace(/[^a-z]/g, "");
18
+ }
19
+ function subdivisionFlag(lettersOnly) {
20
+ const tags = [...lettersOnly].map((c) => TAG_BASE + c.charCodeAt(0));
21
+ return String.fromCodePoint(BLACK_FLAG, ...tags, TAG_CANCEL);
22
+ }
23
+ function flagEmoji(region) {
24
+ const r = region.trim();
25
+ if (r.includes("-")) {
26
+ const letters = r.toLowerCase().replace(/-/g, "");
27
+ return subdivisionFlag(letters);
28
+ }
29
+ const cc = r.toUpperCase();
30
+ if (!/^[A-Z]{2}$/.test(cc)) return NEUTRAL;
31
+ return String.fromCodePoint(
32
+ REGIONAL_INDICATOR_A + (cc.charCodeAt(0) - 65),
33
+ REGIONAL_INDICATOR_A + (cc.charCodeAt(1) - 65)
34
+ );
35
+ }
36
+ var NATIONS = [
37
+ ["Mexico", "MX"],
38
+ ["South Africa", "ZA"],
39
+ ["South Korea", "KR"],
40
+ ["Czechia", "CZ"],
41
+ ["Canada", "CA"],
42
+ ["Bosnia-Herzegovina", "BA"],
43
+ ["United States", "US"],
44
+ ["Paraguay", "PY"],
45
+ ["Qatar", "QA"],
46
+ ["Switzerland", "CH"],
47
+ ["Brazil", "BR"],
48
+ ["Morocco", "MA"],
49
+ ["Haiti", "HT"],
50
+ ["Scotland", "GB-SCT"],
51
+ ["Australia", "AU"],
52
+ ["T\xFCrkiye", "TR"],
53
+ ["Germany", "DE"],
54
+ ["Curacao", "CW"],
55
+ ["Netherlands", "NL"],
56
+ ["Japan", "JP"],
57
+ ["Ivory Coast", "CI"],
58
+ ["Ecuador", "EC"],
59
+ ["Sweden", "SE"],
60
+ ["Tunisia", "TN"],
61
+ ["Argentina", "AR"],
62
+ ["France", "FR"],
63
+ ["Spain", "ES"],
64
+ ["Portugal", "PT"],
65
+ ["England", "GB-ENG"],
66
+ ["Wales", "GB-WLS"],
67
+ ["Belgium", "BE"],
68
+ ["Croatia", "HR"],
69
+ ["Uruguay", "UY"],
70
+ ["Colombia", "CO"],
71
+ ["Senegal", "SN"],
72
+ ["Iran", "IR"],
73
+ ["Saudi Arabia", "SA"],
74
+ ["Egypt", "EG"],
75
+ ["Nigeria", "NG"],
76
+ ["Ghana", "GH"],
77
+ ["Cameroon", "CM"],
78
+ ["Algeria", "DZ"],
79
+ ["Norway", "NO"],
80
+ ["Denmark", "DK"],
81
+ ["Austria", "AT"],
82
+ ["Poland", "PL"],
83
+ ["Italy", "IT"],
84
+ ["Serbia", "RS"],
85
+ ["Panama", "PA"],
86
+ ["Costa Rica", "CR"],
87
+ ["Jordan", "JO"],
88
+ ["Uzbekistan", "UZ"],
89
+ ["New Zealand", "NZ"],
90
+ ["Cape Verde", "CV"],
91
+ ["Jamaica", "JM"],
92
+ ["Peru", "PE"],
93
+ ["Chile", "CL"],
94
+ ["Honduras", "HN"],
95
+ ["DR Congo", "CD"],
96
+ ["Mali", "ML"],
97
+ ["Venezuela", "VE"],
98
+ ["Greece", "GR"],
99
+ ["Hungary", "HU"],
100
+ ["Slovenia", "SI"],
101
+ ["Slovakia", "SK"],
102
+ ["Romania", "RO"],
103
+ ["Ukraine", "UA"],
104
+ ["Angola", "AO"],
105
+ ["Benin", "BJ"],
106
+ ["Gabon", "GA"],
107
+ ["Bolivia", "BO"],
108
+ ["Guinea", "GN"],
109
+ ["Burkina Faso", "BF"],
110
+ ["Zambia", "ZM"],
111
+ ["Iraq", "IQ"],
112
+ ["United Arab Emirates", "AE"],
113
+ ["Oman", "OM"],
114
+ ["Bahrain", "BH"],
115
+ ["China", "CN"],
116
+ ["Indonesia", "ID"],
117
+ ["Thailand", "TH"],
118
+ ["Vietnam", "VN"],
119
+ ["India", "IN"],
120
+ ["Russia", "RU"],
121
+ ["Finland", "FI"],
122
+ ["Ireland", "IE"],
123
+ ["Northern Ireland", "GB-NIR"],
124
+ ["Iceland", "IS"],
125
+ ["Albania", "AL"],
126
+ ["Georgia", "GE"],
127
+ ["North Macedonia", "MK"],
128
+ ["Montenegro", "ME"],
129
+ ["Kosovo", "XK"]
130
+ ];
131
+ var ALIASES = [
132
+ ["Turkey", "TR"],
133
+ ["Korea Republic", "KR"],
134
+ ["Republic of Korea", "KR"],
135
+ ["Korea DPR", "KP"],
136
+ ["North Korea", "KP"],
137
+ ["Czech Republic", "CZ"],
138
+ ["Cote d'Ivoire", "CI"],
139
+ ["Cote dIvoire", "CI"],
140
+ ["C\xF4te d\u2019Ivoire", "CI"],
141
+ ["Bosnia and Herzegovina", "BA"],
142
+ ["Bosnia", "BA"],
143
+ ["USA", "US"],
144
+ ["United States of America", "US"],
145
+ ["US", "US"],
146
+ ["Cabo Verde", "CV"],
147
+ ["Congo DR", "CD"],
148
+ ["Democratic Republic of the Congo", "CD"],
149
+ ["IR Iran", "IR"],
150
+ ["Cura\xE7ao", "CW"],
151
+ ["Holland", "NL"],
152
+ ["Republic of Ireland", "IE"],
153
+ ["UAE", "AE"],
154
+ // Names where Intl's English label differs from the common short form.
155
+ ["Hong Kong", "HK"],
156
+ ["Myanmar", "MM"],
157
+ ["Palestine", "PS"],
158
+ ["Burma", "MM"],
159
+ ["Cape Verde", "CV"]
160
+ ];
161
+ var BY_NATION = Object.fromEntries(
162
+ [...NATIONS, ...ALIASES].map(([name, code]) => [norm(name), code])
163
+ );
164
+ var BY_CODE = {
165
+ MEX: "MX",
166
+ RSA: "ZA",
167
+ KOR: "KR",
168
+ CZE: "CZ",
169
+ CAN: "CA",
170
+ BIH: "BA",
171
+ USA: "US",
172
+ PAR: "PY",
173
+ QAT: "QA",
174
+ SUI: "CH",
175
+ BRA: "BR",
176
+ MAR: "MA",
177
+ HAI: "HT",
178
+ SCO: "GB-SCT",
179
+ AUS: "AU",
180
+ TUR: "TR",
181
+ GER: "DE",
182
+ CUW: "CW",
183
+ NED: "NL",
184
+ JPN: "JP",
185
+ CIV: "CI",
186
+ ECU: "EC",
187
+ SWE: "SE",
188
+ TUN: "TN",
189
+ ARG: "AR",
190
+ FRA: "FR",
191
+ ESP: "ES",
192
+ POR: "PT",
193
+ ENG: "GB-ENG",
194
+ WAL: "GB-WLS",
195
+ BEL: "BE",
196
+ CRO: "HR",
197
+ URU: "UY",
198
+ COL: "CO",
199
+ SEN: "SN",
200
+ IRN: "IR",
201
+ KSA: "SA",
202
+ EGY: "EG",
203
+ NGA: "NG",
204
+ GHA: "GH",
205
+ CMR: "CM",
206
+ ALG: "DZ",
207
+ NOR: "NO",
208
+ DEN: "DK",
209
+ AUT: "AT",
210
+ POL: "PL",
211
+ ITA: "IT",
212
+ SRB: "RS",
213
+ PAN: "PA",
214
+ CRC: "CR",
215
+ JOR: "JO",
216
+ UZB: "UZ",
217
+ NZL: "NZ",
218
+ CPV: "CV",
219
+ JAM: "JM",
220
+ PER: "PE",
221
+ CHI: "CL",
222
+ HON: "HN",
223
+ COD: "CD",
224
+ MLI: "ML"
225
+ };
226
+ function nationToFlag(nameOrCode) {
227
+ const region = nationToRegion(nameOrCode);
228
+ return region ? flagEmoji(region) : NEUTRAL;
229
+ }
230
+ var INTL_BY_NAME;
231
+ function intlNameMap() {
232
+ if (INTL_BY_NAME) return INTL_BY_NAME;
233
+ const map = {};
234
+ try {
235
+ const dn = new Intl.DisplayNames(["en"], { type: "region" });
236
+ for (let a = 65; a <= 90; a++) {
237
+ for (let b = 65; b <= 90; b++) {
238
+ const code = String.fromCharCode(a, b);
239
+ let name;
240
+ try {
241
+ name = dn.of(code);
242
+ } catch {
243
+ name = void 0;
244
+ }
245
+ if (name && name !== code) {
246
+ const key = norm(name);
247
+ if (!(key in map)) map[key] = code;
248
+ }
249
+ }
250
+ }
251
+ } catch {
252
+ }
253
+ INTL_BY_NAME = map;
254
+ return map;
255
+ }
256
+ function nationToRegion(nameOrCode) {
257
+ if (!nameOrCode) return void 0;
258
+ const byName = BY_NATION[norm(nameOrCode)];
259
+ if (byName) return byName;
260
+ const byCode = BY_CODE[nameOrCode.trim().toUpperCase()];
261
+ if (byCode) return byCode;
262
+ return intlNameMap()[norm(nameOrCode)];
263
+ }
264
+ function isValidTimeZone(tz) {
265
+ if (!tz) return false;
266
+ try {
267
+ new Intl.DateTimeFormat("en", { timeZone: tz });
268
+ return true;
269
+ } catch {
270
+ return false;
271
+ }
272
+ }
273
+ function envTz() {
274
+ if (typeof process !== "undefined" && process.env && process.env.CLAUDINHO_TZ) {
275
+ return process.env.CLAUDINHO_TZ;
276
+ }
277
+ return void 0;
278
+ }
279
+ function systemTz() {
280
+ try {
281
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
282
+ } catch {
283
+ return void 0;
284
+ }
285
+ }
286
+ function resolveTz(explicit) {
287
+ if (explicit && isValidTimeZone(explicit)) return explicit;
288
+ const fromEnv = envTz();
289
+ if (fromEnv && isValidTimeZone(fromEnv)) return fromEnv;
290
+ return systemTz();
291
+ }
292
+ function formatKickoff(iso, opts = {}) {
293
+ const tz = resolveTz(opts.tz);
294
+ const locale = opts.locale || "en";
295
+ return new Intl.DateTimeFormat(locale, {
296
+ weekday: "short",
297
+ hour: "2-digit",
298
+ minute: "2-digit",
299
+ hour12: false,
300
+ timeZone: tz
301
+ }).format(new Date(iso));
302
+ }
303
+ function countdown(iso, from = /* @__PURE__ */ new Date()) {
304
+ const ms = new Date(iso).getTime() - from.getTime();
305
+ if (ms <= 0) return "now";
306
+ const totalMin = Math.floor(ms / 6e4);
307
+ const days = Math.floor(totalMin / 1440);
308
+ const hours = Math.floor(totalMin % 1440 / 60);
309
+ const mins = totalMin % 60;
310
+ if (days > 0) return `${days}d${hours}h`;
311
+ if (hours > 0) return `${hours}h${mins}m`;
312
+ return `${mins}m`;
313
+ }
314
+ function localDate(iso, tz) {
315
+ const zone = resolveTz(tz);
316
+ return new Intl.DateTimeFormat("en-CA", {
317
+ year: "numeric",
318
+ month: "2-digit",
319
+ day: "2-digit",
320
+ timeZone: zone
321
+ }).format(new Date(iso));
322
+ }
323
+ function isFinished(status) {
324
+ return status === "FT";
325
+ }
326
+ function scoreline(match) {
327
+ if (!match.score) return "vs";
328
+ return `${match.score.home}\u2013${match.score.away}`;
329
+ }
330
+ function byKickoff(a, b) {
331
+ return a.kickoff.localeCompare(b.kickoff);
332
+ }
333
+ var schedule_2026_default = [
334
+ {
335
+ id: "760415",
336
+ stage: "GROUP",
337
+ group: "A",
338
+ kickoff: "2026-06-11T19:00Z",
339
+ venue: "Estadio Banorte",
340
+ home: {
341
+ code: "MEX",
342
+ name: "Mexico",
343
+ flag: "\u{1F1F2}\u{1F1FD}"
344
+ },
345
+ away: {
346
+ code: "RSA",
347
+ name: "South Africa",
348
+ flag: "\u{1F1FF}\u{1F1E6}"
349
+ },
350
+ status: "SCHEDULED",
351
+ updatedAt: "2026-05-31T08:32:53.559Z"
352
+ },
353
+ {
354
+ id: "760414",
355
+ stage: "GROUP",
356
+ group: "A",
357
+ kickoff: "2026-06-12T02:00Z",
358
+ venue: "Estadio Akron",
359
+ home: {
360
+ code: "KOR",
361
+ name: "South Korea",
362
+ flag: "\u{1F1F0}\u{1F1F7}"
363
+ },
364
+ away: {
365
+ code: "CZE",
366
+ name: "Czechia",
367
+ flag: "\u{1F1E8}\u{1F1FF}"
368
+ },
369
+ status: "SCHEDULED",
370
+ updatedAt: "2026-05-31T08:32:53.560Z"
371
+ },
372
+ {
373
+ id: "760416",
374
+ stage: "GROUP",
375
+ group: "B",
376
+ kickoff: "2026-06-12T19:00Z",
377
+ venue: "BMO Field",
378
+ home: {
379
+ code: "CAN",
380
+ name: "Canada",
381
+ flag: "\u{1F1E8}\u{1F1E6}"
382
+ },
383
+ away: {
384
+ code: "BIH",
385
+ name: "Bosnia-Herzegovina",
386
+ flag: "\u{1F1E7}\u{1F1E6}"
387
+ },
388
+ status: "SCHEDULED",
389
+ updatedAt: "2026-05-31T08:32:53.560Z"
390
+ },
391
+ {
392
+ id: "760417",
393
+ stage: "GROUP",
394
+ group: "D",
395
+ kickoff: "2026-06-13T01:00Z",
396
+ venue: "SoFi Stadium",
397
+ home: {
398
+ code: "USA",
399
+ name: "United States",
400
+ flag: "\u{1F1FA}\u{1F1F8}"
401
+ },
402
+ away: {
403
+ code: "PAR",
404
+ name: "Paraguay",
405
+ flag: "\u{1F1F5}\u{1F1FE}"
406
+ },
407
+ status: "SCHEDULED",
408
+ updatedAt: "2026-05-31T08:32:53.560Z"
409
+ },
410
+ {
411
+ id: "760420",
412
+ stage: "GROUP",
413
+ group: "B",
414
+ kickoff: "2026-06-13T19:00Z",
415
+ venue: "Levi's Stadium",
416
+ home: {
417
+ code: "QAT",
418
+ name: "Qatar",
419
+ flag: "\u{1F1F6}\u{1F1E6}"
420
+ },
421
+ away: {
422
+ code: "SUI",
423
+ name: "Switzerland",
424
+ flag: "\u{1F1E8}\u{1F1ED}"
425
+ },
426
+ status: "SCHEDULED",
427
+ updatedAt: "2026-05-31T08:32:53.560Z"
428
+ },
429
+ {
430
+ id: "760419",
431
+ stage: "GROUP",
432
+ group: "C",
433
+ kickoff: "2026-06-13T22:00Z",
434
+ venue: "MetLife Stadium",
435
+ home: {
436
+ code: "BRA",
437
+ name: "Brazil",
438
+ flag: "\u{1F1E7}\u{1F1F7}"
439
+ },
440
+ away: {
441
+ code: "MAR",
442
+ name: "Morocco",
443
+ flag: "\u{1F1F2}\u{1F1E6}"
444
+ },
445
+ status: "SCHEDULED",
446
+ updatedAt: "2026-05-31T08:32:53.560Z"
447
+ },
448
+ {
449
+ id: "760418",
450
+ stage: "GROUP",
451
+ group: "C",
452
+ kickoff: "2026-06-14T01:00Z",
453
+ venue: "Gillette Stadium",
454
+ home: {
455
+ code: "HAI",
456
+ name: "Haiti",
457
+ flag: "\u{1F1ED}\u{1F1F9}"
458
+ },
459
+ away: {
460
+ code: "SCO",
461
+ name: "Scotland",
462
+ flag: "\u{1F3F4}\u{E0067}\u{E0062}\u{E0073}\u{E0063}\u{E0074}\u{E007F}"
463
+ },
464
+ status: "SCHEDULED",
465
+ updatedAt: "2026-05-31T08:32:53.560Z"
466
+ },
467
+ {
468
+ id: "760421",
469
+ stage: "GROUP",
470
+ group: "D",
471
+ kickoff: "2026-06-14T04:00Z",
472
+ venue: "BC Place",
473
+ home: {
474
+ code: "AUS",
475
+ name: "Australia",
476
+ flag: "\u{1F1E6}\u{1F1FA}"
477
+ },
478
+ away: {
479
+ code: "TUR",
480
+ name: "T\xFCrkiye",
481
+ flag: "\u{1F1F9}\u{1F1F7}"
482
+ },
483
+ status: "SCHEDULED",
484
+ updatedAt: "2026-05-31T08:32:53.560Z"
485
+ },
486
+ {
487
+ id: "760422",
488
+ stage: "GROUP",
489
+ group: "E",
490
+ kickoff: "2026-06-14T17:00Z",
491
+ venue: "NRG Stadium",
492
+ home: {
493
+ code: "GER",
494
+ name: "Germany",
495
+ flag: "\u{1F1E9}\u{1F1EA}"
496
+ },
497
+ away: {
498
+ code: "CUW",
499
+ name: "Curacao",
500
+ flag: "\u{1F1E8}\u{1F1FC}"
501
+ },
502
+ status: "SCHEDULED",
503
+ updatedAt: "2026-05-31T08:32:53.560Z"
504
+ },
505
+ {
506
+ id: "760425",
507
+ stage: "GROUP",
508
+ group: "F",
509
+ kickoff: "2026-06-14T20:00Z",
510
+ venue: "AT&T Stadium",
511
+ home: {
512
+ code: "NED",
513
+ name: "Netherlands",
514
+ flag: "\u{1F1F3}\u{1F1F1}"
515
+ },
516
+ away: {
517
+ code: "JPN",
518
+ name: "Japan",
519
+ flag: "\u{1F1EF}\u{1F1F5}"
520
+ },
521
+ status: "SCHEDULED",
522
+ updatedAt: "2026-05-31T08:32:53.560Z"
523
+ },
524
+ {
525
+ id: "760423",
526
+ stage: "GROUP",
527
+ group: "E",
528
+ kickoff: "2026-06-14T23:00Z",
529
+ venue: "Lincoln Financial Field",
530
+ home: {
531
+ code: "CIV",
532
+ name: "Ivory Coast",
533
+ flag: "\u{1F1E8}\u{1F1EE}"
534
+ },
535
+ away: {
536
+ code: "ECU",
537
+ name: "Ecuador",
538
+ flag: "\u{1F1EA}\u{1F1E8}"
539
+ },
540
+ status: "SCHEDULED",
541
+ updatedAt: "2026-05-31T08:32:53.560Z"
542
+ },
543
+ {
544
+ id: "760424",
545
+ stage: "GROUP",
546
+ group: "F",
547
+ kickoff: "2026-06-15T02:00Z",
548
+ venue: "Estadio BBVA",
549
+ home: {
550
+ code: "SWE",
551
+ name: "Sweden",
552
+ flag: "\u{1F1F8}\u{1F1EA}"
553
+ },
554
+ away: {
555
+ code: "TUN",
556
+ name: "Tunisia",
557
+ flag: "\u{1F1F9}\u{1F1F3}"
558
+ },
559
+ status: "SCHEDULED",
560
+ updatedAt: "2026-05-31T08:32:53.560Z"
561
+ },
562
+ {
563
+ id: "760428",
564
+ stage: "GROUP",
565
+ group: "H",
566
+ kickoff: "2026-06-15T16:00Z",
567
+ venue: "Mercedes-Benz Stadium",
568
+ home: {
569
+ code: "ESP",
570
+ name: "Spain",
571
+ flag: "\u{1F1EA}\u{1F1F8}"
572
+ },
573
+ away: {
574
+ code: "CPV",
575
+ name: "Cape Verde",
576
+ flag: "\u{1F1E8}\u{1F1FB}"
577
+ },
578
+ status: "SCHEDULED",
579
+ updatedAt: "2026-05-31T08:32:53.560Z"
580
+ },
581
+ {
582
+ id: "760426",
583
+ stage: "GROUP",
584
+ group: "G",
585
+ kickoff: "2026-06-15T19:00Z",
586
+ venue: "Lumen Field",
587
+ home: {
588
+ code: "BEL",
589
+ name: "Belgium",
590
+ flag: "\u{1F1E7}\u{1F1EA}"
591
+ },
592
+ away: {
593
+ code: "EGY",
594
+ name: "Egypt",
595
+ flag: "\u{1F1EA}\u{1F1EC}"
596
+ },
597
+ status: "SCHEDULED",
598
+ updatedAt: "2026-05-31T08:32:53.560Z"
599
+ },
600
+ {
601
+ id: "760429",
602
+ stage: "GROUP",
603
+ group: "H",
604
+ kickoff: "2026-06-15T22:00Z",
605
+ venue: "Hard Rock Stadium",
606
+ home: {
607
+ code: "KSA",
608
+ name: "Saudi Arabia",
609
+ flag: "\u{1F1F8}\u{1F1E6}"
610
+ },
611
+ away: {
612
+ code: "URU",
613
+ name: "Uruguay",
614
+ flag: "\u{1F1FA}\u{1F1FE}"
615
+ },
616
+ status: "SCHEDULED",
617
+ updatedAt: "2026-05-31T08:32:53.560Z"
618
+ },
619
+ {
620
+ id: "760427",
621
+ stage: "GROUP",
622
+ group: "G",
623
+ kickoff: "2026-06-16T01:00Z",
624
+ venue: "SoFi Stadium",
625
+ home: {
626
+ code: "IRN",
627
+ name: "Iran",
628
+ flag: "\u{1F1EE}\u{1F1F7}"
629
+ },
630
+ away: {
631
+ code: "NZL",
632
+ name: "New Zealand",
633
+ flag: "\u{1F1F3}\u{1F1FF}"
634
+ },
635
+ status: "SCHEDULED",
636
+ updatedAt: "2026-05-31T08:32:53.560Z"
637
+ },
638
+ {
639
+ id: "760432",
640
+ stage: "GROUP",
641
+ group: "I",
642
+ kickoff: "2026-06-16T19:00Z",
643
+ venue: "MetLife Stadium",
644
+ home: {
645
+ code: "FRA",
646
+ name: "France",
647
+ flag: "\u{1F1EB}\u{1F1F7}"
648
+ },
649
+ away: {
650
+ code: "SEN",
651
+ name: "Senegal",
652
+ flag: "\u{1F1F8}\u{1F1F3}"
653
+ },
654
+ status: "SCHEDULED",
655
+ updatedAt: "2026-05-31T08:32:53.560Z"
656
+ },
657
+ {
658
+ id: "760430",
659
+ stage: "GROUP",
660
+ group: "I",
661
+ kickoff: "2026-06-16T22:00Z",
662
+ venue: "Gillette Stadium",
663
+ home: {
664
+ code: "IRQ",
665
+ name: "Iraq",
666
+ flag: "\u{1F1EE}\u{1F1F6}"
667
+ },
668
+ away: {
669
+ code: "NOR",
670
+ name: "Norway",
671
+ flag: "\u{1F1F3}\u{1F1F4}"
672
+ },
673
+ status: "SCHEDULED",
674
+ updatedAt: "2026-05-31T08:32:53.560Z"
675
+ },
676
+ {
677
+ id: "760433",
678
+ stage: "GROUP",
679
+ group: "J",
680
+ kickoff: "2026-06-17T01:00Z",
681
+ venue: "GEHA Field at Arrowhead Stadium",
682
+ home: {
683
+ code: "ARG",
684
+ name: "Argentina",
685
+ flag: "\u{1F1E6}\u{1F1F7}"
686
+ },
687
+ away: {
688
+ code: "ALG",
689
+ name: "Algeria",
690
+ flag: "\u{1F1E9}\u{1F1FF}"
691
+ },
692
+ status: "SCHEDULED",
693
+ updatedAt: "2026-05-31T08:32:53.560Z"
694
+ },
695
+ {
696
+ id: "760431",
697
+ stage: "GROUP",
698
+ group: "J",
699
+ kickoff: "2026-06-17T04:00Z",
700
+ venue: "Levi's Stadium",
701
+ home: {
702
+ code: "AUT",
703
+ name: "Austria",
704
+ flag: "\u{1F1E6}\u{1F1F9}"
705
+ },
706
+ away: {
707
+ code: "JOR",
708
+ name: "Jordan",
709
+ flag: "\u{1F1EF}\u{1F1F4}"
710
+ },
711
+ status: "SCHEDULED",
712
+ updatedAt: "2026-05-31T08:32:53.560Z"
713
+ },
714
+ {
715
+ id: "760435",
716
+ stage: "GROUP",
717
+ group: "K",
718
+ kickoff: "2026-06-17T17:00Z",
719
+ venue: "NRG Stadium",
720
+ home: {
721
+ code: "POR",
722
+ name: "Portugal",
723
+ flag: "\u{1F1F5}\u{1F1F9}"
724
+ },
725
+ away: {
726
+ code: "COD",
727
+ name: "Congo DR",
728
+ flag: "\u{1F1E8}\u{1F1E9}"
729
+ },
730
+ status: "SCHEDULED",
731
+ updatedAt: "2026-05-31T08:32:53.560Z"
732
+ },
733
+ {
734
+ id: "760437",
735
+ stage: "GROUP",
736
+ group: "L",
737
+ kickoff: "2026-06-17T20:00Z",
738
+ venue: "AT&T Stadium",
739
+ home: {
740
+ code: "ENG",
741
+ name: "England",
742
+ flag: "\u{1F3F4}\u{E0067}\u{E0062}\u{E0065}\u{E006E}\u{E0067}\u{E007F}"
743
+ },
744
+ away: {
745
+ code: "CRO",
746
+ name: "Croatia",
747
+ flag: "\u{1F1ED}\u{1F1F7}"
748
+ },
749
+ status: "SCHEDULED",
750
+ updatedAt: "2026-05-31T08:32:53.560Z"
751
+ },
752
+ {
753
+ id: "760434",
754
+ stage: "GROUP",
755
+ group: "L",
756
+ kickoff: "2026-06-17T23:00Z",
757
+ venue: "BMO Field",
758
+ home: {
759
+ code: "GHA",
760
+ name: "Ghana",
761
+ flag: "\u{1F1EC}\u{1F1ED}"
762
+ },
763
+ away: {
764
+ code: "PAN",
765
+ name: "Panama",
766
+ flag: "\u{1F1F5}\u{1F1E6}"
767
+ },
768
+ status: "SCHEDULED",
769
+ updatedAt: "2026-05-31T08:32:53.560Z"
770
+ },
771
+ {
772
+ id: "760436",
773
+ stage: "GROUP",
774
+ group: "K",
775
+ kickoff: "2026-06-18T02:00Z",
776
+ venue: "Estadio Banorte",
777
+ home: {
778
+ code: "UZB",
779
+ name: "Uzbekistan",
780
+ flag: "\u{1F1FA}\u{1F1FF}"
781
+ },
782
+ away: {
783
+ code: "COL",
784
+ name: "Colombia",
785
+ flag: "\u{1F1E8}\u{1F1F4}"
786
+ },
787
+ status: "SCHEDULED",
788
+ updatedAt: "2026-05-31T08:32:53.560Z"
789
+ },
790
+ {
791
+ id: "760438",
792
+ stage: "GROUP",
793
+ group: "A",
794
+ kickoff: "2026-06-18T16:00Z",
795
+ venue: "Mercedes-Benz Stadium",
796
+ home: {
797
+ code: "CZE",
798
+ name: "Czechia",
799
+ flag: "\u{1F1E8}\u{1F1FF}"
800
+ },
801
+ away: {
802
+ code: "RSA",
803
+ name: "South Africa",
804
+ flag: "\u{1F1FF}\u{1F1E6}"
805
+ },
806
+ status: "SCHEDULED",
807
+ updatedAt: "2026-05-31T08:32:53.624Z"
808
+ },
809
+ {
810
+ id: "760439",
811
+ stage: "GROUP",
812
+ group: "B",
813
+ kickoff: "2026-06-18T19:00Z",
814
+ venue: "SoFi Stadium",
815
+ home: {
816
+ code: "SUI",
817
+ name: "Switzerland",
818
+ flag: "\u{1F1E8}\u{1F1ED}"
819
+ },
820
+ away: {
821
+ code: "BIH",
822
+ name: "Bosnia-Herzegovina",
823
+ flag: "\u{1F1E7}\u{1F1E6}"
824
+ },
825
+ status: "SCHEDULED",
826
+ updatedAt: "2026-05-31T08:32:53.624Z"
827
+ },
828
+ {
829
+ id: "760440",
830
+ stage: "GROUP",
831
+ group: "B",
832
+ kickoff: "2026-06-18T22:00Z",
833
+ venue: "BC Place",
834
+ home: {
835
+ code: "CAN",
836
+ name: "Canada",
837
+ flag: "\u{1F1E8}\u{1F1E6}"
838
+ },
839
+ away: {
840
+ code: "QAT",
841
+ name: "Qatar",
842
+ flag: "\u{1F1F6}\u{1F1E6}"
843
+ },
844
+ status: "SCHEDULED",
845
+ updatedAt: "2026-05-31T08:32:53.624Z"
846
+ },
847
+ {
848
+ id: "760441",
849
+ stage: "GROUP",
850
+ group: "A",
851
+ kickoff: "2026-06-19T01:00Z",
852
+ venue: "Estadio Akron",
853
+ home: {
854
+ code: "MEX",
855
+ name: "Mexico",
856
+ flag: "\u{1F1F2}\u{1F1FD}"
857
+ },
858
+ away: {
859
+ code: "KOR",
860
+ name: "South Korea",
861
+ flag: "\u{1F1F0}\u{1F1F7}"
862
+ },
863
+ status: "SCHEDULED",
864
+ updatedAt: "2026-05-31T08:32:53.624Z"
865
+ },
866
+ {
867
+ id: "760442",
868
+ stage: "GROUP",
869
+ group: "D",
870
+ kickoff: "2026-06-19T19:00Z",
871
+ venue: "Lumen Field",
872
+ home: {
873
+ code: "USA",
874
+ name: "United States",
875
+ flag: "\u{1F1FA}\u{1F1F8}"
876
+ },
877
+ away: {
878
+ code: "AUS",
879
+ name: "Australia",
880
+ flag: "\u{1F1E6}\u{1F1FA}"
881
+ },
882
+ status: "SCHEDULED",
883
+ updatedAt: "2026-05-31T08:32:53.624Z"
884
+ },
885
+ {
886
+ id: "760445",
887
+ stage: "GROUP",
888
+ group: "C",
889
+ kickoff: "2026-06-19T22:00Z",
890
+ venue: "Gillette Stadium",
891
+ home: {
892
+ code: "SCO",
893
+ name: "Scotland",
894
+ flag: "\u{1F3F4}\u{E0067}\u{E0062}\u{E0073}\u{E0063}\u{E0074}\u{E007F}"
895
+ },
896
+ away: {
897
+ code: "MAR",
898
+ name: "Morocco",
899
+ flag: "\u{1F1F2}\u{1F1E6}"
900
+ },
901
+ status: "SCHEDULED",
902
+ updatedAt: "2026-05-31T08:32:53.624Z"
903
+ },
904
+ {
905
+ id: "760444",
906
+ stage: "GROUP",
907
+ group: "C",
908
+ kickoff: "2026-06-20T00:30Z",
909
+ venue: "Lincoln Financial Field",
910
+ home: {
911
+ code: "BRA",
912
+ name: "Brazil",
913
+ flag: "\u{1F1E7}\u{1F1F7}"
914
+ },
915
+ away: {
916
+ code: "HAI",
917
+ name: "Haiti",
918
+ flag: "\u{1F1ED}\u{1F1F9}"
919
+ },
920
+ status: "SCHEDULED",
921
+ updatedAt: "2026-05-31T08:32:53.624Z"
922
+ },
923
+ {
924
+ id: "760443",
925
+ stage: "GROUP",
926
+ group: "D",
927
+ kickoff: "2026-06-20T03:00Z",
928
+ venue: "Levi's Stadium",
929
+ home: {
930
+ code: "TUR",
931
+ name: "T\xFCrkiye",
932
+ flag: "\u{1F1F9}\u{1F1F7}"
933
+ },
934
+ away: {
935
+ code: "PAR",
936
+ name: "Paraguay",
937
+ flag: "\u{1F1F5}\u{1F1FE}"
938
+ },
939
+ status: "SCHEDULED",
940
+ updatedAt: "2026-05-31T08:32:53.624Z"
941
+ },
942
+ {
943
+ id: "760447",
944
+ stage: "GROUP",
945
+ group: "F",
946
+ kickoff: "2026-06-20T17:00Z",
947
+ venue: "NRG Stadium",
948
+ home: {
949
+ code: "NED",
950
+ name: "Netherlands",
951
+ flag: "\u{1F1F3}\u{1F1F1}"
952
+ },
953
+ away: {
954
+ code: "SWE",
955
+ name: "Sweden",
956
+ flag: "\u{1F1F8}\u{1F1EA}"
957
+ },
958
+ status: "SCHEDULED",
959
+ updatedAt: "2026-05-31T08:32:53.624Z"
960
+ },
961
+ {
962
+ id: "760448",
963
+ stage: "GROUP",
964
+ group: "E",
965
+ kickoff: "2026-06-20T20:00Z",
966
+ venue: "BMO Field",
967
+ home: {
968
+ code: "GER",
969
+ name: "Germany",
970
+ flag: "\u{1F1E9}\u{1F1EA}"
971
+ },
972
+ away: {
973
+ code: "CIV",
974
+ name: "Ivory Coast",
975
+ flag: "\u{1F1E8}\u{1F1EE}"
976
+ },
977
+ status: "SCHEDULED",
978
+ updatedAt: "2026-05-31T08:32:53.624Z"
979
+ },
980
+ {
981
+ id: "760446",
982
+ stage: "GROUP",
983
+ group: "E",
984
+ kickoff: "2026-06-21T00:00Z",
985
+ venue: "GEHA Field at Arrowhead Stadium",
986
+ home: {
987
+ code: "ECU",
988
+ name: "Ecuador",
989
+ flag: "\u{1F1EA}\u{1F1E8}"
990
+ },
991
+ away: {
992
+ code: "CUW",
993
+ name: "Curacao",
994
+ flag: "\u{1F1E8}\u{1F1FC}"
995
+ },
996
+ status: "SCHEDULED",
997
+ updatedAt: "2026-05-31T08:32:53.624Z"
998
+ },
999
+ {
1000
+ id: "760449",
1001
+ stage: "GROUP",
1002
+ group: "F",
1003
+ kickoff: "2026-06-21T04:00Z",
1004
+ venue: "Estadio BBVA",
1005
+ home: {
1006
+ code: "TUN",
1007
+ name: "Tunisia",
1008
+ flag: "\u{1F1F9}\u{1F1F3}"
1009
+ },
1010
+ away: {
1011
+ code: "JPN",
1012
+ name: "Japan",
1013
+ flag: "\u{1F1EF}\u{1F1F5}"
1014
+ },
1015
+ status: "SCHEDULED",
1016
+ updatedAt: "2026-05-31T08:32:53.624Z"
1017
+ },
1018
+ {
1019
+ id: "760453",
1020
+ stage: "GROUP",
1021
+ group: "H",
1022
+ kickoff: "2026-06-21T16:00Z",
1023
+ venue: "Mercedes-Benz Stadium",
1024
+ home: {
1025
+ code: "ESP",
1026
+ name: "Spain",
1027
+ flag: "\u{1F1EA}\u{1F1F8}"
1028
+ },
1029
+ away: {
1030
+ code: "KSA",
1031
+ name: "Saudi Arabia",
1032
+ flag: "\u{1F1F8}\u{1F1E6}"
1033
+ },
1034
+ status: "SCHEDULED",
1035
+ updatedAt: "2026-05-31T08:32:53.624Z"
1036
+ },
1037
+ {
1038
+ id: "760451",
1039
+ stage: "GROUP",
1040
+ group: "G",
1041
+ kickoff: "2026-06-21T19:00Z",
1042
+ venue: "SoFi Stadium",
1043
+ home: {
1044
+ code: "BEL",
1045
+ name: "Belgium",
1046
+ flag: "\u{1F1E7}\u{1F1EA}"
1047
+ },
1048
+ away: {
1049
+ code: "IRN",
1050
+ name: "Iran",
1051
+ flag: "\u{1F1EE}\u{1F1F7}"
1052
+ },
1053
+ status: "SCHEDULED",
1054
+ updatedAt: "2026-05-31T08:32:53.624Z"
1055
+ },
1056
+ {
1057
+ id: "760450",
1058
+ stage: "GROUP",
1059
+ group: "H",
1060
+ kickoff: "2026-06-21T22:00Z",
1061
+ venue: "Hard Rock Stadium",
1062
+ home: {
1063
+ code: "URU",
1064
+ name: "Uruguay",
1065
+ flag: "\u{1F1FA}\u{1F1FE}"
1066
+ },
1067
+ away: {
1068
+ code: "CPV",
1069
+ name: "Cape Verde",
1070
+ flag: "\u{1F1E8}\u{1F1FB}"
1071
+ },
1072
+ status: "SCHEDULED",
1073
+ updatedAt: "2026-05-31T08:32:53.624Z"
1074
+ },
1075
+ {
1076
+ id: "760452",
1077
+ stage: "GROUP",
1078
+ group: "G",
1079
+ kickoff: "2026-06-22T01:00Z",
1080
+ venue: "BC Place",
1081
+ home: {
1082
+ code: "NZL",
1083
+ name: "New Zealand",
1084
+ flag: "\u{1F1F3}\u{1F1FF}"
1085
+ },
1086
+ away: {
1087
+ code: "EGY",
1088
+ name: "Egypt",
1089
+ flag: "\u{1F1EA}\u{1F1EC}"
1090
+ },
1091
+ status: "SCHEDULED",
1092
+ updatedAt: "2026-05-31T08:32:53.624Z"
1093
+ },
1094
+ {
1095
+ id: "760456",
1096
+ stage: "GROUP",
1097
+ group: "J",
1098
+ kickoff: "2026-06-22T17:00Z",
1099
+ venue: "AT&T Stadium",
1100
+ home: {
1101
+ code: "ARG",
1102
+ name: "Argentina",
1103
+ flag: "\u{1F1E6}\u{1F1F7}"
1104
+ },
1105
+ away: {
1106
+ code: "AUT",
1107
+ name: "Austria",
1108
+ flag: "\u{1F1E6}\u{1F1F9}"
1109
+ },
1110
+ status: "SCHEDULED",
1111
+ updatedAt: "2026-05-31T08:32:53.624Z"
1112
+ },
1113
+ {
1114
+ id: "760457",
1115
+ stage: "GROUP",
1116
+ group: "I",
1117
+ kickoff: "2026-06-22T21:00Z",
1118
+ venue: "Lincoln Financial Field",
1119
+ home: {
1120
+ code: "FRA",
1121
+ name: "France",
1122
+ flag: "\u{1F1EB}\u{1F1F7}"
1123
+ },
1124
+ away: {
1125
+ code: "IRQ",
1126
+ name: "Iraq",
1127
+ flag: "\u{1F1EE}\u{1F1F6}"
1128
+ },
1129
+ status: "SCHEDULED",
1130
+ updatedAt: "2026-05-31T08:32:53.624Z"
1131
+ },
1132
+ {
1133
+ id: "760454",
1134
+ stage: "GROUP",
1135
+ group: "I",
1136
+ kickoff: "2026-06-23T00:00Z",
1137
+ venue: "MetLife Stadium",
1138
+ home: {
1139
+ code: "NOR",
1140
+ name: "Norway",
1141
+ flag: "\u{1F1F3}\u{1F1F4}"
1142
+ },
1143
+ away: {
1144
+ code: "SEN",
1145
+ name: "Senegal",
1146
+ flag: "\u{1F1F8}\u{1F1F3}"
1147
+ },
1148
+ status: "SCHEDULED",
1149
+ updatedAt: "2026-05-31T08:32:53.624Z"
1150
+ },
1151
+ {
1152
+ id: "760455",
1153
+ stage: "GROUP",
1154
+ group: "J",
1155
+ kickoff: "2026-06-23T03:00Z",
1156
+ venue: "Levi's Stadium",
1157
+ home: {
1158
+ code: "JOR",
1159
+ name: "Jordan",
1160
+ flag: "\u{1F1EF}\u{1F1F4}"
1161
+ },
1162
+ away: {
1163
+ code: "ALG",
1164
+ name: "Algeria",
1165
+ flag: "\u{1F1E9}\u{1F1FF}"
1166
+ },
1167
+ status: "SCHEDULED",
1168
+ updatedAt: "2026-05-31T08:32:53.624Z"
1169
+ },
1170
+ {
1171
+ id: "760461",
1172
+ stage: "GROUP",
1173
+ group: "K",
1174
+ kickoff: "2026-06-23T17:00Z",
1175
+ venue: "NRG Stadium",
1176
+ home: {
1177
+ code: "POR",
1178
+ name: "Portugal",
1179
+ flag: "\u{1F1F5}\u{1F1F9}"
1180
+ },
1181
+ away: {
1182
+ code: "UZB",
1183
+ name: "Uzbekistan",
1184
+ flag: "\u{1F1FA}\u{1F1FF}"
1185
+ },
1186
+ status: "SCHEDULED",
1187
+ updatedAt: "2026-05-31T08:32:53.624Z"
1188
+ },
1189
+ {
1190
+ id: "760458",
1191
+ stage: "GROUP",
1192
+ group: "L",
1193
+ kickoff: "2026-06-23T20:00Z",
1194
+ venue: "Gillette Stadium",
1195
+ home: {
1196
+ code: "ENG",
1197
+ name: "England",
1198
+ flag: "\u{1F3F4}\u{E0067}\u{E0062}\u{E0065}\u{E006E}\u{E0067}\u{E007F}"
1199
+ },
1200
+ away: {
1201
+ code: "GHA",
1202
+ name: "Ghana",
1203
+ flag: "\u{1F1EC}\u{1F1ED}"
1204
+ },
1205
+ status: "SCHEDULED",
1206
+ updatedAt: "2026-05-31T08:32:53.624Z"
1207
+ },
1208
+ {
1209
+ id: "760460",
1210
+ stage: "GROUP",
1211
+ group: "L",
1212
+ kickoff: "2026-06-23T23:00Z",
1213
+ venue: "BMO Field",
1214
+ home: {
1215
+ code: "PAN",
1216
+ name: "Panama",
1217
+ flag: "\u{1F1F5}\u{1F1E6}"
1218
+ },
1219
+ away: {
1220
+ code: "CRO",
1221
+ name: "Croatia",
1222
+ flag: "\u{1F1ED}\u{1F1F7}"
1223
+ },
1224
+ status: "SCHEDULED",
1225
+ updatedAt: "2026-05-31T08:32:53.625Z"
1226
+ },
1227
+ {
1228
+ id: "760459",
1229
+ stage: "GROUP",
1230
+ group: "K",
1231
+ kickoff: "2026-06-24T02:00Z",
1232
+ venue: "Estadio Akron",
1233
+ home: {
1234
+ code: "COL",
1235
+ name: "Colombia",
1236
+ flag: "\u{1F1E8}\u{1F1F4}"
1237
+ },
1238
+ away: {
1239
+ code: "COD",
1240
+ name: "Congo DR",
1241
+ flag: "\u{1F1E8}\u{1F1E9}"
1242
+ },
1243
+ status: "SCHEDULED",
1244
+ updatedAt: "2026-05-31T08:32:53.625Z"
1245
+ },
1246
+ {
1247
+ id: "760462",
1248
+ stage: "GROUP",
1249
+ group: "B",
1250
+ kickoff: "2026-06-24T19:00Z",
1251
+ venue: "Lumen Field",
1252
+ home: {
1253
+ code: "BIH",
1254
+ name: "Bosnia-Herzegovina",
1255
+ flag: "\u{1F1E7}\u{1F1E6}"
1256
+ },
1257
+ away: {
1258
+ code: "QAT",
1259
+ name: "Qatar",
1260
+ flag: "\u{1F1F6}\u{1F1E6}"
1261
+ },
1262
+ status: "SCHEDULED",
1263
+ updatedAt: "2026-05-31T08:32:53.625Z"
1264
+ },
1265
+ {
1266
+ id: "760463",
1267
+ stage: "GROUP",
1268
+ group: "B",
1269
+ kickoff: "2026-06-24T19:00Z",
1270
+ venue: "BC Place",
1271
+ home: {
1272
+ code: "SUI",
1273
+ name: "Switzerland",
1274
+ flag: "\u{1F1E8}\u{1F1ED}"
1275
+ },
1276
+ away: {
1277
+ code: "CAN",
1278
+ name: "Canada",
1279
+ flag: "\u{1F1E8}\u{1F1E6}"
1280
+ },
1281
+ status: "SCHEDULED",
1282
+ updatedAt: "2026-05-31T08:32:53.625Z"
1283
+ },
1284
+ {
1285
+ id: "760464",
1286
+ stage: "GROUP",
1287
+ group: "C",
1288
+ kickoff: "2026-06-24T22:00Z",
1289
+ venue: "Mercedes-Benz Stadium",
1290
+ home: {
1291
+ code: "MAR",
1292
+ name: "Morocco",
1293
+ flag: "\u{1F1F2}\u{1F1E6}"
1294
+ },
1295
+ away: {
1296
+ code: "HAI",
1297
+ name: "Haiti",
1298
+ flag: "\u{1F1ED}\u{1F1F9}"
1299
+ },
1300
+ status: "SCHEDULED",
1301
+ updatedAt: "2026-05-31T08:32:53.625Z"
1302
+ },
1303
+ {
1304
+ id: "760465",
1305
+ stage: "GROUP",
1306
+ group: "C",
1307
+ kickoff: "2026-06-24T22:00Z",
1308
+ venue: "Hard Rock Stadium",
1309
+ home: {
1310
+ code: "SCO",
1311
+ name: "Scotland",
1312
+ flag: "\u{1F3F4}\u{E0067}\u{E0062}\u{E0073}\u{E0063}\u{E0074}\u{E007F}"
1313
+ },
1314
+ away: {
1315
+ code: "BRA",
1316
+ name: "Brazil",
1317
+ flag: "\u{1F1E7}\u{1F1F7}"
1318
+ },
1319
+ status: "SCHEDULED",
1320
+ updatedAt: "2026-05-31T08:32:53.625Z"
1321
+ },
1322
+ {
1323
+ id: "760467",
1324
+ stage: "GROUP",
1325
+ group: "A",
1326
+ kickoff: "2026-06-25T01:00Z",
1327
+ venue: "Estadio Banorte",
1328
+ home: {
1329
+ code: "CZE",
1330
+ name: "Czechia",
1331
+ flag: "\u{1F1E8}\u{1F1FF}"
1332
+ },
1333
+ away: {
1334
+ code: "MEX",
1335
+ name: "Mexico",
1336
+ flag: "\u{1F1F2}\u{1F1FD}"
1337
+ },
1338
+ status: "SCHEDULED",
1339
+ updatedAt: "2026-05-31T08:32:53.625Z"
1340
+ },
1341
+ {
1342
+ id: "760466",
1343
+ stage: "GROUP",
1344
+ group: "A",
1345
+ kickoff: "2026-06-25T01:00Z",
1346
+ venue: "Estadio BBVA",
1347
+ home: {
1348
+ code: "RSA",
1349
+ name: "South Africa",
1350
+ flag: "\u{1F1FF}\u{1F1E6}"
1351
+ },
1352
+ away: {
1353
+ code: "KOR",
1354
+ name: "South Korea",
1355
+ flag: "\u{1F1F0}\u{1F1F7}"
1356
+ },
1357
+ status: "SCHEDULED",
1358
+ updatedAt: "2026-05-31T08:32:53.625Z"
1359
+ },
1360
+ {
1361
+ id: "760473",
1362
+ stage: "GROUP",
1363
+ group: "E",
1364
+ kickoff: "2026-06-25T20:00Z",
1365
+ venue: "Lincoln Financial Field",
1366
+ home: {
1367
+ code: "CUW",
1368
+ name: "Curacao",
1369
+ flag: "\u{1F1E8}\u{1F1FC}"
1370
+ },
1371
+ away: {
1372
+ code: "CIV",
1373
+ name: "Ivory Coast",
1374
+ flag: "\u{1F1E8}\u{1F1EE}"
1375
+ },
1376
+ status: "SCHEDULED",
1377
+ updatedAt: "2026-05-31T08:32:53.682Z"
1378
+ },
1379
+ {
1380
+ id: "760468",
1381
+ stage: "GROUP",
1382
+ group: "E",
1383
+ kickoff: "2026-06-25T20:00Z",
1384
+ venue: "MetLife Stadium",
1385
+ home: {
1386
+ code: "ECU",
1387
+ name: "Ecuador",
1388
+ flag: "\u{1F1EA}\u{1F1E8}"
1389
+ },
1390
+ away: {
1391
+ code: "GER",
1392
+ name: "Germany",
1393
+ flag: "\u{1F1E9}\u{1F1EA}"
1394
+ },
1395
+ status: "SCHEDULED",
1396
+ updatedAt: "2026-05-31T08:32:53.682Z"
1397
+ },
1398
+ {
1399
+ id: "760471",
1400
+ stage: "GROUP",
1401
+ group: "F",
1402
+ kickoff: "2026-06-25T23:00Z",
1403
+ venue: "AT&T Stadium",
1404
+ home: {
1405
+ code: "JPN",
1406
+ name: "Japan",
1407
+ flag: "\u{1F1EF}\u{1F1F5}"
1408
+ },
1409
+ away: {
1410
+ code: "SWE",
1411
+ name: "Sweden",
1412
+ flag: "\u{1F1F8}\u{1F1EA}"
1413
+ },
1414
+ status: "SCHEDULED",
1415
+ updatedAt: "2026-05-31T08:32:53.682Z"
1416
+ },
1417
+ {
1418
+ id: "760472",
1419
+ stage: "GROUP",
1420
+ group: "F",
1421
+ kickoff: "2026-06-25T23:00Z",
1422
+ venue: "GEHA Field at Arrowhead Stadium",
1423
+ home: {
1424
+ code: "TUN",
1425
+ name: "Tunisia",
1426
+ flag: "\u{1F1F9}\u{1F1F3}"
1427
+ },
1428
+ away: {
1429
+ code: "NED",
1430
+ name: "Netherlands",
1431
+ flag: "\u{1F1F3}\u{1F1F1}"
1432
+ },
1433
+ status: "SCHEDULED",
1434
+ updatedAt: "2026-05-31T08:32:53.682Z"
1435
+ },
1436
+ {
1437
+ id: "760469",
1438
+ stage: "GROUP",
1439
+ group: "D",
1440
+ kickoff: "2026-06-26T02:00Z",
1441
+ venue: "Levi's Stadium",
1442
+ home: {
1443
+ code: "PAR",
1444
+ name: "Paraguay",
1445
+ flag: "\u{1F1F5}\u{1F1FE}"
1446
+ },
1447
+ away: {
1448
+ code: "AUS",
1449
+ name: "Australia",
1450
+ flag: "\u{1F1E6}\u{1F1FA}"
1451
+ },
1452
+ status: "SCHEDULED",
1453
+ updatedAt: "2026-05-31T08:32:53.682Z"
1454
+ },
1455
+ {
1456
+ id: "760470",
1457
+ stage: "GROUP",
1458
+ group: "D",
1459
+ kickoff: "2026-06-26T02:00Z",
1460
+ venue: "SoFi Stadium",
1461
+ home: {
1462
+ code: "TUR",
1463
+ name: "T\xFCrkiye",
1464
+ flag: "\u{1F1F9}\u{1F1F7}"
1465
+ },
1466
+ away: {
1467
+ code: "USA",
1468
+ name: "United States",
1469
+ flag: "\u{1F1FA}\u{1F1F8}"
1470
+ },
1471
+ status: "SCHEDULED",
1472
+ updatedAt: "2026-05-31T08:32:53.682Z"
1473
+ },
1474
+ {
1475
+ id: "760475",
1476
+ stage: "GROUP",
1477
+ group: "I",
1478
+ kickoff: "2026-06-26T19:00Z",
1479
+ venue: "Gillette Stadium",
1480
+ home: {
1481
+ code: "NOR",
1482
+ name: "Norway",
1483
+ flag: "\u{1F1F3}\u{1F1F4}"
1484
+ },
1485
+ away: {
1486
+ code: "FRA",
1487
+ name: "France",
1488
+ flag: "\u{1F1EB}\u{1F1F7}"
1489
+ },
1490
+ status: "SCHEDULED",
1491
+ updatedAt: "2026-05-31T08:32:53.682Z"
1492
+ },
1493
+ {
1494
+ id: "760474",
1495
+ stage: "GROUP",
1496
+ group: "I",
1497
+ kickoff: "2026-06-26T19:00Z",
1498
+ venue: "BMO Field",
1499
+ home: {
1500
+ code: "SEN",
1501
+ name: "Senegal",
1502
+ flag: "\u{1F1F8}\u{1F1F3}"
1503
+ },
1504
+ away: {
1505
+ code: "IRQ",
1506
+ name: "Iraq",
1507
+ flag: "\u{1F1EE}\u{1F1F6}"
1508
+ },
1509
+ status: "SCHEDULED",
1510
+ updatedAt: "2026-05-31T08:32:53.682Z"
1511
+ },
1512
+ {
1513
+ id: "760478",
1514
+ stage: "GROUP",
1515
+ group: "H",
1516
+ kickoff: "2026-06-27T00:00Z",
1517
+ venue: "NRG Stadium",
1518
+ home: {
1519
+ code: "CPV",
1520
+ name: "Cape Verde",
1521
+ flag: "\u{1F1E8}\u{1F1FB}"
1522
+ },
1523
+ away: {
1524
+ code: "KSA",
1525
+ name: "Saudi Arabia",
1526
+ flag: "\u{1F1F8}\u{1F1E6}"
1527
+ },
1528
+ status: "SCHEDULED",
1529
+ updatedAt: "2026-05-31T08:32:53.682Z"
1530
+ },
1531
+ {
1532
+ id: "760479",
1533
+ stage: "GROUP",
1534
+ group: "H",
1535
+ kickoff: "2026-06-27T00:00Z",
1536
+ venue: "Estadio Akron",
1537
+ home: {
1538
+ code: "URU",
1539
+ name: "Uruguay",
1540
+ flag: "\u{1F1FA}\u{1F1FE}"
1541
+ },
1542
+ away: {
1543
+ code: "ESP",
1544
+ name: "Spain",
1545
+ flag: "\u{1F1EA}\u{1F1F8}"
1546
+ },
1547
+ status: "SCHEDULED",
1548
+ updatedAt: "2026-05-31T08:32:53.682Z"
1549
+ },
1550
+ {
1551
+ id: "760476",
1552
+ stage: "GROUP",
1553
+ group: "G",
1554
+ kickoff: "2026-06-27T03:00Z",
1555
+ venue: "Lumen Field",
1556
+ home: {
1557
+ code: "EGY",
1558
+ name: "Egypt",
1559
+ flag: "\u{1F1EA}\u{1F1EC}"
1560
+ },
1561
+ away: {
1562
+ code: "IRN",
1563
+ name: "Iran",
1564
+ flag: "\u{1F1EE}\u{1F1F7}"
1565
+ },
1566
+ status: "SCHEDULED",
1567
+ updatedAt: "2026-05-31T08:32:53.682Z"
1568
+ },
1569
+ {
1570
+ id: "760477",
1571
+ stage: "GROUP",
1572
+ group: "G",
1573
+ kickoff: "2026-06-27T03:00Z",
1574
+ venue: "BC Place",
1575
+ home: {
1576
+ code: "NZL",
1577
+ name: "New Zealand",
1578
+ flag: "\u{1F1F3}\u{1F1FF}"
1579
+ },
1580
+ away: {
1581
+ code: "BEL",
1582
+ name: "Belgium",
1583
+ flag: "\u{1F1E7}\u{1F1EA}"
1584
+ },
1585
+ status: "SCHEDULED",
1586
+ updatedAt: "2026-05-31T08:32:53.682Z"
1587
+ },
1588
+ {
1589
+ id: "760480",
1590
+ stage: "GROUP",
1591
+ group: "L",
1592
+ kickoff: "2026-06-27T21:00Z",
1593
+ venue: "Lincoln Financial Field",
1594
+ home: {
1595
+ code: "CRO",
1596
+ name: "Croatia",
1597
+ flag: "\u{1F1ED}\u{1F1F7}"
1598
+ },
1599
+ away: {
1600
+ code: "GHA",
1601
+ name: "Ghana",
1602
+ flag: "\u{1F1EC}\u{1F1ED}"
1603
+ },
1604
+ status: "SCHEDULED",
1605
+ updatedAt: "2026-05-31T08:32:53.682Z"
1606
+ },
1607
+ {
1608
+ id: "760485",
1609
+ stage: "GROUP",
1610
+ group: "L",
1611
+ kickoff: "2026-06-27T21:00Z",
1612
+ venue: "MetLife Stadium",
1613
+ home: {
1614
+ code: "PAN",
1615
+ name: "Panama",
1616
+ flag: "\u{1F1F5}\u{1F1E6}"
1617
+ },
1618
+ away: {
1619
+ code: "ENG",
1620
+ name: "England",
1621
+ flag: "\u{1F3F4}\u{E0067}\u{E0062}\u{E0065}\u{E006E}\u{E0067}\u{E007F}"
1622
+ },
1623
+ status: "SCHEDULED",
1624
+ updatedAt: "2026-05-31T08:32:53.682Z"
1625
+ },
1626
+ {
1627
+ id: "760481",
1628
+ stage: "GROUP",
1629
+ group: "K",
1630
+ kickoff: "2026-06-27T23:30Z",
1631
+ venue: "Hard Rock Stadium",
1632
+ home: {
1633
+ code: "COL",
1634
+ name: "Colombia",
1635
+ flag: "\u{1F1E8}\u{1F1F4}"
1636
+ },
1637
+ away: {
1638
+ code: "POR",
1639
+ name: "Portugal",
1640
+ flag: "\u{1F1F5}\u{1F1F9}"
1641
+ },
1642
+ status: "SCHEDULED",
1643
+ updatedAt: "2026-05-31T08:32:53.682Z"
1644
+ },
1645
+ {
1646
+ id: "760482",
1647
+ stage: "GROUP",
1648
+ group: "K",
1649
+ kickoff: "2026-06-27T23:30Z",
1650
+ venue: "Mercedes-Benz Stadium",
1651
+ home: {
1652
+ code: "COD",
1653
+ name: "Congo DR",
1654
+ flag: "\u{1F1E8}\u{1F1E9}"
1655
+ },
1656
+ away: {
1657
+ code: "UZB",
1658
+ name: "Uzbekistan",
1659
+ flag: "\u{1F1FA}\u{1F1FF}"
1660
+ },
1661
+ status: "SCHEDULED",
1662
+ updatedAt: "2026-05-31T08:32:53.682Z"
1663
+ },
1664
+ {
1665
+ id: "760484",
1666
+ stage: "GROUP",
1667
+ group: "J",
1668
+ kickoff: "2026-06-28T02:00Z",
1669
+ venue: "GEHA Field at Arrowhead Stadium",
1670
+ home: {
1671
+ code: "ALG",
1672
+ name: "Algeria",
1673
+ flag: "\u{1F1E9}\u{1F1FF}"
1674
+ },
1675
+ away: {
1676
+ code: "AUT",
1677
+ name: "Austria",
1678
+ flag: "\u{1F1E6}\u{1F1F9}"
1679
+ },
1680
+ status: "SCHEDULED",
1681
+ updatedAt: "2026-05-31T08:32:53.682Z"
1682
+ },
1683
+ {
1684
+ id: "760483",
1685
+ stage: "GROUP",
1686
+ group: "J",
1687
+ kickoff: "2026-06-28T02:00Z",
1688
+ venue: "AT&T Stadium",
1689
+ home: {
1690
+ code: "JOR",
1691
+ name: "Jordan",
1692
+ flag: "\u{1F1EF}\u{1F1F4}"
1693
+ },
1694
+ away: {
1695
+ code: "ARG",
1696
+ name: "Argentina",
1697
+ flag: "\u{1F1E6}\u{1F1F7}"
1698
+ },
1699
+ status: "SCHEDULED",
1700
+ updatedAt: "2026-05-31T08:32:53.682Z"
1701
+ },
1702
+ {
1703
+ id: "760486",
1704
+ stage: "R32",
1705
+ kickoff: "2026-06-28T19:00Z",
1706
+ venue: "SoFi Stadium",
1707
+ home: {
1708
+ code: "2A",
1709
+ name: "Group A 2nd Place",
1710
+ flag: "\u{1F3F3}\uFE0F"
1711
+ },
1712
+ away: {
1713
+ code: "2B",
1714
+ name: "Group B 2nd Place",
1715
+ flag: "\u{1F3F3}\uFE0F"
1716
+ },
1717
+ status: "SCHEDULED",
1718
+ updatedAt: "2026-05-31T08:32:53.682Z"
1719
+ },
1720
+ {
1721
+ id: "760487",
1722
+ stage: "R32",
1723
+ kickoff: "2026-06-29T17:00Z",
1724
+ venue: "NRG Stadium",
1725
+ home: {
1726
+ code: "1C",
1727
+ name: "Group C Winner",
1728
+ flag: "\u{1F3F3}\uFE0F"
1729
+ },
1730
+ away: {
1731
+ code: "2F",
1732
+ name: "Group F 2nd Place",
1733
+ flag: "\u{1F3F3}\uFE0F"
1734
+ },
1735
+ status: "SCHEDULED",
1736
+ updatedAt: "2026-05-31T08:32:53.682Z"
1737
+ },
1738
+ {
1739
+ id: "760489",
1740
+ stage: "R32",
1741
+ kickoff: "2026-06-29T20:30Z",
1742
+ venue: "Gillette Stadium",
1743
+ home: {
1744
+ code: "1E",
1745
+ name: "Group E Winner",
1746
+ flag: "\u{1F3F3}\uFE0F"
1747
+ },
1748
+ away: {
1749
+ code: "3RD",
1750
+ name: "Third Place Group A/B/C/D/F",
1751
+ flag: "\u{1F3F3}\uFE0F"
1752
+ },
1753
+ status: "SCHEDULED",
1754
+ updatedAt: "2026-05-31T08:32:53.682Z"
1755
+ },
1756
+ {
1757
+ id: "760488",
1758
+ stage: "R32",
1759
+ kickoff: "2026-06-30T01:00Z",
1760
+ venue: "Estadio BBVA",
1761
+ home: {
1762
+ code: "1F",
1763
+ name: "Group F Winner",
1764
+ flag: "\u{1F3F3}\uFE0F"
1765
+ },
1766
+ away: {
1767
+ code: "2C",
1768
+ name: "Group C 2nd Place",
1769
+ flag: "\u{1F3F3}\uFE0F"
1770
+ },
1771
+ status: "SCHEDULED",
1772
+ updatedAt: "2026-05-31T08:32:53.682Z"
1773
+ },
1774
+ {
1775
+ id: "760490",
1776
+ stage: "R32",
1777
+ kickoff: "2026-06-30T17:00Z",
1778
+ venue: "AT&T Stadium",
1779
+ home: {
1780
+ code: "2E",
1781
+ name: "Group E 2nd Place",
1782
+ flag: "\u{1F3F3}\uFE0F"
1783
+ },
1784
+ away: {
1785
+ code: "2I",
1786
+ name: "Group I 2nd Place",
1787
+ flag: "\u{1F3F3}\uFE0F"
1788
+ },
1789
+ status: "SCHEDULED",
1790
+ updatedAt: "2026-05-31T08:32:53.682Z"
1791
+ },
1792
+ {
1793
+ id: "760492",
1794
+ stage: "R32",
1795
+ kickoff: "2026-06-30T21:00Z",
1796
+ venue: "MetLife Stadium",
1797
+ home: {
1798
+ code: "1I",
1799
+ name: "Group I Winner",
1800
+ flag: "\u{1F3F3}\uFE0F"
1801
+ },
1802
+ away: {
1803
+ code: "3RD",
1804
+ name: "Third Place Group C/D/F/G/H",
1805
+ flag: "\u{1F3F3}\uFE0F"
1806
+ },
1807
+ status: "SCHEDULED",
1808
+ updatedAt: "2026-05-31T08:32:53.682Z"
1809
+ },
1810
+ {
1811
+ id: "760491",
1812
+ stage: "R32",
1813
+ kickoff: "2026-07-01T01:00Z",
1814
+ venue: "Estadio Banorte",
1815
+ home: {
1816
+ code: "1A",
1817
+ name: "Group A Winner",
1818
+ flag: "\u{1F3F3}\uFE0F"
1819
+ },
1820
+ away: {
1821
+ code: "3RD",
1822
+ name: "Third Place Group C/E/F/H/I",
1823
+ flag: "\u{1F3F3}\uFE0F"
1824
+ },
1825
+ status: "SCHEDULED",
1826
+ updatedAt: "2026-05-31T08:32:53.682Z"
1827
+ },
1828
+ {
1829
+ id: "760495",
1830
+ stage: "R32",
1831
+ kickoff: "2026-07-01T16:00Z",
1832
+ venue: "Mercedes-Benz Stadium",
1833
+ home: {
1834
+ code: "1L",
1835
+ name: "Group L Winner",
1836
+ flag: "\u{1F3F3}\uFE0F"
1837
+ },
1838
+ away: {
1839
+ code: "3RD",
1840
+ name: "Third Place Group E/H/I/J/K",
1841
+ flag: "\u{1F3F3}\uFE0F"
1842
+ },
1843
+ status: "SCHEDULED",
1844
+ updatedAt: "2026-05-31T08:32:53.682Z"
1845
+ },
1846
+ {
1847
+ id: "760493",
1848
+ stage: "R32",
1849
+ kickoff: "2026-07-01T20:00Z",
1850
+ venue: "Lumen Field",
1851
+ home: {
1852
+ code: "1G",
1853
+ name: "Group G Winner",
1854
+ flag: "\u{1F3F3}\uFE0F"
1855
+ },
1856
+ away: {
1857
+ code: "3RD",
1858
+ name: "Third Place Group A/E/H/I/J",
1859
+ flag: "\u{1F3F3}\uFE0F"
1860
+ },
1861
+ status: "SCHEDULED",
1862
+ updatedAt: "2026-05-31T08:32:53.682Z"
1863
+ },
1864
+ {
1865
+ id: "760494",
1866
+ stage: "R32",
1867
+ kickoff: "2026-07-02T00:00Z",
1868
+ venue: "Levi's Stadium",
1869
+ home: {
1870
+ code: "1D",
1871
+ name: "Group D Winner",
1872
+ flag: "\u{1F3F3}\uFE0F"
1873
+ },
1874
+ away: {
1875
+ code: "3RD",
1876
+ name: "Third Place Group B/E/F/I/J",
1877
+ flag: "\u{1F3F3}\uFE0F"
1878
+ },
1879
+ status: "SCHEDULED",
1880
+ updatedAt: "2026-05-31T08:32:53.683Z"
1881
+ },
1882
+ {
1883
+ id: "760497",
1884
+ stage: "R32",
1885
+ kickoff: "2026-07-02T19:00Z",
1886
+ venue: "SoFi Stadium",
1887
+ home: {
1888
+ code: "1H",
1889
+ name: "Group H Winner",
1890
+ flag: "\u{1F3F3}\uFE0F"
1891
+ },
1892
+ away: {
1893
+ code: "2J",
1894
+ name: "Group J 2nd Place",
1895
+ flag: "\u{1F3F3}\uFE0F"
1896
+ },
1897
+ status: "SCHEDULED",
1898
+ updatedAt: "2026-05-31T08:32:53.746Z"
1899
+ },
1900
+ {
1901
+ id: "760496",
1902
+ stage: "R32",
1903
+ kickoff: "2026-07-02T23:00Z",
1904
+ venue: "BMO Field",
1905
+ home: {
1906
+ code: "2K",
1907
+ name: "Group K 2nd Place",
1908
+ flag: "\u{1F3F3}\uFE0F"
1909
+ },
1910
+ away: {
1911
+ code: "2L",
1912
+ name: "Group L 2nd Place",
1913
+ flag: "\u{1F3F3}\uFE0F"
1914
+ },
1915
+ status: "SCHEDULED",
1916
+ updatedAt: "2026-05-31T08:32:53.746Z"
1917
+ },
1918
+ {
1919
+ id: "760498",
1920
+ stage: "R32",
1921
+ kickoff: "2026-07-03T03:00Z",
1922
+ venue: "BC Place",
1923
+ home: {
1924
+ code: "1B",
1925
+ name: "Group B Winner",
1926
+ flag: "\u{1F3F3}\uFE0F"
1927
+ },
1928
+ away: {
1929
+ code: "3RD",
1930
+ name: "Third Place Group E/F/G/I/J",
1931
+ flag: "\u{1F3F3}\uFE0F"
1932
+ },
1933
+ status: "SCHEDULED",
1934
+ updatedAt: "2026-05-31T08:32:53.746Z"
1935
+ },
1936
+ {
1937
+ id: "760499",
1938
+ stage: "R32",
1939
+ kickoff: "2026-07-03T18:00Z",
1940
+ venue: "AT&T Stadium",
1941
+ home: {
1942
+ code: "2D",
1943
+ name: "Group D 2nd Place",
1944
+ flag: "\u{1F3F3}\uFE0F"
1945
+ },
1946
+ away: {
1947
+ code: "2G",
1948
+ name: "Group G 2nd Place",
1949
+ flag: "\u{1F3F3}\uFE0F"
1950
+ },
1951
+ status: "SCHEDULED",
1952
+ updatedAt: "2026-05-31T08:32:53.746Z"
1953
+ },
1954
+ {
1955
+ id: "760500",
1956
+ stage: "R32",
1957
+ kickoff: "2026-07-03T22:00Z",
1958
+ venue: "Hard Rock Stadium",
1959
+ home: {
1960
+ code: "1J",
1961
+ name: "Group J Winner",
1962
+ flag: "\u{1F3F3}\uFE0F"
1963
+ },
1964
+ away: {
1965
+ code: "2H",
1966
+ name: "Group H 2nd Place",
1967
+ flag: "\u{1F3F3}\uFE0F"
1968
+ },
1969
+ status: "SCHEDULED",
1970
+ updatedAt: "2026-05-31T08:32:53.746Z"
1971
+ },
1972
+ {
1973
+ id: "760501",
1974
+ stage: "R32",
1975
+ kickoff: "2026-07-04T01:30Z",
1976
+ venue: "GEHA Field at Arrowhead Stadium",
1977
+ home: {
1978
+ code: "1K",
1979
+ name: "Group K Winner",
1980
+ flag: "\u{1F3F3}\uFE0F"
1981
+ },
1982
+ away: {
1983
+ code: "3RD",
1984
+ name: "Third Place Group D/E/I/J/L",
1985
+ flag: "\u{1F3F3}\uFE0F"
1986
+ },
1987
+ status: "SCHEDULED",
1988
+ updatedAt: "2026-05-31T08:32:53.746Z"
1989
+ },
1990
+ {
1991
+ id: "760502",
1992
+ stage: "R16",
1993
+ kickoff: "2026-07-04T17:00Z",
1994
+ venue: "NRG Stadium",
1995
+ home: {
1996
+ code: "RD32",
1997
+ name: "Round of 32 1 Winner",
1998
+ flag: "\u{1F3F3}\uFE0F"
1999
+ },
2000
+ away: {
2001
+ code: "RD32",
2002
+ name: "Round of 32 3 Winner",
2003
+ flag: "\u{1F3F3}\uFE0F"
2004
+ },
2005
+ status: "SCHEDULED",
2006
+ updatedAt: "2026-05-31T08:32:53.746Z"
2007
+ },
2008
+ {
2009
+ id: "760503",
2010
+ stage: "R16",
2011
+ kickoff: "2026-07-04T21:00Z",
2012
+ venue: "Lincoln Financial Field",
2013
+ home: {
2014
+ code: "RD32",
2015
+ name: "Round of 32 2 Winner",
2016
+ flag: "\u{1F3F3}\uFE0F"
2017
+ },
2018
+ away: {
2019
+ code: "RD32",
2020
+ name: "Round of 32 5 Winner",
2021
+ flag: "\u{1F3F3}\uFE0F"
2022
+ },
2023
+ status: "SCHEDULED",
2024
+ updatedAt: "2026-05-31T08:32:53.746Z"
2025
+ },
2026
+ {
2027
+ id: "760504",
2028
+ stage: "R16",
2029
+ kickoff: "2026-07-05T20:00Z",
2030
+ venue: "MetLife Stadium",
2031
+ home: {
2032
+ code: "RD32",
2033
+ name: "Round of 32 4 Winner",
2034
+ flag: "\u{1F3F3}\uFE0F"
2035
+ },
2036
+ away: {
2037
+ code: "RD32",
2038
+ name: "Round of 32 6 Winner",
2039
+ flag: "\u{1F3F3}\uFE0F"
2040
+ },
2041
+ status: "SCHEDULED",
2042
+ updatedAt: "2026-05-31T08:32:53.746Z"
2043
+ },
2044
+ {
2045
+ id: "760505",
2046
+ stage: "R16",
2047
+ kickoff: "2026-07-06T00:00Z",
2048
+ venue: "Estadio Banorte",
2049
+ home: {
2050
+ code: "RD32",
2051
+ name: "Round of 32 7 Winner",
2052
+ flag: "\u{1F3F3}\uFE0F"
2053
+ },
2054
+ away: {
2055
+ code: "RD32",
2056
+ name: "Round of 32 8 Winner",
2057
+ flag: "\u{1F3F3}\uFE0F"
2058
+ },
2059
+ status: "SCHEDULED",
2060
+ updatedAt: "2026-05-31T08:32:53.746Z"
2061
+ },
2062
+ {
2063
+ id: "760506",
2064
+ stage: "R16",
2065
+ kickoff: "2026-07-06T19:00Z",
2066
+ venue: "AT&T Stadium",
2067
+ home: {
2068
+ code: "RD32",
2069
+ name: "Round of 32 11 Winner",
2070
+ flag: "\u{1F3F3}\uFE0F"
2071
+ },
2072
+ away: {
2073
+ code: "RD32",
2074
+ name: "Round of 32 12 Winner",
2075
+ flag: "\u{1F3F3}\uFE0F"
2076
+ },
2077
+ status: "SCHEDULED",
2078
+ updatedAt: "2026-05-31T08:32:53.746Z"
2079
+ },
2080
+ {
2081
+ id: "760507",
2082
+ stage: "R16",
2083
+ kickoff: "2026-07-07T00:00Z",
2084
+ venue: "Lumen Field",
2085
+ home: {
2086
+ code: "RD32",
2087
+ name: "Round of 32 9 Winner",
2088
+ flag: "\u{1F3F3}\uFE0F"
2089
+ },
2090
+ away: {
2091
+ code: "RD32",
2092
+ name: "Round of 32 10 Winner",
2093
+ flag: "\u{1F3F3}\uFE0F"
2094
+ },
2095
+ status: "SCHEDULED",
2096
+ updatedAt: "2026-05-31T08:32:53.746Z"
2097
+ },
2098
+ {
2099
+ id: "760509",
2100
+ stage: "R16",
2101
+ kickoff: "2026-07-07T16:00Z",
2102
+ venue: "Mercedes-Benz Stadium",
2103
+ home: {
2104
+ code: "RD32",
2105
+ name: "Round of 32 14 Winner",
2106
+ flag: "\u{1F3F3}\uFE0F"
2107
+ },
2108
+ away: {
2109
+ code: "RD32",
2110
+ name: "Round of 32 16 Winner",
2111
+ flag: "\u{1F3F3}\uFE0F"
2112
+ },
2113
+ status: "SCHEDULED",
2114
+ updatedAt: "2026-05-31T08:32:53.746Z"
2115
+ },
2116
+ {
2117
+ id: "760508",
2118
+ stage: "R16",
2119
+ kickoff: "2026-07-07T20:00Z",
2120
+ venue: "BC Place",
2121
+ home: {
2122
+ code: "RD32",
2123
+ name: "Round of 32 13 Winner",
2124
+ flag: "\u{1F3F3}\uFE0F"
2125
+ },
2126
+ away: {
2127
+ code: "RD32",
2128
+ name: "Round of 32 15 Winner",
2129
+ flag: "\u{1F3F3}\uFE0F"
2130
+ },
2131
+ status: "SCHEDULED",
2132
+ updatedAt: "2026-05-31T08:32:53.746Z"
2133
+ },
2134
+ {
2135
+ id: "760510",
2136
+ stage: "QF",
2137
+ kickoff: "2026-07-09T20:00Z",
2138
+ venue: "Gillette Stadium",
2139
+ home: {
2140
+ code: "RD16 W1",
2141
+ name: "Round of 16 1 Winner",
2142
+ flag: "\u{1F3F3}\uFE0F"
2143
+ },
2144
+ away: {
2145
+ code: "RD16 W2",
2146
+ name: "Round of 16 2 Winner",
2147
+ flag: "\u{1F3F3}\uFE0F"
2148
+ },
2149
+ status: "SCHEDULED",
2150
+ updatedAt: "2026-05-31T08:32:53.806Z"
2151
+ },
2152
+ {
2153
+ id: "760511",
2154
+ stage: "QF",
2155
+ kickoff: "2026-07-10T19:00Z",
2156
+ venue: "SoFi Stadium",
2157
+ home: {
2158
+ code: "RD16 W5",
2159
+ name: "Round of 16 5 Winner",
2160
+ flag: "\u{1F3F3}\uFE0F"
2161
+ },
2162
+ away: {
2163
+ code: "RD16 W6",
2164
+ name: "Round of 16 6 Winner",
2165
+ flag: "\u{1F3F3}\uFE0F"
2166
+ },
2167
+ status: "SCHEDULED",
2168
+ updatedAt: "2026-05-31T08:32:53.806Z"
2169
+ },
2170
+ {
2171
+ id: "760512",
2172
+ stage: "QF",
2173
+ kickoff: "2026-07-11T21:00Z",
2174
+ venue: "Hard Rock Stadium",
2175
+ home: {
2176
+ code: "RD16 W3",
2177
+ name: "Round of 16 3 Winner",
2178
+ flag: "\u{1F3F3}\uFE0F"
2179
+ },
2180
+ away: {
2181
+ code: "RD16 W4",
2182
+ name: "Round of 16 4 Winner",
2183
+ flag: "\u{1F3F3}\uFE0F"
2184
+ },
2185
+ status: "SCHEDULED",
2186
+ updatedAt: "2026-05-31T08:32:53.806Z"
2187
+ },
2188
+ {
2189
+ id: "760513",
2190
+ stage: "QF",
2191
+ kickoff: "2026-07-12T01:00Z",
2192
+ venue: "GEHA Field at Arrowhead Stadium",
2193
+ home: {
2194
+ code: "RD16 W7",
2195
+ name: "Round of 16 7 Winner",
2196
+ flag: "\u{1F3F3}\uFE0F"
2197
+ },
2198
+ away: {
2199
+ code: "RD16 W8",
2200
+ name: "Round of 16 8 Winner",
2201
+ flag: "\u{1F3F3}\uFE0F"
2202
+ },
2203
+ status: "SCHEDULED",
2204
+ updatedAt: "2026-05-31T08:32:53.806Z"
2205
+ },
2206
+ {
2207
+ id: "760514",
2208
+ stage: "SF",
2209
+ kickoff: "2026-07-14T19:00Z",
2210
+ venue: "AT&T Stadium",
2211
+ home: {
2212
+ code: "QFW1",
2213
+ name: "Quarterfinal 1 Winner",
2214
+ flag: "\u{1F3F3}\uFE0F"
2215
+ },
2216
+ away: {
2217
+ code: "QFW2",
2218
+ name: "Quarterfinal 2 Winner",
2219
+ flag: "\u{1F3F3}\uFE0F"
2220
+ },
2221
+ status: "SCHEDULED",
2222
+ updatedAt: "2026-05-31T08:32:53.806Z"
2223
+ },
2224
+ {
2225
+ id: "760515",
2226
+ stage: "SF",
2227
+ kickoff: "2026-07-15T19:00Z",
2228
+ venue: "Mercedes-Benz Stadium",
2229
+ home: {
2230
+ code: "QFW3",
2231
+ name: "Quarterfinal 3 Winner",
2232
+ flag: "\u{1F3F3}\uFE0F"
2233
+ },
2234
+ away: {
2235
+ code: "QW4",
2236
+ name: "Quarterfinal 4 Winner",
2237
+ flag: "\u{1F3F3}\uFE0F"
2238
+ },
2239
+ status: "SCHEDULED",
2240
+ updatedAt: "2026-05-31T08:32:53.806Z"
2241
+ },
2242
+ {
2243
+ id: "760516",
2244
+ stage: "3P",
2245
+ kickoff: "2026-07-18T21:00Z",
2246
+ venue: "Hard Rock Stadium",
2247
+ home: {
2248
+ code: "SF L1",
2249
+ name: "Semifinal 1 Loser",
2250
+ flag: "\u{1F3F3}\uFE0F"
2251
+ },
2252
+ away: {
2253
+ code: "SF L2",
2254
+ name: "Semifinal 2 Loser",
2255
+ flag: "\u{1F3F3}\uFE0F"
2256
+ },
2257
+ status: "SCHEDULED",
2258
+ updatedAt: "2026-05-31T08:32:53.923Z"
2259
+ },
2260
+ {
2261
+ id: "760517",
2262
+ stage: "F",
2263
+ kickoff: "2026-07-19T19:00Z",
2264
+ venue: "MetLife Stadium",
2265
+ home: {
2266
+ code: "SFW1",
2267
+ name: "Semifinal 1 Winner",
2268
+ flag: "\u{1F3F3}\uFE0F"
2269
+ },
2270
+ away: {
2271
+ code: "SFW2",
2272
+ name: "Semifinal 2 Winner",
2273
+ flag: "\u{1F3F3}\uFE0F"
2274
+ },
2275
+ status: "SCHEDULED",
2276
+ updatedAt: "2026-05-31T08:32:53.924Z"
2277
+ }
2278
+ ];
2279
+ var SCHEDULE = schedule_2026_default;
2280
+ function allFixtures() {
2281
+ return SCHEDULE;
2282
+ }
2283
+ function fixturesByDate(dateISO, fixtures = SCHEDULE) {
2284
+ const day = dateISO.slice(0, 10);
2285
+ return fixtures.filter((m) => m.kickoff.slice(0, 10) === day).sort(byKickoff);
2286
+ }
2287
+ function fixturesByTeam(code, fixtures = SCHEDULE) {
2288
+ const c = code.toUpperCase();
2289
+ return fixtures.filter((m) => m.home.code.toUpperCase() === c || m.away.code.toUpperCase() === c).sort(byKickoff);
2290
+ }
2291
+ function fixturesByGroup(group, fixtures = SCHEDULE) {
2292
+ const g = group.toUpperCase();
2293
+ return fixtures.filter((m) => (m.group ?? "").toUpperCase() === g).sort(byKickoff);
2294
+ }
2295
+ function nextFixtureForTeam(code, opts = {}) {
2296
+ const from = opts.from ?? /* @__PURE__ */ new Date();
2297
+ return fixturesByTeam(code, opts.fixtures ?? SCHEDULE).find(
2298
+ (m) => new Date(m.kickoff).getTime() >= from.getTime()
2299
+ );
2300
+ }
2301
+ function groups(fixtures = SCHEDULE) {
2302
+ const set = /* @__PURE__ */ new Set();
2303
+ for (const m of fixtures) if (m.group) set.add(m.group);
2304
+ return [...set].sort();
2305
+ }
2306
+ function blankRow(team) {
2307
+ return {
2308
+ team,
2309
+ played: 0,
2310
+ won: 0,
2311
+ drawn: 0,
2312
+ lost: 0,
2313
+ goalsFor: 0,
2314
+ goalsAgainst: 0,
2315
+ goalDiff: 0,
2316
+ points: 0
2317
+ };
2318
+ }
2319
+ function computeStandings(matches) {
2320
+ const rows = /* @__PURE__ */ new Map();
2321
+ const ensure = (t) => {
2322
+ let r = rows.get(t.code);
2323
+ if (!r) {
2324
+ r = blankRow(t);
2325
+ rows.set(t.code, r);
2326
+ }
2327
+ return r;
2328
+ };
2329
+ for (const m of matches) {
2330
+ const home = ensure(m.home);
2331
+ const away = ensure(m.away);
2332
+ if (!isFinished(m.status) || !m.score) continue;
2333
+ const { home: hg, away: ag } = m.score;
2334
+ home.played++;
2335
+ away.played++;
2336
+ home.goalsFor += hg;
2337
+ home.goalsAgainst += ag;
2338
+ away.goalsFor += ag;
2339
+ away.goalsAgainst += hg;
2340
+ if (hg > ag) {
2341
+ home.won++;
2342
+ away.lost++;
2343
+ home.points += 3;
2344
+ } else if (hg < ag) {
2345
+ away.won++;
2346
+ home.lost++;
2347
+ away.points += 3;
2348
+ } else {
2349
+ home.drawn++;
2350
+ away.drawn++;
2351
+ home.points++;
2352
+ away.points++;
2353
+ }
2354
+ }
2355
+ for (const r of rows.values()) r.goalDiff = r.goalsFor - r.goalsAgainst;
2356
+ return [...rows.values()].sort(
2357
+ (a, b) => b.points - a.points || b.goalDiff - a.goalDiff || b.goalsFor - a.goalsFor || a.team.name.localeCompare(b.team.name)
2358
+ );
2359
+ }
2360
+ var ESPN_SOCCER = "https://site.api.espn.com/apis/site/v2/sports/soccer";
2361
+ var DEFAULT_COMPETITION = "fifa.world";
2362
+ var DEFAULT_BASE = `${ESPN_SOCCER}/${DEFAULT_COMPETITION}`;
2363
+ var USER_AGENT = "claudinho/0.0 (+https://github.com/arturogarrido/claudinho)";
2364
+ function competitionBase(slug) {
2365
+ return `${ESPN_SOCCER}/${slug}`;
2366
+ }
2367
+ function mapStatus(st) {
2368
+ const name = (st?.type?.name ?? "").toUpperCase();
2369
+ const state = st?.type?.state ?? "";
2370
+ if (name.includes("HALFTIME")) return "HT";
2371
+ if (name.includes("POSTPONED")) return "POSTPONED";
2372
+ if (name.includes("CANCEL")) return "CANCELLED";
2373
+ if (state === "pre") return "SCHEDULED";
2374
+ if (state === "post") return "FT";
2375
+ if (state === "in") return "LIVE";
2376
+ return "SCHEDULED";
2377
+ }
2378
+ function parseMinute(st) {
2379
+ if (st?.type?.state !== "in") return void 0;
2380
+ const dc = st.displayClock?.match(/(\d+)/);
2381
+ if (dc) return parseInt(dc[1], 10);
2382
+ if (typeof st.clock === "number" && st.clock > 0) {
2383
+ return Math.floor(st.clock / 60) || void 0;
2384
+ }
2385
+ return void 0;
2386
+ }
2387
+ var SLUG_TO_STAGE = {
2388
+ "group-stage": "GROUP",
2389
+ "round-of-32": "R32",
2390
+ "round-of-16": "R16",
2391
+ quarterfinals: "QF",
2392
+ semifinals: "SF",
2393
+ "3rd-place-match": "3P",
2394
+ final: "F"
2395
+ };
2396
+ function stageFromSlug(slug) {
2397
+ if (slug && SLUG_TO_STAGE[slug]) return SLUG_TO_STAGE[slug];
2398
+ if (!slug) return "GROUP";
2399
+ return "FRIENDLY";
2400
+ }
2401
+ function toInt(s) {
2402
+ if (s == null || s === "") return void 0;
2403
+ const n = parseInt(s, 10);
2404
+ return Number.isFinite(n) ? n : void 0;
2405
+ }
2406
+ function toTeam(t) {
2407
+ const name = t?.displayName ?? t?.name ?? t?.location ?? t?.shortDisplayName ?? "TBD";
2408
+ const code = (t?.abbreviation ?? name.slice(0, 3)).toUpperCase();
2409
+ return { code, name, flag: nationToFlag(t?.displayName ?? t?.abbreviation ?? name) };
2410
+ }
2411
+ function mapEspnEvent(ev, ctx = {}) {
2412
+ const comp = ev.competitions?.[0];
2413
+ const competitors = comp?.competitors ?? [];
2414
+ const homeC = competitors.find((c) => c.homeAway === "home") ?? competitors[0];
2415
+ const awayC = competitors.find((c) => c.homeAway === "away") ?? competitors[1];
2416
+ const status = mapStatus(ev.status ?? comp?.status);
2417
+ const stage = stageFromSlug(ev.season?.slug);
2418
+ const home = toTeam(homeC?.team);
2419
+ const away = toTeam(awayC?.team);
2420
+ let group;
2421
+ if (stage === "GROUP" && ctx.groupByTeam) {
2422
+ group = ctx.groupByTeam[home.code] ?? ctx.groupByTeam[away.code];
2423
+ }
2424
+ const hs = toInt(homeC?.score);
2425
+ const as = toInt(awayC?.score);
2426
+ const hasScore = status !== "SCHEDULED" && hs !== void 0 && as !== void 0;
2427
+ return {
2428
+ id: ev.id,
2429
+ stage,
2430
+ group,
2431
+ kickoff: ev.date,
2432
+ venue: comp?.venue?.fullName ?? "",
2433
+ home,
2434
+ away,
2435
+ score: hasScore ? { home: hs, away: as } : void 0,
2436
+ minute: parseMinute(ev.status ?? comp?.status),
2437
+ status,
2438
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
2439
+ };
2440
+ }
2441
+ function toEspnDate(d) {
2442
+ return d.replace(/\D/g, "").slice(0, 8);
2443
+ }
2444
+ var EspnAdapter = class {
2445
+ constructor(opts = {}) {
2446
+ this.opts = opts;
2447
+ }
2448
+ opts;
2449
+ name = "espn";
2450
+ capabilities = { push: false, latencyHintSec: 45 };
2451
+ /** Cached team-code -> group-letter map (built lazily from standings). */
2452
+ groupMap;
2453
+ async fetchByDate(dateISO) {
2454
+ return this.fetchScoreboard(toEspnDate(dateISO));
2455
+ }
2456
+ async fetchWindow(startDate, endDate) {
2457
+ return this.fetchScoreboard(`${toEspnDate(startDate)}-${toEspnDate(endDate)}`);
2458
+ }
2459
+ async fetchLive() {
2460
+ const today = await this.fetchScoreboard();
2461
+ return today.filter((m) => m.status === "LIVE" || m.status === "HT");
2462
+ }
2463
+ /**
2464
+ * Build (and cache) a team-code -> group-letter map from the standings
2465
+ * endpoint. Best-effort: returns {} if standings are unavailable.
2466
+ */
2467
+ async fetchGroupMap(force = false) {
2468
+ if (this.groupMap && !force) return this.groupMap;
2469
+ const base = this.opts.baseUrl ?? DEFAULT_BASE;
2470
+ const standingsUrl = `${base.replace("/apis/site/v2/", "/apis/v2/")}/standings`;
2471
+ const map = {};
2472
+ try {
2473
+ const data = await this.get(standingsUrl);
2474
+ for (const child of data.children ?? []) {
2475
+ const letter = (child.name ?? child.abbreviation ?? "").match(/Group\s+([A-L])/i)?.[1]?.toUpperCase();
2476
+ if (!letter) continue;
2477
+ for (const e of child.standings?.entries ?? []) {
2478
+ const code = e.team?.abbreviation?.toUpperCase();
2479
+ if (code) map[code] = letter;
2480
+ }
2481
+ }
2482
+ } catch {
2483
+ }
2484
+ this.groupMap = map;
2485
+ return map;
2486
+ }
2487
+ async fetchScoreboard(dates) {
2488
+ const base = this.opts.baseUrl ?? DEFAULT_BASE;
2489
+ const url = new URL(`${base}/scoreboard`);
2490
+ url.searchParams.set("limit", "300");
2491
+ if (dates) url.searchParams.set("dates", dates);
2492
+ const groupByTeam = this.opts.enrichGroups === false ? {} : await this.fetchGroupMap();
2493
+ const data = await this.get(url.toString());
2494
+ return (data.events ?? []).map((ev) => mapEspnEvent(ev, { groupByTeam }));
2495
+ }
2496
+ async get(url) {
2497
+ const doFetch = this.opts.fetchImpl ?? fetch;
2498
+ const controller = new AbortController();
2499
+ const timer = setTimeout(
2500
+ () => controller.abort(),
2501
+ this.opts.timeoutMs ?? 15e3
2502
+ );
2503
+ try {
2504
+ const res = await doFetch(url, {
2505
+ signal: controller.signal,
2506
+ headers: { Accept: "application/json", "User-Agent": USER_AGENT }
2507
+ });
2508
+ if (!res.ok) {
2509
+ throw new Error(`ESPN request failed: ${res.status} ${res.statusText}`);
2510
+ }
2511
+ return await res.json();
2512
+ } finally {
2513
+ clearTimeout(timer);
2514
+ }
2515
+ }
2516
+ };
2517
+ function resolveCompetition(explicit) {
2518
+ if (explicit) return explicit;
2519
+ if (typeof process !== "undefined" && process.env?.CLAUDINHO_COMPETITION) {
2520
+ return process.env.CLAUDINHO_COMPETITION;
2521
+ }
2522
+ return DEFAULT_COMPETITION;
2523
+ }
2524
+ function makeAdapter(source = "espn") {
2525
+ switch (source) {
2526
+ case "espn":
2527
+ default: {
2528
+ const competition = resolveCompetition();
2529
+ const baseUrl = competition === DEFAULT_COMPETITION ? void 0 : competitionBase(competition);
2530
+ return new EspnAdapter({ baseUrl });
2531
+ }
2532
+ }
2533
+ }
2534
+ function mergeLive(base, live) {
2535
+ const byId = new Map(base.map((m) => [m.id, m]));
2536
+ for (const m of live) byId.set(m.id, m);
2537
+ return [...byId.values()];
2538
+ }
2539
+ async function getMatchesForDate(adapter, dateISO) {
2540
+ const base = allFixtures();
2541
+ try {
2542
+ const live = await adapter.fetchByDate(dateISO);
2543
+ return { matches: mergeLive(base, live), degraded: false };
2544
+ } catch {
2545
+ return { matches: base, degraded: true };
2546
+ }
2547
+ }
2548
+ async function getLiveMatches(adapter) {
2549
+ try {
2550
+ return { matches: await adapter.fetchLive(), degraded: false };
2551
+ } catch {
2552
+ return { matches: [], degraded: true };
2553
+ }
2554
+ }
2555
+
2556
+ // src/format.ts
2557
+ var STATUS_LABEL = {
2558
+ SCHEDULED: "scheduled",
2559
+ LIVE: "live",
2560
+ HT: "half-time",
2561
+ FT: "full-time",
2562
+ POSTPONED: "postponed",
2563
+ CANCELLED: "cancelled"
2564
+ };
2565
+ function stageName(stage) {
2566
+ switch (stage) {
2567
+ case "GROUP":
2568
+ return "Group stage";
2569
+ case "R32":
2570
+ return "Round of 32";
2571
+ case "R16":
2572
+ return "Round of 16";
2573
+ case "QF":
2574
+ return "Quarter-final";
2575
+ case "SF":
2576
+ return "Semi-final";
2577
+ case "3P":
2578
+ return "Third-place play-off";
2579
+ case "F":
2580
+ return "Final";
2581
+ case "FRIENDLY":
2582
+ return "Friendly";
2583
+ }
2584
+ }
2585
+ function matchLine(m, opts = {}) {
2586
+ const head = `${m.home.flag} ${m.home.name} ${scoreline(m)} ${m.away.name} ${m.away.flag}`;
2587
+ const stage = m.group ? `Group ${m.group}` : stageName(m.stage);
2588
+ let tail;
2589
+ if (m.status === "SCHEDULED") {
2590
+ tail = `${formatKickoff(m.kickoff, opts)} (in ${countdown(m.kickoff)})`;
2591
+ } else if (m.status === "LIVE") {
2592
+ tail = m.minute ? `LIVE ${m.minute}'` : "LIVE";
2593
+ } else {
2594
+ tail = STATUS_LABEL[m.status];
2595
+ }
2596
+ return `${head} \u2014 ${tail} \xB7 ${stage} \xB7 ${m.venue}`.trimEnd();
2597
+ }
2598
+ function matchList(matches, empty, opts = {}) {
2599
+ if (matches.length === 0) return empty;
2600
+ return matches.map((m) => `\u2022 ${matchLine(m, opts)}`).join("\n");
2601
+ }
2602
+ function standingsTable(group, rows) {
2603
+ const header = `Group ${group}`;
2604
+ const cols = "Team P W D L GD Pts";
2605
+ const lines = rows.map((r) => {
2606
+ const name = `${r.team.flag} ${r.team.name}`.padEnd(24).slice(0, 24);
2607
+ const gd = (r.goalDiff > 0 ? `+${r.goalDiff}` : `${r.goalDiff}`).padStart(3);
2608
+ return `${name} ${pad(r.played)} ${pad(r.won)} ${pad(r.drawn)} ${pad(r.lost)} ${gd} ${pad(r.points)}`;
2609
+ });
2610
+ return [header, cols, ...lines].join("\n");
2611
+ }
2612
+ function pad(n) {
2613
+ return `${n}`.padStart(2);
2614
+ }
2615
+ var DISCLAIMER = "Claudinho is an independent fan project \u2014 not affiliated with or endorsed by FIFA or Anthropic. Data: ESPN.";
2616
+
2617
+ // src/tools.ts
2618
+ function resolveAdapter(args) {
2619
+ return args.adapter ?? makeAdapter(args.source);
2620
+ }
2621
+ function withDisclaimer(text) {
2622
+ return `${text}
2623
+
2624
+ ${DISCLAIMER}`;
2625
+ }
2626
+ async function toolGetToday(args) {
2627
+ const adapter = resolveAdapter(args);
2628
+ const date = args.date ?? localDate((/* @__PURE__ */ new Date()).toISOString(), args.tz);
2629
+ const { matches, degraded } = await getMatchesForDate(adapter, date);
2630
+ const todays = fixturesByDate(date, matches);
2631
+ const opts = { tz: args.tz, locale: args.lang };
2632
+ const text = `Matches on ${date}:
2633
+ ${matchList(todays, "No matches scheduled.", opts)}`;
2634
+ return {
2635
+ text: withDisclaimer(text),
2636
+ data: { date, degraded, count: todays.length, matches: todays }
2637
+ };
2638
+ }
2639
+ async function toolGetLive(args = {}) {
2640
+ const adapter = resolveAdapter(args);
2641
+ const { matches, degraded } = await getLiveMatches(adapter);
2642
+ const opts = { tz: args.tz, locale: args.lang };
2643
+ const text = `Live now:
2644
+ ${matchList(matches, "No matches in play right now.", opts)}`;
2645
+ return {
2646
+ text: withDisclaimer(text),
2647
+ data: { degraded, count: matches.length, matches }
2648
+ };
2649
+ }
2650
+ async function toolGetMatch(args) {
2651
+ let match = allFixtures().find((m) => m.id === args.id);
2652
+ let degraded = false;
2653
+ if (match) {
2654
+ try {
2655
+ const adapter = resolveAdapter(args);
2656
+ const live = await adapter.fetchByDate(match.kickoff.slice(0, 10));
2657
+ match = live.find((m) => m.id === args.id) ?? match;
2658
+ } catch {
2659
+ degraded = true;
2660
+ }
2661
+ }
2662
+ if (!match) {
2663
+ return { text: withDisclaimer(`No match found with id ${args.id}.`), data: { match: null } };
2664
+ }
2665
+ const opts = { tz: args.tz, locale: args.lang };
2666
+ return { text: withDisclaimer(matchLine(match, opts)), data: { degraded, match } };
2667
+ }
2668
+ async function toolGetStandings(args) {
2669
+ let matches = allFixtures();
2670
+ let degraded = false;
2671
+ try {
2672
+ const adapter = resolveAdapter(args);
2673
+ const live = await adapter.fetchByDate(localDate((/* @__PURE__ */ new Date()).toISOString(), args.tz));
2674
+ const byId = new Map(matches.map((m) => [m.id, m]));
2675
+ for (const m of live) byId.set(m.id, m);
2676
+ matches = [...byId.values()];
2677
+ } catch {
2678
+ degraded = true;
2679
+ }
2680
+ const known = groups(matches);
2681
+ if (args.group) {
2682
+ const g = args.group.toUpperCase();
2683
+ if (!known.includes(g)) {
2684
+ return {
2685
+ text: withDisclaimer(
2686
+ `No group "${g}". Groups are ${known.join(", ")}.`
2687
+ ),
2688
+ data: { degraded, tables: null }
2689
+ };
2690
+ }
2691
+ }
2692
+ const wanted = args.group ? [args.group.toUpperCase()] : known;
2693
+ const tables = wanted.map((g) => ({
2694
+ group: g,
2695
+ standings: computeStandings(fixturesByGroup(g, matches))
2696
+ }));
2697
+ const text = tables.map((t) => standingsTable(t.group, t.standings)).join("\n\n");
2698
+ return {
2699
+ text: withDisclaimer(text || `No group found.`),
2700
+ data: { degraded, tables: args.group ? tables[0] ?? null : tables }
2701
+ };
2702
+ }
2703
+ async function toolGetNextFixture(args) {
2704
+ const code = args.team.toUpperCase();
2705
+ const fixture = nextFixtureForTeam(code);
2706
+ if (!fixture) {
2707
+ return {
2708
+ text: withDisclaimer(`No upcoming fixture found for ${code}.`),
2709
+ data: { team: code, fixture: null }
2710
+ };
2711
+ }
2712
+ const opts = { tz: args.tz, locale: args.lang };
2713
+ return {
2714
+ text: withDisclaimer(`Next up for ${code}:
2715
+ ${matchLine(fixture, opts)}`),
2716
+ data: { team: code, fixture }
2717
+ };
2718
+ }
2719
+
2720
+ // src/server.ts
2721
+ var SERVER_NAME = "claudinho";
2722
+ var SERVER_VERSION = "0.1.0";
2723
+ var INSTRUCTIONS = `Claudinho serves live scores, fixtures, and group standings for the 2026 men's football tournament.
2724
+ Use get_live during matches, get_today for a day's schedule, get_next_fixture for a specific team (3-letter code, e.g. MEX), and get_standings for group tables.
2725
+ ${DISCLAIMER}`;
2726
+ var commonArgs = {
2727
+ tz: z.string().optional().describe("IANA timezone for kickoff times, e.g. America/Mexico_City"),
2728
+ lang: z.string().optional().describe("Locale for formatting, e.g. en, es, pt, fr")
2729
+ };
2730
+ function toContent(r) {
2731
+ return {
2732
+ content: [
2733
+ { type: "text", text: r.text },
2734
+ { type: "text", text: "```json\n" + JSON.stringify(r.data, null, 2) + "\n```" }
2735
+ ]
2736
+ };
2737
+ }
2738
+ function buildServer() {
2739
+ const server = new McpServer(
2740
+ { name: SERVER_NAME, version: SERVER_VERSION },
2741
+ { instructions: INSTRUCTIONS }
2742
+ );
2743
+ server.registerTool(
2744
+ "get_today",
2745
+ {
2746
+ title: "Today's matches",
2747
+ description: "Fixtures for a given date (default: today), with live scores overlaid.",
2748
+ inputSchema: {
2749
+ date: z.string().optional().describe("Date as YYYY-MM-DD (default: today)"),
2750
+ ...commonArgs
2751
+ },
2752
+ // Read-only; reaches an external data source (ESPN) for live overlay.
2753
+ annotations: { readOnlyHint: true, openWorldHint: true }
2754
+ },
2755
+ async (args) => toContent(await toolGetToday(args))
2756
+ );
2757
+ server.registerTool(
2758
+ "get_live",
2759
+ {
2760
+ title: "Live matches",
2761
+ description: "Matches currently in play, with score and minute.",
2762
+ inputSchema: { ...commonArgs },
2763
+ annotations: { readOnlyHint: true, openWorldHint: true }
2764
+ },
2765
+ async (args) => toContent(await toolGetLive(args))
2766
+ );
2767
+ server.registerTool(
2768
+ "get_match",
2769
+ {
2770
+ title: "Match detail",
2771
+ description: "A single match by its id, with live state if available.",
2772
+ inputSchema: { id: z.string().describe("Match id"), ...commonArgs },
2773
+ annotations: { readOnlyHint: true, openWorldHint: true }
2774
+ },
2775
+ async (args) => toContent(await toolGetMatch(args))
2776
+ );
2777
+ server.registerTool(
2778
+ "get_standings",
2779
+ {
2780
+ title: "Group standings",
2781
+ description: "Group table(s). Pass a group letter A\u2013L, or omit for all groups.",
2782
+ inputSchema: {
2783
+ group: z.string().optional().describe("Group letter A\u2013L (omit for all)"),
2784
+ ...commonArgs
2785
+ },
2786
+ annotations: { readOnlyHint: true, openWorldHint: true }
2787
+ },
2788
+ async (args) => toContent(await toolGetStandings(args))
2789
+ );
2790
+ server.registerTool(
2791
+ "get_next_fixture",
2792
+ {
2793
+ title: "Next fixture for a team",
2794
+ description: "A team's next scheduled match. Use a 3-letter code, e.g. MEX, BRA, USA.",
2795
+ inputSchema: { team: z.string().describe("3-letter team code, e.g. MEX"), ...commonArgs },
2796
+ // Read-only and served entirely from the bundled static schedule.
2797
+ annotations: { readOnlyHint: true, openWorldHint: false }
2798
+ },
2799
+ async (args) => toContent(await toolGetNextFixture(args))
2800
+ );
2801
+ server.registerResource(
2802
+ "standings",
2803
+ new ResourceTemplate("standings://{group}", { list: void 0 }),
2804
+ {
2805
+ title: "Group standings",
2806
+ description: "Static group table for a group letter A\u2013L.",
2807
+ mimeType: "text/plain"
2808
+ },
2809
+ async (uri, variables) => {
2810
+ const group = String(variables.group ?? "").toUpperCase();
2811
+ const rows = computeStandings(fixturesByGroup(group));
2812
+ const text = rows.length ? standingsTable(group, rows) : `No group ${group}.`;
2813
+ return { contents: [{ uri: uri.href, mimeType: "text/plain", text }] };
2814
+ }
2815
+ );
2816
+ server.registerResource(
2817
+ "fixtures",
2818
+ new ResourceTemplate("fixtures://{date}", { list: void 0 }),
2819
+ {
2820
+ title: "Fixtures by date",
2821
+ description: "Static fixture list for a date (YYYY-MM-DD).",
2822
+ mimeType: "text/plain"
2823
+ },
2824
+ async (uri, variables) => {
2825
+ const date = String(variables.date ?? "");
2826
+ const text = matchList(fixturesByDate(date), `No matches on ${date}.`);
2827
+ return { contents: [{ uri: uri.href, mimeType: "text/plain", text }] };
2828
+ }
2829
+ );
2830
+ server.registerPrompt(
2831
+ "tournament_today",
2832
+ {
2833
+ title: "Today's tournament summary",
2834
+ description: "Summarize today's matches and what to watch."
2835
+ },
2836
+ () => ({
2837
+ messages: [
2838
+ {
2839
+ role: "user",
2840
+ content: {
2841
+ type: "text",
2842
+ text: "Use the get_today and get_live tools to summarize today's football matches in the 2026 tournament. Highlight any matches in play, then list the rest with kickoff times in my timezone."
2843
+ }
2844
+ }
2845
+ ]
2846
+ })
2847
+ );
2848
+ server.registerPrompt(
2849
+ "my_team",
2850
+ {
2851
+ title: "My team",
2852
+ description: "Focus on one team's next match and group situation.",
2853
+ argsSchema: { team: z.string().describe("3-letter team code, e.g. MEX") }
2854
+ },
2855
+ ({ team }) => ({
2856
+ messages: [
2857
+ {
2858
+ role: "user",
2859
+ content: {
2860
+ type: "text",
2861
+ text: `Using get_next_fixture and get_standings, tell me about ${team}'s next match in the 2026 tournament and their current group standing.`
2862
+ }
2863
+ }
2864
+ ]
2865
+ })
2866
+ );
2867
+ return server;
2868
+ }
2869
+
2870
+ // src/index.ts
2871
+ async function main() {
2872
+ const server = buildServer();
2873
+ const transport = new StdioServerTransport();
2874
+ await server.connect(transport);
2875
+ process.stderr.write("claudinho-mcp: ready (stdio)\n");
2876
+ }
2877
+ main().catch((err) => {
2878
+ process.stderr.write(`claudinho-mcp: fatal: ${err.message}
2879
+ `);
2880
+ process.exit(1);
2881
+ });