@@ -74,6 +74,106 @@ beforeEach(() => {
7474 mocks . listServers . mockResolvedValue ( { servers : [ { id : 'mcp-abc' } ] } )
7575} )
7676describe ( 'integration catalog projection' , ( ) => {
77+ it . each ( [ 'google_calendar' , 'google-calendar' , 'Google Calendar' , ' GOOGLE-CALENDAR ' ] ) (
78+ 'resolves the registered Calendar service name %s without changing the operation' ,
79+ ( service ) => {
80+ const calendar = {
81+ name : 'google_calendar_list_v2' ,
82+ service : 'google_calendar' ,
83+ description : 'List calendar events' ,
84+ input_schema : { type : 'object' , properties : { calendarId : { type : 'string' } } } ,
85+ }
86+ expect ( projectIntegrationCatalog ( [ calendar ] , { ...input , service, query : 'events' } ) ) . toEqual (
87+ projectIntegrationCatalog ( [ calendar ] , {
88+ ...input ,
89+ service : 'google_calendar' ,
90+ query : 'events' ,
91+ } )
92+ )
93+ expect (
94+ projectIntegrationCatalog ( [ calendar ] , { ...input , service, query : 'events' } ) . operations
95+ ) . toHaveLength ( 1 )
96+ }
97+ )
98+
99+ it . each ( [
100+ [ 'google-email' , 'gmail' ] ,
101+ [ 'github-repositories' , 'github' ] ,
102+ [ 'Microsoft Teams' , 'microsoft_teams' ] ,
103+ [ 'microsoft-excel' , 'microsoft_excel' ] ,
104+ [ 'Cal.com' , 'calcom' ] ,
105+ [ 'Zoho Desk' , 'zoho_desk' ] ,
106+ [ 'salesforce-sandbox' , 'salesforce' ] ,
107+ ] ) ( 'resolves metadata-backed alias %s to %s' , ( alias , service ) => {
108+ const tool = { ...tools [ 0 ] ! , name : `${ service } _read` , service }
109+ expect (
110+ projectIntegrationCatalog ( [ tool ] , { ...input , service : alias } ) . operations . map (
111+ ( operation ) => operation . toolId
112+ )
113+ ) . toEqual ( [ tool . name ] )
114+ } )
115+
116+ it ( 'keeps specific service filters narrow and shared credential families scoped to supplied tools' , ( ) => {
117+ const authorized = [ 'google_drive' , 'google_slides' , 'gmail' , 'slack' ] . map ( ( service ) => ( {
118+ ...tools [ 0 ] ! ,
119+ name : `${ service } _read` ,
120+ service,
121+ } ) )
122+ for ( const service of [ 'google_drive' , 'google-drive' , 'Google Drive' ] ) {
123+ expect (
124+ projectIntegrationCatalog ( authorized , { ...input , service } ) . operations . map (
125+ ( operation ) => operation . service
126+ )
127+ ) . toEqual ( [ 'google_drive' ] )
128+ }
129+ expect (
130+ projectIntegrationCatalog ( authorized , {
131+ ...input ,
132+ service : 'google-service-account' ,
133+ } ) . operations . map ( ( operation ) => operation . service )
134+ ) . toEqual ( [ 'gmail' , 'google_drive' , 'google_slides' ] )
135+ expect (
136+ projectIntegrationCatalog (
137+ authorized . filter ( ( tool ) => tool . service === 'google_slides' ) ,
138+ {
139+ ...input ,
140+ service : 'google-drive' ,
141+ }
142+ ) . operations
143+ ) . toEqual ( [ ] )
144+ } )
145+
146+ it ( 'derives new provider bindings from callable tools before public metadata is published' , ( ) => {
147+ const preview = {
148+ ...tools [ 0 ] ! ,
149+ name : 'preview_service_read' ,
150+ service : 'preview_service' ,
151+ oauth : { required : true , provider : 'preview-service-provider' } ,
152+ }
153+ expect (
154+ projectIntegrationCatalog ( [ preview , ...tools ] , {
155+ ...input ,
156+ service : 'preview-service-provider' ,
157+ } ) . operations . map ( ( operation ) => operation . toolId )
158+ ) . toEqual ( [ preview . name ] )
159+ } )
160+
161+ it ( 'distinguishes an unrecognized filter from valid empty results without revealing other tools' , ( ) => {
162+ expect ( ( ) => projectIntegrationCatalog ( tools , { ...input , service : 'gogle-calndar' } ) ) . toThrow (
163+ 'Unknown integration service'
164+ )
165+ expect (
166+ projectIntegrationCatalog ( tools , { ...input , service : 'Google Calendar' } ) . operations
167+ ) . toEqual ( [ ] )
168+ expect (
169+ projectIntegrationCatalog ( tools , { ...input , service : 'gmail' , query : 'nonexistent' } )
170+ . operations
171+ ) . toEqual ( [ ] )
172+ expect (
173+ projectIntegrationCatalog ( tools , { ...input , service : 'mcp:unselected-server' } ) . operations
174+ ) . toEqual ( [ ] )
175+ } )
176+
77177 it ( 'omits schemas from broad listings and treats zero as an explicit full listing' , ( ) => {
78178 expect ( projectIntegrationCatalog ( tools , { ...input , limit : 1 } ) ) . toEqual ( {
79179 total : 2 ,
@@ -102,6 +202,27 @@ describe('integration catalog projection', () => {
102202 } )
103203} )
104204describe ( 'catalog authorization' , ( ) => {
205+ it . each ( [ 'assistant' , 'agent' ] as const ) (
206+ 'resolves provider aliases after the existing %s authorization and catalog projection' ,
207+ async ( mode ) => {
208+ queueChat ( mode )
209+ const result = await readIntegrationCatalog . execute ( {
210+ principal : principal ( ) ,
211+ input : { ...input , mode, service : 'google-email' , query : 'email' } ,
212+ } )
213+ expect ( result . operations . map ( ( operation ) => operation . toolId ) ) . toEqual ( [ 'gmail_send' ] )
214+ expect ( mocks . build ) . toHaveBeenCalledWith (
215+ 'actor' ,
216+ {
217+ schemaSurface : 'copilot' ,
218+ personalAccountsOnly : mode === 'assistant' ,
219+ organizationId : 'org-1' ,
220+ } ,
221+ undefined
222+ )
223+ }
224+ )
225+
105226 it ( 'preserves assistant personal-account and organization-approval projection and excludes MCP' , async ( ) => {
106227 queueChat ( )
107228 await readIntegrationCatalog . execute ( {
0 commit comments