-
Notifications
You must be signed in to change notification settings - Fork 2
Description
GitHub Issue #7: TypeScript Compatibility: protect() method forces type conversion causing integration errors
Issue Type
🐛 Bug Report
Summary
The SDK's protect() method has a rigid type signature that forces all handlers to the MCPHandler type, causing TypeScript errors when integrating with the MCP TypeScript SDK and other frameworks that have specific handler type signatures.
Current Behavior
The current method signature forces type conversion:
protect(tokenId: number | number[], handler: MCPHandler): MCPHandlerWhen developers use handlers with specific type signatures from their MCP framework:
// MCP TypeScript SDK handler with specific types
type SpecificMCPHandler = (
request: MCPRequest,
extra?: { session?: string }
) => Promise<MCPResponse>;
const myHandler: SpecificMCPHandler = async (request, extra) => {
const sessionId = extra?.session; // TypeScript knows this is string | undefined
return { content: [{ type: 'text', text: 'Result' }] };
};
// This causes TypeScript error
const protectedHandler = radius.protect(101, myHandler);
// ❌ Error: Type 'MCPHandler' is not assignable to type 'SpecificMCPHandler'
// Developers must use type assertion as workaround
const protectedHandler = radius.protect(101, myHandler) as SpecificMCPHandler;This also affects FastMCP and other framework integrations:
// FastMCP handler
type FastMCPHandler = (args: any) => Promise<{ result: string }>;
const fastHandler: FastMCPHandler = async (args) => {
return { result: 'success' };
};
// ❌ Type error: loses FastMCP-specific return type
const protected = radius.protect(102, fastHandler);Expected Behavior
The protect() method should preserve the original handler's type signature, allowing seamless integration without type errors or requiring type assertions. The protected handler should maintain the exact same type as the input handler.
Steps to Reproduce
- Install Radius MCP SDK in a TypeScript project with strict mode
- Create a handler with specific type signature from MCP TypeScript SDK
- Apply
protect()to the handler - Observe TypeScript error about type incompatibility
- Note that type assertion is required as workaround
Developer Experience Impact
Current Developer Experience
- TypeScript Errors on Integration: Every protected handler causes type errors with framework-specific handlers
- Type Assertion Workarounds: Developers must add
as TypeOfHandlerafter everyprotect()call - Lost Type Safety: Type assertions bypass TypeScript's type checking, potentially hiding real issues
- Poor IntelliSense: IDE autocomplete breaks due to forced type conversion
- Integration Friction: What should be a simple one-line protection requires additional type management
Expected Developer Experience
- Seamless Type Preservation: Protected handlers maintain their original type signatures
- No Type Assertions Needed: Clean, readable code without workarounds
- Full Type Safety: TypeScript validates the actual handler types throughout
- Perfect IntelliSense: IDE autocomplete works correctly with protected handlers
- Zero-Friction Integration: Works out-of-the-box with any MCP framework
Impact
- Critical: Blocks adoption for teams using TypeScript strict mode
- Affects: All TypeScript users integrating with MCP TypeScript SDK, FastMCP, or custom typed handlers
- Workaround: Type assertions work but compromise type safety
Environment
- SDK Version: 1.0.0
- TypeScript Version: 5.x with strict mode
- Node.js: 16.0.0+
- Affected Frameworks: MCP TypeScript SDK, FastMCP, custom implementations
Proposed Solution
Make the protect() method generic to preserve the original handler type:
// Current implementation (forces type conversion)
protect(tokenId: number | number[], handler: MCPHandler): MCPHandler
// Proposed implementation (preserves original type)
protect<T extends (...args: any[]) => any>(
tokenId: number | number[],
handler: T
): TThis change would:
- Preserve the exact type of the input handler
- Eliminate all TypeScript errors on integration
- Remove the need for type assertion workarounds
- Maintain full backward compatibility (existing code continues to work)
- Enable seamless integration with any MCP framework
Additional Context
This issue was reported by multiple developers integrating the SDK with the official MCP TypeScript SDK. The TypeScript team's recommendation for wrapper functions is to use generics to preserve type information, which is considered a best practice for SDK design.
The proposed solution has been validated to:
- Fix all type errors
- Maintain backward compatibility
- Pass all existing tests
- Work with MCP SDK, FastMCP, and generic handlers
Acceptance Criteria
-
protect()method uses generic type parameter to preserve handler type - No TypeScript errors when using with MCP TypeScript SDK handlers
- No TypeScript errors when using with FastMCP handlers
- Type assertions are no longer needed
- All existing tests continue to pass
- IntelliSense/autocomplete works correctly with protected handlers
- No breaking changes to existing code
- Documentation updated with typed examples
Labels: bug, typescript, developer-experience, compatibility
Priority: High
Milestone: Next Release