@pipeworx/mcp-usgs-volcano 0.1.0 → 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.
- package/README.md +2 -2
- package/package.json +1 -1
- package/server.json +1 -1
- package/src/index.ts +91 -79
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
USGS Volcano MCP — Volcano Hazards Program HANS-public feed (no auth)
|
|
4
4
|
|
|
5
|
-
Part of [Pipeworx](https://pipeworx.io) — an MCP gateway connecting AI agents to
|
|
5
|
+
Part of [Pipeworx](https://pipeworx.io) — an MCP gateway connecting AI agents to 1170+ live data sources.
|
|
6
6
|
|
|
7
7
|
## Tools
|
|
8
8
|
|
|
@@ -23,7 +23,7 @@ Add to your MCP client (Claude Desktop, Cursor, Windsurf, etc.):
|
|
|
23
23
|
}
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
Or connect to the full Pipeworx gateway for access to all
|
|
26
|
+
Or connect to the full Pipeworx gateway for access to all 1170+ data sources:
|
|
27
27
|
|
|
28
28
|
```json
|
|
29
29
|
{
|
package/package.json
CHANGED
package/server.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "io.github.pipeworx-io/usgs-volcano",
|
|
4
4
|
"title": "Usgs Volcano",
|
|
5
5
|
"description": "USGS Volcano MCP — Volcano Hazards Program HANS-public feed (no auth)",
|
|
6
|
-
"version": "0.1.
|
|
6
|
+
"version": "0.1.1",
|
|
7
7
|
"websiteUrl": "https://pipeworx.io/packs/usgs-volcano",
|
|
8
8
|
"repository": {
|
|
9
9
|
"url": "https://github.com/pipeworx-io/mcp-usgs-volcano",
|
package/src/index.ts
CHANGED
|
@@ -75,16 +75,15 @@ const tools: McpToolExport['tools'] = [
|
|
|
75
75
|
];
|
|
76
76
|
|
|
77
77
|
async function callTool(name: string, args: Record<string, unknown>): Promise<unknown> {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
78
|
+
// list_elevated re-pointed to the renamed getCAPElevated action (2026-06-11).
|
|
79
|
+
if (name === 'list_elevated') return await listElevated();
|
|
80
|
+
|
|
81
|
+
// Re-pointed 2026-07: USGS HANS renamed getAllVolcanoes -> getMonitoredVolcanoes
|
|
82
|
+
// (each record carries the volcano's latest notice) and dropped the standalone
|
|
83
|
+
// notices action, so both tools are served from that one endpoint now.
|
|
84
|
+
if (name === 'list_volcanoes') return await listVolcanoes(args.observatory as string | undefined);
|
|
85
|
+
if (name === 'list_notices') return await listNotices(args.volcano_slug as string | undefined, (args.limit as number) ?? 20);
|
|
86
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
88
87
|
}
|
|
89
88
|
|
|
90
89
|
async function hansFetch<T>(path: string): Promise<T> {
|
|
@@ -96,109 +95,122 @@ async function hansFetch<T>(path: string): Promise<T> {
|
|
|
96
95
|
return res.json() as Promise<T>;
|
|
97
96
|
}
|
|
98
97
|
|
|
99
|
-
|
|
98
|
+
// getMonitoredVolcanoes returns one record per monitored volcano, each carrying
|
|
99
|
+
// its latest alert + notice.
|
|
100
|
+
interface MonitoredRecord {
|
|
100
101
|
volcano_name?: string;
|
|
101
|
-
|
|
102
|
-
|
|
102
|
+
vnum?: string;
|
|
103
|
+
volcano_cd?: string;
|
|
104
|
+
obs_abbr?: string;
|
|
105
|
+
obs_fullname?: string;
|
|
103
106
|
alert_level?: string;
|
|
104
107
|
color_code?: string;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
alert_url?: string;
|
|
112
|
-
alert_message?: string;
|
|
113
|
-
date_modified?: string;
|
|
108
|
+
sent_utc?: string;
|
|
109
|
+
sent_unixtime?: number;
|
|
110
|
+
notice_type_cd?: string;
|
|
111
|
+
notice_identifier?: string;
|
|
112
|
+
notice_url?: string;
|
|
113
|
+
notice_data?: string;
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
function
|
|
116
|
+
function slugify(name?: string): string | null {
|
|
117
|
+
return name ? name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') : null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function normalizeVolcano(v: MonitoredRecord) {
|
|
117
121
|
return {
|
|
118
122
|
name: v.volcano_name ?? null,
|
|
119
|
-
slug: v.
|
|
120
|
-
observatory: v.
|
|
123
|
+
slug: slugify(v.volcano_name),
|
|
124
|
+
observatory: v.obs_abbr ?? null,
|
|
125
|
+
observatory_full: v.obs_fullname ?? null,
|
|
121
126
|
alert_level: v.alert_level ?? null,
|
|
122
127
|
color_code: v.color_code ?? null,
|
|
123
|
-
latitude: v.latitude ?? null,
|
|
124
|
-
longitude: v.longitude ?? null,
|
|
125
|
-
elevation_m: v.elevation ?? null,
|
|
126
128
|
vnum: v.vnum ?? null,
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
modified: v.date_modified ?? null,
|
|
129
|
+
latest_notice_type: v.notice_type_cd ?? null,
|
|
130
|
+
latest_notice_url: v.notice_url ?? null,
|
|
131
|
+
updated_utc: v.sent_utc ?? null,
|
|
131
132
|
};
|
|
132
133
|
}
|
|
133
134
|
|
|
134
135
|
async function listVolcanoes(observatory: string | undefined) {
|
|
135
|
-
const data = await hansFetch<
|
|
136
|
+
const data = await hansFetch<MonitoredRecord[]>('/volcano/getMonitoredVolcanoes');
|
|
136
137
|
const all = (data ?? []).map(normalizeVolcano);
|
|
137
138
|
const filtered = observatory
|
|
138
|
-
? all.filter(
|
|
139
|
-
(v) => v.observatory?.toLowerCase() === observatory.toLowerCase(),
|
|
140
|
-
)
|
|
139
|
+
? all.filter((v) => v.observatory?.toLowerCase() === observatory.toLowerCase())
|
|
141
140
|
: all;
|
|
142
|
-
return {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
141
|
+
return { total: all.length, returned: filtered.length, volcanoes: filtered };
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// USGS HANS renamed elevated/getElevatedVolcanoes → volcano/getCAPElevated
|
|
145
|
+
// (CAP = Common Alerting Protocol) with new field names. Re-pointed 2026-06-11.
|
|
146
|
+
interface CapElevatedRecord {
|
|
147
|
+
volcano_name_appended?: string;
|
|
148
|
+
latitude?: number;
|
|
149
|
+
longitude?: number;
|
|
150
|
+
vnum?: string;
|
|
151
|
+
elevation_meters?: number;
|
|
152
|
+
obs_fullname?: string;
|
|
153
|
+
alert_level?: string;
|
|
154
|
+
color_code?: string;
|
|
155
|
+
cap_certainty?: string;
|
|
156
|
+
cap_severity?: string;
|
|
157
|
+
cap_urgency?: string;
|
|
158
|
+
notice_identifier?: string;
|
|
159
|
+
sent_date_cap?: string;
|
|
147
160
|
}
|
|
148
161
|
|
|
149
162
|
async function listElevated() {
|
|
150
|
-
const data = await hansFetch<
|
|
151
|
-
const list = (data ?? []).map(
|
|
163
|
+
const data = await hansFetch<CapElevatedRecord[]>('/volcano/getCAPElevated');
|
|
164
|
+
const list = (data ?? []).map((v) => ({
|
|
165
|
+
volcano_name: v.volcano_name_appended ?? null,
|
|
166
|
+
alert_level: v.alert_level ?? null,
|
|
167
|
+
color_code: v.color_code ?? null,
|
|
168
|
+
observatory: v.obs_fullname ?? null,
|
|
169
|
+
latitude: v.latitude ?? null,
|
|
170
|
+
longitude: v.longitude ?? null,
|
|
171
|
+
elevation_m: v.elevation_meters ?? null,
|
|
172
|
+
vnum: v.vnum ?? null,
|
|
173
|
+
cap_certainty: v.cap_certainty ?? null,
|
|
174
|
+
cap_severity: v.cap_severity ?? null,
|
|
175
|
+
cap_urgency: v.cap_urgency ?? null,
|
|
176
|
+
notice_id: v.notice_identifier ?? null,
|
|
177
|
+
sent_at: v.sent_date_cap ?? null,
|
|
178
|
+
}));
|
|
152
179
|
return {
|
|
153
180
|
count: list.length,
|
|
154
|
-
note: '
|
|
181
|
+
note: 'Volcanoes currently above Normal/Green status (advisory / watch / warning), with CAP alert details. Source: USGS HANS getCAPElevated.',
|
|
155
182
|
volcanoes: list,
|
|
156
183
|
};
|
|
157
184
|
}
|
|
158
185
|
|
|
159
|
-
|
|
160
|
-
notice_id?: string;
|
|
161
|
-
volcano_name?: string;
|
|
162
|
-
url_name?: string;
|
|
163
|
-
observatory?: string;
|
|
164
|
-
message_type?: string;
|
|
165
|
-
alert_level?: string;
|
|
166
|
-
color_code?: string;
|
|
167
|
-
sent_utc?: string;
|
|
168
|
-
date_modified?: string;
|
|
169
|
-
url?: string;
|
|
170
|
-
summary?: string;
|
|
171
|
-
full_message?: string;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
function normalizeNotice(n: NoticeRecord) {
|
|
186
|
+
function normalizeNotice(n: MonitoredRecord) {
|
|
175
187
|
return {
|
|
176
|
-
id: n.notice_id ?? null,
|
|
177
188
|
volcano: n.volcano_name ?? null,
|
|
178
|
-
slug: n.
|
|
179
|
-
observatory: n.
|
|
180
|
-
type: n.
|
|
189
|
+
slug: slugify(n.volcano_name),
|
|
190
|
+
observatory: n.obs_abbr ?? null,
|
|
191
|
+
type: n.notice_type_cd ?? null,
|
|
192
|
+
notice_id: n.notice_identifier ?? null,
|
|
181
193
|
alert_level: n.alert_level ?? null,
|
|
182
194
|
color_code: n.color_code ?? null,
|
|
183
|
-
sent_utc: n.sent_utc ??
|
|
184
|
-
|
|
185
|
-
message: n.
|
|
186
|
-
url: n.url ?? null,
|
|
195
|
+
sent_utc: n.sent_utc ?? null,
|
|
196
|
+
url: n.notice_url ?? null,
|
|
197
|
+
message: n.notice_data ?? null,
|
|
187
198
|
};
|
|
188
199
|
}
|
|
189
200
|
|
|
190
201
|
async function listNotices(volcanoSlug: string | undefined, limit: number) {
|
|
191
|
-
//
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
+
// No standalone notices action survives the HANS rename; each monitored
|
|
203
|
+
// volcano carries its latest notice, so derive the list from
|
|
204
|
+
// getMonitoredVolcanoes (sorted newest-first, optionally filtered by volcano).
|
|
205
|
+
const data = await hansFetch<MonitoredRecord[]>('/volcano/getMonitoredVolcanoes');
|
|
206
|
+
let list = (data ?? []).filter((n) => n.notice_identifier || n.notice_url);
|
|
207
|
+
if (volcanoSlug) {
|
|
208
|
+
const s = volcanoSlug.toLowerCase();
|
|
209
|
+
list = list.filter((n) => slugify(n.volcano_name)?.includes(s) || n.volcano_cd?.toLowerCase() === s);
|
|
210
|
+
}
|
|
211
|
+
list.sort((a, b) => (b.sent_unixtime ?? 0) - (a.sent_unixtime ?? 0));
|
|
212
|
+
const notices = list.slice(0, Math.max(1, limit)).map(normalizeNotice);
|
|
213
|
+
return { volcano_slug: volcanoSlug ?? null, count: notices.length, notices };
|
|
202
214
|
}
|
|
203
215
|
|
|
204
216
|
export default { tools, callTool, meter: { credits: 1 } } satisfies McpToolExport;
|