mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-24 12:42:38 +00:00
chore(mcp): bump to 1.4.1 + log /mcp auth-failure paths for diagnostics
Bump version so the deployed build is visible at /health (it stayed 1.4.0 across several fixes, so neither side could tell what was live). Add one log line to each /mcp 401/403 branch in accessGuard. The success path stays quiet, but a stuck client — e.g. VS Code looping unauthenticated `initialize` — is otherwise invisible because the happy paths emit nothing. The trace records the JSON-RPC method and the failure reason so the next connection attempt is diagnosable from container logs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "autopilot-monitor-mcp",
|
||||
"version": "1.4.0",
|
||||
"version": "1.4.1",
|
||||
"description": "MCP server for Autopilot-Monitor — enables AI agents to query enrollment sessions, device properties, events and vulnerabilities",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
|
||||
@@ -202,8 +202,15 @@ export function accessGuard(req: Request, res: Response, next: NextFunction): vo
|
||||
const baseUrl = getPublicBaseUrl(req);
|
||||
const resourceMetadataUrl = `${baseUrl}/.well-known/oauth-protected-resource`;
|
||||
|
||||
// Lightweight auth-flow trace. The success path stays quiet (runWithCaller →
|
||||
// next), but every 401/403 logs one line so a stuck client (e.g. VS Code
|
||||
// looping unauthenticated `initialize`) is visible in container logs — the
|
||||
// happy paths otherwise emit nothing and the flow is a black box.
|
||||
const rpcMethod = (req.body as { method?: string } | undefined)?.method ?? '?';
|
||||
|
||||
const authHeader = req.headers.authorization;
|
||||
if (!authHeader?.startsWith('Bearer ')) {
|
||||
console.error(`[mcp-auth] 401 no-bearer (method=${rpcMethod}) — client has not attached a token yet`);
|
||||
res.setHeader('WWW-Authenticate', `Bearer resource_metadata="${resourceMetadataUrl}"`);
|
||||
res.status(401).json({ error: 'Missing or invalid Authorization header' });
|
||||
return;
|
||||
@@ -212,12 +219,14 @@ export function accessGuard(req: Request, res: Response, next: NextFunction): vo
|
||||
const token = authHeader.slice(7);
|
||||
const claims = extractTokenClaims(token);
|
||||
if (!claims || !claims.upn) {
|
||||
console.error(`[mcp-auth] 401 invalid-token-claims (method=${rpcMethod})`);
|
||||
res.setHeader('WWW-Authenticate', `Bearer resource_metadata="${resourceMetadataUrl}", error="invalid_token"`);
|
||||
res.status(401).json({ error: 'Invalid token: missing required claims' });
|
||||
return;
|
||||
}
|
||||
|
||||
if (isTokenExpired(claims)) {
|
||||
console.error(`[mcp-auth] 401 token-expired (method=${rpcMethod}, upn=${claims.upn})`);
|
||||
res.setHeader('WWW-Authenticate', `Bearer resource_metadata="${resourceMetadataUrl}", error="invalid_token"`);
|
||||
res.status(401).json({ error: 'Token expired' });
|
||||
return;
|
||||
@@ -242,9 +251,11 @@ export function accessGuard(req: Request, res: Response, next: NextFunction): vo
|
||||
// Backend could not reach a verdict (unreachable / malformed). Fail
|
||||
// closed, but do NOT tell the user they are "not whitelisted" — it is
|
||||
// not their fault and would send them chasing the wrong fix.
|
||||
console.error(`[mcp-auth] 403 access-check-unavailable (method=${rpcMethod}, upn=${upn})`);
|
||||
res.status(403).json({ error: 'MCP access check unavailable', reason: result.reason });
|
||||
return;
|
||||
}
|
||||
console.error(`[mcp-auth] 403 not-whitelisted (method=${rpcMethod}, upn=${upn})`);
|
||||
// Genuine authorization denial — most commonly the user's account is not
|
||||
// on the MCP whitelist. Spell that out and tell them what to do, so they
|
||||
// can ask the MCP server owner to enable their account instead of being
|
||||
|
||||
Reference in New Issue
Block a user