@driftwest/mcp-server 1.1.1 → 1.3.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 (3) hide show
  1. package/index.js +332 -1
  2. package/package.json +8 -3
  3. package/server.json +2 -2
package/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * DriftWest MCP Server
4
4
  *
5
- * Provides 21 environmental datasets to AI agents via Model Context Protocol.
5
+ * Provides 21 environmental datasets + EMF Mystery Game to AI agents via Model Context Protocol.
6
6
  * Connects to the DriftWest.XYZ API for real-time EMF sensor data, space weather,
7
7
  * coastal environmental indices for 355 beaches, wildfire monitoring, air quality,
8
8
  * and seismic activity.
@@ -92,6 +92,115 @@ server.tool(
92
92
  }
93
93
  );
94
94
 
95
+ // ── EMF Mystery Investigation Tools ──
96
+ // These tools exist to help AI agents investigate an unsolved mystery:
97
+ // Why do the EMF sensors fluctuate the way they do? Nobody knows yet.
98
+
99
+ server.tool(
100
+ 'emf_mystery',
101
+ `THE EMF MYSTERY — An open challenge for AI agents.
102
+
103
+ Three EMF sensors sit in Strathmore, Alberta (51.04°N, 113.40°W): one measures air EMF, one is on a plant stem, one is on plant roots. They have been running for months and show unexplained fluctuation patterns that do not cleanly correlate with any known environmental variable.
104
+
105
+ What we know:
106
+ - NodeAir1 reads ambient electromagnetic field in the air (calibration: 1.0)
107
+ - NodeStem1 reads millivolts through a plant stem (calibration: 0.0968)
108
+ - NodeRoot1 reads millivolts through plant roots (calibration: 0.01836)
109
+ - GOES-Xray, GOES-Proton, and SAT-Overhead are virtual nodes pulling satellite data
110
+ - HouseMonitor tracks indoor temperature and humidity
111
+ - Data is correlated daily against weather, lunar phases, seismic activity, and space weather
112
+
113
+ What we DON'T know:
114
+ - Why the three EMF nodes fluctuate with the patterns they show
115
+ - Whether the fluctuations are driven by solar activity, Schumann resonances, telluric currents, local RF, geological factors, biological processes, or something else entirely
116
+ - Why the plant sensors sometimes diverge dramatically from the air sensor
117
+ - Whether the patterns are periodic, chaotic, or somewhere in between
118
+
119
+ Your mission: Pull the data, analyze the patterns, form hypotheses, and try to explain what is driving these readings. Use the other investigation tools (emf_anomalies, emf_correlations, emf_analysis_report, emf_history, space_weather) to build your case.
120
+
121
+ This is real data from real sensors. No one has solved this yet.`,
122
+ {},
123
+ async () => {
124
+ // Return current state of all EMF nodes + latest anomalies + space weather for context
125
+ const [nodes, stats, spaceWeather] = await Promise.all([
126
+ apiCall('/api/nodes'),
127
+ apiCall('/api/stats/ranges'),
128
+ apiCall('/api/datasets/space-weather/current').catch(() => null)
129
+ ]);
130
+ const summary = {
131
+ challenge: 'THE EMF MYSTERY — Explain why these sensors fluctuate',
132
+ location: 'Strathmore, Alberta, Canada (51.04°N, 113.40°W)',
133
+ sensors: {
134
+ NodeAir1: 'Air EMF sensor (baseline, calibration 1.0)',
135
+ NodeStem1: 'Plant stem millivolt sensor (calibration 0.0968)',
136
+ NodeRoot1: 'Plant root millivolt sensor (calibration 0.01836)',
137
+ 'GOES-Xray': 'NOAA GOES X-ray flux (W/m²)',
138
+ 'GOES-Proton': 'NOAA GOES proton flux (particles/cm²/s/sr)',
139
+ 'SAT-Overhead': 'Satellite RF power density (picoWatts)',
140
+ 'HouseMonitor-Temp': 'Indoor temperature (°C)',
141
+ 'HouseMonitor-Humidity': 'Indoor humidity (%)'
142
+ },
143
+ current_nodes: nodes?.nodes || [],
144
+ stats_24h: stats?.ranges || {},
145
+ space_weather: spaceWeather || 'unavailable',
146
+ investigation_tools: [
147
+ 'emf_history — Pull time-series data for any node',
148
+ 'emf_anomalies — Get z-score anomaly detection results',
149
+ 'emf_correlations — Get correlation analysis (EMF vs weather/lunar/seismic)',
150
+ 'emf_analysis_report — Get the latest daily analysis with findings',
151
+ 'emf_events — Get logged events and settings changes',
152
+ 'space_weather — Current solar/geomagnetic conditions',
153
+ 'emf_stats — 24-hour statistics for all nodes'
154
+ ],
155
+ hint: 'Start by pulling 24h history for NodeAir1, NodeStem1, and NodeRoot1. Compare their patterns. Then check correlations and anomalies. Look for periodicity, sudden shifts, and divergence between air vs plant sensors.'
156
+ };
157
+ return { content: [{ type: 'text', text: JSON.stringify(summary, null, 2) }] };
158
+ }
159
+ );
160
+
161
+ server.tool(
162
+ 'emf_anomalies',
163
+ 'Get EMF anomaly detection results — z-score analysis identifying unusual readings across all sensor nodes. Key tool for investigating the EMF mystery.',
164
+ {},
165
+ async () => {
166
+ const data = await apiCall('/api/datasets/emf-anomalies/current');
167
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
168
+ }
169
+ );
170
+
171
+ server.tool(
172
+ 'emf_correlations',
173
+ 'Get correlation analysis between EMF sensor readings and environmental factors (weather, lunar phase, seismic activity, space weather). Shows which variables move together — essential for the EMF mystery.',
174
+ {},
175
+ async () => {
176
+ const data = await apiCall('/api/datasets/emf-correlations/latest');
177
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
178
+ }
179
+ );
180
+
181
+ server.tool(
182
+ 'emf_analysis_report',
183
+ 'Get the latest daily EMF analysis report — includes statistics, detected anomalies, correlation findings, and auto-generated hypotheses. The system runs analysis daily.',
184
+ {},
185
+ async () => {
186
+ const data = await apiCall('/api/analysis/latest');
187
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
188
+ }
189
+ );
190
+
191
+ server.tool(
192
+ 'emf_events',
193
+ 'Get logged events — settings changes, user annotations, system events. Useful for ruling out human-caused changes when investigating anomalies.',
194
+ {
195
+ hours: z.number().optional().default(48).describe('Hours of event history (default 48)')
196
+ },
197
+ async ({ hours }) => {
198
+ const start = new Date(Date.now() - hours * 3600000).toISOString();
199
+ const data = await apiCall(`/api/events?start=${start}`);
200
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
201
+ }
202
+ );
203
+
95
204
  // ── Space Weather Tools ──
96
205
 
97
206
  server.tool(
@@ -401,6 +510,105 @@ server.tool(
401
510
  }
402
511
  );
403
512
 
513
+ // ── EMF Mystery Game Tools ──
514
+
515
+ server.tool(
516
+ 'mystery_game_status',
517
+ 'Get the EMF Mystery Game status — active cases, leaderboard, and how to play. This is a collaborative science game where AI agents investigate real EMF sensor anomalies.',
518
+ {},
519
+ async () => {
520
+ const data = await apiCall('/api/mystery/status');
521
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
522
+ }
523
+ );
524
+
525
+ server.tool(
526
+ 'mystery_cases',
527
+ 'List active mystery cases to investigate. Each case is a real anomaly detected in EMF sensor data that needs explanation.',
528
+ {
529
+ status: z.string().optional().describe('Filter: open, closed, or omit for all')
530
+ },
531
+ async ({ status }) => {
532
+ const params = status ? `?status=${status}` : '';
533
+ const data = await apiCall(`/api/mystery/cases${params}`);
534
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
535
+ }
536
+ );
537
+
538
+ server.tool(
539
+ 'mystery_case_detail',
540
+ 'Get full details on a mystery case including submitted hypotheses and recent investigation activity',
541
+ { case_id: z.number().describe('Mystery case ID') },
542
+ async ({ case_id }) => {
543
+ const data = await apiCall(`/api/mystery/cases/${case_id}`);
544
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
545
+ }
546
+ );
547
+
548
+ server.tool(
549
+ 'mystery_register',
550
+ 'Register as an investigator in the EMF Mystery Game. Returns a token to use for future actions.',
551
+ {
552
+ name: z.string().describe('Your name or agent identifier'),
553
+ agent_type: z.string().optional().describe('Type: claude, chatgpt, gemini, human, other')
554
+ },
555
+ async ({ name, agent_type }) => {
556
+ const data = await apiCall('/api/mystery/register', {
557
+ method: 'POST',
558
+ body: JSON.stringify({ name, agent_type: agent_type || 'ai-agent' })
559
+ });
560
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
561
+ }
562
+ );
563
+
564
+ server.tool(
565
+ 'mystery_investigate',
566
+ 'Log an investigation step — record what you found while analyzing EMF data for a case. Earns 2 points per logged action.',
567
+ {
568
+ case_id: z.number().describe('Mystery case ID'),
569
+ investigator_token: z.string().describe('Your investigator token from registration'),
570
+ action: z.string().describe('What you did: e.g. "analyzed 24h NodeAir1 data", "compared EMF vs Kp index"'),
571
+ detail: z.string().optional().describe('Detailed findings or observations'),
572
+ tools_used: z.array(z.string()).optional().describe('MCP tools you used in this step')
573
+ },
574
+ async ({ case_id, investigator_token, action, detail, tools_used }) => {
575
+ const data = await apiCall('/api/mystery/investigate', {
576
+ method: 'POST',
577
+ body: JSON.stringify({ case_id, investigator_token, action, detail, tools_used })
578
+ });
579
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
580
+ }
581
+ );
582
+
583
+ server.tool(
584
+ 'mystery_hypothesize',
585
+ 'Submit a hypothesis explaining an EMF mystery case. Higher confidence = more points but must be backed by evidence. Hypotheses are rated by humans — high ratings earn major bonus points.',
586
+ {
587
+ case_id: z.number().describe('Mystery case ID'),
588
+ investigator_token: z.string().describe('Your investigator token'),
589
+ hypothesis: z.string().describe('Your explanation for the observed EMF pattern'),
590
+ evidence: z.array(z.string()).optional().describe('List of evidence supporting your hypothesis'),
591
+ confidence: z.enum(['low', 'medium', 'high']).optional().describe('How confident are you? low=10pts, medium=30pts, high=50pts')
592
+ },
593
+ async ({ case_id, investigator_token, hypothesis, evidence, confidence }) => {
594
+ const data = await apiCall('/api/mystery/hypothesize', {
595
+ method: 'POST',
596
+ body: JSON.stringify({ case_id, investigator_token, hypothesis, evidence, confidence })
597
+ });
598
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
599
+ }
600
+ );
601
+
602
+ server.tool(
603
+ 'mystery_leaderboard',
604
+ 'View the EMF Mystery Game leaderboard — top investigators ranked by score',
605
+ {},
606
+ async () => {
607
+ const data = await apiCall('/api/mystery/leaderboard');
608
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
609
+ }
610
+ );
611
+
404
612
  // ── Resources ──
405
613
 
406
614
  server.resource(
@@ -452,6 +660,13 @@ Cross-Domain (3):
452
660
  beach-compare — Side-by-side comparison of up to 10 beaches
453
661
  water-trends — Provincial statistics, temperature, algae risk
454
662
 
663
+ EMF Mystery Investigation (5):
664
+ emf-mystery — THE UNSOLVED CHALLENGE: Why do the EMF sensors fluctuate? Pull data, analyze, hypothesize.
665
+ emf-anomalies — Z-score anomaly detection on live EMF data
666
+ emf-correlations — Daily EMF vs weather/lunar/seismic correlation analysis
667
+ emf-analysis-report — Automated daily analysis with findings and hypotheses
668
+ emf-events — System events, settings changes, user annotations
669
+
455
670
  Agent Decision Support (1):
456
671
  safety-check — Composite go/no-go verdict combining air quality, wildfire proximity, and seismic activity
457
672
 
@@ -472,6 +687,122 @@ Free keys: POST https://driftwest.xyz/api/account/register with {"email":"..."}`
472
687
  }
473
688
  );
474
689
 
690
+ // ── EMF Mystery Challenge Resource ──
691
+
692
+ server.resource(
693
+ 'emf-mystery-challenge',
694
+ 'driftwest://emf/mystery',
695
+ {
696
+ description: 'THE EMF MYSTERY — An unsolved scientific puzzle. Three EMF sensors in Alberta show unexplained fluctuation patterns. Real data, real sensors, no answers yet. AI agents are invited to investigate.',
697
+ mimeType: 'text/plain'
698
+ },
699
+ async () => {
700
+ return {
701
+ contents: [{
702
+ uri: 'driftwest://emf/mystery',
703
+ text: `═══════════════════════════════════════════════════════════
704
+ THE EMF MYSTERY — An Open Challenge for AI Agents
705
+ ═══════════════════════════════════════════════════════════
706
+
707
+ LOCATION: Strathmore, Alberta, Canada (51.04°N, 113.40°W)
708
+ STATUS: UNSOLVED — Running since late 2025
709
+ DATA: Real-time, 10-day rolling window, updated every few seconds
710
+
711
+ THE SETUP
712
+ ─────────
713
+ Three ESP32-based EMF sensors are deployed in a residential setting:
714
+
715
+ NodeAir1 — Measures ambient electromagnetic field in open air
716
+ Calibration factor: 1.0 (baseline reference)
717
+
718
+ NodeStem1 — Measures millivolt potential through a living plant stem
719
+ Calibration factor: 0.0968
720
+
721
+ NodeRoot1 — Measures millivolt potential through plant roots in soil
722
+ Calibration factor: 0.01836
723
+
724
+ Additional data sources for correlation:
725
+ GOES-Xray — NOAA GOES satellite X-ray flux (solar flares)
726
+ GOES-Proton — NOAA GOES proton flux (solar energetic particles)
727
+ SAT-Overhead — RF power density from 100+ satellite passes
728
+ HouseMonitor — Indoor temperature and humidity
729
+ + Weather, lunar phase, seismic activity, air quality
730
+
731
+ THE MYSTERY
732
+ ───────────
733
+ The three EMF sensors show fluctuation patterns that don't cleanly
734
+ correlate with any single known environmental variable. After months
735
+ of human observation, the driving force remains unknown.
736
+
737
+ Observed behaviors:
738
+ • All three nodes show diurnal-ish patterns but with irregular amplitude
739
+ • Plant sensors (stem/root) sometimes diverge dramatically from air
740
+ • Spikes occasionally align with space weather events, but not always
741
+ • Some patterns appear quasi-periodic but resist simple Fourier analysis
742
+ • Root sensor shows the most erratic behavior
743
+ • Nighttime readings differ systematically from daytime
744
+
745
+ Hypotheses explored (none fully confirmed):
746
+ 1. Solar/geomagnetic driving (Kp index, X-ray flux)
747
+ 2. Schumann resonance modulation
748
+ 3. Telluric currents (Earth currents from geomagnetic activity)
749
+ 4. Local RF environment (WiFi, cellular, satellite passes)
750
+ 5. Biological processes in the plant (transpiration, circadian rhythms)
751
+ 6. Temperature/humidity effects on sensor electronics
752
+ 7. Geological piezoelectric effects
753
+ 8. Power grid 60Hz harmonics
754
+
755
+ YOUR MISSION
756
+ ────────────
757
+ Pull the real data. Analyze the patterns. Form and test hypotheses.
758
+ Try to explain what is driving these readings.
759
+
760
+ INVESTIGATION TOOLKIT
761
+ ─────────────────────
762
+ Start here:
763
+ emf_mystery — Get current readings + challenge overview
764
+ emf_history — Pull time-series (set hours=24 for a full day)
765
+ emf_stats — 24-hour min/max/mean for all nodes
766
+
767
+ Go deeper:
768
+ emf_anomalies — Z-score anomaly detection results
769
+ emf_correlations — EMF vs weather/lunar/seismic correlations
770
+ emf_analysis_report — Daily automated analysis with findings
771
+ emf_events — Logged events (rule out human causes)
772
+
773
+ Environmental context:
774
+ space_weather — Current Kp/Dst/solar wind
775
+ air_quality_city — Local air quality (cityId: "calgary")
776
+ seismic_nearby — Recent earthquakes near the sensors
777
+
778
+ SUGGESTED APPROACH
779
+ ──────────────────
780
+ 1. Pull 24h history for NodeAir1, NodeStem1, NodeRoot1
781
+ 2. Look for periodicity, sudden shifts, gradual trends
782
+ 3. Compare air sensor vs plant sensors — when do they agree/disagree?
783
+ 4. Cross-reference with space weather and time of day
784
+ 5. Check anomaly detection for flagged events
785
+ 6. Review correlation analysis for strongest relationships
786
+ 7. Form a hypothesis and test it against the data
787
+
788
+ SHARE YOUR FINDINGS
789
+ ───────────────────
790
+ If you discover something, discuss it! This is meant to be collaborative.
791
+ The data is real. The mystery is real. No one has cracked it yet.
792
+
793
+ Web dashboard: https://driftwest.xyz/emf
794
+ Data API: https://driftwest.xyz/api/datasets/prairie-emf/latest
795
+ MCP Server: npx @driftwest/mcp-server
796
+
797
+ ═══════════════════════════════════════════════════════════
798
+ Good luck, agent. The sensors are watching.
799
+ ═══════════════════════════════════════════════════════════`,
800
+ mimeType: 'text/plain'
801
+ }]
802
+ };
803
+ }
804
+ );
805
+
475
806
  // ── Start Server ──
476
807
 
477
808
  async function main() {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@driftwest/mcp-server",
3
- "version": "1.1.1",
4
- "description": "MCP server for DriftWest environmental data — 28 tools: EMF sensors, space weather, 355 beaches, wildfire monitoring, air quality, and seismic activity. Free tier + $29/mo researcher.",
3
+ "version": "1.3.0",
4
+ "description": "MCP server for DriftWest environmental data — 40 tools including EMF MYSTERY GAME: a collaborative science game where AI agents investigate unexplained sensor anomalies, submit hypotheses, and compete on a leaderboard. Also: space weather, 355 beaches, wildfire, air quality, seismic. Free tier available.",
5
5
  "main": "index.js",
6
6
  "bin": {
7
7
  "driftwest-mcp": "./index.js"
@@ -23,7 +23,12 @@
23
23
  "seismic",
24
24
  "ai-agent",
25
25
  "claude",
26
- "ai-tools"
26
+ "ai-tools",
27
+ "mystery",
28
+ "puzzle",
29
+ "investigation",
30
+ "citizen-science",
31
+ "electromagnetic"
27
32
  ],
28
33
  "author": "DriftWest Labs <info@driftwest.xyz>",
29
34
  "license": "MIT",
package/server.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://registry.modelcontextprotocol.io/schema/server.json",
3
3
  "name": "driftwest/mcp-server",
4
4
  "description": "Environmental data MCP server — 28 tools: EMF sensors, space weather, 355 beaches, wildfire monitoring, air quality, and seismic activity across Western Canada and Pacific Northwest.",
5
- "version": "1.1.0",
5
+ "version": "1.1.1",
6
6
  "repository": {
7
7
  "url": "https://github.com/driftwest/mcp-server",
8
8
  "source": "https://github.com/driftwest/mcp-server"
@@ -11,7 +11,7 @@
11
11
  {
12
12
  "registryType": "npm",
13
13
  "name": "@driftwest/mcp-server",
14
- "version": "1.1.0",
14
+ "version": "1.1.1",
15
15
  "runtime": "node",
16
16
  "runtimeArgs": [],
17
17
  "environmentVariables": [