@@ -54,7 +54,7 @@ The schema field allows defining a Zod-based validation schema for tool input pa
5454 To use hooks with MCP tools, follow the provider-based approach:
5555
5656 Step 1: Create a hook provider:
57- ``` typescript
57+ ``` ts
5858 // src/providers/my-hook.provider.ts
5959 export class MyHookProvider implements Provider <McpHookFunction > {
6060 constructor (@inject (LOGGER .LOGGER_INJECT ) private logger : ILogger ) {}
@@ -66,7 +66,7 @@ The schema field allows defining a Zod-based validation schema for tool input pa
6666 }
6767 ```
6868 Step 2: Add binding key to McpHookBindings:
69- ``` typescript
69+ ``` ts
7070 // src/keys.ts
7171 export namespace McpHookBindings {
7272 export const MY_HOOK = BindingKey .create <McpHookFunction >(' hooks.mcp.myHook' );
@@ -77,10 +77,64 @@ The schema field allows defining a Zod-based validation schema for tool input pa
7777 this .bind (McpHookBindings .MY_HOOK ).toProvider (MyHookProvider );
7878 ```
7979 Step 4: Use in decorator:
80- ``` typescript
80+ ``` ts
8181 @mcpTool ({
8282 name: ' my-tool' ,
8383 description: ' my-description'
8484 preHookBinding : McpHookBindings .MY_HOOK ,
8585 postHookBinding: ' hooks.mcp.myOtherHook' // or string binding key
8686 })
87+ ```
88+ ## MCP Access Control
89+ By default, any authenticated user can call the ` /mcp ` endpoint.
90+ To restrict which users can access MCP functionality, this extension supports adding a custom LoopBack 4 interceptor.
91+
92+ Create an interceptor that validates the authenticated user before the request reaches the MCP controller.
93+
94+ ``` ts
95+ import {
96+ InvocationContext ,
97+ InvocationResult ,
98+ Provider ,
99+ ValueOrPromise ,
100+ inject ,
101+ interceptor ,
102+ } from ' @loopback/core' ;
103+ import {HttpErrors } from ' @loopback/rest' ;
104+ import {AuthenticationBindings , IAuthUser } from ' loopback4-authentication' ;
105+
106+ export class McpAccessInterceptor implements Provider <Interceptor > {
107+ constructor (
108+ @inject (AuthenticationBindings .CURRENT_USER , {optional: true })
109+ private readonly currentUser : IAuthUser ,
110+ ) {}
111+
112+ value() {
113+ return this .intercept .bind (this );
114+ }
115+
116+ intercept(
117+ invocationCtx : InvocationContext ,
118+ next : () => ValueOrPromise <InvocationResult >,
119+ ): ValueOrPromise <InvocationResult > {
120+ if (! this .currentUser ) {
121+ throw new HttpErrors .Unauthorized (' User not authenticated' );
122+ }
123+
124+ const user = this .currentUser ;
125+
126+ // Example rule: only admins or users with `access-mcp` permission
127+ if (user .role !== ' admin' && ! user .permissions ?.includes (' access-mcp' )) {
128+ throw new HttpErrors .Forbidden (
129+ ` User ${user .username } is not allowed to access MCP ` ,
130+ );
131+ }
132+
133+ return next ();
134+ }
135+ }
136+ ```
137+ Bind it in your ` application.ts ` :
138+ ``` ts
139+ this .bind (McpBindings .ACCESS_INTERCEPTOR ).toProvider (McpAccessInterceptor );
140+ ```
0 commit comments