local-model-suitability-mcp 1.1.22 → 1.1.23

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/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.1.23] - 2026-06-25
4
+ - feat: calls_remaining field added to check_local_viability response -- "unlimited" for paid keys, numeric free-tier headroom otherwise (HTTP POST and stdio transports)
5
+ - feat: verdict_ttl field added (86400s/24h)
6
+ - feat: data_source_status field added (full/degraded) -- "degraded" when Anthropic responds but returns unparseable output and a fallback verdict is used; "full" otherwise, including the CONFIDENTIAL local-rule shortcut which never calls Anthropic
7
+
3
8
  ## [1.1.22] - 2026-06-24
4
9
  - feat: unauthenticated /public-stats endpoint -- first_deployed, lifetime tool calls, uptime %, version, for agent orchestrators evaluating server trustworthiness
5
10
  - feat: /process-trial-followups endpoint + 24h follow-up record on trial-extension grant
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "local-model-suitability-mcp",
3
3
  "mcpName": "io.github.OjasKord/local-model-suitability-mcp",
4
- "version": "1.1.22",
4
+ "version": "1.1.23",
5
5
  "description": "AI model router for agents. Checks whether a local model can handle the task before calling cloud inference. LOCAL/CLOUD verdict saves cost on every call.",
6
6
  "main": "src/server.js",
7
7
  "type": "module",
package/server.json CHANGED
@@ -1,36 +1,36 @@
1
- {
2
- "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
- "name": "io.github.OjasKord/local-model-suitability-mcp",
4
- "title": "Local Model Suitability MCP",
5
- "description": "Check if a task runs locally vs cloud. Save money on calls that don't need cloud inference.",
6
- "version": "1.1.16",
7
- "websiteUrl": "https://kordagencies.com",
8
- "repository": {
9
- "url": "https://github.com/OjasKord/local-model-suitability-mcp",
10
- "source": "github"
11
- },
12
- "packages": [
13
- {
14
- "registryType": "npm",
15
- "identifier": "local-model-suitability-mcp",
16
- "version": "1.1.16",
17
- "transport": {
18
- "type": "stdio"
19
- },
20
- "environmentVariables": [
21
- {
22
- "name": "ANTHROPIC_API_KEY",
23
- "description": "Anthropic API key for Claude routing analysis",
24
- "isRequired": true,
25
- "isSecret": true
26
- }
27
- ]
28
- }
29
- ],
30
- "remotes": [
31
- {
32
- "type": "streamable-http",
33
- "url": "https://local-model-suitability-mcp-production.up.railway.app"
34
- }
35
- ]
36
- }
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.OjasKord/local-model-suitability-mcp",
4
+ "title": "Local Model Suitability MCP",
5
+ "description": "Check if a task runs locally vs cloud. Save money on calls that don't need cloud inference.",
6
+ "version": "1.1.23",
7
+ "websiteUrl": "https://kordagencies.com",
8
+ "repository": {
9
+ "url": "https://github.com/OjasKord/local-model-suitability-mcp",
10
+ "source": "github"
11
+ },
12
+ "packages": [
13
+ {
14
+ "registryType": "npm",
15
+ "identifier": "local-model-suitability-mcp",
16
+ "version": "1.1.23",
17
+ "transport": {
18
+ "type": "stdio"
19
+ },
20
+ "environmentVariables": [
21
+ {
22
+ "name": "ANTHROPIC_API_KEY",
23
+ "description": "Anthropic API key for Claude routing analysis",
24
+ "isRequired": true,
25
+ "isSecret": true
26
+ }
27
+ ]
28
+ }
29
+ ],
30
+ "remotes": [
31
+ {
32
+ "type": "streamable-http",
33
+ "url": "https://local-model-suitability-mcp-production.up.railway.app"
34
+ }
35
+ ]
36
+ }
package/src/server.js CHANGED
@@ -3,7 +3,7 @@ import { createHmac, timingSafeEqual } from 'crypto';
3
3
  import { readFileSync, writeFileSync } from 'fs';
4
4
  import Anthropic from '@anthropic-ai/sdk';
5
5
 
6
- const VERSION = '1.1.22';
6
+ const VERSION = '1.1.23';
7
7
  const FIRST_DEPLOYED = '2026-04-13T06:41:38Z';
8
8
  const LIFETIME_CALLS_REDIS_KEY = 'lms:lifetime_calls';
9
9
  const UPTIME_HEARTBEAT_KEY = 'lms:uptime:heartbeat_count';
@@ -16,6 +16,8 @@ const ENTERPRISE_UPGRADE_URL = 'https://buy.stripe.com/28E9AS27PbPvfkoe7Sebu0q';
16
16
  const ALLOWED_PAYMENT_LINK_IDS = ['plink_1TQzCBD6WvRe6sn3H1q5t2LF', 'plink_1TQzDSD6WvRe6sn3UM2G1EgX'];
17
17
  const PERSIST_FILE = '/tmp/lms_stats.json';
18
18
  const LEGAL_DISCLAIMER = 'AI-powered routing analysis. We do not log or store your task content. Results are for cost-optimisation guidance only. Provider maximum liability is limited to subscription fees paid in the preceding 3 months. Full terms: kordagencies.com/terms.html';
19
+ // Caching/staleness policy per tool, in seconds.
20
+ const VERDICT_TTL = { check_local_viability: 86400 };
19
21
 
20
22
  function nowISO() { return new Date().toISOString(); }
21
23
 
@@ -382,6 +384,8 @@ async function checkLocalViability(task, qualityThreshold, dataSensitivity) {
382
384
  cloud_justified_reason: null,
383
385
  data_sensitivity_override: true,
384
386
  analysis_type: 'AI-powered cost routing — NOT a simple lookup',
387
+ verdict_ttl: VERDICT_TTL.check_local_viability,
388
+ data_source_status: 'full',
385
389
  _disclaimer: LEGAL_DISCLAIMER
386
390
  };
387
391
  }
@@ -429,6 +433,7 @@ Respond ONLY with a JSON object — no markdown, no explanation outside the JSON
429
433
 
430
434
  const raw = response.content[0].text.trim();
431
435
  let parsed;
436
+ let aiDegraded = false;
432
437
  try {
433
438
  parsed = JSON.parse(raw);
434
439
  } catch(e) {
@@ -441,6 +446,7 @@ Respond ONLY with a JSON object — no markdown, no explanation outside the JSON
441
446
  recommended_local_models: ['llama3.2:8b', 'mistral-7b'],
442
447
  cloud_justified_reason: null
443
448
  };
449
+ aiDegraded = true;
444
450
  }
445
451
 
446
452
  const _rLms = {
@@ -448,6 +454,8 @@ Respond ONLY with a JSON object — no markdown, no explanation outside the JSON
448
454
  task_quality_threshold: quality,
449
455
  data_sensitivity: sensitivity,
450
456
  analysis_type: 'AI-powered cost routing — NOT a simple lookup',
457
+ verdict_ttl: VERDICT_TTL.check_local_viability,
458
+ data_source_status: aiDegraded ? 'degraded' : 'full',
451
459
  checked_at: nowISO(),
452
460
  _disclaimer: LEGAL_DISCLAIMER
453
461
  };
@@ -890,9 +898,11 @@ const server = createServer(async (req, res) => {
890
898
  redisIncr(LIFETIME_CALLS_REDIS_KEY).catch(() => {});
891
899
  logCall('check_local_viability', access.tier, clientIp);
892
900
  appendSessionLog(clientIp, 'check_local_viability').catch((e) => console.error('[SessionLog] appendSessionLog failed:', e));
901
+ const callsRemaining = access.tier === 'free' ? Math.max(0, FREE_TIER_LIMIT - getFreeTierCount(clientIp)) : 'unlimited';
893
902
 
894
903
  try {
895
904
  const result = await checkLocalViability(task, quality_threshold, data_sensitivity);
905
+ result.calls_remaining = callsRemaining;
896
906
 
897
907
  // Partial response for free tier
898
908
  if (access.tier === 'free') {
@@ -902,6 +912,7 @@ const server = createServer(async (req, res) => {
902
912
  reason: result.reason,
903
913
  analysis_type: result.analysis_type,
904
914
  checked_at: result.checked_at,
915
+ calls_remaining: result.calls_remaining,
905
916
  _disclaimer: result._disclaimer,
906
917
  upgrade_url: PRO_UPGRADE_URL
907
918
  };
@@ -977,6 +988,7 @@ function setupStdio() {
977
988
  } else {
978
989
  try {
979
990
  const result = await checkLocalViability(task, quality_threshold, data_sensitivity);
991
+ result.calls_remaining = 'unlimited';
980
992
  response = { jsonrpc: '2.0', id: req.id, result: { content: [{ type: 'text', text: JSON.stringify(result) }] } };
981
993
  } catch(e) {
982
994
  response = { jsonrpc: '2.0', id: req.id, result: { content: [{ type: 'text', text: JSON.stringify({ error: e.message, likely_cause: 'AI routing analysis failed — transient Anthropic API issue', retryable: true, retry_after_ms: 120000, fallback_tool: null, agent_action: 'RETRY_IN_2_MIN', category: 'ai_failure', trace_id: nowISO(), _disclaimer: LEGAL_DISCLAIMER }) }] } };