Fix all ESLint errors

- Remove unused imports and variables
- Replace 'any' types with proper type guards
- Add comments to empty catch blocks
- Fix Response/Request type imports in logger
- Use 'unknown' instead of 'any' for generic types
- Remove unused createMcpServer and setSessionOwner imports

All ESLint checks now pass.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Jerome 2025-07-10 16:52:32 +01:00
commit c6f3f40937
No known key found for this signature in database
5 changed files with 41 additions and 38 deletions

View file

@ -1,10 +1,10 @@
import { jest } from '@jest/globals'; import { jest } from '@jest/globals';
import { Request, Response } from 'express'; import { Request, Response } from 'express';
import { JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js'; import { JSONRPCMessage, JSONRPCResponse } from '@modelcontextprotocol/sdk/types.js';
import { MockRedisClient, setRedisClient } from '../redis.js'; import { MockRedisClient, setRedisClient } from '../redis.js';
import { handleStreamableHTTP } from './shttp.js'; import { handleStreamableHTTP } from './shttp.js';
import { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js'; import { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js';
import { randomUUID } from 'crypto'; // import { randomUUID } from 'crypto'; // Currently unused but may be needed for future tests
import { shutdownSession } from '../services/redisTransport.js'; import { shutdownSession } from '../services/redisTransport.js';
describe('Streamable HTTP Handler Integration Tests', () => { describe('Streamable HTTP Handler Integration Tests', () => {
@ -147,7 +147,6 @@ describe('Streamable HTTP Handler Integration Tests', () => {
}); });
it('should handle cleanup errors gracefully', async () => { it('should handle cleanup errors gracefully', async () => {
const sessionId = randomUUID();
const initRequest: JSONRPCMessage = { const initRequest: JSONRPCMessage = {
jsonrpc: '2.0', jsonrpc: '2.0',
id: 'init-1', id: 'init-1',
@ -176,7 +175,6 @@ describe('Streamable HTTP Handler Integration Tests', () => {
)?.[1] as (() => Promise<void>) | undefined; )?.[1] as (() => Promise<void>) | undefined;
// Simulate error during cleanup // Simulate error during cleanup
const originalSimulateError = mockRedis.simulateError.bind(mockRedis);
// Cleanup should not throw error even if Redis operations fail // Cleanup should not throw error even if Redis operations fail
if (finishHandler) { if (finishHandler) {
@ -240,7 +238,7 @@ describe('Streamable HTTP Handler Integration Tests', () => {
let sessionId: string | undefined; let sessionId: string | undefined;
if (jsonCalls.length > 0) { if (jsonCalls.length > 0) {
const response = jsonCalls[0][0] as any; const response = jsonCalls[0][0] as JSONRPCResponse;
if (response?.result?._meta?.sessionId) { if (response?.result?._meta?.sessionId) {
sessionId = response.result._meta.sessionId; sessionId = response.result._meta.sessionId;
} }
@ -254,11 +252,11 @@ describe('Streamable HTTP Handler Integration Tests', () => {
try { try {
// SSE data format: "data: {...}\n\n" // SSE data format: "data: {...}\n\n"
const jsonStr = data.replace(/^data: /, '').trim(); const jsonStr = data.replace(/^data: /, '').trim();
const parsed = JSON.parse(jsonStr) as any; const parsed = JSON.parse(jsonStr) as JSONRPCResponse;
if (parsed?.result?._meta?.sessionId) { if (parsed?.result?._meta?.sessionId) {
sessionId = parsed.result._meta.sessionId; sessionId = parsed.result._meta.sessionId;
} }
} catch (e) { } catch {
// Not valid JSON, continue // Not valid JSON, continue
} }
} }
@ -344,7 +342,7 @@ describe('Streamable HTTP Handler Integration Tests', () => {
// Check JSON responses // Check JSON responses
const jsonCalls = (mockRes.json as jest.Mock).mock.calls; const jsonCalls = (mockRes.json as jest.Mock).mock.calls;
if (jsonCalls.length > 0) { if (jsonCalls.length > 0) {
const response = jsonCalls[0][0] as any; const response = jsonCalls[0][0] as JSONRPCResponse;
if (response?.result?._meta?.sessionId) { if (response?.result?._meta?.sessionId) {
sessionId = response.result._meta.sessionId; sessionId = response.result._meta.sessionId;
} }
@ -357,11 +355,13 @@ describe('Streamable HTTP Handler Integration Tests', () => {
if (typeof data === 'string' && data.includes('sessionId')) { if (typeof data === 'string' && data.includes('sessionId')) {
try { try {
const jsonStr = data.replace(/^data: /, '').trim(); const jsonStr = data.replace(/^data: /, '').trim();
const parsed = JSON.parse(jsonStr) as any; const parsed = JSON.parse(jsonStr) as JSONRPCResponse;
if (parsed?.result?._meta?.sessionId) { if (parsed?.result?._meta?.sessionId) {
sessionId = parsed.result._meta.sessionId; sessionId = parsed.result._meta.sessionId;
} }
} catch (e) {} } catch {
// Ignore JSON parse errors
}
} }
} }
} }
@ -442,7 +442,7 @@ describe('Streamable HTTP Handler Integration Tests', () => {
// Check JSON responses // Check JSON responses
const jsonCalls = (mockRes.json as jest.Mock).mock.calls; const jsonCalls = (mockRes.json as jest.Mock).mock.calls;
if (jsonCalls.length > 0) { if (jsonCalls.length > 0) {
const response = jsonCalls[0][0] as any; const response = jsonCalls[0][0] as JSONRPCResponse;
if (response?.result?._meta?.sessionId) { if (response?.result?._meta?.sessionId) {
actualSessionId = response.result._meta.sessionId; actualSessionId = response.result._meta.sessionId;
} }
@ -459,7 +459,9 @@ describe('Streamable HTTP Handler Integration Tests', () => {
if (parsed?.result?._meta?.sessionId) { if (parsed?.result?._meta?.sessionId) {
actualSessionId = parsed.result._meta.sessionId; actualSessionId = parsed.result._meta.sessionId;
} }
} catch (e) {} } catch {
// Ignore JSON parse errors
}
} }
} }
} }
@ -658,8 +660,7 @@ describe('Streamable HTTP Handler Integration Tests', () => {
await finishHandler2(); await finishHandler2();
} }
// Track session 2 ID // Track session 2 ID (placeholder for actual implementation)
const session2Id = 'user2-session-id';
// User 1 deletes their session // User 1 deletes their session
jest.clearAllMocks(); jest.clearAllMocks();

View file

@ -4,8 +4,7 @@ import { MockRedisClient, setRedisClient } from '../redis.js';
import { import {
ServerRedisTransport, ServerRedisTransport,
redisRelayToMcpServer, redisRelayToMcpServer,
shutdownSession, shutdownSession
setSessionOwner
} from './redisTransport.js'; } from './redisTransport.js';
import { createMcpServer } from './mcp.js'; import { createMcpServer } from './mcp.js';
import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js'; import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';

View file

@ -12,7 +12,6 @@ import {
isSessionOwnedBy isSessionOwnedBy
} from './redisTransport.js'; } from './redisTransport.js';
import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js'; import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
import { createMcpServer } from './mcp.js';
describe('Redis Transport', () => { describe('Redis Transport', () => {
let mockRedis: MockRedisClient; let mockRedis: MockRedisClient;

View file

@ -28,8 +28,8 @@ function sendToMcpServer(sessionId: string, message: JSONRPCMessage, extra?: { a
logger.debug('Sending message to MCP server via Redis', { logger.debug('Sending message to MCP server via Redis', {
sessionId, sessionId,
channel: toServerChannel, channel: toServerChannel,
method: (message as any).method, method: ('method' in message ? message.method : undefined),
id: (message as any).id id: ('id' in message ? message.id : undefined)
}); });
const redisMessage: RedisMessage = { type: 'mcp', message, extra, options }; const redisMessage: RedisMessage = { type: 'mcp', message, extra, options };
@ -125,7 +125,7 @@ export async function redisRelayToMcpServer(sessionId: string, transport: Transp
logger.debug('Relaying message from Redis to client', { logger.debug('Relaying message from Redis to client', {
sessionId, sessionId,
requestId, requestId,
method: (redisMessage.message as any).method method: ('method' in redisMessage.message ? redisMessage.message.method : undefined)
}); });
await transport.send(redisMessage.message, redisMessage.options); await transport.send(redisMessage.message, redisMessage.options);
} }
@ -148,7 +148,7 @@ export async function redisRelayToMcpServer(sessionId: string, transport: Transp
logger.debug('Setting up response subscription', { logger.debug('Setting up response subscription', {
sessionId, sessionId,
messageId: message.id, messageId: message.id,
method: (message as any).method method: ('method' in message ? message.method : undefined)
}); });
await subscribe(message.id.toString()); await subscribe(message.id.toString());
} }
@ -235,8 +235,8 @@ export class ServerRedisTransport implements Transport {
logger.debug('Received MCP message from client', { logger.debug('Received MCP message from client', {
sessionId: this._sessionId, sessionId: this._sessionId,
method: (redisMessage.message as any).method, method: ('method' in redisMessage.message ? redisMessage.message.method : undefined),
id: (redisMessage.message as any).id id: ('id' in redisMessage.message ? redisMessage.message.id : undefined)
}); });
this.onmessage?.(redisMessage.message, redisMessage.extra); this.onmessage?.(redisMessage.message, redisMessage.extra);
@ -295,8 +295,8 @@ export class ServerRedisTransport implements Transport {
logger.debug('Sending message to client', { logger.debug('Sending message to client', {
sessionId: this._sessionId, sessionId: this._sessionId,
channel, channel,
method: (message as any).method, method: ('method' in message ? message.method : undefined),
id: (message as any).id, id: ('id' in message ? message.id : undefined),
relatedRequestId relatedRequestId
}); });

View file

@ -1,5 +1,5 @@
import { AsyncLocalStorage } from 'async_hooks'; import { AsyncLocalStorage } from 'async_hooks';
import { Request } from 'express'; import { Request, Response, NextFunction } from 'express';
// Severity levels as per Google Cloud Logging // Severity levels as per Google Cloud Logging
export enum LogSeverity { export enum LogSeverity {
@ -17,7 +17,11 @@ export enum LogSeverity {
interface LogContext { interface LogContext {
trace?: string; trace?: string;
spanId?: string; spanId?: string;
[key: string]: any; requestId?: string;
userAgent?: string;
method?: string;
path?: string;
[key: string]: string | undefined;
} }
interface StructuredLogEntry { interface StructuredLogEntry {
@ -26,7 +30,7 @@ interface StructuredLogEntry {
timestamp: string; timestamp: string;
'logging.googleapis.com/trace'?: string; 'logging.googleapis.com/trace'?: string;
'logging.googleapis.com/spanId'?: string; 'logging.googleapis.com/spanId'?: string;
[key: string]: any; [key: string]: unknown;
} }
class StructuredLogger { class StructuredLogger {
@ -73,7 +77,7 @@ class StructuredLogger {
* Create Express middleware for request context * Create Express middleware for request context
*/ */
middleware() { middleware() {
return (req: Request, res: any, next: any) => { return (req: Request, res: Response, next: NextFunction) => {
const context = this.extractTraceContext(req); const context = this.extractTraceContext(req);
this.runWithContext(context, () => { this.runWithContext(context, () => {
next(); next();
@ -84,7 +88,7 @@ class StructuredLogger {
/** /**
* Log a structured message * Log a structured message
*/ */
private log(severity: LogSeverity, message: string, metadata?: Record<string, any>) { private log(severity: LogSeverity, message: string, metadata?: Record<string, unknown>) {
const context = this.asyncLocalStorage.getStore() || {}; const context = this.asyncLocalStorage.getStore() || {};
const entry: StructuredLogEntry = { const entry: StructuredLogEntry = {
@ -114,23 +118,23 @@ class StructuredLogger {
} }
// Convenience methods for different severity levels // Convenience methods for different severity levels
debug(message: string, metadata?: Record<string, any>) { debug(message: string, metadata?: Record<string, unknown>) {
this.log(LogSeverity.DEBUG, message, metadata); this.log(LogSeverity.DEBUG, message, metadata);
} }
info(message: string, metadata?: Record<string, any>) { info(message: string, metadata?: Record<string, unknown>) {
this.log(LogSeverity.INFO, message, metadata); this.log(LogSeverity.INFO, message, metadata);
} }
notice(message: string, metadata?: Record<string, any>) { notice(message: string, metadata?: Record<string, unknown>) {
this.log(LogSeverity.NOTICE, message, metadata); this.log(LogSeverity.NOTICE, message, metadata);
} }
warning(message: string, metadata?: Record<string, any>) { warning(message: string, metadata?: Record<string, unknown>) {
this.log(LogSeverity.WARNING, message, metadata); this.log(LogSeverity.WARNING, message, metadata);
} }
error(message: string, error?: Error, metadata?: Record<string, any>) { error(message: string, error?: Error, metadata?: Record<string, unknown>) {
const errorMetadata = { const errorMetadata = {
...metadata, ...metadata,
error: error ? { error: error ? {
@ -142,15 +146,15 @@ class StructuredLogger {
this.log(LogSeverity.ERROR, message, errorMetadata); this.log(LogSeverity.ERROR, message, errorMetadata);
} }
critical(message: string, metadata?: Record<string, any>) { critical(message: string, metadata?: Record<string, unknown>) {
this.log(LogSeverity.CRITICAL, message, metadata); this.log(LogSeverity.CRITICAL, message, metadata);
} }
alert(message: string, metadata?: Record<string, any>) { alert(message: string, metadata?: Record<string, unknown>) {
this.log(LogSeverity.ALERT, message, metadata); this.log(LogSeverity.ALERT, message, metadata);
} }
emergency(message: string, metadata?: Record<string, any>) { emergency(message: string, metadata?: Record<string, unknown>) {
this.log(LogSeverity.EMERGENCY, message, metadata); this.log(LogSeverity.EMERGENCY, message, metadata);
} }