fix: replace any types with proper TypeScript types

Replace all `any` types with properly defined TypeScript interfaces and types throughout the codebase to improve type safety and eliminate type-related code quality issues.

Changes:
- Define ElectronSafeStorage interface for Electron's safeStorage API
- Create LegacySettings interface for settings migration in main.ts
- Define JSONValue, JSONRPCParams types for JSON-RPC protocol
- Define JSONSchemaProperty for tool input schemas
- Create YAMLValue type for frontmatter values
- Define FrontmatterValue type for adapter interfaces
- Update middleware to use proper Express NextFunction and JSONRPCResponse types
- Fix tool registry to handle args with proper typing (with eslint-disable for dynamic dispatch)
- Fix notifications to use proper types with eslint-disable where dynamic access is needed
- Add proper null safety assertions where appropriate
- Fix TFolder stat access with proper type extension

All type errors resolved. TypeScript compilation passes with --skipLibCheck.
This commit is contained in:
2025-11-07 11:10:52 -05:00
parent b0fc0be629
commit 2a7fce45af
13 changed files with 127 additions and 50 deletions

View File

@@ -4,6 +4,8 @@ import { Server } from 'http';
import {
JSONRPCRequest,
JSONRPCResponse,
JSONRPCParams,
JSONValue,
ErrorCodes,
InitializeResult,
ListToolsResult,
@@ -36,11 +38,11 @@ export class MCPServer {
try {
switch (request.method) {
case 'initialize':
return this.createSuccessResponse(request.id, await this.handleInitialize(request.params));
return this.createSuccessResponse(request.id, await this.handleInitialize(request.params ?? {}));
case 'tools/list':
return this.createSuccessResponse(request.id, await this.handleListTools());
case 'tools/call':
return this.createSuccessResponse(request.id, await this.handleCallTool(request.params));
return this.createSuccessResponse(request.id, await this.handleCallTool(request.params ?? {}));
case 'ping':
return this.createSuccessResponse(request.id, {});
default:
@@ -52,7 +54,7 @@ export class MCPServer {
}
}
private async handleInitialize(_params: any): Promise<InitializeResult> {
private async handleInitialize(_params: JSONRPCParams): Promise<InitializeResult> {
return {
protocolVersion: "2024-11-05",
capabilities: {
@@ -71,20 +73,20 @@ export class MCPServer {
};
}
private async handleCallTool(params: any): Promise<CallToolResult> {
const { name, arguments: args } = params;
return await this.toolRegistry.callTool(name, args);
private async handleCallTool(params: JSONRPCParams): Promise<CallToolResult> {
const paramsObj = params as { name: string; arguments: Record<string, unknown> };
return await this.toolRegistry.callTool(paramsObj.name, paramsObj.arguments);
}
private createSuccessResponse(id: string | number | undefined, result: any): JSONRPCResponse {
private createSuccessResponse(id: string | number | undefined, result: unknown): JSONRPCResponse {
return {
jsonrpc: "2.0",
id: id ?? null,
result
result: result as JSONValue
};
}
private createErrorResponse(id: string | number | undefined | null, code: number, message: string, data?: any): JSONRPCResponse {
private createErrorResponse(id: string | number | undefined | null, code: number, message: string, data?: JSONValue): JSONRPCResponse {
return {
jsonrpc: "2.0",
id: id ?? null,
@@ -104,7 +106,7 @@ export class MCPServer {
resolve();
});
this.server.on('error', (error: any) => {
this.server.on('error', (error: NodeJS.ErrnoException) => {
if (error.code === 'EADDRINUSE') {
reject(new Error(`Port ${this.settings.port} is already in use`));
} else {

View File

@@ -1,10 +1,10 @@
import { Express, Request, Response } from 'express';
import { Express, Request, Response, NextFunction } from 'express';
import express from 'express';
import cors from 'cors';
import { MCPServerSettings } from '../types/settings-types';
import { ErrorCodes } from '../types/mcp-types';
import { ErrorCodes, JSONRPCResponse } from '../types/mcp-types';
export function setupMiddleware(app: Express, settings: MCPServerSettings, createErrorResponse: (id: any, code: number, message: string) => any): void {
export function setupMiddleware(app: Express, settings: MCPServerSettings, createErrorResponse: (id: string | number | null, code: number, message: string) => JSONRPCResponse): void {
// Parse JSON bodies
app.use(express.json());
@@ -29,7 +29,7 @@ export function setupMiddleware(app: Express, settings: MCPServerSettings, creat
app.use(cors(corsOptions));
// Authentication middleware - Always enabled
app.use((req: Request, res: Response, next: any) => {
app.use((req: Request, res: Response, next: NextFunction) => {
// Defensive check: if no API key is set, reject all requests
if (!settings.apiKey || settings.apiKey.trim() === '') {
return res.status(500).json(createErrorResponse(null, ErrorCodes.InternalError, 'Server misconfigured: No API key set'));
@@ -45,7 +45,7 @@ export function setupMiddleware(app: Express, settings: MCPServerSettings, creat
});
// Origin validation for security (DNS rebinding protection)
app.use((req: Request, res: Response, next: any) => {
app.use((req: Request, res: Response, next: NextFunction) => {
const host = req.headers.host;
// Only allow localhost connections

View File

@@ -2,9 +2,9 @@ import { Express, Request, Response } from 'express';
import { JSONRPCRequest, JSONRPCResponse, ErrorCodes } from '../types/mcp-types';
export function setupRoutes(
app: Express,
app: Express,
handleRequest: (request: JSONRPCRequest) => Promise<JSONRPCResponse>,
createErrorResponse: (id: any, code: number, message: string) => JSONRPCResponse
createErrorResponse: (id: string | number | null, code: number, message: string) => JSONRPCResponse
): void {
// Main MCP endpoint
app.post('/mcp', async (req: Request, res: Response) => {