@andrewcaires/api 5.2.2 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  /*!
2
- * @andrewcaires/api v5.2.2
2
+ * @andrewcaires/api v5.3.0
3
3
  * Simple api for small applications using express, jsonwebtoken, sequelize and websocket
4
4
  * (c) 2026 Andrew Caires
5
5
  * @license: MIT
6
6
  */
7
- import { Context, Application as Application$1, ExpressOptions, IStore } from '@andrewcaires/express';
7
+ import { Context, Application as Application$1, ExpressOptions, IStore, ResponseError } from '@andrewcaires/express';
8
8
  import { Hash, Env as Env$1 } from '@andrewcaires/node';
9
9
  import { ModelFindOptions, ModelUpdateOptions, Model as Model$1, Sequelize } from '@andrewcaires/sequelize';
10
- import { TypeAnyObject, TypeObjectString, TypeAnyFunction, TypeAnyConstructor, EventEmitter, TypeObject, ValidationBase } from '@andrewcaires/utils.js';
10
+ import { TypeAnyObject, TypeObjectString, TypeAnyFunction, TypeAnyConstructor, EventEmitter, TypeObject, ValidationBase, ValidationShape } from '@andrewcaires/utils.js';
11
11
  import { WebSocketServer } from 'ws';
12
12
  import { Model, CreateOptions, Attributes, FindOptions, IncludeOptions, FindAttributeOptions, ModelStatic } from 'sequelize';
13
13
  import { Store, SessionData } from 'express-session';
@@ -499,7 +499,7 @@ declare abstract class CrudController<M extends Model<any>, T extends TypeAnyObj
499
499
  protected del(ctx: Context): Promise<void>;
500
500
  protected get(ctx: Context): Promise<void>;
501
501
  protected set(ctx: Context): Promise<void>;
502
- protected validate(ctx: Context, obj: TypeObject<ValidationBase>): Promise<void>;
502
+ protected validate(ctx: Context, obj: TypeObject<ValidationBase>): void;
503
503
  protected validateCreate(ctx: Context): Promise<void>;
504
504
  protected validateUpdate(ctx: Context): Promise<void>;
505
505
  }
@@ -545,6 +545,25 @@ declare class LogsController extends ModelController<LogModel> {
545
545
  protected all(ctx: Context): Promise<void>;
546
546
  }
547
547
 
548
+ declare class McpController extends BaseController {
549
+ private readonly tools;
550
+ private toolsRegistered;
551
+ private readonly handler;
552
+ private readonly rateLimiter;
553
+ sync(app?: Application): Promise<void>;
554
+ protected options(ctx: Context): Promise<void>;
555
+ protected post(ctx: Context): Promise<void>;
556
+ protected delete(ctx: Context): Promise<void>;
557
+ private getMcpToolMetadata;
558
+ private discoverMcpTools;
559
+ private createMcpToolFromMetadata;
560
+ private request;
561
+ private isJsonParseError;
562
+ private isMcpEndpoint;
563
+ private jsonParseErrorResponse;
564
+ private respond;
565
+ }
566
+
548
567
  declare class PermissionsController extends CrudController<PermissionModel> {
549
568
  protected readonly model: typeof PermissionModel;
550
569
  private schemaCreate;
@@ -565,6 +584,301 @@ declare class SetupController extends BaseController {
565
584
  protected setup(ctx: Context): Promise<void>;
566
585
  }
567
586
 
587
+ declare const McpErrorCode: {
588
+ readonly ParseError: -32700;
589
+ readonly InvalidRequest: -32600;
590
+ readonly MethodNotFound: -32601;
591
+ readonly InvalidParams: -32602;
592
+ readonly InternalError: -32603;
593
+ readonly ServerError: -32000;
594
+ readonly InvalidSession: -32001;
595
+ };
596
+ type McpErrorCode = typeof McpErrorCode[keyof typeof McpErrorCode];
597
+ declare class McpError extends ResponseError {
598
+ readonly code: McpErrorCode;
599
+ readonly data?: unknown;
600
+ constructor(message: string, code?: McpErrorCode, status?: number, data?: unknown);
601
+ }
602
+ declare class McpParseError extends McpError {
603
+ constructor(message?: string, data?: unknown);
604
+ }
605
+ declare class McpInvalidRequestError extends McpError {
606
+ constructor(message?: string, data?: unknown);
607
+ }
608
+ declare class McpMethodNotFoundError extends McpError {
609
+ constructor(method: string);
610
+ }
611
+ declare class McpInvalidParamsError extends McpError {
612
+ constructor(message?: string, data?: unknown);
613
+ }
614
+ declare class McpInternalError extends McpError {
615
+ constructor(message?: string, data?: unknown);
616
+ }
617
+ declare class McpServerError extends McpError {
618
+ constructor(message?: string, data?: unknown);
619
+ }
620
+ declare class McpInvalidSessionError extends McpError {
621
+ constructor(message?: string, status?: number);
622
+ }
623
+ declare class McpToolNotFoundError extends McpError {
624
+ constructor(toolName: string);
625
+ }
626
+
627
+ declare const MCP_SUPPORTED_PROTOCOL_VERSIONS: readonly ["2025-11-25", "2025-06-18"];
628
+ declare const MCP_DEFAULT_PROTOCOL_VERSION: "2025-11-25";
629
+ declare const MCP_PROTOCOL_VERSION_HEADER = "MCP-Protocol-Version";
630
+ declare const MCP_SESSION_ID_HEADER = "MCP-Session-Id";
631
+ type McpProtocolVersion = typeof MCP_SUPPORTED_PROTOCOL_VERSIONS[number];
632
+ type McpJsonRpcId = string | number;
633
+ interface McpJsonRpcRequest {
634
+ jsonrpc: "2.0";
635
+ id?: McpJsonRpcId;
636
+ method: string;
637
+ params?: unknown;
638
+ }
639
+ interface McpJsonRpcErrorBody {
640
+ code: number;
641
+ message: string;
642
+ data?: unknown;
643
+ }
644
+ interface McpJsonRpcResult {
645
+ jsonrpc: "2.0";
646
+ id: McpJsonRpcId;
647
+ result: unknown;
648
+ }
649
+ interface McpJsonRpcErrorResult {
650
+ jsonrpc: "2.0";
651
+ id: McpJsonRpcId | null;
652
+ error: McpJsonRpcErrorBody;
653
+ }
654
+ interface McpSessionContext {
655
+ auth?: unknown;
656
+ groups?: unknown;
657
+ permissions?: unknown;
658
+ profile?: unknown;
659
+ user?: unknown;
660
+ userId?: string | number;
661
+ }
662
+ interface McpSession extends McpSessionContext {
663
+ sessionId: string;
664
+ createdAt: number;
665
+ expiresAt: number;
666
+ protocolVersion: McpProtocolVersion;
667
+ initialized: boolean;
668
+ }
669
+ interface McpToolDefinition {
670
+ name: string;
671
+ title: string;
672
+ description: string;
673
+ inputSchema: Record<string, unknown>;
674
+ outputSchema?: Record<string, unknown>;
675
+ }
676
+ interface McpToolDeclaration {
677
+ name: string;
678
+ title: string;
679
+ description: string;
680
+ input?: ValidationShape;
681
+ output?: ValidationShape;
682
+ }
683
+ interface McpToolContext extends McpSessionContext {
684
+ session: McpSession;
685
+ }
686
+ type McpToolInput = Record<string, unknown>;
687
+ type McpToolOutput = unknown;
688
+ interface McpCallToolResult {
689
+ content: Array<{
690
+ type: "text";
691
+ text: string;
692
+ }>;
693
+ structuredContent?: unknown;
694
+ isError?: boolean;
695
+ }
696
+ type McpToolHandlerResult = McpCallToolResult | McpToolOutput;
697
+ interface McpRegisteredTool extends McpToolDeclaration {
698
+ run(_argumentsValue: McpToolInput, _context: McpToolContext): Promise<McpToolHandlerResult> | McpToolHandlerResult;
699
+ }
700
+ interface McpHttpRequest {
701
+ body: unknown;
702
+ headers: Record<string, string | undefined>;
703
+ context?: McpSessionContext;
704
+ ip?: string;
705
+ }
706
+ interface McpHttpResponse {
707
+ status: number;
708
+ headers?: Record<string, string>;
709
+ body?: unknown;
710
+ }
711
+ interface McpToolCallLog {
712
+ sessionId: string;
713
+ userId?: string | number;
714
+ toolName: string;
715
+ durationMs: number;
716
+ success: boolean;
717
+ error?: string;
718
+ }
719
+ interface McpLogger {
720
+ toolCall(_log: McpToolCallLog): void | Promise<void>;
721
+ }
722
+
723
+ declare class McpSessionStore {
724
+ private readonly sessions;
725
+ private readonly ttl;
726
+ private readonly now;
727
+ constructor(ttl?: number, now?: () => number);
728
+ create(protocolVersion: McpProtocolVersion, context?: McpSessionContext): McpSession;
729
+ get(sessionId: string): McpSession | undefined;
730
+ require(sessionId: string): McpSession;
731
+ markInitialized(sessionId: string): McpSession;
732
+ delete(sessionId: string): boolean;
733
+ cleanup(): void;
734
+ size(): number;
735
+ private isExpired;
736
+ }
737
+
738
+ interface McpNormalizedValidation {
739
+ schema: TypeAnyObject;
740
+ validation?: ValidationBase;
741
+ }
742
+ declare class McpToolRegistry {
743
+ private readonly tools;
744
+ constructor(tools?: Array<McpRegisteredTool>);
745
+ register(tool: McpRegisteredTool): void;
746
+ list(): Array<McpToolDefinition>;
747
+ call(name: string, argumentsValue: unknown, session: McpSession): Promise<McpCallToolResult>;
748
+ private isCallToolResult;
749
+ private normalizeMcpValidation;
750
+ private outputValidationError;
751
+ private toolInputValidationError;
752
+ private validateAdditionalProperties;
753
+ }
754
+
755
+ interface McpHttpHandlerOptions {
756
+ sessions: McpSessionStore;
757
+ tools: McpToolRegistry;
758
+ allowedOrigins?: Array<string>;
759
+ logger?: McpLogger;
760
+ serverName?: string;
761
+ serverVersion?: string;
762
+ }
763
+ declare const MCP_HTTP_ALLOWED_METHODS: readonly ["POST", "DELETE", "OPTIONS"];
764
+ declare const MCP_HTTP_ALLOW: string;
765
+ declare const isJsonParseError: (error: unknown) => error is Error & {
766
+ status?: number;
767
+ statusCode?: number;
768
+ type?: string;
769
+ };
770
+ declare const jsonParseErrorResponse: (error: unknown) => McpHttpResponse | undefined;
771
+ declare class McpHttpHandler {
772
+ private readonly sessions;
773
+ private readonly tools;
774
+ private readonly allowedOrigins;
775
+ private readonly logger?;
776
+ private readonly serverName;
777
+ private readonly serverVersion;
778
+ constructor(options: McpHttpHandlerOptions);
779
+ post(request: McpHttpRequest): Promise<McpHttpResponse>;
780
+ delete(request: McpHttpRequest): McpHttpResponse;
781
+ get(request: McpHttpRequest): McpHttpResponse;
782
+ options(request: McpHttpRequest): McpHttpResponse;
783
+ private initialize;
784
+ private initialized;
785
+ private callTool;
786
+ private requireRequestId;
787
+ private withSession;
788
+ private withInitializedSession;
789
+ private requireSession;
790
+ private validateProtocolHeader;
791
+ private negotiateProtocolVersion;
792
+ private parseToolCallParams;
793
+ private validateObjectParams;
794
+ private validateOrigin;
795
+ private withTransportHeaders;
796
+ private transportHeaders;
797
+ private getAllowedOrigin;
798
+ private getSessionHeader;
799
+ private getHeader;
800
+ private errorResponse;
801
+ }
802
+
803
+ declare const isJsonRpcId: (value: unknown) => value is McpJsonRpcId;
804
+ declare const jsonRpcResult: (id: McpJsonRpcId, result: unknown) => McpJsonRpcResult;
805
+ declare const jsonRpcError: (id: McpJsonRpcId | null, error: McpError) => McpJsonRpcErrorResult;
806
+ declare const jsonRpcErrorFromCode: (id: McpJsonRpcId | null, code: McpErrorCode, message: string, data?: unknown) => McpJsonRpcErrorResult;
807
+ declare const parseJsonRpcRequest: (body: unknown) => McpJsonRpcRequest;
808
+
809
+ declare class McpRateLimiter {
810
+ private readonly entries;
811
+ private readonly max;
812
+ private readonly windowMs;
813
+ private readonly now;
814
+ constructor(max?: number, windowMs?: number, now?: () => number);
815
+ consume(key: string): boolean;
816
+ }
817
+
818
+ declare const MCP_TOOL_METADATA: unique symbol;
819
+ interface McpToolMetadata extends McpToolDeclaration {
820
+ propertyKey: string | symbol;
821
+ }
822
+ type McpDecoratedToolHandler = (_argumentsValue: Record<string, unknown>, _context: McpToolContext) => ReturnType<McpRegisteredTool["run"]>;
823
+ declare const assertValidMcpToolDefinition: (definition: McpToolDeclaration) => void;
824
+
825
+ declare class TestController extends BaseController {
826
+ protected json(ctx: Context): Promise<void>;
827
+ protected sum(args: TypeAnyObject, _context: McpToolContext): Promise<{
828
+ value: number;
829
+ }>;
830
+ protected multiply(args: TypeAnyObject, _context: McpToolContext): Promise<{
831
+ value: number;
832
+ }>;
833
+ protected average(args: TypeAnyObject, _context: McpToolContext): Promise<{
834
+ value: number;
835
+ count: number;
836
+ }>;
837
+ protected validationString(args: TypeAnyObject, _context: McpToolContext): Promise<{
838
+ length: number;
839
+ normalized: string;
840
+ }>;
841
+ protected validationNumber(args: TypeAnyObject, _context: McpToolContext): Promise<{
842
+ doubled: number;
843
+ }>;
844
+ protected validationBoolean(args: TypeAnyObject, _context: McpToolContext): Promise<{
845
+ active: any;
846
+ }>;
847
+ protected validationArray(args: TypeAnyObject, _context: McpToolContext): Promise<{
848
+ count: number;
849
+ }>;
850
+ protected validationObject(args: TypeAnyObject, _context: McpToolContext): Promise<{
851
+ summary: {
852
+ name: any;
853
+ adult: boolean;
854
+ };
855
+ }>;
856
+ protected validationEnum(args: TypeAnyObject, _context: McpToolContext): Promise<{
857
+ status: any;
858
+ }>;
859
+ protected validationDate(args: TypeAnyObject, _context: McpToolContext): Promise<{
860
+ iso: string;
861
+ timestamp: number;
862
+ }>;
863
+ protected validationOptional(args: TypeAnyObject, _context: McpToolContext): Promise<{
864
+ nickname?: string | undefined;
865
+ name: any;
866
+ hasNickname: boolean;
867
+ }>;
868
+ protected validationDefaults(args: TypeAnyObject, _context: McpToolContext): Promise<{
869
+ name: any;
870
+ limit: any;
871
+ }>;
872
+ protected validationParse(args: TypeAnyObject, _context: McpToolContext): Promise<{
873
+ active: any;
874
+ amount: any;
875
+ }>;
876
+ protected validationNested(args: TypeAnyObject, _context: McpToolContext): Promise<{
877
+ userId: any;
878
+ scoreCount: number;
879
+ }>;
880
+ }
881
+
568
882
  declare class UsersController extends ModelController<UserModel> {
569
883
  protected readonly model: typeof UserModel;
570
884
  path: string;
@@ -616,6 +930,9 @@ declare const ReqPermissions: (key?: string) => ParameterDecorator;
616
930
 
617
931
  declare const ReqUser: (key?: string) => ParameterDecorator;
618
932
 
933
+ type McpToolOptions = Omit<McpToolMetadata, "propertyKey">;
934
+ declare const McpTool: (options: McpToolOptions) => MethodDecorator;
935
+
619
936
  declare const Audit: (active?: boolean) => ClassDecorator;
620
937
 
621
938
  declare class Env extends Env$1 {
@@ -632,6 +949,10 @@ declare class Env extends Env$1 {
632
949
  static readonly HTTP_TLS_KEY: Buffer<ArrayBufferLike> | null;
633
950
  static readonly MODEL_LIMIT: number;
634
951
  static readonly MODEL_LIMIT_MAX: number;
952
+ static readonly MCP_ALLOWED_ORIGINS: string;
953
+ static readonly MCP_RATE_LIMIT_MAX: number;
954
+ static readonly MCP_RATE_LIMIT_WINDOW: number;
955
+ static readonly MCP_SESSION_TTL: number;
635
956
  static readonly PASSWORD_ALGORITHM: number;
636
957
  static readonly PASSWORD_MEMORY_COST: number;
637
958
  static readonly PASSWORD_PARALLELISM: number;
@@ -668,5 +989,5 @@ declare class Env extends Env$1 {
668
989
  static readonly API_WEBSOCKET_START: boolean;
669
990
  }
670
991
 
671
- export { Application, Audit, AuditModel, AuditTypes, AuditsController, AuthController, AuthService, BaseController, CanCreate, CanDelete, CanRead, CanUpdate, Config, ConfigModel, CrudController, Env, FilesController, ForgotController, ForgotModel, GroupModel, GroupPermissionModel, GroupsController, GroupsPermissionsController, HasGroups, HasPermissions, HealthController, IsAuthenticated, Log, LogModel, Loggable, Loglevels, LogsController, MigrationModel, ModelController, ModelService, PermissionModel, PermissionsController, RegisterController, RegisterModel, ReqAuth, ReqGroup, ReqGroups, ReqPermission, ReqPermissions, ReqUser, Service, SessionModel, SessionStore, SetupController, UserAuthModel, UserGroupModel, UserModel, UserPasswordModel, UserService, UserStatus, UsersController, UsersGroupsController, canFactory, sequelize };
672
- export type { ApplicationEvents, AuthEvents, ForgotEvents, IAuthParameters, ModelArgumentsBase, ModelArgumentsCount, ModelArgumentsCreate, ModelArgumentsDelete, ModelArgumentsFindAll, ModelArgumentsFindOne, ModelArgumentsInclude, ModelArgumentsUpdate, ModelCallbackFindAll, ModelCallbackFindOne, ModelOptions, ModelResultFindAll, RegisterEvents };
992
+ export { Application, Audit, AuditModel, AuditTypes, AuditsController, AuthController, AuthService, BaseController, CanCreate, CanDelete, CanRead, CanUpdate, Config, ConfigModel, CrudController, Env, FilesController, ForgotController, ForgotModel, GroupModel, GroupPermissionModel, GroupsController, GroupsPermissionsController, HasGroups, HasPermissions, HealthController, IsAuthenticated, Log, LogModel, Loggable, Loglevels, LogsController, MCP_DEFAULT_PROTOCOL_VERSION, MCP_HTTP_ALLOW, MCP_HTTP_ALLOWED_METHODS, MCP_PROTOCOL_VERSION_HEADER, MCP_SESSION_ID_HEADER, MCP_SUPPORTED_PROTOCOL_VERSIONS, MCP_TOOL_METADATA, McpController, McpError, McpErrorCode, McpHttpHandler, McpInternalError, McpInvalidParamsError, McpInvalidRequestError, McpInvalidSessionError, McpMethodNotFoundError, McpParseError, McpRateLimiter, McpServerError, McpSessionStore, McpTool, McpToolNotFoundError, McpToolRegistry, MigrationModel, ModelController, ModelService, PermissionModel, PermissionsController, RegisterController, RegisterModel, ReqAuth, ReqGroup, ReqGroups, ReqPermission, ReqPermissions, ReqUser, Service, SessionModel, SessionStore, SetupController, TestController, UserAuthModel, UserGroupModel, UserModel, UserPasswordModel, UserService, UserStatus, UsersController, UsersGroupsController, assertValidMcpToolDefinition, canFactory, isJsonParseError, isJsonRpcId, jsonParseErrorResponse, jsonRpcError, jsonRpcErrorFromCode, jsonRpcResult, parseJsonRpcRequest, sequelize };
993
+ export type { ApplicationEvents, AuthEvents, ForgotEvents, IAuthParameters, McpCallToolResult, McpDecoratedToolHandler, McpHttpHandlerOptions, McpHttpRequest, McpHttpResponse, McpJsonRpcErrorBody, McpJsonRpcErrorResult, McpJsonRpcId, McpJsonRpcRequest, McpJsonRpcResult, McpLogger, McpNormalizedValidation, McpProtocolVersion, McpRegisteredTool, McpSession, McpSessionContext, McpToolCallLog, McpToolContext, McpToolDeclaration, McpToolDefinition, McpToolHandlerResult, McpToolInput, McpToolMetadata, McpToolOptions, McpToolOutput, ModelArgumentsBase, ModelArgumentsCount, ModelArgumentsCreate, ModelArgumentsDelete, ModelArgumentsFindAll, ModelArgumentsFindOne, ModelArgumentsInclude, ModelArgumentsUpdate, ModelCallbackFindAll, ModelCallbackFindOne, ModelOptions, ModelResultFindAll, RegisterEvents };