@cyanheads/gdelt-mcp-server 0.1.1

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 (80) hide show
  1. package/CLAUDE.md +405 -0
  2. package/Dockerfile +98 -0
  3. package/README.md +336 -0
  4. package/changelog/0.1.x/0.1.0.md +23 -0
  5. package/changelog/0.1.x/0.1.1.md +18 -0
  6. package/changelog/template.md +119 -0
  7. package/dist/config/server-config.d.ts +13 -0
  8. package/dist/config/server-config.d.ts.map +1 -0
  9. package/dist/config/server-config.js +28 -0
  10. package/dist/config/server-config.js.map +1 -0
  11. package/dist/index.d.ts +7 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +44 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/mcp-server/tools/date-resolution.d.ts +7 -0
  16. package/dist/mcp-server/tools/date-resolution.d.ts.map +1 -0
  17. package/dist/mcp-server/tools/date-resolution.js +13 -0
  18. package/dist/mcp-server/tools/date-resolution.js.map +1 -0
  19. package/dist/mcp-server/tools/definitions/get-coverage-breakdown.tool.d.ts +52 -0
  20. package/dist/mcp-server/tools/definitions/get-coverage-breakdown.tool.d.ts.map +1 -0
  21. package/dist/mcp-server/tools/definitions/get-coverage-breakdown.tool.js +182 -0
  22. package/dist/mcp-server/tools/definitions/get-coverage-breakdown.tool.js.map +1 -0
  23. package/dist/mcp-server/tools/definitions/get-coverage-timeline.tool.d.ts +54 -0
  24. package/dist/mcp-server/tools/definitions/get-coverage-timeline.tool.d.ts.map +1 -0
  25. package/dist/mcp-server/tools/definitions/get-coverage-timeline.tool.js +173 -0
  26. package/dist/mcp-server/tools/definitions/get-coverage-timeline.tool.js.map +1 -0
  27. package/dist/mcp-server/tools/definitions/get-tone-distribution.tool.d.ts +41 -0
  28. package/dist/mcp-server/tools/definitions/get-tone-distribution.tool.d.ts.map +1 -0
  29. package/dist/mcp-server/tools/definitions/get-tone-distribution.tool.js +143 -0
  30. package/dist/mcp-server/tools/definitions/get-tone-distribution.tool.js.map +1 -0
  31. package/dist/mcp-server/tools/definitions/get-tv-clips.tool.d.ts +44 -0
  32. package/dist/mcp-server/tools/definitions/get-tv-clips.tool.d.ts.map +1 -0
  33. package/dist/mcp-server/tools/definitions/get-tv-clips.tool.js +134 -0
  34. package/dist/mcp-server/tools/definitions/get-tv-clips.tool.js.map +1 -0
  35. package/dist/mcp-server/tools/definitions/get-tv-context.tool.d.ts +32 -0
  36. package/dist/mcp-server/tools/definitions/get-tv-context.tool.d.ts.map +1 -0
  37. package/dist/mcp-server/tools/definitions/get-tv-context.tool.js +114 -0
  38. package/dist/mcp-server/tools/definitions/get-tv-context.tool.js.map +1 -0
  39. package/dist/mcp-server/tools/definitions/get-tv-trending.tool.d.ts +27 -0
  40. package/dist/mcp-server/tools/definitions/get-tv-trending.tool.d.ts.map +1 -0
  41. package/dist/mcp-server/tools/definitions/get-tv-trending.tool.js +82 -0
  42. package/dist/mcp-server/tools/definitions/get-tv-trending.tool.js.map +1 -0
  43. package/dist/mcp-server/tools/definitions/index.d.ts +14 -0
  44. package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -0
  45. package/dist/mcp-server/tools/definitions/index.js +14 -0
  46. package/dist/mcp-server/tools/definitions/index.js.map +1 -0
  47. package/dist/mcp-server/tools/definitions/list-tv-stations.tool.d.ts +32 -0
  48. package/dist/mcp-server/tools/definitions/list-tv-stations.tool.d.ts.map +1 -0
  49. package/dist/mcp-server/tools/definitions/list-tv-stations.tool.js +94 -0
  50. package/dist/mcp-server/tools/definitions/list-tv-stations.tool.js.map +1 -0
  51. package/dist/mcp-server/tools/definitions/search-articles.tool.d.ts +45 -0
  52. package/dist/mcp-server/tools/definitions/search-articles.tool.d.ts.map +1 -0
  53. package/dist/mcp-server/tools/definitions/search-articles.tool.js +142 -0
  54. package/dist/mcp-server/tools/definitions/search-articles.tool.js.map +1 -0
  55. package/dist/mcp-server/tools/definitions/search-tv.tool.d.ts +48 -0
  56. package/dist/mcp-server/tools/definitions/search-tv.tool.d.ts.map +1 -0
  57. package/dist/mcp-server/tools/definitions/search-tv.tool.js +159 -0
  58. package/dist/mcp-server/tools/definitions/search-tv.tool.js.map +1 -0
  59. package/dist/services/gdelt/gdelt-doc-service.d.ts +89 -0
  60. package/dist/services/gdelt/gdelt-doc-service.d.ts.map +1 -0
  61. package/dist/services/gdelt/gdelt-doc-service.js +116 -0
  62. package/dist/services/gdelt/gdelt-doc-service.js.map +1 -0
  63. package/dist/services/gdelt/gdelt-fetch.d.ts +11 -0
  64. package/dist/services/gdelt/gdelt-fetch.d.ts.map +1 -0
  65. package/dist/services/gdelt/gdelt-fetch.js +46 -0
  66. package/dist/services/gdelt/gdelt-fetch.js.map +1 -0
  67. package/dist/services/gdelt/gdelt-tv-service.d.ts +78 -0
  68. package/dist/services/gdelt/gdelt-tv-service.d.ts.map +1 -0
  69. package/dist/services/gdelt/gdelt-tv-service.js +153 -0
  70. package/dist/services/gdelt/gdelt-tv-service.js.map +1 -0
  71. package/dist/services/gdelt/rate-limiter.d.ts +19 -0
  72. package/dist/services/gdelt/rate-limiter.d.ts.map +1 -0
  73. package/dist/services/gdelt/rate-limiter.js +47 -0
  74. package/dist/services/gdelt/rate-limiter.js.map +1 -0
  75. package/dist/services/gdelt/types.d.ts +87 -0
  76. package/dist/services/gdelt/types.d.ts.map +1 -0
  77. package/dist/services/gdelt/types.js +6 -0
  78. package/dist/services/gdelt/types.js.map +1 -0
  79. package/package.json +80 -0
  80. package/server.json +99 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @fileoverview Barrel export for all GDELT MCP tool definitions.
3
+ * @module mcp-server/tools/definitions/index
4
+ */
5
+ export { gdeltGetCoverageBreakdown } from './get-coverage-breakdown.tool.js';
6
+ export { gdeltGetCoverageTimeline } from './get-coverage-timeline.tool.js';
7
+ export { gdeltGetToneDistribution } from './get-tone-distribution.tool.js';
8
+ export { gdeltGetTvClips } from './get-tv-clips.tool.js';
9
+ export { gdeltGetTvContext } from './get-tv-context.tool.js';
10
+ export { gdeltGetTvTrending } from './get-tv-trending.tool.js';
11
+ export { gdeltListTvStations } from './list-tv-stations.tool.js';
12
+ export { gdeltSearchArticles } from './search-articles.tool.js';
13
+ export { gdeltSearchTv } from './search-tv.tool.js';
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @fileoverview GDELT TV station listing tool. Lists all television stations available
3
+ * for TV search with monitoring date ranges and active status.
4
+ * @module mcp-server/tools/definitions/list-tv-stations.tool
5
+ */
6
+ import { z } from '@cyanheads/mcp-ts-core';
7
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
8
+ export declare const gdeltListTvStations: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{}, z.core.$strip>, z.ZodObject<{
9
+ stations: z.ZodArray<z.ZodObject<{
10
+ stationId: z.ZodString;
11
+ description: z.ZodString;
12
+ market: z.ZodString;
13
+ network: z.ZodString;
14
+ startDate: z.ZodString;
15
+ endDate: z.ZodString;
16
+ isActive: z.ZodBoolean;
17
+ }, z.core.$strip>>;
18
+ activeCount: z.ZodNumber;
19
+ totalCount: z.ZodNumber;
20
+ }, z.core.$strip>, readonly [{
21
+ readonly reason: "no_stations";
22
+ readonly code: JsonRpcErrorCode.NotFound;
23
+ readonly when: "The station list returned empty — API may be temporarily unavailable.";
24
+ readonly recovery: "Retry after a short delay; the station list is static and should always return data.";
25
+ }, {
26
+ readonly reason: "gdelt_unavailable";
27
+ readonly code: JsonRpcErrorCode.ServiceUnavailable;
28
+ readonly when: "GDELT TV API is unreachable or rate-limited.";
29
+ readonly retryable: true;
30
+ readonly recovery: "Wait at least 5 seconds before retrying — GDELT enforces 1 request per 5 seconds.";
31
+ }]>;
32
+ //# sourceMappingURL=list-tv-stations.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-tv-stations.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/list-tv-stations.tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;GAyG9B,CAAC"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * @fileoverview GDELT TV station listing tool. Lists all television stations available
3
+ * for TV search with monitoring date ranges and active status.
4
+ * @module mcp-server/tools/definitions/list-tv-stations.tool
5
+ */
6
+ import { tool, z } from '@cyanheads/mcp-ts-core';
7
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
8
+ import { getGdeltTvService } from '../../../services/gdelt/gdelt-tv-service.js';
9
+ export const gdeltListTvStations = tool('gdelt_list_tv_stations', {
10
+ title: 'List GDELT TV Stations',
11
+ description: 'List all television stations available for TV search with their market, network, monitoring ' +
12
+ 'start date, and monitoring end date. ' +
13
+ 'Stations with an end date within the last 24 hours are flagged as active; ' +
14
+ 'stations with earlier end dates are discontinued. ' +
15
+ 'Use before querying to verify a station was active during the target time period, ' +
16
+ 'or to discover valid station IDs for the stations parameter in other TV tools. ' +
17
+ 'Most station monitoring ended October 2024 when the Internet Archive TV feed stopped updating.',
18
+ annotations: { readOnlyHint: true, openWorldHint: false },
19
+ errors: [
20
+ {
21
+ reason: 'no_stations',
22
+ code: JsonRpcErrorCode.NotFound,
23
+ when: 'The station list returned empty — API may be temporarily unavailable.',
24
+ recovery: 'Retry after a short delay; the station list is static and should always return data.',
25
+ },
26
+ {
27
+ reason: 'gdelt_unavailable',
28
+ code: JsonRpcErrorCode.ServiceUnavailable,
29
+ when: 'GDELT TV API is unreachable or rate-limited.',
30
+ retryable: true,
31
+ recovery: 'Wait at least 5 seconds before retrying — GDELT enforces 1 request per 5 seconds.',
32
+ },
33
+ ],
34
+ input: z.object({}),
35
+ output: z.object({
36
+ stations: z
37
+ .array(z
38
+ .object({
39
+ stationId: z.string().describe('Station ID used in TV query operators (e.g. "CNN").'),
40
+ description: z.string().describe('Human-readable station description.'),
41
+ market: z.string().describe('Market (e.g. "National", "San Francisco").'),
42
+ network: z.string().describe('Network affiliation (e.g. "CNN", "NBC").'),
43
+ startDate: z.string().describe('Monitoring start date in ISO 8601 format.'),
44
+ endDate: z.string().describe('Monitoring end date in ISO 8601 format.'),
45
+ isActive: z
46
+ .boolean()
47
+ .describe('True when the end date is within the last 24 hours (recently updated feed). ' +
48
+ 'False for discontinued stations.'),
49
+ })
50
+ .describe('A single TV station with monitoring metadata.'))
51
+ .describe('All TV stations sorted by station ID.'),
52
+ activeCount: z.number().describe('Number of stations currently flagged as active.'),
53
+ totalCount: z.number().describe('Total number of stations in the list.'),
54
+ }),
55
+ async handler(_input, ctx) {
56
+ ctx.log.info('gdelt_list_tv_stations');
57
+ const svc = getGdeltTvService();
58
+ const stations = await svc.listStations(ctx);
59
+ if (stations.length === 0) {
60
+ throw ctx.fail('no_stations', 'Station list returned empty', {
61
+ ...ctx.recoveryFor('no_stations'),
62
+ });
63
+ }
64
+ const sorted = stations.slice().sort((a, b) => a.stationId.localeCompare(b.stationId));
65
+ const activeCount = sorted.filter((s) => s.isActive).length;
66
+ ctx.log.info('gdelt_list_tv_stations completed', { total: sorted.length, active: activeCount });
67
+ return { stations: sorted, activeCount, totalCount: sorted.length };
68
+ },
69
+ format: (result) => {
70
+ const lines = [
71
+ `## GDELT TV Stations`,
72
+ `**Total:** ${result.totalCount} | **Active:** ${result.activeCount}`,
73
+ ];
74
+ // Group by market for readability
75
+ const national = result.stations.filter((s) => s.market === 'National');
76
+ const local = result.stations.filter((s) => s.market !== 'National');
77
+ if (national.length > 0) {
78
+ lines.push('\n### National Networks');
79
+ for (const s of national) {
80
+ const status = s.isActive ? '✓ Active' : `Ended ${s.endDate}`;
81
+ lines.push(`- **${s.stationId}** — ${s.description} | ${s.network} | ${s.startDate}–${s.endDate} | ${status}`);
82
+ }
83
+ }
84
+ if (local.length > 0) {
85
+ lines.push('\n### Local/Regional Stations');
86
+ for (const s of local) {
87
+ const status = s.isActive ? '✓ Active' : `Ended ${s.endDate}`;
88
+ lines.push(`- **${s.stationId}** — ${s.description} | Market: ${s.market} | ${s.network} | ${s.startDate}–${s.endDate} | ${status}`);
89
+ }
90
+ }
91
+ return [{ type: 'text', text: lines.join('\n') }];
92
+ },
93
+ });
94
+ //# sourceMappingURL=list-tv-stations.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-tv-stations.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/list-tv-stations.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @fileoverview GDELT article search tool. Full-text search across the last 3 months
3
+ * of global news coverage in 65+ languages using the GDELT DOC API.
4
+ * @module mcp-server/tools/definitions/search-articles.tool
5
+ */
6
+ import { z } from '@cyanheads/mcp-ts-core';
7
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
8
+ export declare const gdeltSearchArticles: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
9
+ query: z.ZodString;
10
+ timespan: z.ZodOptional<z.ZodString>;
11
+ startDatetime: z.ZodOptional<z.ZodString>;
12
+ endDatetime: z.ZodOptional<z.ZodString>;
13
+ maxRecords: z.ZodDefault<z.ZodNumber>;
14
+ sort: z.ZodDefault<z.ZodEnum<{
15
+ date: "date";
16
+ relevance: "relevance";
17
+ social: "social";
18
+ }>>;
19
+ }, z.core.$strip>, z.ZodObject<{
20
+ articles: z.ZodArray<z.ZodObject<{
21
+ url: z.ZodString;
22
+ title: z.ZodString;
23
+ seendate: z.ZodString;
24
+ domain: z.ZodString;
25
+ language: z.ZodString;
26
+ sourcecountry: z.ZodString;
27
+ socialimage: z.ZodOptional<z.ZodString>;
28
+ }, z.core.$strip>>;
29
+ totalReturned: z.ZodNumber;
30
+ query: z.ZodString;
31
+ timespan: z.ZodOptional<z.ZodString>;
32
+ notice: z.ZodOptional<z.ZodString>;
33
+ }, z.core.$strip>, readonly [{
34
+ readonly reason: "no_articles";
35
+ readonly code: JsonRpcErrorCode.NotFound;
36
+ readonly when: "No articles matched the query within the specified time range.";
37
+ readonly recovery: "Broaden the query, remove operators, extend timespan, or try synonym terms.";
38
+ }, {
39
+ readonly reason: "gdelt_unavailable";
40
+ readonly code: JsonRpcErrorCode.ServiceUnavailable;
41
+ readonly when: "GDELT DOC API is unreachable or rate-limited.";
42
+ readonly retryable: true;
43
+ readonly recovery: "Wait at least 5 seconds before retrying — GDELT enforces 1 request per 5 seconds.";
44
+ }]>;
45
+ //# sourceMappingURL=search-articles.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-articles.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/search-articles.tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6J9B,CAAC"}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * @fileoverview GDELT article search tool. Full-text search across the last 3 months
3
+ * of global news coverage in 65+ languages using the GDELT DOC API.
4
+ * @module mcp-server/tools/definitions/search-articles.tool
5
+ */
6
+ import { tool, z } from '@cyanheads/mcp-ts-core';
7
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
8
+ import { getGdeltDocService } from '../../../services/gdelt/gdelt-doc-service.js';
9
+ export const gdeltSearchArticles = tool('gdelt_search_articles', {
10
+ title: 'Search GDELT Articles',
11
+ description: 'Search the last 3 months of global news coverage (65+ languages) using the GDELT DOC API. ' +
12
+ 'Returns up to 250 articles with URL, title, source domain, language, country, publication date, and social image URL. ' +
13
+ 'Query supports full GDELT syntax: phrases ("bird flu"), boolean OR ((flu OR pandemic)), source country (sourcecountry:china), ' +
14
+ 'source language (sourcelang:spanish), domain (domain:who.int), GKG theme (theme:DISEASE_OUTBREAK), ' +
15
+ 'tone filter (tone<-5 for negative), proximity (near20:"flu virus"), and repeat (repeat3:"outbreak"). ' +
16
+ 'Note: this API covers only the most recent 3 months — use gdelt_search_tv for historical TV transcripts back to 2009.',
17
+ annotations: { readOnlyHint: true, openWorldHint: true },
18
+ errors: [
19
+ {
20
+ reason: 'no_articles',
21
+ code: JsonRpcErrorCode.NotFound,
22
+ when: 'No articles matched the query within the specified time range.',
23
+ recovery: 'Broaden the query, remove operators, extend timespan, or try synonym terms.',
24
+ },
25
+ {
26
+ reason: 'gdelt_unavailable',
27
+ code: JsonRpcErrorCode.ServiceUnavailable,
28
+ when: 'GDELT DOC API is unreachable or rate-limited.',
29
+ retryable: true,
30
+ recovery: 'Wait at least 5 seconds before retrying — GDELT enforces 1 request per 5 seconds.',
31
+ },
32
+ ],
33
+ input: z.object({
34
+ query: z
35
+ .string()
36
+ .min(1)
37
+ .describe('Search query. Supports GDELT operators: phrases ("bird flu"), boolean OR ((flu OR pandemic)), ' +
38
+ 'sourcecountry:china, sourcelang:spanish, domain:who.int, theme:DISEASE_OUTBREAK, tone<-5, ' +
39
+ 'near20:"flu virus", repeat3:"outbreak".'),
40
+ timespan: z
41
+ .string()
42
+ .optional()
43
+ .describe('Time window relative to now, e.g. "24h", "7d", "1m". Ignored when startDatetime/endDatetime are set. ' +
44
+ 'Maximum is 3 months (the full DOC API window). Defaults to the full 3-month window.'),
45
+ startDatetime: z
46
+ .string()
47
+ .optional()
48
+ .describe('Start of date range in GDELT format YYYYMMDDHHMMSS (e.g. 20240101000000). ' +
49
+ 'Must be used together with endDatetime.'),
50
+ endDatetime: z
51
+ .string()
52
+ .optional()
53
+ .describe('End of date range in GDELT format YYYYMMDDHHMMSS (e.g. 20240131235959). ' +
54
+ 'Must be used together with startDatetime.'),
55
+ maxRecords: z
56
+ .number()
57
+ .int()
58
+ .min(1)
59
+ .max(250)
60
+ .default(75)
61
+ .describe('Maximum number of articles to return (1–250).'),
62
+ sort: z
63
+ .enum(['date', 'relevance', 'social'])
64
+ .default('relevance')
65
+ .describe('Sort order: relevance (default), date (newest first), social (most socially shared).'),
66
+ }),
67
+ output: z.object({
68
+ articles: z
69
+ .array(z
70
+ .object({
71
+ url: z.string().describe('Article URL.'),
72
+ title: z.string().describe('Article title.'),
73
+ seendate: z
74
+ .string()
75
+ .describe('Publication datetime in GDELT format (YYYYMMDDTHHMMSSZ).'),
76
+ domain: z.string().describe('Source domain (e.g. "nytimes.com").'),
77
+ language: z.string().describe('Article language (e.g. "English", "Spanish").'),
78
+ sourcecountry: z
79
+ .string()
80
+ .describe('Country of the source outlet (e.g. "United States").'),
81
+ socialimage: z
82
+ .string()
83
+ .optional()
84
+ .describe('Social sharing image URL when provided by the source.'),
85
+ })
86
+ .describe('A single news article with metadata.'))
87
+ .describe('Matching articles sorted per the sort parameter.'),
88
+ totalReturned: z.number().describe('Number of articles returned in this response.'),
89
+ query: z.string().describe('Echoed query string for use in follow-up calls.'),
90
+ timespan: z.string().optional().describe('Echoed timespan parameter when provided.'),
91
+ notice: z
92
+ .string()
93
+ .optional()
94
+ .describe('Recovery hint when no articles matched — echoes filters and suggests how to broaden. Absent on successful responses.'),
95
+ }),
96
+ async handler(input, ctx) {
97
+ ctx.log.info('gdelt_search_articles', { query: input.query });
98
+ const svc = getGdeltDocService();
99
+ const result = await svc.searchArticles({
100
+ query: input.query,
101
+ ...(input.timespan && { timespan: input.timespan }),
102
+ ...(input.startDatetime && { startDatetime: input.startDatetime }),
103
+ ...(input.endDatetime && { endDatetime: input.endDatetime }),
104
+ maxRecords: input.maxRecords,
105
+ sort: input.sort,
106
+ }, ctx);
107
+ if (result.articles.length === 0) {
108
+ throw ctx.fail('no_articles', `No articles matched "${input.query}"`, {
109
+ recovery: {
110
+ hint: `No articles matched "${input.query}". Try broadening the query or extending the timespan.`,
111
+ },
112
+ });
113
+ }
114
+ ctx.log.info('gdelt_search_articles completed', { count: result.articles.length });
115
+ return {
116
+ articles: result.articles,
117
+ totalReturned: result.totalReturned,
118
+ query: input.query,
119
+ ...(input.timespan && { timespan: input.timespan }),
120
+ };
121
+ },
122
+ format: (result) => {
123
+ const lines = [
124
+ `## GDELT Article Search`,
125
+ `**Query:** ${result.query}`,
126
+ ...(result.timespan ? [`**Timespan:** ${result.timespan}`] : []),
127
+ `**Articles returned:** ${result.totalReturned}`,
128
+ ];
129
+ if (result.notice)
130
+ lines.push(`\n> ${result.notice}`);
131
+ for (const a of result.articles) {
132
+ lines.push(`\n### ${a.title}`);
133
+ lines.push(`**URL:** ${a.url}`);
134
+ lines.push(`**Source:** ${a.domain} | **Country:** ${a.sourcecountry} | **Language:** ${a.language}`);
135
+ lines.push(`**Date:** ${a.seendate}`);
136
+ if (a.socialimage)
137
+ lines.push(`**Image:** ${a.socialimage}`);
138
+ }
139
+ return [{ type: 'text', text: lines.join('\n') }];
140
+ },
141
+ });
142
+ //# sourceMappingURL=search-articles.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-articles.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/search-articles.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @fileoverview GDELT TV search tool. Searches US television news closed captions
3
+ * for spoken mentions and returns normalized per-station coverage time series.
4
+ * @module mcp-server/tools/definitions/search-tv.tool
5
+ */
6
+ import { z } from '@cyanheads/mcp-ts-core';
7
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
8
+ export declare const gdeltSearchTv: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
9
+ query: z.ZodString;
10
+ stations: z.ZodOptional<z.ZodArray<z.ZodString>>;
11
+ timespan: z.ZodOptional<z.ZodString>;
12
+ startDatetime: z.ZodOptional<z.ZodString>;
13
+ endDatetime: z.ZodOptional<z.ZodString>;
14
+ smoothing: z.ZodOptional<z.ZodNumber>;
15
+ normalize: z.ZodDefault<z.ZodBoolean>;
16
+ }, z.core.$strip>, z.ZodObject<{
17
+ query: z.ZodString;
18
+ dateResolution: z.ZodEnum<{
19
+ hour: "hour";
20
+ day: "day";
21
+ month: "month";
22
+ }>;
23
+ timeRange: z.ZodObject<{
24
+ start: z.ZodString;
25
+ end: z.ZodString;
26
+ }, z.core.$strip>;
27
+ series: z.ZodArray<z.ZodObject<{
28
+ station: z.ZodString;
29
+ data: z.ZodArray<z.ZodObject<{
30
+ date: z.ZodString;
31
+ value: z.ZodNumber;
32
+ }, z.core.$strip>>;
33
+ }, z.core.$strip>>;
34
+ normalized: z.ZodBoolean;
35
+ notice: z.ZodOptional<z.ZodString>;
36
+ }, z.core.$strip>, readonly [{
37
+ readonly reason: "no_tv_coverage";
38
+ readonly code: JsonRpcErrorCode.NotFound;
39
+ readonly when: "No TV coverage found for the query in the specified time range.";
40
+ readonly recovery: string;
41
+ }, {
42
+ readonly reason: "gdelt_unavailable";
43
+ readonly code: JsonRpcErrorCode.ServiceUnavailable;
44
+ readonly when: "GDELT TV API is unreachable or rate-limited.";
45
+ readonly retryable: true;
46
+ readonly recovery: "Wait at least 5 seconds before retrying — GDELT enforces 1 request per 5 seconds.";
47
+ }]>;
48
+ //# sourceMappingURL=search-tv.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-tv.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/search-tv.tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgLxB,CAAC"}
@@ -0,0 +1,159 @@
1
+ /**
2
+ * @fileoverview GDELT TV search tool. Searches US television news closed captions
3
+ * for spoken mentions and returns normalized per-station coverage time series.
4
+ * @module mcp-server/tools/definitions/search-tv.tool
5
+ */
6
+ import { tool, z } from '@cyanheads/mcp-ts-core';
7
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
8
+ import { getGdeltTvService } from '../../../services/gdelt/gdelt-tv-service.js';
9
+ export const gdeltSearchTv = tool('gdelt_search_tv', {
10
+ title: 'Search GDELT TV News',
11
+ description: 'Search US television news closed captions (2009–October 2024, 150+ stations) for spoken mentions ' +
12
+ 'of a query. Returns a normalized per-station time series showing relative airtime devoted to the topic. ' +
13
+ 'Use the stations parameter to compare specific networks (e.g. ["CNN", "FOXNEWS", "MSNBC"]); ' +
14
+ 'omit to get combined national coverage. ' +
15
+ 'TV query also supports in-query operators: station:CNN, network:CBS, market:"National", ' +
16
+ 'show:"Anderson Cooper 360", context:"vaccine". ' +
17
+ 'Important: most station monitoring ended October 2024 — use gdelt_list_tv_stations to verify ' +
18
+ 'active date ranges before querying recent events.',
19
+ annotations: { readOnlyHint: true, openWorldHint: true },
20
+ errors: [
21
+ {
22
+ reason: 'no_tv_coverage',
23
+ code: JsonRpcErrorCode.NotFound,
24
+ when: 'No TV coverage found for the query in the specified time range.',
25
+ recovery: 'Check that the stations were active during the time range using gdelt_list_tv_stations, ' +
26
+ 'broaden the query, or extend the timespan.',
27
+ },
28
+ {
29
+ reason: 'gdelt_unavailable',
30
+ code: JsonRpcErrorCode.ServiceUnavailable,
31
+ when: 'GDELT TV API is unreachable or rate-limited.',
32
+ retryable: true,
33
+ recovery: 'Wait at least 5 seconds before retrying — GDELT enforces 1 request per 5 seconds.',
34
+ },
35
+ ],
36
+ input: z.object({
37
+ query: z
38
+ .string()
39
+ .min(1)
40
+ .describe('Search query for TV transcript content. Supports TV operators: ' +
41
+ 'station:CNN, network:CBS, market:"National", show:"Anderson Cooper", context:"vaccine". ' +
42
+ 'Boolean OR and phrase operators also work.'),
43
+ stations: z
44
+ .array(z.string())
45
+ .optional()
46
+ .describe('Station IDs to filter to (e.g. ["CNN", "FOXNEWS", "MSNBC"]). ' +
47
+ 'Omit to get coverage across all available stations. ' +
48
+ 'Use gdelt_list_tv_stations to see valid station IDs.'),
49
+ timespan: z
50
+ .string()
51
+ .optional()
52
+ .describe('Time window, e.g. "1m", "6m", "1y". ' +
53
+ 'Ignored when startDatetime/endDatetime are set. ' +
54
+ 'TV data spans 2009–October 2024.'),
55
+ startDatetime: z
56
+ .string()
57
+ .optional()
58
+ .describe('Start datetime in GDELT format YYYYMMDDHHMMSS. Must pair with endDatetime.'),
59
+ endDatetime: z
60
+ .string()
61
+ .optional()
62
+ .describe('End datetime in GDELT format YYYYMMDDHHMMSS. Must pair with startDatetime.'),
63
+ smoothing: z
64
+ .number()
65
+ .int()
66
+ .min(0)
67
+ .max(5)
68
+ .optional()
69
+ .describe('Smoothing window in timesteps (0 = none). Reduces noise for sporadic topics.'),
70
+ normalize: z
71
+ .boolean()
72
+ .default(true)
73
+ .describe('When true (default), values are normalized as % of total airtime, enabling cross-station comparison. ' +
74
+ 'When false, returns raw coverage volume.'),
75
+ }),
76
+ output: z.object({
77
+ query: z.string().describe('Echoed query string.'),
78
+ dateResolution: z
79
+ .enum(['hour', 'day', 'month'])
80
+ .describe('Temporal resolution of data points.'),
81
+ timeRange: z
82
+ .object({
83
+ start: z.string().describe('Earliest date in the returned data.'),
84
+ end: z.string().describe('Latest date in the returned data.'),
85
+ })
86
+ .describe('Date range spanned by the returned data.'),
87
+ series: z
88
+ .array(z
89
+ .object({
90
+ station: z.string().describe('Station ID (e.g. "CNN").'),
91
+ data: z
92
+ .array(z
93
+ .object({
94
+ date: z.string().describe('Timestep in ISO 8601 format.'),
95
+ value: z.number().describe('Coverage value (normalized % or raw count).'),
96
+ })
97
+ .describe('A single coverage data point.'))
98
+ .describe('Time-ordered coverage data for this station.'),
99
+ })
100
+ .describe('Coverage time series for a single station.'))
101
+ .describe('One series per station or combined national coverage.'),
102
+ normalized: z.boolean().describe('True when values are normalized coverage percentages.'),
103
+ notice: z
104
+ .string()
105
+ .optional()
106
+ .describe('Recovery hint when no coverage was found. Absent on successful responses.'),
107
+ }),
108
+ async handler(input, ctx) {
109
+ ctx.log.info('gdelt_search_tv', { query: input.query, stations: input.stations });
110
+ const svc = getGdeltTvService();
111
+ const result = await svc.searchTv({
112
+ query: input.query,
113
+ ...(input.stations?.length && { stations: input.stations }),
114
+ ...(input.timespan && { timespan: input.timespan }),
115
+ ...(input.startDatetime && { startDatetime: input.startDatetime }),
116
+ ...(input.endDatetime && { endDatetime: input.endDatetime }),
117
+ ...(input.smoothing != null && { smoothing: input.smoothing }),
118
+ normalize: input.normalize,
119
+ }, ctx);
120
+ if (result.series.length === 0 || result.series.every((s) => s.data.length === 0)) {
121
+ throw ctx.fail('no_tv_coverage', `No TV coverage found for "${input.query}"`, {
122
+ recovery: {
123
+ hint: `No TV coverage for "${input.query}". Most TV data ends October 2024 — ` +
124
+ `use gdelt_list_tv_stations to check station active dates.`,
125
+ },
126
+ });
127
+ }
128
+ ctx.log.info('gdelt_search_tv completed', { seriesCount: result.series.length });
129
+ return {
130
+ query: input.query,
131
+ dateResolution: result.dateResolution,
132
+ timeRange: result.timeRange,
133
+ series: result.series,
134
+ normalized: result.normalized,
135
+ };
136
+ },
137
+ format: (result) => {
138
+ const lines = [
139
+ `## GDELT TV News Coverage`,
140
+ `**Query:** ${result.query}`,
141
+ `**Date Resolution:** ${result.dateResolution}`,
142
+ `**Time Range:** ${result.timeRange.start} to ${result.timeRange.end}`,
143
+ `**Normalized:** ${result.normalized ? 'Yes (% of airtime)' : 'No (raw count)'}`,
144
+ `**Stations:** ${result.series.length}`,
145
+ ];
146
+ if (result.notice)
147
+ lines.push(`\n> ${result.notice}`);
148
+ for (const s of result.series) {
149
+ const peak = s.data.reduce((max, d) => (d.value > max.value ? d : max), s.data[0] ?? { date: '', value: 0 });
150
+ const total = s.data.reduce((sum, d) => sum + d.value, 0);
151
+ lines.push(`\n### ${s.station}`);
152
+ lines.push(`Points: ${s.data.length} | Total: ${total.toFixed(2)}`);
153
+ if (peak.date)
154
+ lines.push(`Peak: ${peak.value.toFixed(3)} at ${peak.date}`);
155
+ }
156
+ return [{ type: 'text', text: lines.join('\n') }];
157
+ },
158
+ });
159
+ //# sourceMappingURL=search-tv.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-tv.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/search-tv.tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAEzE,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC,iBAAiB,EAAE;IACnD,KAAK,EAAE,sBAAsB;IAC7B,WAAW,EACT,mGAAmG;QACnG,0GAA0G;QAC1G,8FAA8F;QAC9F,0CAA0C;QAC1C,0FAA0F;QAC1F,iDAAiD;QACjD,+FAA+F;QAC/F,mDAAmD;IACrD,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;IAExD,MAAM,EAAE;QACN;YACE,MAAM,EAAE,gBAAgB;YACxB,IAAI,EAAE,gBAAgB,CAAC,QAAQ;YAC/B,IAAI,EAAE,iEAAiE;YACvE,QAAQ,EACN,0FAA0F;gBAC1F,4CAA4C;SAC/C;QACD;YACE,MAAM,EAAE,mBAAmB;YAC3B,IAAI,EAAE,gBAAgB,CAAC,kBAAkB;YACzC,IAAI,EAAE,8CAA8C;YACpD,SAAS,EAAE,IAAI;YACf,QAAQ,EAAE,mFAAmF;SAC9F;KACF;IAED,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,CACP,iEAAiE;YAC/D,0FAA0F;YAC1F,4CAA4C,CAC/C;QACH,QAAQ,EAAE,CAAC;aACR,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;aACjB,QAAQ,EAAE;aACV,QAAQ,CACP,+DAA+D;YAC7D,sDAAsD;YACtD,sDAAsD,CACzD;QACH,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,sCAAsC;YACpC,kDAAkD;YAClD,kCAAkC,CACrC;QACH,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,4EAA4E,CAAC;QACzF,WAAW,EAAE,CAAC;aACX,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,4EAA4E,CAAC;QACzF,SAAS,EAAE,CAAC;aACT,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,EAAE;aACV,QAAQ,CAAC,8EAA8E,CAAC;QAC3F,SAAS,EAAE,CAAC;aACT,OAAO,EAAE;aACT,OAAO,CAAC,IAAI,CAAC;aACb,QAAQ,CACP,uGAAuG;YACrG,0CAA0C,CAC7C;KACJ,CAAC;IAEF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QAClD,cAAc,EAAE,CAAC;aACd,IAAI,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;aAC9B,QAAQ,CAAC,qCAAqC,CAAC;QAClD,SAAS,EAAE,CAAC;aACT,MAAM,CAAC;YACN,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC;YACjE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;SAC9D,CAAC;aACD,QAAQ,CAAC,0CAA0C,CAAC;QACvD,MAAM,EAAE,CAAC;aACN,KAAK,CACJ,CAAC;aACE,MAAM,CAAC;YACN,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;YACxD,IAAI,EAAE,CAAC;iBACJ,KAAK,CACJ,CAAC;iBACE,MAAM,CAAC;gBACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;gBACzD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;aAC1E,CAAC;iBACD,QAAQ,CAAC,+BAA+B,CAAC,CAC7C;iBACA,QAAQ,CAAC,8CAA8C,CAAC;SAC5D,CAAC;aACD,QAAQ,CAAC,4CAA4C,CAAC,CAC1D;aACA,QAAQ,CAAC,uDAAuD,CAAC;QACpE,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,uDAAuD,CAAC;QACzF,MAAM,EAAE,CAAC;aACN,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,2EAA2E,CAAC;KACzF,CAAC;IAEF,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG;QACtB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QAClF,MAAM,GAAG,GAAG,iBAAiB,EAAE,CAAC;QAEhC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAC/B;YACE,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC3D,GAAG,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;YACnD,GAAG,CAAC,KAAK,CAAC,aAAa,IAAI,EAAE,aAAa,EAAE,KAAK,CAAC,aAAa,EAAE,CAAC;YAClE,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC;YAC5D,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,IAAI,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC;YAC9D,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B,EACD,GAAG,CACJ,CAAC;QAEF,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;YAClF,MAAM,GAAG,CAAC,IAAI,CAAC,gBAAgB,EAAE,6BAA6B,KAAK,CAAC,KAAK,GAAG,EAAE;gBAC5E,QAAQ,EAAE;oBACR,IAAI,EACF,uBAAuB,KAAK,CAAC,KAAK,sCAAsC;wBACxE,2DAA2D;iBAC9D;aACF,CAAC,CAAC;QACL,CAAC;QAED,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,2BAA2B,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACjF,OAAO;YACL,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;QACjB,MAAM,KAAK,GAAa;YACtB,2BAA2B;YAC3B,cAAc,MAAM,CAAC,KAAK,EAAE;YAC5B,wBAAwB,MAAM,CAAC,cAAc,EAAE;YAC/C,mBAAmB,MAAM,CAAC,SAAS,CAAC,KAAK,OAAO,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE;YACtE,mBAAmB,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,gBAAgB,EAAE;YAChF,iBAAiB,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE;SACxC,CAAC;QACF,IAAI,MAAM,CAAC,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACtD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CACxB,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAC3C,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CACpC,CAAC;YACF,MAAM,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAC1D,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;YACjC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,MAAM,aAAa,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACpE,IAAI,IAAI,CAAC,IAAI;gBAAE,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9E,CAAC;QACD,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpD,CAAC;CACF,CAAC,CAAC"}