@cyanheads/fema-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 (65) hide show
  1. package/AGENTS.md +360 -0
  2. package/CLAUDE.md +360 -0
  3. package/Dockerfile +100 -0
  4. package/LICENSE +201 -0
  5. package/README.md +340 -0
  6. package/changelog/0.1.x/0.1.1.md +41 -0
  7. package/changelog/template.md +127 -0
  8. package/dist/config/server-config.d.ts +9 -0
  9. package/dist/config/server-config.d.ts.map +1 -0
  10. package/dist/config/server-config.js +22 -0
  11. package/dist/config/server-config.js.map +1 -0
  12. package/dist/index.d.ts +7 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +45 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/mcp-server/resources/definitions/fema-disaster.resource.d.ts +9 -0
  17. package/dist/mcp-server/resources/definitions/fema-disaster.resource.d.ts.map +1 -0
  18. package/dist/mcp-server/resources/definitions/fema-disaster.resource.js +59 -0
  19. package/dist/mcp-server/resources/definitions/fema-disaster.resource.js.map +1 -0
  20. package/dist/mcp-server/tools/definitions/fema-dataframe-describe.tool.d.ts +27 -0
  21. package/dist/mcp-server/tools/definitions/fema-dataframe-describe.tool.d.ts.map +1 -0
  22. package/dist/mcp-server/tools/definitions/fema-dataframe-describe.tool.js +99 -0
  23. package/dist/mcp-server/tools/definitions/fema-dataframe-describe.tool.js.map +1 -0
  24. package/dist/mcp-server/tools/definitions/fema-dataframe-query.tool.d.ts +25 -0
  25. package/dist/mcp-server/tools/definitions/fema-dataframe-query.tool.d.ts.map +1 -0
  26. package/dist/mcp-server/tools/definitions/fema-dataframe-query.tool.js +87 -0
  27. package/dist/mcp-server/tools/definitions/fema-dataframe-query.tool.js.map +1 -0
  28. package/dist/mcp-server/tools/definitions/fema-get-disaster.tool.d.ts +33 -0
  29. package/dist/mcp-server/tools/definitions/fema-get-disaster.tool.d.ts.map +1 -0
  30. package/dist/mcp-server/tools/definitions/fema-get-disaster.tool.js +142 -0
  31. package/dist/mcp-server/tools/definitions/fema-get-disaster.tool.js.map +1 -0
  32. package/dist/mcp-server/tools/definitions/fema-get-housing-assistance.tool.d.ts +53 -0
  33. package/dist/mcp-server/tools/definitions/fema-get-housing-assistance.tool.d.ts.map +1 -0
  34. package/dist/mcp-server/tools/definitions/fema-get-housing-assistance.tool.js +246 -0
  35. package/dist/mcp-server/tools/definitions/fema-get-housing-assistance.tool.js.map +1 -0
  36. package/dist/mcp-server/tools/definitions/fema-get-public-assistance.tool.d.ts +45 -0
  37. package/dist/mcp-server/tools/definitions/fema-get-public-assistance.tool.d.ts.map +1 -0
  38. package/dist/mcp-server/tools/definitions/fema-get-public-assistance.tool.js +210 -0
  39. package/dist/mcp-server/tools/definitions/fema-get-public-assistance.tool.js.map +1 -0
  40. package/dist/mcp-server/tools/definitions/fema-query-dataset.tool.d.ts +32 -0
  41. package/dist/mcp-server/tools/definitions/fema-query-dataset.tool.d.ts.map +1 -0
  42. package/dist/mcp-server/tools/definitions/fema-query-dataset.tool.js +128 -0
  43. package/dist/mcp-server/tools/definitions/fema-query-dataset.tool.js.map +1 -0
  44. package/dist/mcp-server/tools/definitions/fema-search-disasters.tool.d.ts +50 -0
  45. package/dist/mcp-server/tools/definitions/fema-search-disasters.tool.d.ts.map +1 -0
  46. package/dist/mcp-server/tools/definitions/fema-search-disasters.tool.js +281 -0
  47. package/dist/mcp-server/tools/definitions/fema-search-disasters.tool.js.map +1 -0
  48. package/dist/mcp-server/tools/definitions/fema-search-nfip.tool.d.ts +38 -0
  49. package/dist/mcp-server/tools/definitions/fema-search-nfip.tool.d.ts.map +1 -0
  50. package/dist/mcp-server/tools/definitions/fema-search-nfip.tool.js +307 -0
  51. package/dist/mcp-server/tools/definitions/fema-search-nfip.tool.js.map +1 -0
  52. package/dist/services/canvas/canvas-accessor.d.ts +9 -0
  53. package/dist/services/canvas/canvas-accessor.d.ts.map +1 -0
  54. package/dist/services/canvas/canvas-accessor.js +11 -0
  55. package/dist/services/canvas/canvas-accessor.js.map +1 -0
  56. package/dist/services/openfema/openfema-service.d.ts +52 -0
  57. package/dist/services/openfema/openfema-service.d.ts.map +1 -0
  58. package/dist/services/openfema/openfema-service.js +157 -0
  59. package/dist/services/openfema/openfema-service.js.map +1 -0
  60. package/dist/services/openfema/types.d.ts +139 -0
  61. package/dist/services/openfema/types.d.ts.map +1 -0
  62. package/dist/services/openfema/types.js +6 -0
  63. package/dist/services/openfema/types.js.map +1 -0
  64. package/package.json +105 -0
  65. package/server.json +99 -0
@@ -0,0 +1,59 @@
1
+ /**
2
+ * @fileoverview Resource: fema://disaster/{disasterNumber} — disaster declaration summary.
3
+ * @module mcp-server/resources/definitions/fema-disaster
4
+ */
5
+ import { resource, z } from '@cyanheads/mcp-ts-core';
6
+ import { notFound } from '@cyanheads/mcp-ts-core/errors';
7
+ import { getOpenFemaService } from '../../../services/openfema/openfema-service.js';
8
+ export const femaDisasterResource = resource('fema://disaster/{disasterNumber}', {
9
+ name: 'FEMA Disaster Declaration',
10
+ description: 'Summary for a specific FEMA disaster declaration — title, state, incident type, ' +
11
+ 'programs declared (IA/PA/HM), incident period, and designated area count. ' +
12
+ 'Read-once context injection for agents already holding a disaster number.',
13
+ params: z.object({
14
+ disasterNumber: z
15
+ .string()
16
+ .describe('FEMA disaster number as a string (e.g., "4781"). Obtain from fema_search_disasters.'),
17
+ }),
18
+ async handler(params, ctx) {
19
+ const num = parseInt(params.disasterNumber, 10);
20
+ if (Number.isNaN(num) || num <= 0) {
21
+ throw notFound(`Invalid disaster number "${params.disasterNumber}". Expected a positive integer.`, { disasterNumber: params.disasterNumber });
22
+ }
23
+ const svc = getOpenFemaService();
24
+ const { rows } = await svc.fetchDisasters({
25
+ filter: `disasterNumber eq ${num}`,
26
+ select: 'disasterNumber,declarationTitle,state,incidentType,declarationType,' +
27
+ 'declarationDate,incidentBeginDate,incidentEndDate,' +
28
+ 'iaProgramDeclared,paProgramDeclared,hmProgramDeclared',
29
+ top: 500,
30
+ }, ctx);
31
+ if (rows.length === 0) {
32
+ throw notFound(`Disaster number ${num} not found in FEMA records.`, { disasterNumber: num });
33
+ }
34
+ // biome-ignore lint/style/noNonNullAssertion: rows.length === 0 checked above via notFound throw
35
+ const first = rows[0];
36
+ const programs = [];
37
+ if (first.iaProgramDeclared)
38
+ programs.push('IA');
39
+ if (first.paProgramDeclared)
40
+ programs.push('PA');
41
+ if (first.hmProgramDeclared)
42
+ programs.push('HM');
43
+ const summary = {
44
+ disaster_number: first.disasterNumber ?? num,
45
+ title: first.declarationTitle ?? 'Unknown',
46
+ state: first.state ?? '',
47
+ incident_type: first.incidentType ?? '',
48
+ declaration_type: first.declarationType ?? '',
49
+ declaration_date: first.declarationDate ?? '',
50
+ incident_begin_date: first.incidentBeginDate,
51
+ incident_end_date: first.incidentEndDate,
52
+ programs_declared: programs,
53
+ designated_area_count: rows.length,
54
+ };
55
+ ctx.log.info('Disaster resource fetched', { disasterNumber: num });
56
+ return summary;
57
+ },
58
+ });
59
+ //# sourceMappingURL=fema-disaster.resource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fema-disaster.resource.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/fema-disaster.resource.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAE7E,MAAM,CAAC,MAAM,oBAAoB,GAAG,QAAQ,CAAC,kCAAkC,EAAE;IAC/E,IAAI,EAAE,2BAA2B;IACjC,WAAW,EACT,kFAAkF;QAClF,4EAA4E;QAC5E,2EAA2E;IAC7E,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,cAAc,EAAE,CAAC;aACd,MAAM,EAAE;aACR,QAAQ,CACP,qFAAqF,CACtF;KACJ,CAAC;IAEF,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG;QACvB,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QAChD,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;YAClC,MAAM,QAAQ,CACZ,4BAA4B,MAAM,CAAC,cAAc,iCAAiC,EAClF,EAAE,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,CAC1C,CAAC;QACJ,CAAC;QAED,MAAM,GAAG,GAAG,kBAAkB,EAAE,CAAC;QACjC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,GAAG,CAAC,cAAc,CACvC;YACE,MAAM,EAAE,qBAAqB,GAAG,EAAE;YAClC,MAAM,EACJ,qEAAqE;gBACrE,oDAAoD;gBACpD,uDAAuD;YACzD,GAAG,EAAE,GAAG;SACT,EACD,GAAG,CACJ,CAAC;QAEF,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,MAAM,QAAQ,CAAC,mBAAmB,GAAG,6BAA6B,EAAE,EAAE,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC;QAC/F,CAAC;QAED,iGAAiG;QACjG,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QACvB,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,IAAI,KAAK,CAAC,iBAAiB;YAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,KAAK,CAAC,iBAAiB;YAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,KAAK,CAAC,iBAAiB;YAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEjD,MAAM,OAAO,GAAG;YACd,eAAe,EAAE,KAAK,CAAC,cAAc,IAAI,GAAG;YAC5C,KAAK,EAAE,KAAK,CAAC,gBAAgB,IAAI,SAAS;YAC1C,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,EAAE;YACxB,aAAa,EAAE,KAAK,CAAC,YAAY,IAAI,EAAE;YACvC,gBAAgB,EAAE,KAAK,CAAC,eAAe,IAAI,EAAE;YAC7C,gBAAgB,EAAE,KAAK,CAAC,eAAe,IAAI,EAAE;YAC7C,mBAAmB,EAAE,KAAK,CAAC,iBAAiB;YAC5C,iBAAiB,EAAE,KAAK,CAAC,eAAe;YACxC,iBAAiB,EAAE,QAAQ;YAC3B,qBAAqB,EAAE,IAAI,CAAC,MAAM;SACnC,CAAC;QAEF,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,2BAA2B,EAAE,EAAE,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC;QAEnE,OAAO,OAAO,CAAC;IACjB,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @fileoverview Tool: fema_dataframe_describe — describe tables on a DataCanvas staged by fema_search_nfip.
3
+ * @module mcp-server/tools/definitions/fema-dataframe-describe
4
+ */
5
+ import { z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ export declare const femaDataframeDescribe: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
8
+ canvas_id: z.ZodString;
9
+ }, z.core.$strip>, z.ZodObject<{
10
+ tables: z.ZodArray<z.ZodObject<{
11
+ name: z.ZodString;
12
+ kind: z.ZodString;
13
+ row_count: z.ZodNumber;
14
+ columns: z.ZodArray<z.ZodObject<{
15
+ name: z.ZodString;
16
+ type: z.ZodString;
17
+ nullable: z.ZodOptional<z.ZodBoolean>;
18
+ }, z.core.$strip>>;
19
+ }, z.core.$strip>>;
20
+ canvas_id: z.ZodString;
21
+ }, z.core.$strip>, readonly [{
22
+ readonly reason: "canvas_not_found";
23
+ readonly code: JsonRpcErrorCode.NotFound;
24
+ readonly when: "The canvas_id does not correspond to an active canvas session.";
25
+ readonly recovery: "Re-run fema_search_nfip to stage a fresh canvas, then use the new canvas_id.";
26
+ }], undefined>;
27
+ //# sourceMappingURL=fema-dataframe-describe.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fema-dataframe-describe.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/fema-dataframe-describe.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;cA8GhC,CAAC"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * @fileoverview Tool: fema_dataframe_describe — describe tables on a DataCanvas staged by fema_search_nfip.
3
+ * @module mcp-server/tools/definitions/fema-dataframe-describe
4
+ */
5
+ import { tool, z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ import { getCanvas } from '../../../services/canvas/canvas-accessor.js';
8
+ export const femaDataframeDescribe = tool('fema_dataframe_describe', {
9
+ title: 'Describe FEMA DataCanvas Tables',
10
+ description: 'List tables and column schemas on a DataCanvas staged by fema_search_nfip. ' +
11
+ 'Call this before fema_dataframe_query to discover the exact table name, column names, and DuckDB data types needed to write valid SQL. ' +
12
+ 'The canvas holds the full NFIP claims result set — row count here is the total available for queries.',
13
+ annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
14
+ input: z.object({
15
+ canvas_id: z.string().describe('Canvas ID from the fema_search_nfip response.'),
16
+ }),
17
+ output: z.object({
18
+ tables: z
19
+ .array(z
20
+ .object({
21
+ name: z
22
+ .string()
23
+ .describe('Table or view name — use this exact string in SQL FROM clauses.'),
24
+ kind: z
25
+ .string()
26
+ .describe('Object type: "table" for a registered data table, "view" for a derived view.'),
27
+ row_count: z
28
+ .number()
29
+ .describe('Total rows in this table — the full staged result set, not the inline preview count.'),
30
+ columns: z
31
+ .array(z
32
+ .object({
33
+ name: z
34
+ .string()
35
+ .describe('Column name — use in SELECT, WHERE, GROUP BY, and ORDER BY clauses.'),
36
+ type: z
37
+ .string()
38
+ .describe('DuckDB SQL data type (e.g., VARCHAR, DOUBLE, INTEGER, BOOLEAN).'),
39
+ nullable: z
40
+ .boolean()
41
+ .optional()
42
+ .describe('True when the column can contain NULL values. Absent when nullability is unknown.'),
43
+ })
44
+ .describe('A single column in the table.'))
45
+ .describe('All columns in this table, in schema order.'),
46
+ })
47
+ .describe('A single registered table or view on the canvas.'))
48
+ .describe('All tables and views available on this canvas.'),
49
+ canvas_id: z.string().describe('Canvas ID that was described — pass to fema_dataframe_query.'),
50
+ }),
51
+ errors: [
52
+ {
53
+ reason: 'canvas_not_found',
54
+ code: JsonRpcErrorCode.NotFound,
55
+ when: 'The canvas_id does not correspond to an active canvas session.',
56
+ recovery: 'Re-run fema_search_nfip to stage a fresh canvas, then use the new canvas_id.',
57
+ },
58
+ ],
59
+ async handler(input, ctx) {
60
+ const canvas = getCanvas();
61
+ if (!canvas) {
62
+ throw new Error('DataCanvas is not enabled. Set CANVAS_PROVIDER_TYPE=duckdb to use fema_dataframe_describe.');
63
+ }
64
+ const instance = await canvas.acquire(input.canvas_id, ctx);
65
+ const tableInfos = await instance.describe();
66
+ ctx.log.info('DataCanvas describe complete', {
67
+ canvasId: input.canvas_id,
68
+ tableCount: tableInfos.length,
69
+ });
70
+ return {
71
+ tables: tableInfos.map((t) => ({
72
+ name: t.name,
73
+ kind: t.kind,
74
+ row_count: t.rowCount,
75
+ columns: t.columns.map((c) => ({
76
+ name: c.name,
77
+ type: c.type,
78
+ ...(c.nullable != null ? { nullable: c.nullable } : {}),
79
+ })),
80
+ })),
81
+ canvas_id: input.canvas_id,
82
+ };
83
+ },
84
+ format: (result) => {
85
+ const lines = [];
86
+ lines.push(`**Canvas:** ${result.canvas_id} | **${result.tables.length} table(s)**\n`);
87
+ for (const t of result.tables) {
88
+ lines.push(`## ${t.name} (${t.kind}, ${t.row_count} rows)`);
89
+ lines.push(`| Column | Type | Nullable |`);
90
+ lines.push(`| --- | --- | --- |`);
91
+ for (const c of t.columns) {
92
+ lines.push(`| ${c.name} | ${c.type} | ${c.nullable ?? 'unknown'} |`);
93
+ }
94
+ lines.push('');
95
+ }
96
+ return [{ type: 'text', text: lines.join('\n') }];
97
+ },
98
+ });
99
+ //# sourceMappingURL=fema-dataframe-describe.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fema-dataframe-describe.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/fema-dataframe-describe.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @fileoverview Tool: fema_dataframe_query — SQL SELECT against a DataCanvas table staged by fema_search_nfip.
3
+ * @module mcp-server/tools/definitions/fema-dataframe-query
4
+ */
5
+ import { z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ export declare const femaDataframeQuery: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
8
+ canvas_id: z.ZodString;
9
+ query: z.ZodString;
10
+ }, z.core.$strip>, z.ZodObject<{
11
+ rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
12
+ row_count: z.ZodNumber;
13
+ canvas_id: z.ZodString;
14
+ }, z.core.$strip>, readonly [{
15
+ readonly reason: "canvas_not_found";
16
+ readonly code: JsonRpcErrorCode.NotFound;
17
+ readonly when: "The canvas_id does not correspond to an active canvas session.";
18
+ readonly recovery: "Re-run fema_search_nfip to stage a fresh canvas, then use the new canvas_id.";
19
+ }, {
20
+ readonly reason: "invalid_query";
21
+ readonly code: JsonRpcErrorCode.InvalidParams;
22
+ readonly when: "The SQL statement is not a valid SELECT, references a non-existent table or column, or uses blocked operations.";
23
+ readonly recovery: "Call fema_dataframe_describe to verify table and column names, then correct the SQL. Only SELECT statements are permitted.";
24
+ }], undefined>;
25
+ //# sourceMappingURL=fema-dataframe-query.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fema-dataframe-query.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/fema-dataframe-query.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;cA4F7B,CAAC"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * @fileoverview Tool: fema_dataframe_query — SQL SELECT against a DataCanvas table staged by fema_search_nfip.
3
+ * @module mcp-server/tools/definitions/fema-dataframe-query
4
+ */
5
+ import { tool, z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ import { getCanvas } from '../../../services/canvas/canvas-accessor.js';
8
+ export const femaDataframeQuery = tool('fema_dataframe_query', {
9
+ title: 'Query FEMA DataCanvas Table',
10
+ description: 'Run a read-only SQL SELECT against a DataCanvas table staged by fema_search_nfip. ' +
11
+ 'Enables aggregation, GROUP BY, SUM/COUNT, time-series, and filtered analysis over the full NFIP claims result ' +
12
+ 'without re-fetching from the API. ' +
13
+ 'Call fema_dataframe_describe first to get the exact table name and column names needed for valid SQL. ' +
14
+ 'Only SELECT statements are allowed — DDL, DML, COPY, and file-reading functions are blocked.',
15
+ annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
16
+ input: z.object({
17
+ canvas_id: z
18
+ .string()
19
+ .describe('Canvas ID from the fema_search_nfip response (the canvas_id field).'),
20
+ query: z
21
+ .string()
22
+ .describe('SQL SELECT statement to run against the staged table. Use the table name from fema_dataframe_describe. ' +
23
+ 'Example: "SELECT year_of_loss, COUNT(*) AS claims, SUM(amount_paid_building) AS total_building_paid FROM df_nfip_abc123 GROUP BY year_of_loss ORDER BY year_of_loss"'),
24
+ }),
25
+ output: z.object({
26
+ rows: z
27
+ .array(z
28
+ .record(z.string(), z.unknown())
29
+ .describe('A single result row — keys are column names from the SELECT, values are the computed data.'))
30
+ .describe('All rows returned by the query.'),
31
+ row_count: z
32
+ .number()
33
+ .describe('Number of rows in this response (may be capped at the canvas row limit).'),
34
+ canvas_id: z.string().describe('Canvas ID that was queried — reuse for follow-up queries.'),
35
+ }),
36
+ errors: [
37
+ {
38
+ reason: 'canvas_not_found',
39
+ code: JsonRpcErrorCode.NotFound,
40
+ when: 'The canvas_id does not correspond to an active canvas session.',
41
+ recovery: 'Re-run fema_search_nfip to stage a fresh canvas, then use the new canvas_id.',
42
+ },
43
+ {
44
+ reason: 'invalid_query',
45
+ code: JsonRpcErrorCode.InvalidParams,
46
+ when: 'The SQL statement is not a valid SELECT, references a non-existent table or column, or uses blocked operations.',
47
+ recovery: 'Call fema_dataframe_describe to verify table and column names, then correct the SQL. Only SELECT statements are permitted.',
48
+ },
49
+ ],
50
+ async handler(input, ctx) {
51
+ const canvas = getCanvas();
52
+ if (!canvas) {
53
+ throw new Error('DataCanvas is not enabled. Set CANVAS_PROVIDER_TYPE=duckdb to use fema_dataframe_query.');
54
+ }
55
+ const instance = await canvas.acquire(input.canvas_id, ctx);
56
+ const result = await instance.query(input.query, { signal: ctx.signal });
57
+ ctx.log.info('DataCanvas query complete', {
58
+ canvasId: input.canvas_id,
59
+ rowCount: result.rowCount,
60
+ });
61
+ return {
62
+ rows: result.rows,
63
+ row_count: result.rowCount,
64
+ canvas_id: input.canvas_id,
65
+ };
66
+ },
67
+ format: (result) => {
68
+ const lines = [];
69
+ lines.push(`**${result.row_count} rows** | Canvas: ${result.canvas_id}\n`);
70
+ if (result.rows.length === 0) {
71
+ lines.push('_No rows returned._');
72
+ }
73
+ else {
74
+ const headers = Object.keys(result.rows[0] ?? {});
75
+ if (headers.length > 0) {
76
+ lines.push(`| ${headers.join(' | ')} |`);
77
+ lines.push(`| ${headers.map(() => '---').join(' | ')} |`);
78
+ for (const row of result.rows) {
79
+ const cells = headers.map((h) => String(row[h] ?? ''));
80
+ lines.push(`| ${cells.join(' | ')} |`);
81
+ }
82
+ }
83
+ }
84
+ return [{ type: 'text', text: lines.join('\n') }];
85
+ },
86
+ });
87
+ //# sourceMappingURL=fema-dataframe-query.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fema-dataframe-query.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/fema-dataframe-query.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @fileoverview Tool: fema_get_disaster — fetch all designated-area rows for a specific disaster.
3
+ * @module mcp-server/tools/definitions/fema-get-disaster
4
+ */
5
+ import { z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ export declare const femaGetDisaster: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
8
+ disaster_number: z.ZodNumber;
9
+ }, z.core.$strip>, z.ZodObject<{
10
+ disaster_number: z.ZodNumber;
11
+ title: z.ZodString;
12
+ state: z.ZodString;
13
+ incident_type: z.ZodString;
14
+ declaration_type: z.ZodString;
15
+ declaration_date: z.ZodString;
16
+ incident_begin_date: z.ZodOptional<z.ZodString>;
17
+ incident_end_date: z.ZodOptional<z.ZodString>;
18
+ ia_declared: z.ZodBoolean;
19
+ pa_declared: z.ZodBoolean;
20
+ hm_declared: z.ZodBoolean;
21
+ designated_areas: z.ZodArray<z.ZodObject<{
22
+ area: z.ZodString;
23
+ fips_state_code: z.ZodOptional<z.ZodString>;
24
+ fips_county_code: z.ZodOptional<z.ZodString>;
25
+ }, z.core.$strip>>;
26
+ designated_area_count: z.ZodNumber;
27
+ }, z.core.$strip>, readonly [{
28
+ readonly reason: "not_found";
29
+ readonly code: JsonRpcErrorCode.NotFound;
30
+ readonly when: "No declaration found with the given disaster number.";
31
+ readonly recovery: "Verify the disaster number using fema_search_disasters. FEMA disaster numbers are typically 4-digit integers.";
32
+ }], undefined>;
33
+ //# sourceMappingURL=fema-get-disaster.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fema-get-disaster.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/fema-get-disaster.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;cAyJ1B,CAAC"}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * @fileoverview Tool: fema_get_disaster — fetch all designated-area rows for a specific disaster.
3
+ * @module mcp-server/tools/definitions/fema-get-disaster
4
+ */
5
+ import { tool, z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ import { getOpenFemaService } from '../../../services/openfema/openfema-service.js';
8
+ export const femaGetDisaster = tool('fema_get_disaster', {
9
+ title: 'Get FEMA Disaster Details',
10
+ description: 'Fetch all designated-area rows for a specific FEMA disaster by disaster number (e.g., 4781). ' +
11
+ 'Returns every county/municipality designated under the declaration along with programs activated, ' +
12
+ 'incident period, and state info. Use fema_search_disasters to find disaster numbers. ' +
13
+ 'The returned disaster_number chains to fema_get_public_assistance and fema_get_housing_assistance.',
14
+ annotations: { readOnlyHint: true, openWorldHint: false },
15
+ input: z.object({
16
+ disaster_number: z
17
+ .number()
18
+ .int()
19
+ .positive()
20
+ .describe('FEMA disaster number (e.g., 4781). Obtain from fema_search_disasters.'),
21
+ }),
22
+ output: z.object({
23
+ disaster_number: z
24
+ .number()
25
+ .describe('FEMA disaster number — use as the chain key for PA and housing assistance tools.'),
26
+ title: z.string().describe('Official declaration title (e.g., "SEVERE STORMS AND FLOODING").'),
27
+ state: z.string().describe('Two-letter state/territory code.'),
28
+ incident_type: z.string().describe('Type of incident (e.g., Flood, Hurricane, Severe Storm).'),
29
+ declaration_type: z
30
+ .string()
31
+ .describe('Declaration type: DR (major disaster), EM (emergency), or FM (fire management).'),
32
+ declaration_date: z.string().describe('ISO 8601 date the declaration was signed.'),
33
+ incident_begin_date: z
34
+ .string()
35
+ .optional()
36
+ .describe('ISO 8601 start date of the incident. Absent when not recorded.'),
37
+ incident_end_date: z
38
+ .string()
39
+ .optional()
40
+ .describe('ISO 8601 end date of the incident. Absent for ongoing or unrecorded incidents.'),
41
+ ia_declared: z
42
+ .boolean()
43
+ .describe('True when Individual Assistance (housing/personal grants) was declared.'),
44
+ pa_declared: z
45
+ .boolean()
46
+ .describe('True when Public Assistance (infrastructure recovery grants) was declared.'),
47
+ hm_declared: z.boolean().describe('True when Hazard Mitigation grants were declared.'),
48
+ designated_areas: z
49
+ .array(z
50
+ .object({
51
+ area: z.string().describe('Name of the designated county or municipality.'),
52
+ fips_state_code: z
53
+ .string()
54
+ .optional()
55
+ .describe('2-digit state FIPS code. Absent when not returned.'),
56
+ fips_county_code: z
57
+ .string()
58
+ .optional()
59
+ .describe('3-digit county FIPS code. Absent when not returned.'),
60
+ })
61
+ .describe('A single designated area entry.'))
62
+ .describe('All counties/municipalities designated for assistance under this declaration.'),
63
+ designated_area_count: z
64
+ .number()
65
+ .describe('Total number of designated areas in this declaration.'),
66
+ }),
67
+ errors: [
68
+ {
69
+ reason: 'not_found',
70
+ code: JsonRpcErrorCode.NotFound,
71
+ when: 'No declaration found with the given disaster number.',
72
+ recovery: 'Verify the disaster number using fema_search_disasters. FEMA disaster numbers are typically 4-digit integers.',
73
+ },
74
+ ],
75
+ async handler(input, ctx) {
76
+ const svc = getOpenFemaService();
77
+ const { rows } = await svc.fetchDisasters({
78
+ filter: `disasterNumber eq ${input.disaster_number}`,
79
+ select: 'disasterNumber,declarationTitle,state,incidentType,declarationType,' +
80
+ 'declarationDate,incidentBeginDate,incidentEndDate,' +
81
+ 'iaProgramDeclared,paProgramDeclared,hmProgramDeclared,' +
82
+ 'designatedArea,fipsStateCode,fipsCountyCode',
83
+ top: 1000,
84
+ }, ctx);
85
+ if (rows.length === 0) {
86
+ throw ctx.fail('not_found', `No disaster declaration found with number ${input.disaster_number}.`, { disasterNumber: input.disaster_number, ...ctx.recoveryFor('not_found') });
87
+ }
88
+ // biome-ignore lint/style/noNonNullAssertion: rows.length === 0 checked above
89
+ const first = rows[0];
90
+ const designatedAreas = rows.map((r) => ({
91
+ area: r.designatedArea ?? 'Unknown',
92
+ ...(r.fipsStateCode ? { fips_state_code: r.fipsStateCode } : {}),
93
+ ...(r.fipsCountyCode ? { fips_county_code: r.fipsCountyCode } : {}),
94
+ }));
95
+ ctx.log.info('Disaster fetch complete', {
96
+ disasterNumber: input.disaster_number,
97
+ areaCount: designatedAreas.length,
98
+ });
99
+ return {
100
+ disaster_number: first.disasterNumber ?? input.disaster_number,
101
+ title: first.declarationTitle ?? 'Unknown',
102
+ state: first.state ?? '',
103
+ incident_type: first.incidentType ?? '',
104
+ declaration_type: first.declarationType ?? '',
105
+ declaration_date: first.declarationDate ?? '',
106
+ ...(first.incidentBeginDate ? { incident_begin_date: first.incidentBeginDate } : {}),
107
+ ...(first.incidentEndDate ? { incident_end_date: first.incidentEndDate } : {}),
108
+ ia_declared: first.iaProgramDeclared ?? false,
109
+ pa_declared: first.paProgramDeclared ?? false,
110
+ hm_declared: first.hmProgramDeclared ?? false,
111
+ designated_areas: designatedAreas,
112
+ designated_area_count: designatedAreas.length,
113
+ };
114
+ },
115
+ format: (result) => {
116
+ const lines = [];
117
+ lines.push(`# DR-${result.disaster_number} — ${result.title}`);
118
+ lines.push(`**State:** ${result.state} | **Type:** ${result.declaration_type} | **Incident:** ${result.incident_type}`);
119
+ lines.push(`**Declared:** ${result.declaration_date}`);
120
+ if (result.incident_begin_date) {
121
+ lines.push(`**Incident Period:** ${result.incident_begin_date}${result.incident_end_date ? ` → ${result.incident_end_date}` : ' (ongoing)'}`);
122
+ }
123
+ const programs = [];
124
+ if (result.ia_declared)
125
+ programs.push('Individual Assistance (IA)');
126
+ if (result.pa_declared)
127
+ programs.push('Public Assistance (PA)');
128
+ if (result.hm_declared)
129
+ programs.push('Hazard Mitigation (HM)');
130
+ lines.push(`**Programs Declared:** ${programs.length > 0 ? programs.join(', ') : 'None'}`);
131
+ lines.push('');
132
+ lines.push(`## Designated Areas (${result.designated_area_count})`);
133
+ for (const area of result.designated_areas) {
134
+ const fips = area.fips_state_code && area.fips_county_code
135
+ ? ` (FIPS ${area.fips_state_code}${area.fips_county_code})`
136
+ : '';
137
+ lines.push(`- ${area.area}${fips}`);
138
+ }
139
+ return [{ type: 'text', text: lines.join('\n') }];
140
+ },
141
+ });
142
+ //# sourceMappingURL=fema-get-disaster.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fema-get-disaster.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/fema-get-disaster.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @fileoverview Tool: fema_get_housing_assistance — IA housing assistance data for a disaster.
3
+ * @module mcp-server/tools/definitions/fema-get-housing-assistance
4
+ */
5
+ import { z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ export declare const femaGetHousingAssistance: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
8
+ disaster_number: z.ZodNumber;
9
+ state: z.ZodOptional<z.ZodString>;
10
+ type: z.ZodDefault<z.ZodEnum<{
11
+ owners: "owners";
12
+ renters: "renters";
13
+ both: "both";
14
+ }>>;
15
+ limit: z.ZodDefault<z.ZodNumber>;
16
+ offset: z.ZodDefault<z.ZodNumber>;
17
+ }, z.core.$strip>, z.ZodObject<{
18
+ owners: z.ZodArray<z.ZodObject<{
19
+ disaster_number: z.ZodNumber;
20
+ state: z.ZodOptional<z.ZodString>;
21
+ county: z.ZodOptional<z.ZodString>;
22
+ city: z.ZodOptional<z.ZodString>;
23
+ zip_code: z.ZodOptional<z.ZodString>;
24
+ valid_registrations: z.ZodOptional<z.ZodNumber>;
25
+ approved_for_fema_assistance: z.ZodOptional<z.ZodNumber>;
26
+ total_approved_ihp_amount: z.ZodOptional<z.ZodNumber>;
27
+ repair_replace_amount: z.ZodOptional<z.ZodNumber>;
28
+ rental_amount: z.ZodOptional<z.ZodNumber>;
29
+ other_needs_amount: z.ZodOptional<z.ZodNumber>;
30
+ }, z.core.$strip>>;
31
+ renters: z.ZodArray<z.ZodObject<{
32
+ disaster_number: z.ZodNumber;
33
+ state: z.ZodOptional<z.ZodString>;
34
+ county: z.ZodOptional<z.ZodString>;
35
+ city: z.ZodOptional<z.ZodString>;
36
+ zip_code: z.ZodOptional<z.ZodString>;
37
+ valid_registrations: z.ZodOptional<z.ZodNumber>;
38
+ approved_for_fema_assistance: z.ZodOptional<z.ZodNumber>;
39
+ total_approved_ihp_amount: z.ZodOptional<z.ZodNumber>;
40
+ rental_amount: z.ZodOptional<z.ZodNumber>;
41
+ other_needs_amount: z.ZodOptional<z.ZodNumber>;
42
+ }, z.core.$strip>>;
43
+ owners_count: z.ZodNumber;
44
+ renters_count: z.ZodNumber;
45
+ }, z.core.$strip>, readonly [{
46
+ readonly reason: "no_results";
47
+ readonly code: JsonRpcErrorCode.NotFound;
48
+ readonly when: "No IA housing records found for this disaster.";
49
+ readonly recovery: "Check that ia_declared is true for this disaster using fema_get_disaster. IA housing data may take weeks to appear after a declaration.";
50
+ }], {
51
+ readonly notice: z.ZodOptional<z.ZodString>;
52
+ }>;
53
+ //# sourceMappingURL=fema-get-housing-assistance.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fema-get-housing-assistance.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/fema-get-housing-assistance.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwRnC,CAAC"}