sigrank 0.16.0 → 0.17.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.
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
+ # SigRank MCP
2
+
1
3
  > **🏆 SigRank is live: [signalaf.com](https://signalaf.com)** — the leaderboard for how
2
4
  > efficiently you use AI, not how much. See your projected rank in 60 seconds at
3
- > [signalaf.com/score](https://signalaf.com/score). *Token counts only. Never your prompts.*
5
+ > [signalaf.com/score](https://signalaf.com/score). _Token counts only. Never your prompts._
4
6
 
5
7
  <div align="center">
6
8
 
@@ -19,14 +21,31 @@ For all builders, burners and 10xers.
19
21
  [![platform](https://img.shields.io/badge/platform-node-grey.svg?style=flat-square)](https://nodejs.org)
20
22
  [![live](https://img.shields.io/badge/board-signalaf.com-gold.svg?style=flat-square)](https://signalaf.com)
21
23
  [![SunrisesIllNeverSee/sigrank-mcp MCP server](https://glama.ai/mcp/servers/SunrisesIllNeverSee/sigrank-mcp/badges/score.svg)](https://glama.ai/mcp/servers/SunrisesIllNeverSee/sigrank-mcp)
22
- [![Smithery](https://smithery.ai/badge/burnmydays/sigrank-mcp)](https://smithery.ai/servers/burnmydays/sigrank-mcp)
24
+ [![Smithery](https://smithery.ai/badge/burnmydays/sigrank)](https://smithery.ai/servers/burnmydays/sigrank)
23
25
 
24
26
  </div>
25
27
 
26
- | The board | Your operator profile |
27
- |:---:|:---:|
28
- | [![SigRank leaderboard](./.github/assets/board.png)](https://signalaf.com/board/all) | [![SigRank operator profile](./.github/assets/profile.png)](https://signalaf.com) |
29
- | Every operator ranked by **Υ Yield** — the architecture of the cascade, not raw spend | Cascade layer, class, and fingerprint — derived from four token counts |
28
+ ## Table of Contents
29
+
30
+ - [Quickstart](#quickstart--3-steps-to-the-board)
31
+ - [Install from GitHub](#install-from-github)
32
+ - [Install via Smithery](#install-via-smithery)
33
+ - [Commands](#commands)
34
+ - [MCP Server mode](#mcp-server-mode)
35
+ - [Cascade math](#cascade-math)
36
+ - [Token Pillars](#token-pillars--sources)
37
+ - [Platform adapters](#platform-adapters)
38
+ - [Privacy](#privacy)
39
+ - [Env vars](#env-vars)
40
+ - [Dev / test](#dev--test)
41
+ - [File map](#file-map)
42
+ - [Contributing](#contributing)
43
+ - [License](#license)
44
+
45
+ | The board | Your operator profile |
46
+ | :-----------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------: |
47
+ | [![SigRank leaderboard](./.github/assets/board.png)](https://signalaf.com/board/all) | [![SigRank operator profile](./.github/assets/profile.png)](https://signalaf.com) |
48
+ | Every operator ranked by **Υ Yield** — the architecture of the cascade, not raw spend | Cascade layer, class, and fingerprint — derived from four token counts |
30
49
 
31
50
  > **Run [`sigrank enroll`](#sign-in--submit) then [`sigrank submit`](#sign-in--submit) to get ranked and claim your public profile at [signalaf.com](https://signalaf.com).**
32
51
 
@@ -76,14 +95,14 @@ sigrank
76
95
  **Repo:** [`SunrisesIllNeverSee/sigrank-mcp`](https://github.com/SunrisesIllNeverSee/sigrank-mcp)
77
96
  **Site:** [signalaf.com](https://signalaf.com)
78
97
  **npm:** [sigrank](https://www.npmjs.com/package/sigrank)
79
- **Smithery:** [smithery.ai/servers/burnmydays/sigrank-mcp](https://smithery.ai/servers/burnmydays/sigrank-mcp)
98
+ **Smithery:** [smithery.ai/servers/burnmydays/sigrank](https://smithery.ai/servers/burnmydays/sigrank)
80
99
  **Glama:** [glama.ai/mcp/servers/SunrisesIllNeverSee/sigrank-mcp](https://glama.ai/mcp/servers/SunrisesIllNeverSee/sigrank-mcp)
81
100
 
82
101
  ---
83
102
 
84
103
  ## Install via Smithery
85
104
 
86
- SigRank is available on [Smithery](https://smithery.ai/servers/burnmydays/sigrank-mcp) as a stdio MCP bundle — one-click install for Claude Desktop, Cursor, and other MCP clients.
105
+ SigRank is available on [Smithery](https://smithery.ai/servers/burnmydays/sigrank) as a stdio MCP bundle — one-click install for Claude Desktop, Cursor, and other MCP clients.
87
106
 
88
107
  ### Smithery CLI
89
108
 
@@ -92,7 +111,7 @@ SigRank is available on [Smithery](https://smithery.ai/servers/burnmydays/sigran
92
111
  npm install -g smithery
93
112
 
94
113
  # Connect to SigRank (downloads the MCPB bundle locally)
95
- smithery mcp add burnmydays/sigrank-mcp --id sigrank
114
+ smithery mcp add burnmydays/sigrank --id sigrank
96
115
 
97
116
  # List available tools
98
117
  smithery tool list sigrank
@@ -104,7 +123,7 @@ smithery tool call sigrank rank_paste '{"text": "1000000 500000 50000 800000"}'
104
123
 
105
124
  ### Claude Desktop (via Smithery)
106
125
 
107
- 1. Go to [smithery.ai/servers/burnmydays/sigrank-mcp](https://smithery.ai/servers/burnmydays/sigrank-mcp)
126
+ 1. Go to [smithery.ai/servers/burnmydays/sigrank](https://smithery.ai/servers/burnmydays/sigrank)
108
127
  2. Click **Install**
109
128
  3. Smithery handles the rest — no manual config editing
110
129
 
@@ -113,7 +132,7 @@ smithery tool call sigrank rank_paste '{"text": "1000000 500000 50000 800000"}'
113
132
  ## Commands
114
133
 
115
134
  ```
116
- ⊙ SigRank CLI v0.15.5
135
+ ⊙ SigRank CLI v0.16.0
117
136
 
118
137
  Default (no args)
119
138
  sigrank unified dashboard: cascade + token pillars + board
@@ -162,14 +181,14 @@ npx sigrank
162
181
 
163
182
  Six tabs. Keys: `1`-`6` or `←` `→` to switch · `R` refresh · `Q` quit.
164
183
 
165
- | Tab | Key | Content |
166
- |---|---|---|
167
- | **Dashboard** | `1` | Cascade table (all platforms × windows + combined) · Υ sparklines · token composition bars · mini board |
168
- | **Trends** | `2` | Every metric across windows — sub-views: You / Platform / Field |
169
- | **Compare** | `3` | 4-source pillar audit (tokenpull vs ccusage vs token-dash vs tokscale) · delta % · cascade metrics per source · cache read bar chart |
170
- | **Board** | `4` | Full leaderboard with all fields · `[W]` cycles window (7d/30d/90d/all) |
171
- | **Watch** | `5` | In-TUI landing panel · `[Enter]` launches the live watcher (big numbers + pillar bars + Υ trend, auto-refreshes 30s) |
172
- | **Connect** | `6` | Sign in / switch device — paste a connect code from signalaf.com → Settings. Then `[S]` submits. |
184
+ | Tab | Key | Content |
185
+ | ------------- | --- | ------------------------------------------------------------------------------------------------------------------------------------ |
186
+ | **Dashboard** | `1` | Cascade table (all platforms × windows + combined) · Υ sparklines · token composition bars · mini board |
187
+ | **Trends** | `2` | Every metric across windows — sub-views: You / Platform / Field |
188
+ | **Compare** | `3` | 4-source pillar audit (tokenpull vs ccusage vs token-dash vs tokscale) · delta % · cascade metrics per source · cache read bar chart |
189
+ | **Board** | `4` | Full leaderboard with all fields · `[W]` cycles window (7d/30d/90d/all) |
190
+ | **Watch** | `5` | In-TUI landing panel · `[Enter]` launches the live watcher (big numbers + pillar bars + Υ trend, auto-refreshes 30s) |
191
+ | **Connect** | `6` | Sign in / switch device — paste a connect code from signalaf.com → Settings. Then `[S]` submits. |
173
192
 
174
193
  ### Sign in + submit
175
194
 
@@ -188,6 +207,7 @@ Or do it inside the TUI on the **Connect** tab (`6`), then press `[S]` to submit
188
207
  When stdout is not a TTY (i.e. piped to an AI client), `sigrank` starts an MCP stdio server automatically. AI clients (Claude Code, Cursor, Windsurf, etc.) use this path.
189
208
 
190
209
  Add to `.mcp.json` or equivalent:
210
+
191
211
  ```json
192
212
  {
193
213
  "mcpServers": {
@@ -198,7 +218,9 @@ Add to `.mcp.json` or equivalent:
198
218
  }
199
219
  }
200
220
  ```
221
+
201
222
  Or if installed globally:
223
+
202
224
  ```json
203
225
  {
204
226
  "mcpServers": {
@@ -211,23 +233,23 @@ Or if installed globally:
211
233
 
212
234
  ### MCP Tools
213
235
 
214
- | Tool | Args | What |
215
- |---|---|---|
216
- | `rank_paste(text)` | `{input, output, cacheCreate, cacheRead}` JSON or 4 whitespace-delimited numbers | Scores token pillars → Υ Yield / SNR / Leverage / Velocity / 10xDEV / Class + prose narration card |
217
- | `get_leaderboard()` | `{window?}` | Live board from signalaf.com — sorted by Υ Yield |
218
- | `get_operator(codename)` | `{codename}` | One operator's live profile |
219
- | `submit_paste(text, codename)` | `{text, codename?}` | Rank locally then POST to board. Omit codename for preview-only |
220
- | `tokenpull(platform?)` | `{platform?}` | On-device local reader: scans local logs → 4-window cascade. Zero paste, token-only |
221
- | `tokenpull_submit(codename, window?)` | `{codename?, window?}` | `tokenpull` → publish to board. Omit codename for preview |
222
- | `tokenpull_compare(platform?)` | `{platform?}` | All four sources side-by-side: tokenpull + ccusage + token-dash + tokscale. Returns pillars, cascade metrics, and delta % vs tokenpull per window |
223
- | `rank_windows` | `{platform?, window?}` | Multi-window cascade from local logs |
224
- | `watch_tokenpull` | `{platform?, interval_s?}` | One cascade snapshot per call (interval_s advisory) |
225
- | `submit_verified` | `{window?, platform?, dry_run?}` | THE ranked path: builds + ed25519-signs Schema 1.0 snapshots and POSTs them. `platform:'multi'` sums all active platforms. `dry_run:true` returns the exact payload unsent |
226
- | `enroll` | `{code, device_label?}` | Bind this device with a connect code from signalaf.com → Settings |
227
- | `diagnose_cascade` | `{text?}` | Diagnoses where your token cascade is leaking efficiency — ranked findings with severity + estimated Υ impact |
228
- | `simulate_change` | `{text?, changes}` | Prescriptive "what if" — test proposed pillar changes and see the exact Υ delta + class change before committing |
229
- | `suggest_improvements` | `{text?}` | Generates ranked, simulated improvement suggestions — tests strategies and returns them sorted by Υ yield impact |
230
- | `self_improve` | `{text?}` | One-click optimize: diagnoses, suggests, and simulates the best change in a single call |
236
+ | Tool | Args | What |
237
+ | ------------------------------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
238
+ | `rank_paste(text)` | `{input, output, cacheCreate, cacheRead}` JSON or 4 whitespace-delimited numbers | Scores token pillars → Υ Yield / SNR / Leverage / Velocity / 10xDEV / Class + prose narration card |
239
+ | `get_leaderboard()` | `{window?}` | Live board from signalaf.com — sorted by Υ Yield |
240
+ | `get_operator(codename)` | `{codename}` | One operator's live profile |
241
+ | `submit_paste(text, codename)` | `{text, codename?}` | Rank locally then POST to board. Omit codename for preview-only |
242
+ | `tokenpull(platform?)` | `{platform?}` | On-device local reader: scans local logs → 4-window cascade. Zero paste, token-only |
243
+ | `tokenpull_submit(codename, window?)` | `{codename?, window?}` | `tokenpull` → publish to board. Omit codename for preview |
244
+ | `tokenpull_compare(platform?)` | `{platform?}` | All four sources side-by-side: tokenpull + ccusage + token-dash + tokscale. Returns pillars, cascade metrics, and delta % vs tokenpull per window |
245
+ | `rank_windows` | `{platform?, window?}` | Multi-window cascade from local logs |
246
+ | `watch_tokenpull` | `{platform?, interval_s?}` | One cascade snapshot per call (interval_s advisory) |
247
+ | `submit_verified` | `{window?, platform?, dry_run?}` | THE ranked path: builds + ed25519-signs Schema 1.0 snapshots and POSTs them. `platform:'multi'` sums all active platforms. `dry_run:true` returns the exact payload unsent |
248
+ | `enroll` | `{code, device_label?}` | Bind this device with a connect code from signalaf.com → Settings |
249
+ | `diagnose_cascade` | `{text?}` | Diagnoses where your token cascade is leaking efficiency — ranked findings with severity + estimated Υ impact |
250
+ | `simulate_change` | `{text?, changes}` | Prescriptive "what if" — test proposed pillar changes and see the exact Υ delta + class change before committing |
251
+ | `suggest_improvements` | `{text?}` | Generates ranked, simulated improvement suggestions — tests strategies and returns them sorted by Υ yield impact |
252
+ | `self_improve` | `{text?}` | One-click optimize: diagnoses, suggests, and simulates the best change in a single call |
231
253
 
232
254
  ---
233
255
 
@@ -250,19 +272,21 @@ Canon check: `MO§ES (1251211, 11296121, 128196310, 2555179769) → Υ 18436.98`
250
272
 
251
273
  The dashboard pulls from multiple sources and shows them side-by-side for verification:
252
274
 
253
- | Source | What | Platform |
254
- |---|---|---|
255
- | `tokenpull` | On-device JSONL scanner (canon source) | claude, codex, amp, … |
256
- | `ccusage` | `ccusage <platform> daily --json` CLI (bundled) | claude, codex |
257
- | `token-dashboard` | `~/.claude/token-dashboard.db` SQLite (bundled) | claude only |
258
- | `tokscale` | `tokscale models --json` CLI (bundled, falls back to `~/tokscale_report.json`) | claude, codex |
275
+ | Source | What | Platform |
276
+ | ----------------- | ------------------------------------------------------------------------------ | --------------------- |
277
+ | `tokenpull` | On-device JSONL scanner (canon source) | claude, codex, amp, … |
278
+ | `ccusage` | `ccusage <platform> daily --json` CLI (bundled) | claude, codex |
279
+ | `token-dashboard` | `~/.claude/token-dashboard.db` SQLite (bundled) | claude only |
280
+ | `tokscale` | `tokscale models --json` CLI (bundled, falls back to `~/tokscale_report.json`) | claude, codex |
259
281
 
260
282
  **Codex input is estimated** — Codex logs don't expose true input tokens directly. The formula:
283
+
261
284
  ```
262
285
  input = output × ioRatio (ioRatio derived from Claude ratio, else 2.0)
263
286
  cacheCreate = uncached − input (uncached = input_tokens − cached_input_tokens)
264
287
  cacheRead = exact (from logs)
265
288
  ```
289
+
266
290
  Verifier numbers (ccusage/tokscale for codex) show **raw uncached input** (`input_tokens − cached`) — a different field than the estimated input above. The discrepancy is expected and explained inline in the dashboard.
267
291
 
268
292
  ---
@@ -271,25 +295,25 @@ Verifier numbers (ccusage/tokscale for codex) show **raw uncached input** (`inpu
271
295
 
272
296
  All adapters are token-only (no message content, no cost fields, no credentials).
273
297
 
274
- | Platform | Path | Notes |
275
- |---|---|---|
276
- | Claude Code | ✅ `~/.claude/projects` | Native; dedup by `(session_id, message_id)`; subagents included |
277
- | Codex | ✅ `~/.codex/sessions` | Estimated input via `io_ratio`; verified vs ccusage |
278
- | Amp | ✅ `~/.local/share/amp/threads` | Full 4-pillar; per-message |
279
- | Kimi | ✅ `~/.kimi/sessions` | Full 4-pillar; `StatusUpdate` lines only |
280
- | pi-agent | ✅ `~/.pi/agent/sessions` | Full 4-pillar; per-message JSONL |
281
- | OpenClaw | ✅ `~/.openclaw` | Full 4-pillar; per-message JSONL |
282
- | Droid | ✅ `~/.factory/sessions/*.settings.json` | Full 4-pillar; thinking→output |
283
- | Codebuff | ✅ `~/.config/manicode` | Full 4-pillar; `chat-messages.json` |
284
- | Hermes | ✅ `~/.hermes/state.db` | Full 4-pillar; SQLite; reasoning→output |
285
- | Kilo | ✅ `~/.local/share/kilo/kilo.db` | Full 4-pillar; SQLite |
286
- | Qwen | ✅ `~/.qwen/projects` | `cacheCreate=0` estimated; thought→output |
287
- | Goose | ✅ `~/.local/share/goose/sessions/sessions.db` | `cacheCreate=cacheRead=0` estimated; SQLite |
288
- | Gemini CLI | ✅ `~/.gemini/tmp` | `cacheCreate=0` estimated; cache extracted from input field |
289
- | GitHub Copilot CLI | ✅ `~/.copilot/otel` | OTel JSONL; requires `COPILOT_OTEL_ENABLED=true` |
290
- | OpenCode | ⚠️ `~/.local/share/opencode` | Raw token counts not persisted in log format |
291
- | Cursor | 🔜 | Chat log path TBD |
292
- | Windsurf | 🔜 | Session logs at `~/.codeium/windsurf/` |
298
+ | Platform | Path | Notes |
299
+ | ------------------ | ---------------------------------------------- | --------------------------------------------------------------- |
300
+ | Claude Code | ✅ `~/.claude/projects` | Native; dedup by `(session_id, message_id)`; subagents included |
301
+ | Codex | ✅ `~/.codex/sessions` | Estimated input via `io_ratio`; verified vs ccusage |
302
+ | Amp | ✅ `~/.local/share/amp/threads` | Full 4-pillar; per-message |
303
+ | Kimi | ✅ `~/.kimi/sessions` | Full 4-pillar; `StatusUpdate` lines only |
304
+ | pi-agent | ✅ `~/.pi/agent/sessions` | Full 4-pillar; per-message JSONL |
305
+ | OpenClaw | ✅ `~/.openclaw` | Full 4-pillar; per-message JSONL |
306
+ | Droid | ✅ `~/.factory/sessions/*.settings.json` | Full 4-pillar; thinking→output |
307
+ | Codebuff | ✅ `~/.config/manicode` | Full 4-pillar; `chat-messages.json` |
308
+ | Hermes | ✅ `~/.hermes/state.db` | Full 4-pillar; SQLite; reasoning→output |
309
+ | Kilo | ✅ `~/.local/share/kilo/kilo.db` | Full 4-pillar; SQLite |
310
+ | Qwen | ✅ `~/.qwen/projects` | `cacheCreate=0` estimated; thought→output |
311
+ | Goose | ✅ `~/.local/share/goose/sessions/sessions.db` | `cacheCreate=cacheRead=0` estimated; SQLite |
312
+ | Gemini CLI | ✅ `~/.gemini/tmp` | `cacheCreate=0` estimated; cache extracted from input field |
313
+ | GitHub Copilot CLI | ✅ `~/.copilot/otel` | OTel JSONL; requires `COPILOT_OTEL_ENABLED=true` |
314
+ | OpenCode | ⚠️ `~/.local/share/opencode` | Raw token counts not persisted in log format |
315
+ | Cursor | 🔜 | Chat log path TBD |
316
+ | Windsurf | 🔜 | Session logs at `~/.codeium/windsurf/` |
293
317
 
294
318
  `estimated=true` means one or more pillars are derived, not native. The server re-scores all submitted pillars authoritatively; local preview Υ is indicative only.
295
319
 
@@ -307,10 +331,10 @@ All adapters are token-only (no message content, no cost fields, no credentials)
307
331
 
308
332
  ## Env vars
309
333
 
310
- | Var | Default | Description |
311
- |---|---|---|
312
- | `SIGRANK_API_BASE` | `https://signalaf.com` | Override the board host |
313
- | `SIGRANK_FETCH_TIMEOUT` | `10000` | Board API fetch timeout (ms) |
334
+ | Var | Default | Description |
335
+ | ----------------------- | ---------------------- | ---------------------------- |
336
+ | `SIGRANK_API_BASE` | `https://signalaf.com` | Override the board host |
337
+ | `SIGRANK_FETCH_TIMEOUT` | `10000` | Board API fetch timeout (ms) |
314
338
 
315
339
  ---
316
340
 
@@ -323,6 +347,7 @@ node index.mjs # stdio MCP server directly (pipe to MCP client)
323
347
  ```
324
348
 
325
349
  Tests verify (13 groups, 200 assertions):
350
+
326
351
  - `rank_paste` canon: MO§ES `(1251211, 11296121, 128196310, 2555179769)` → Υ 18436.98 · TRANSMITTER
327
352
  - `submit_paste` preview (no codename) + POST shape (injected fetch, no live writes)
328
353
  - `tokenpull` dedup, window slicing, 4-window pillars (mock adapter)
@@ -341,20 +366,35 @@ Tests verify (13 groups, 200 assertions):
341
366
 
342
367
  ## File map
343
368
 
344
- | File | Responsibility |
345
- |---|---|
346
- | `index.mjs` | Entry point — TTY detection, routes to CLI or MCP server |
347
- | `cli.mjs` | CLI commands: board, compare, watch, enroll, submit, help |
348
- | `tui.mjs` | Full tabbed TUI: Dashboard / Trends / Compare / Board / Watch / Connect |
349
- | `cascade.mjs` | Pure cascade math (Υ, SNR, leverage, velocity, 10xDEV, class) |
350
- | `tokenpull.mjs` | On-device log scanner — Claude, Codex, multi-platform |
351
- | `adapters.mjs` | Platform adapter registry (15+ platforms) |
352
- | `tools.mjs` | MCP tool table + dispatcher |
353
- | `connect.mjs` | Connect-code enrollment + device identity |
354
- | `keystore.mjs` | Local key management (paste-keys, not API keys) |
355
- | `submit.mjs` | Verified submit flow (signs + POSTs to board) |
356
- | `sign.mjs` | Schema 1.0 signing (X-Agent-Signature) |
357
- | `narrate.mjs` | Deterministic prose narration card |
358
- | `preflight.mjs` | Plausibility checks (Benford, bounds, anomaly detection) |
359
- | `test.mjs` | Unit tests (no external deps) |
360
- | `sign.test.mjs` | ed25519 signing + canon parity test |
369
+ | File | Responsibility |
370
+ | --------------- | ----------------------------------------------------------------------- |
371
+ | `index.mjs` | Entry point — TTY detection, routes to CLI or MCP server |
372
+ | `cli.mjs` | CLI commands: board, compare, watch, enroll, submit, help |
373
+ | `tui.mjs` | Full tabbed TUI: Dashboard / Trends / Compare / Board / Watch / Connect |
374
+ | `cascade.mjs` | Pure cascade math (Υ, SNR, leverage, velocity, 10xDEV, class) |
375
+ | `tokenpull.mjs` | On-device log scanner — Claude, Codex, multi-platform |
376
+ | `adapters.mjs` | Platform adapter registry (15+ platforms) |
377
+ | `tools.mjs` | MCP tool table + dispatcher |
378
+ | `connect.mjs` | Connect-code enrollment + device identity |
379
+ | `keystore.mjs` | Local key management (paste-keys, not API keys) |
380
+ | `submit.mjs` | Verified submit flow (signs + POSTs to board) |
381
+ | `sign.mjs` | Schema 1.0 signing (X-Agent-Signature) |
382
+ | `narrate.mjs` | Deterministic prose narration card |
383
+ | `preflight.mjs` | Plausibility checks (Benford, bounds, anomaly detection) |
384
+ | `test.mjs` | Unit tests (no external deps) |
385
+ | `sign.test.mjs` | ed25519 signing + canon parity test |
386
+
387
+ ---
388
+
389
+ ## Contributing
390
+
391
+ Contributions welcome. SigRank MCP is built in the open.
392
+
393
+ - [Contributing guide](./.github/CONTRIBUTING.md)
394
+ - [Security policy](https://github.com/SunrisesIllNeverSee/sigrank-mcp/security/policy)
395
+ - Report bugs via [GitHub Issues](https://github.com/SunrisesIllNeverSee/sigrank-mcp/issues)
396
+ - PRs: fork → branch → `node test.mjs` passes → open PR against `main`
397
+
398
+ ## License
399
+
400
+ MIT — see [`LICENSE`](./LICENSE).