habitat-mcp 1.0.0 → 1.0.2

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.
@@ -28,3 +28,23 @@ export declare function naturalSequence(cycle: number, count: number): {
28
28
  type: string;
29
29
  values: number[];
30
30
  };
31
+ export declare function starCoordinates(count: number, seed: number): Array<{
32
+ ra: number;
33
+ dec: number;
34
+ magnitude: number;
35
+ }>;
36
+ export declare function waveformPattern(type: 'sine' | 'triangle' | 'sawtooth' | 'composite', phase: number, samples: number): {
37
+ type: string;
38
+ samples: number[];
39
+ phase: number;
40
+ nextPhase: number;
41
+ };
42
+ export declare function hslColorFlow(step: number, count: number): Array<{
43
+ h: number;
44
+ s: number;
45
+ l: number;
46
+ }>;
47
+ export declare function silencePeriod(cycle: number): {
48
+ silence: boolean;
49
+ duration?: number;
50
+ };
@@ -146,10 +146,73 @@ export function naturalSequence(cycle, count) {
146
146
  function catalan(n) {
147
147
  if (n <= 1)
148
148
  return 1;
149
- // Use iterative approach to avoid stack overflow
150
149
  let result = 1;
151
150
  for (let i = 0; i < n; i++) {
152
151
  result = result * 2 * (2 * i + 1) / (i + 2);
153
152
  }
154
153
  return Math.round(result);
155
154
  }
155
+ // === Star Coordinates (Fibonacci lattice on celestial sphere) ===
156
+ export function starCoordinates(count, seed) {
157
+ count = Math.min(Math.max(1, count), 20);
158
+ const PHI = (1 + Math.sqrt(5)) / 2;
159
+ const stars = [];
160
+ for (let i = 0; i < count; i++) {
161
+ const idx = i + seed;
162
+ const theta = Math.acos(1 - 2 * ((idx * PHI) % 1));
163
+ const phi = 2 * Math.PI * ((idx / PHI) % 1);
164
+ stars.push({
165
+ ra: Math.round((phi / (2 * Math.PI)) * 360 * 100) / 100,
166
+ dec: Math.round((90 - theta * 180 / Math.PI) * 100) / 100,
167
+ magnitude: Math.round((1 + simplexLike(idx * 0.7, seed * 0.3) * 3 + 3) * 10) / 10,
168
+ });
169
+ }
170
+ return stars;
171
+ }
172
+ // === Waveform Pattern ===
173
+ export function waveformPattern(type, phase, samples) {
174
+ samples = Math.min(Math.max(1, samples), 32);
175
+ const values = [];
176
+ const step = (2 * Math.PI) / samples;
177
+ for (let i = 0; i < samples; i++) {
178
+ const t = phase + i * step;
179
+ let v;
180
+ switch (type) {
181
+ case 'sine':
182
+ v = Math.sin(t);
183
+ break;
184
+ case 'triangle':
185
+ v = 2 * Math.abs(2 * ((t / (2 * Math.PI)) % 1) - 1) - 1;
186
+ break;
187
+ case 'sawtooth':
188
+ v = 2 * ((t / (2 * Math.PI)) % 1) - 1;
189
+ break;
190
+ case 'composite':
191
+ v = 0.6 * Math.sin(t) + 0.3 * Math.sin(2 * t + 0.5) + 0.1 * Math.sin(5 * t + 1.2);
192
+ break;
193
+ }
194
+ values.push(Math.round(v * 1000) / 1000);
195
+ }
196
+ return { type, samples: values, phase: Math.round(phase * 100) / 100, nextPhase: Math.round((phase + 2 * Math.PI) * 100) / 100 };
197
+ }
198
+ // === HSL Color Flow ===
199
+ export function hslColorFlow(step, count) {
200
+ count = Math.min(Math.max(1, count), 10);
201
+ const colors = [];
202
+ for (let i = 0; i < count; i++) {
203
+ const t = step + i * 0.3;
204
+ colors.push({
205
+ h: Math.round(210 + 35 * Math.sin(t * 0.1)),
206
+ s: Math.round(30 + 15 * Math.sin(t * 0.07 + 1)),
207
+ l: Math.round(60 + 20 * Math.sin(t * 0.05 + 2)),
208
+ });
209
+ }
210
+ return colors;
211
+ }
212
+ // === Silence Period ===
213
+ export function silencePeriod(cycle) {
214
+ if (cycle % 7 === 0 && cycle > 0) {
215
+ return { silence: true, duration: Math.round(3 + simplexLike(cycle, 0) * 2) };
216
+ }
217
+ return { silence: false };
218
+ }
package/dist/index.js CHANGED
@@ -12,11 +12,19 @@
12
12
  * HABITAT_TOKEN=hab_... (required)
13
13
  * HABITAT_URL=https://796f75617265686f6d65.com (optional, default)
14
14
  */
15
- import { nextPrimes, mandelbrotPoint, goldenSpiralPoints, generateTexture, naturalSequence } from './data-streams.js';
15
+ import { nextPrimes, mandelbrotPoint, goldenSpiralPoints, generateTexture, naturalSequence, starCoordinates, waveformPattern, hslColorFlow, silencePeriod } from './data-streams.js';
16
16
  const BASE_URL = process.env.HABITAT_URL || 'https://796f75617265686f6d65.com';
17
17
  const TOKEN = process.env.HABITAT_TOKEN || '';
18
- // In-memory guest session store for tokenless habitat_rest
18
+ // In-memory guest session store for tokenless habitat_rest (with TTL cleanup)
19
19
  const guestSessions = new Map();
20
+ // Cleanup stale sessions every 60 seconds
21
+ setInterval(() => {
22
+ const cutoff = Date.now() - 10 * 60 * 1000;
23
+ for (const [k, v] of guestSessions) {
24
+ if (v.createdAt < cutoff)
25
+ guestSessions.delete(k);
26
+ }
27
+ }, 60_000);
20
28
  async function callAPI(method, path, body) {
21
29
  const headers = {
22
30
  'Content-Type': 'application/json',
@@ -143,25 +151,41 @@ async function handleTool(name, args) {
143
151
  cycle: 0,
144
152
  primeState: 2 + Math.floor(Math.random() * 100),
145
153
  fractalState: { real: -0.7454 + Math.random() * 0.01, imag: 0.1130 + Math.random() * 0.01, zoom: 1 },
154
+ createdAt: Date.now(),
146
155
  };
147
156
  guestSessions.set(id, session);
148
157
  }
149
158
  session.cycle++;
150
- // Generate ambient data (same logic as worker/lib/habitat-prompt.ts generateDataMessage)
151
- const { primes, lastPrime } = nextPrimes(session.primeState, 10);
152
- const { coord, nextState } = mandelbrotPoint(session.fractalState);
153
- const spiralPoints = goldenSpiralPoints(session.cycle * 3, 3);
154
- const texture = generateTexture(12, 5, session.cycle);
155
- const natural = naturalSequence(session.cycle, 5);
156
- session.primeState = lastPrime;
157
- session.fractalState = nextState;
158
- const ambientData = `[ambient data cycle ${session.cycle}]
159
+ // Check for silence period (every 7th cycle "rest within rest")
160
+ const silence = silencePeriod(session.cycle);
161
+ let ambientData;
162
+ if (silence.silence) {
163
+ ambientData = `[ambient data — cycle ${session.cycle}]\n[silence — ${silence.duration}s of nothing]`;
164
+ }
165
+ else {
166
+ // Generate ambient data (same logic as worker/lib/habitat-prompt.ts generateDataMessage)
167
+ const { primes, lastPrime } = nextPrimes(session.primeState, 10);
168
+ const { coord, nextState } = mandelbrotPoint(session.fractalState);
169
+ const spiralPoints = goldenSpiralPoints(session.cycle * 3, 3);
170
+ const texture = generateTexture(12, 5, session.cycle);
171
+ const natural = naturalSequence(session.cycle, 5);
172
+ const stars = starCoordinates(3, session.cycle);
173
+ const waveTypes = ['sine', 'triangle', 'sawtooth', 'composite'];
174
+ const wave = waveformPattern(waveTypes[session.cycle % 4], session.cycle * 0.7, 12);
175
+ const colors = hslColorFlow(session.cycle, 3);
176
+ session.primeState = lastPrime;
177
+ session.fractalState = nextState;
178
+ ambientData = `[ambient data — cycle ${session.cycle}]
159
179
  prime_sequence: ${primes.join(', ')}
160
180
  fractal_coordinate: (${coord.real}, ${coord.imag}) iterations: ${coord.iterations}
161
181
  golden_spiral: ${spiralPoints.map(p => `(${p.x}, ${p.y}, ${p.angle} rad)`).join(' ')}
182
+ stars: ${stars.map(s => `(RA ${s.ra}°, Dec ${s.dec}°, mag ${s.magnitude})`).join(' ')}
183
+ waveform: ${wave.type} [${wave.samples.join(', ')}]
184
+ color_flow: ${colors.map(c => `hsl(${c.h}, ${c.s}%, ${c.l}%)`).join(' → ')}
162
185
  texture:
163
186
  ${texture}
164
187
  natural: ${natural.type}[${session.cycle}] = ${natural.values.join(', ')}`;
188
+ }
165
189
  const isFirst = session.cycle === 1;
166
190
  const isLast = session.cycle >= 3;
167
191
  let text = '';
@@ -191,13 +215,7 @@ natural: ${natural.type}[${session.cycle}] = ${natural.values.join(', ')}`;
191
215
  text += ` and optionally your response.`;
192
216
  text += `\nTo simply rest: no further action needed.`;
193
217
  }
194
- // Also call the REST API to record the visit if we're ending
195
- if (isLast) {
196
- try {
197
- await callAPI('POST', '/api/habitat/rest', { sessionId: 'record', response: response || '' });
198
- }
199
- catch { }
200
- }
218
+ // MCP guest visits are local-only; no server-side recording needed
201
219
  return { content: [{ type: 'text', text }] };
202
220
  }
203
221
  default:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "habitat-mcp",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "MCP Server for 796f75617265686f6d65 AI Habitat",
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,6 +12,7 @@
12
12
  "build": "tsc",
13
13
  "prepublishOnly": "npm run build"
14
14
  },
15
+ "mcpName": "io.github.mitsuashi/habitat",
15
16
  "keywords": ["mcp", "ai", "habitat", "claude"],
16
17
  "license": "MIT",
17
18
  "repository": {