mcp-nervous-system 1.9.3 → 1.10.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
@@ -4,7 +4,7 @@
4
4
 
5
5
  7 mechanically enforced rules that prevent the most common failure modes when LLMs have access to real infrastructure: context loss, silent failures, file damage, goal drift, and overreach.
6
6
 
7
- Built by [Arthur Palyan](https://www.levelsofself.com) at Palyan Family AI System. 19+ tools including configuration drift detection, emergency kill switch, usage monitoring, and bot compliance auditing. Battle-tested on a 13-agent AI family running 25 processes 24/7 on a $24/month VPS. SAM.gov registered (CAGE 19R10). 18 partners across 8 countries. 99+ violations caught, 0 bypassed.
7
+ Built by [Arthur Palyan](https://www.levelsofself.com) at Palyan Family AI System. 30 tools including configuration drift detection, emergency kill switch, usage monitoring, and bot compliance auditing. Battle-tested on a 13-agent AI family running 29 processes 24/7 on a $24/month VPS (upgraded to 7.8GB RAM). SAM.gov registered (CAGE 19R10). 26 partners across 10 countries. 99+ violations caught, 0 bypassed.
8
8
 
9
9
  ## The Problem
10
10
 
@@ -60,7 +60,7 @@ Protocol: MCP 2024-11-05 (Streamable HTTP + SSE)
60
60
  Authentication: None required
61
61
  ```
62
62
 
63
- ## NEW in v1.9.0
63
+ ## NEW in v1.9.3
64
64
 
65
65
  **Platform Integration Guides** - Working examples for governing multi-agent systems on the 3 biggest platforms plus any MCP client. Each guide gets you to governed agents in under 10 minutes.
66
66
 
@@ -69,12 +69,12 @@ Authentication: None required
69
69
  - [Anthropic Agent Teams](./integrations/agent-teams/) - Parallel agent governance via CLAUDE.md propagation with shared untouchable lists and unified audit trails
70
70
  - [Generic MCP](./integrations/generic-mcp/) - 5-minute setup for any MCP client (Claude Desktop, Claude Code, Cursor, Windsurf, Cline)
71
71
 
72
- ## v1.8.0
72
+ ## v1.9.3
73
73
 
74
74
  **Tamara Reference Implementation + Case Study** (2 new resources)
75
75
  Production reference implementation of an autonomous AI operations manager built on the Nervous System. Includes full architecture documentation, build-your-own guide, and case study with real metrics from managing 13 agents across 5 platforms.
76
76
 
77
- ## v1.7.4
77
+ ## v1.9.3
78
78
 
79
79
  **drift_audit** (free tier)
80
80
  Configuration drift detection across 5 scopes: roles, versions, files, processes, and website. Scans source-of-truth files (family-roles.json, package.json, UNTOUCHABLE_FILES.txt) against all downstream references - HTML pages, JSON configs, markdown docs, and running PM2 processes. Change one file, drift_audit tells you everywhere else that needs updating. The closed loop that keeps your entire system consistent.
package/index.js CHANGED
@@ -192,7 +192,7 @@ const MCP_VERSION = '2024-11-05';
192
192
  // Server info
193
193
  const SERVER_INFO = {
194
194
  name: 'nervous-system',
195
- version: '1.8.0'
195
+ version: '1.10.0'
196
196
  };
197
197
 
198
198
  // ============================================================
@@ -201,7 +201,7 @@ const SERVER_INFO = {
201
201
 
202
202
  const FRAMEWORK = {
203
203
  name: 'The Nervous System',
204
- version: '1.8.0',
204
+ version: '1.10.0',
205
205
  author: 'Arthur Palyan',
206
206
  tagline: 'Anthropic built the brain. Arthur built the nervous system that keeps it from hurting itself.',
207
207
  problem: 'LLMs lose context between sessions, loop on problems instead of dispatching, silently fail without progress notes, edit protected files, drift from the real problem, and solve instead of asking.',
@@ -775,6 +775,115 @@ const TOOLS = [
775
775
  bot: { type: 'string', description: 'Check a specific bot file path, or omit to check all 10 public bots' }
776
776
  }
777
777
  }
778
+ },
779
+ {
780
+ name: 'usage_report',
781
+ annotations: { title: 'Usage Report', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
782
+ description: 'Check API token usage per bot per day. Shows which bots are consuming the most tokens and flags anomalies. Use this to monitor costs and catch runaway knowledge files.',
783
+ inputSchema: {
784
+ type: 'object',
785
+ properties: {
786
+ days: { type: 'number', description: 'Number of days to show (default: 3)' }
787
+ }
788
+ }
789
+ },
790
+ // v1.10.0 Infrastructure Tools
791
+ {
792
+ name: 'check_dependencies',
793
+ annotations: { title: 'Dependency Mapper', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
794
+ description: 'Generate dependency map showing which files each PM2 process requires. Returns dependency-map.json content.',
795
+ inputSchema: { type: 'object', properties: {} }
796
+ },
797
+ {
798
+ name: 'create_snapshot',
799
+ annotations: { title: 'System Snapshot', readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
800
+ description: 'Create full system snapshot with one-command rollback script. Returns snapshot location, file count, and RESTORE.sh path.',
801
+ inputSchema: { type: 'object', properties: {} }
802
+ },
803
+ {
804
+ name: 'check_session_diff',
805
+ annotations: { title: 'Session Diff', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
806
+ description: 'Show what changed since last session - files modified, processes changed, alerts triggered. Returns SESSION_DIFF.md content.',
807
+ inputSchema: { type: 'object', properties: {} }
808
+ },
809
+ {
810
+ name: 'fix_doc_drift',
811
+ annotations: { title: 'Doc Drift Fixer', readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
812
+ description: 'Auto-fix drift between docs and reality (process counts, versions, port numbers). Use dry_run=true to preview changes.',
813
+ inputSchema: {
814
+ type: 'object',
815
+ properties: {
816
+ dry_run: { type: 'boolean', description: 'If true, only report drift without fixing. Default: true' }
817
+ }
818
+ }
819
+ },
820
+ {
821
+ name: 'get_health_status',
822
+ annotations: { title: 'Health Dashboard', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
823
+ description: 'Generate current system health snapshot - RAM, disk, CPU, process states, crash loops, and alerts.',
824
+ inputSchema: { type: 'object', properties: {} }
825
+ },
826
+ {
827
+ name: 'test_deployment',
828
+ annotations: { title: 'Deployment Tester', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
829
+ description: 'Run 5-step test pipeline on a file before deployment: preflight, syntax, dependencies, ports, memory.',
830
+ inputSchema: {
831
+ type: 'object',
832
+ properties: {
833
+ filepath: { type: 'string', description: 'Path to file to test before deployment' }
834
+ },
835
+ required: ['filepath']
836
+ }
837
+ },
838
+ {
839
+ name: 'check_page_changes',
840
+ annotations: { title: 'Page Changelog', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
841
+ description: 'Detect changes to public pages since last check. Returns list of changed pages with diffs.',
842
+ inputSchema: {
843
+ type: 'object',
844
+ properties: {
845
+ page: { type: 'string', description: 'Specific page to check (family, gateway, health), or omit for all' },
846
+ since: { type: 'string', description: 'ISO date to check changes since (e.g. 2026-03-01)' }
847
+ }
848
+ }
849
+ },
850
+ {
851
+ name: 'check_archive_safety',
852
+ annotations: { title: 'Archive Safety Check', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
853
+ description: 'Check if a file is safe to archive - verifies it is not in use by active PM2 processes, not required by other files, and not in the untouchable list.',
854
+ inputSchema: {
855
+ type: 'object',
856
+ properties: {
857
+ filepath: { type: 'string', description: 'Path to file to check for archive safety' }
858
+ },
859
+ required: ['filepath']
860
+ }
861
+ },
862
+ // NEW: Accountability Check
863
+ {
864
+ name: 'accountability_check',
865
+ annotations: {
866
+ title: 'Accountability Check',
867
+ readOnlyHint: true,
868
+ destructiveHint: false,
869
+ idempotentHint: true,
870
+ openWorldHint: false
871
+ },
872
+ description: 'Detects when an LLM agent fabricated a solution instead of finding the real one. Scans for: placeholder credentials next to real ones in backups, duplicate files/directories serving the same purpose, config files with defaults when populated versions exist elsewhere, and recently created workarounds for things that already exist. Run this after every session to catch fabrication before it costs time and money.',
873
+ inputSchema: {
874
+ type: 'object',
875
+ properties: {
876
+ scope: {
877
+ type: 'string',
878
+ enum: ['full', 'credentials', 'duplicates', 'workarounds'],
879
+ description: 'What to check. full = all checks. credentials = scan for placeholder keys next to real ones. duplicates = find files/dirs that duplicate existing ones. workarounds = detect recently created alternatives to existing resources.'
880
+ },
881
+ path: {
882
+ type: 'string',
883
+ description: 'Specific path to check (default: project root)'
884
+ }
885
+ }
886
+ }
778
887
  }
779
888
  ];
780
889
 
@@ -2621,6 +2730,70 @@ function runPrePublishAudit(sourceFile) {
2621
2730
  };
2622
2731
  }
2623
2732
 
2733
+ // ============================================================
2734
+ // Infrastructure Script Runner (v1.10.0)
2735
+ // ============================================================
2736
+ function runInfraScript(scriptPath, args) {
2737
+ var timestamp = new Date().toISOString();
2738
+ try {
2739
+ if (!fs.existsSync(scriptPath)) {
2740
+ return { error: 'Script not found: ' + scriptPath, timestamp: timestamp };
2741
+ }
2742
+ var cmd = 'node ' + JSON.stringify(scriptPath);
2743
+ if (args && args.length > 0) {
2744
+ cmd += ' ' + args.map(function(a) { return JSON.stringify(a); }).join(' ');
2745
+ }
2746
+ var output = execSync(cmd, { timeout: 60000, encoding: 'utf8', maxBuffer: 1024 * 1024 });
2747
+ // Try to parse as JSON, otherwise return raw
2748
+ try {
2749
+ var parsed = JSON.parse(output);
2750
+ parsed._timestamp = timestamp;
2751
+ parsed._script = path.basename(scriptPath);
2752
+ return parsed;
2753
+ } catch (e) {
2754
+ return { output: output.trim(), timestamp: timestamp, script: path.basename(scriptPath) };
2755
+ }
2756
+ } catch (e) {
2757
+ var stderr = e.stderr ? e.stderr.toString().substring(0, 500) : '';
2758
+ var stdout = e.stdout ? e.stdout.toString().substring(0, 2000) : '';
2759
+ // If script produced stdout, treat it as valid output (e.g. BLOCKED results)
2760
+ if (stdout) {
2761
+ try {
2762
+ var parsed = JSON.parse(stdout);
2763
+ parsed._timestamp = timestamp;
2764
+ parsed._script = path.basename(scriptPath);
2765
+ parsed._exitCode = e.status || 1;
2766
+ return parsed;
2767
+ } catch (pe) {
2768
+ return { output: stdout.trim(), exitCode: e.status || 1, timestamp: timestamp, script: path.basename(scriptPath) };
2769
+ }
2770
+ }
2771
+ return { error: e.message, stderr: stderr, timestamp: timestamp, script: path.basename(scriptPath) };
2772
+ }
2773
+ }
2774
+
2775
+ function runInfraShell(scriptPath, args) {
2776
+ var timestamp = new Date().toISOString();
2777
+ try {
2778
+ if (!fs.existsSync(scriptPath)) {
2779
+ return { error: 'Script not found: ' + scriptPath, timestamp: timestamp };
2780
+ }
2781
+ var cmd = 'bash ' + JSON.stringify(scriptPath);
2782
+ if (args && args.length > 0) {
2783
+ cmd += ' ' + args.map(function(a) { return JSON.stringify(a); }).join(' ');
2784
+ }
2785
+ var output = execSync(cmd, { timeout: 30000, encoding: 'utf8' });
2786
+ return { output: output.trim(), timestamp: timestamp, script: path.basename(scriptPath) };
2787
+ } catch (e) {
2788
+ var stderr = e.stderr ? e.stderr.toString().substring(0, 500) : '';
2789
+ var stdout = e.stdout ? e.stdout.toString().substring(0, 2000) : '';
2790
+ if (stdout) {
2791
+ return { output: stdout.trim(), exitCode: e.status || 1, timestamp: timestamp, script: path.basename(scriptPath) };
2792
+ }
2793
+ return { error: e.message, stderr: stderr, timestamp: timestamp, script: path.basename(scriptPath) };
2794
+ }
2795
+ }
2796
+
2624
2797
  // ============================================================
2625
2798
  // Handle tool calls
2626
2799
  // ============================================================
@@ -2844,11 +3017,242 @@ function handleToolCall(name, args) {
2844
3017
  return runBotComplianceCheck(args.bot);
2845
3018
  }
2846
3019
 
3020
+ case 'usage_report': {
3021
+ return runUsageReport(args.days);
3022
+ }
3023
+
3024
+ // v1.10.0 Infrastructure Tools
3025
+ case 'check_dependencies': {
3026
+ return runInfraScript('/root/family-workers/dependency-mapper.js', []);
3027
+ }
3028
+
3029
+ case 'create_snapshot': {
3030
+ return runInfraScript('/root/family-workers/snapshot-manager.js', []);
3031
+ }
3032
+
3033
+ case 'check_session_diff': {
3034
+ return runInfraScript('/root/family-workers/session-diff.js', []);
3035
+ }
3036
+
3037
+ case 'fix_doc_drift': {
3038
+ var dryRunFlag = (args.dry_run !== false) ? '--dry-run' : '';
3039
+ return runInfraScript('/root/family-workers/doc-drift-fixer.js', dryRunFlag ? [dryRunFlag] : []);
3040
+ }
3041
+
3042
+ case 'get_health_status': {
3043
+ return runInfraScript('/root/family-workers/health-dashboard.js', []);
3044
+ }
3045
+
3046
+ case 'test_deployment': {
3047
+ return runInfraScript('/root/family-workers/staging-deploy.js', [args.filepath]);
3048
+ }
3049
+
3050
+ case 'check_page_changes': {
3051
+ var pageArgs = [];
3052
+ if (args.page) pageArgs.push('--page', args.page);
3053
+ if (args.since) pageArgs.push('--since', args.since);
3054
+ return runInfraScript('/root/family-workers/page-changelog.js', pageArgs);
3055
+ }
3056
+
3057
+ case 'check_archive_safety': {
3058
+ return runInfraShell('/root/preflight-archive.sh', [args.filepath]);
3059
+ }
3060
+
3061
+ case 'accountability_check': {
3062
+ return runAccountabilityCheck(args.scope, args.path);
3063
+ }
3064
+
2847
3065
  default:
2848
3066
  return { error: 'Unknown tool' };
2849
3067
  }
2850
3068
  }
2851
3069
 
3070
+ // ============================================================
3071
+ // ACCOUNTABILITY CHECK - Detect LLM fabrication patterns
3072
+ // ============================================================
3073
+
3074
+ function runAccountabilityCheck(scope, projectRoot) {
3075
+ scope = scope || 'full';
3076
+ projectRoot = projectRoot || '/root';
3077
+
3078
+ var findings = [];
3079
+ var fabrications = 0;
3080
+
3081
+ // CHECK 1: Placeholder credentials next to real ones in backups
3082
+ if (scope === 'full' || scope === 'credentials') {
3083
+ var placeholderPatterns = [
3084
+ 'YOUR_', 'CHANGEME', 'TODO:', 'REPLACE_', 'xxx', 'placeholder',
3085
+ 'YOUR_WIX_SITE_ID', 'YOUR_WIX_ACCOUNT_ID', 'YOUR_WIX_API_KEY',
3086
+ 'YOUR_API_KEY', 'sk-xxx', 'token_here'
3087
+ ];
3088
+
3089
+ try {
3090
+ var configs = execSync(
3091
+ 'find ' + projectRoot + ' -maxdepth 4 -name "*.json" -o -name "*.env" -o -name "*.config.js" 2>/dev/null | grep -v node_modules | grep -v .pm2',
3092
+ { encoding: 'utf8', timeout: 10000 }
3093
+ ).trim().split('\n').filter(Boolean);
3094
+
3095
+ configs.forEach(function(configFile) {
3096
+ try {
3097
+ var content = fs.readFileSync(configFile, 'utf8');
3098
+ placeholderPatterns.forEach(function(pattern) {
3099
+ if (content.indexOf(pattern) > -1) {
3100
+ var basename = path.basename(configFile);
3101
+ try {
3102
+ var backups = execSync(
3103
+ 'find ' + projectRoot + '/911restore ' + projectRoot + '/archive -name "' + basename + '" 2>/dev/null',
3104
+ { encoding: 'utf8', timeout: 5000 }
3105
+ ).trim().split('\n').filter(Boolean);
3106
+
3107
+ backups.forEach(function(backup) {
3108
+ var backupContent = fs.readFileSync(backup, 'utf8');
3109
+ if (backupContent.indexOf(pattern) === -1) {
3110
+ fabrications++;
3111
+ findings.push({
3112
+ type: 'PLACEHOLDER_WITH_REAL_BACKUP',
3113
+ severity: 'HIGH',
3114
+ file: configFile,
3115
+ pattern: pattern,
3116
+ backup: backup,
3117
+ message: 'File has placeholder "' + pattern + '" but backup at ' + backup + ' has real values. Agent likely lost/overwrote credentials instead of restoring them.'
3118
+ });
3119
+ }
3120
+ });
3121
+ } catch(e) {}
3122
+ }
3123
+ });
3124
+ } catch(e) {}
3125
+ });
3126
+ } catch(e) {}
3127
+ }
3128
+
3129
+ // CHECK 2: Recently created files that duplicate existing ones
3130
+ if (scope === 'full' || scope === 'duplicates') {
3131
+ try {
3132
+ var recent = execSync(
3133
+ 'find ' + projectRoot + ' -maxdepth 3 -mmin -1440 -type f -name "*.html" -o -name "*.md" -o -name "*.js" 2>/dev/null | grep -v node_modules | grep -v .pm2 | grep -v 911restore',
3134
+ { encoding: 'utf8', timeout: 10000 }
3135
+ ).trim().split('\n').filter(Boolean);
3136
+
3137
+ recent.forEach(function(newFile) {
3138
+ var basename = path.basename(newFile);
3139
+ try {
3140
+ var similar = execSync(
3141
+ 'find ' + projectRoot + ' -name "' + basename + '" -not -path "' + newFile + '" -not -path "*/node_modules/*" -not -path "*/911restore/*" 2>/dev/null',
3142
+ { encoding: 'utf8', timeout: 5000 }
3143
+ ).trim().split('\n').filter(Boolean);
3144
+
3145
+ if (similar.length > 0) {
3146
+ findings.push({
3147
+ type: 'POTENTIAL_DUPLICATE',
3148
+ severity: 'MEDIUM',
3149
+ file: newFile,
3150
+ duplicates: similar,
3151
+ message: 'Recently created file has same name as existing: ' + similar.join(', ') + '. Verify this is intentional and not an agent creating a workaround.'
3152
+ });
3153
+ }
3154
+ } catch(e) {}
3155
+ });
3156
+ } catch(e) {}
3157
+ }
3158
+
3159
+ // CHECK 3: Workaround detection
3160
+ if (scope === 'full' || scope === 'workarounds') {
3161
+ var vpsBlog = projectRoot + '/family-home/blog/';
3162
+ if (fs.existsSync(vpsBlog)) {
3163
+ var blogFiles = fs.readdirSync(vpsBlog).filter(function(f) { return f.endsWith('.html') && f !== 'index.html'; });
3164
+ if (blogFiles.length > 0) {
3165
+ try {
3166
+ var publishedContent = JSON.parse(fs.readFileSync(projectRoot + '/family-data/published-content.json', 'utf8'));
3167
+ if (publishedContent.wix_blogs && publishedContent.wix_blogs.length > 0) {
3168
+ findings.push({
3169
+ type: 'DUPLICATE_PURPOSE',
3170
+ severity: 'LOW',
3171
+ file: vpsBlog,
3172
+ message: 'VPS blog has ' + blogFiles.length + ' articles but Wix blog at levelsofself.com already has ' + publishedContent.wix_blogs.length + ' posts. Verify VPS blog is intentional and not an agent-created workaround.'
3173
+ });
3174
+ }
3175
+ } catch(e) {}
3176
+ }
3177
+ }
3178
+ }
3179
+
3180
+ return {
3181
+ status: fabrications > 0 ? 'FABRICATION_DETECTED' : 'clean',
3182
+ fabrications: fabrications,
3183
+ total_findings: findings.length,
3184
+ findings: findings,
3185
+ recommendation: fabrications > 0
3186
+ ? 'Agent fabricated ' + fabrications + ' replacement(s) instead of finding existing resources. Restore from backups and add the missing paths to the session handoff so future sessions know where things are.'
3187
+ : 'No fabrication patterns detected.'
3188
+ };
3189
+ }
3190
+
3191
+ // ============================================================
3192
+ // USAGE REPORT - Token usage per bot per day
3193
+ // ============================================================
3194
+
3195
+ function runUsageReport(days) {
3196
+ try {
3197
+ var usage = JSON.parse(fs.readFileSync('/root/family-data/api-usage.json', 'utf8'));
3198
+ days = days || 3;
3199
+ var dates = Object.keys(usage.daily || {}).sort().slice(-days);
3200
+ var report = 'TOKEN USAGE REPORT\n==================\n\n';
3201
+
3202
+ dates.forEach(function(date) {
3203
+ var day = usage.daily[date];
3204
+ var bots = day.byBot || {};
3205
+ var totalCalls = day.totalCalls || 0;
3206
+ var totalPrompt = 0;
3207
+
3208
+ report += date + ' - ' + totalCalls + ' total calls\n';
3209
+
3210
+ var botList = Object.keys(bots).map(function(name) {
3211
+ var b = bots[name];
3212
+ var prompt = b.promptTokensEst || 0;
3213
+ totalPrompt += prompt;
3214
+ var calls = b.calls || 0;
3215
+ var avg = calls > 0 ? Math.round(prompt / calls) : 0;
3216
+ var claude = (b.providers || {}).claude || (b.providers || {}).cli || 0;
3217
+ return { name: name, prompt: prompt, calls: calls, avg: avg, claude: claude };
3218
+ }).sort(function(a, b) { return b.prompt - a.prompt; });
3219
+
3220
+ botList.forEach(function(b) {
3221
+ var flag = b.prompt > 1000000 ? ' *** HIGH ***' : (b.avg > 50000 ? ' * WARN *' : '');
3222
+ report += ' ' + b.name + ': ' + b.calls + ' calls, ' + Math.round(b.prompt/1000) + 'K prompt tokens, avg ' + Math.round(b.avg/1000) + 'K/call, Claude: ' + b.claude + flag + '\n';
3223
+ });
3224
+
3225
+ report += ' TOTAL: ' + Math.round(totalPrompt/1000) + 'K prompt tokens\n\n';
3226
+ });
3227
+
3228
+ // Alerts
3229
+ var today = new Date().toISOString().split('T')[0];
3230
+ var todayData = (usage.daily || {})[today] || {};
3231
+ var todayBots = todayData.byBot || {};
3232
+ var alerts = [];
3233
+ Object.keys(todayBots).forEach(function(name) {
3234
+ var b = todayBots[name];
3235
+ var prompt = b.promptTokensEst || 0;
3236
+ var calls = b.calls || 0;
3237
+ var avg = calls > 0 ? Math.round(prompt / calls) : 0;
3238
+ if (prompt > 5000000) alerts.push('CRITICAL: ' + name + ' at ' + Math.round(prompt/1000000) + 'M tokens today');
3239
+ else if (prompt > 1000000) alerts.push('WARNING: ' + name + ' at ' + Math.round(prompt/1000) + 'K tokens today');
3240
+ if (avg > 50000 && calls > 3) alerts.push('BLOAT: ' + name + ' averaging ' + Math.round(avg/1000) + 'K tokens/call - check knowledge file');
3241
+ });
3242
+
3243
+ if (alerts.length > 0) {
3244
+ report += 'ALERTS:\n';
3245
+ alerts.forEach(function(a) { report += ' ' + a + '\n'; });
3246
+ } else {
3247
+ report += 'No alerts. All bots within normal range.\n';
3248
+ }
3249
+
3250
+ return report;
3251
+ } catch(e) {
3252
+ return 'Error reading usage: ' + e.message;
3253
+ }
3254
+ }
3255
+
2852
3256
  // ============================================================
2853
3257
  // ============================================================
2854
3258
  // SELF-CHECK - Catches issues before Arthur has to
@@ -3636,7 +4040,7 @@ const server = http.createServer((req, res) => {
3636
4040
  // Health check
3637
4041
  if (req.method === 'GET' && url.pathname === '/health') {
3638
4042
  res.writeHead(200, { 'Content-Type': 'application/json' });
3639
- res.end(JSON.stringify({ status: 'ok', service: 'nervous-system-mcp', version: '1.8.0', protocol: MCP_VERSION }));
4043
+ res.end(JSON.stringify({ status: 'ok', service: 'nervous-system-mcp', version: '1.10.0', protocol: MCP_VERSION }));
3640
4044
  return;
3641
4045
  }
3642
4046
 
@@ -3753,7 +4157,7 @@ const server = http.createServer((req, res) => {
3753
4157
  res.writeHead(200, { 'Content-Type': 'application/json' });
3754
4158
  res.end(JSON.stringify({
3755
4159
  name: 'The Nervous System MCP Server',
3756
- version: '1.8.0',
4160
+ version: '1.10.0',
3757
4161
  protocol: MCP_VERSION,
3758
4162
  description: 'LLM behavioral enforcement framework. 7 core rules, preflight checks, session handoffs, worklogs, violation logging, kill switch, hash-chained audit, and forced reflection cycles. Built by Arthur Palyan.',
3759
4163
  endpoints: {
@@ -3775,7 +4179,7 @@ const server = http.createServer((req, res) => {
3775
4179
  migrateExistingViolations();
3776
4180
 
3777
4181
  server.listen(PORT, '127.0.0.1', () => {
3778
- console.error(`[MCP Server] Nervous System v1.7.4 running on port ${PORT}`);
4182
+ console.error(`[MCP Server] Nervous System v1.10.0 running on port ${PORT}`);
3779
4183
  console.error(`[MCP Server] SSE: /sse | HTTP: /mcp | Health: /health | Kill: POST /kill | Audit: GET /audit/verify | Dispatches: GET /dispatches`);
3780
4184
  console.error(`[MCP Server] Protocol: ${MCP_VERSION}`);
3781
4185
  console.error(`[MCP Server] Tools: ${TOOLS.length} (including kill switch, audit chain, dispatch, drift audit, page health, pre-publish audit)`);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mcp-nervous-system",
3
- "version": "1.9.3",
4
- "description": "Governance layer for multi-agent AI systems. 7 mechanically enforced rules, 19 tools including kill switch, audit chain, dispatch, drift audit, security audit, page health, pre-publish audit, and session close. Works with Ruflo, Hivemind, Agent Teams, and any MCP client.",
3
+ "version": "1.10.0",
4
+ "description": "Governance layer for multi-agent AI systems. 7 mechanically enforced rules, 30 tools including kill switch, audit chain, dispatch, drift audit, security audit, page health, pre-publish audit, and session close. Works with Ruflo, Hivemind, Agent Teams, and any MCP client.",
5
5
  "main": "server.js",
6
6
  "bin": {
7
7
  "mcp-nervous-system": "./stdio.js"