Sign In

@mcpspend/proxy

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@mcpspend/proxy - npm Package Compare versions

Comparing version
0.5.0
to
0.5.1
+1
-1
dist/cli.js

@@ -9,3 +9,3 @@ #!/usr/bin/env node

const http_bridge_js_1 = require("./http-bridge.js");
const VERSION = '0.5.0';
const VERSION = '0.5.1';
const HELP = `mcpspend — observability proxy for MCP servers (v${VERSION})

@@ -12,0 +12,0 @@

@@ -42,2 +42,13 @@ import { ClientDefinition, WrapResult } from './clients.js';

endpointError?: string;
account?: {
orgName: string;
plan: string;
callsThisMonth: number;
callsLimit: number;
};
lastCall?: {
serverName: string;
toolName: string;
calledAt: string;
} | null;
clients: Array<{

@@ -44,0 +55,0 @@ client: ClientDefinition['id'];

@@ -224,9 +224,9 @@ "use strict";

});
const baseUrl = cfg.endpoint || 'https://api.mcpspend.com';
let endpointReachable;
let endpointError;
try {
const url = (cfg.endpoint || 'https://api.mcpspend.com') + '/health';
const ac = new AbortController();
const timer = setTimeout(() => ac.abort(), 5000);
const resp = await fetch(url, { signal: ac.signal });
const resp = await fetch(baseUrl + '/health', { signal: ac.signal });
clearTimeout(timer);

@@ -241,2 +241,60 @@ endpointReachable = resp.ok;

}
// Probe the key — gives users actionable confirmation that the key resolves,
// which org it points at, and current usage. We catch every error so doctor
// never crashes on a broken backend; account just stays undefined.
let account;
let lastCall;
const key = process.env.MCPSPEND_API_KEY || cfg.apiKey;
if (key && endpointReachable) {
try {
const ac = new AbortController();
const timer = setTimeout(() => ac.abort(), 5000);
const r = await fetch(baseUrl + '/api/stats/sessions?limit=1', {
headers: { Authorization: `Bearer ${key}` },
signal: ac.signal,
});
clearTimeout(timer);
if (r.ok) {
const sessions = (await r.json());
if (sessions[0]) {
// No per-call endpoint here — last session's startedAt is the cheapest
// proxy for "we've seen activity recently".
lastCall = {
serverName: 'session',
toolName: sessions[0].id,
calledAt: sessions[0].startedAt,
};
}
else {
lastCall = null;
}
}
}
catch {
// ignore — best-effort
}
// Org/plan probe via /api/auth/me equivalent — API keys reach this through
// the same auth middleware but only get back their own org details.
try {
const ac = new AbortController();
const timer = setTimeout(() => ac.abort(), 5000);
const r = await fetch(baseUrl + '/api/organizations/current', {
headers: { Authorization: `Bearer ${key}` },
signal: ac.signal,
});
clearTimeout(timer);
if (r.ok) {
const org = (await r.json());
account = {
orgName: org.name,
plan: org.plan,
callsThisMonth: org.callsThisMonth,
callsLimit: org.callsLimit,
};
}
}
catch {
// ignore
}
}
return {

@@ -248,2 +306,4 @@ cliVersion,

endpointError,
account,
lastCall,
clients,

@@ -258,2 +318,19 @@ };

lines.push(`Endpoint: ${report.endpointReachable ? '✓ reachable' : `✗ ${report.endpointError || 'unreachable'}`}`);
if (report.account) {
const a = report.account;
const pct = a.callsLimit > 0 ? Math.round((a.callsThisMonth / a.callsLimit) * 100) : 0;
lines.push(`Account: ✓ ${a.orgName} (${a.plan})`);
lines.push(`Usage: ${a.callsThisMonth.toLocaleString()} / ${a.callsLimit.toLocaleString()} calls this month (${pct}%)`);
}
else if (report.apiKeyConfigured && report.endpointReachable) {
lines.push(`Account: ✗ API key was rejected — generate a new one at https://mcpspend.com/dashboard/keys`);
}
if (report.lastCall) {
const when = report.lastCall.calledAt;
const ago = humanAgo(new Date(when));
lines.push(`Last call: ${ago}`);
}
else if (report.account) {
lines.push(`Last call: none yet — make any tool call in your MCP client and it shows up here within seconds`);
}
lines.push('');

@@ -277,1 +354,15 @@ lines.push('Clients:');

}
function humanAgo(d) {
const ms = Date.now() - d.getTime();
const s = Math.floor(ms / 1000);
if (s < 60)
return `${s}s ago`;
const m = Math.floor(s / 60);
if (m < 60)
return `${m}m ago`;
const h = Math.floor(m / 60);
if (h < 24)
return `${h}h ago`;
const days = Math.floor(h / 24);
return `${days}d ago`;
}
{
"name": "@mcpspend/proxy",
"version": "0.5.0",
"version": "0.5.1",
"description": "Transparent proxy CLI for MCP servers — tracks tool calls, latency, and cost via MCPSpend.",

@@ -5,0 +5,0 @@ "license": "MIT",