44 */
55
66import type { Features } from '@aws/language-server-runtimes/server-interface/server'
7+ import { ChatTelemetryEventName } from '../../../../shared/telemetry/types'
8+ import { ChatTelemetryController } from '../../../chat/telemetry/chatTelemetryController'
9+ import { getGlobalMcpConfigPath } from './mcpUtils'
710import { Client } from '@modelcontextprotocol/sdk/client/index.js'
811import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'
912import {
@@ -45,7 +48,10 @@ export class McpManager {
4548 private constructor (
4649 private configPaths : string [ ] ,
4750 private personaPaths : string [ ] ,
48- private features : Pick < Features , 'logging' | 'workspace' | 'lsp' >
51+ private features : Pick <
52+ Features ,
53+ 'logging' | 'workspace' | 'lsp' | 'telemetry' | 'credentialsProvider' | 'runtime'
54+ >
4955 ) {
5056 this . mcpTools = [ ]
5157 this . clients = new Map < string , Client > ( )
@@ -61,16 +67,60 @@ export class McpManager {
6167 /**
6268 * Initialize or return existing manager, then discover all servers.
6369 */
70+ #telemetryController?: ChatTelemetryController
71+
6472 public static async init (
6573 configPaths : string [ ] ,
6674 personaPaths : string [ ] ,
67- features : Pick < Features , 'logging' | 'workspace' | 'lsp' >
75+ features : Pick < Features , 'logging' | 'workspace' | 'lsp' | 'telemetry' | 'credentialsProvider' | 'runtime' >
6876 ) : Promise < McpManager > {
6977 if ( ! McpManager . #instance) {
7078 const mgr = new McpManager ( configPaths , personaPaths , features )
7179 McpManager . #instance = mgr
7280 await mgr . discoverAllServers ( )
7381 features . logging . info ( `MCP: discovered ${ mgr . mcpTools . length } tools across all servers` )
82+
83+ // Emit MCP configuration metrics
84+ const serverConfigs = mgr . getAllServerConfigs ( )
85+ const activeServers = Array . from ( serverConfigs . entries ( ) ) . filter ( ( [ name , _ ] ) => ! mgr . isServerDisabled ( name ) )
86+
87+ // Count global vs project servers
88+ const globalServers = Array . from ( serverConfigs . entries ( ) ) . filter (
89+ ( [ _ , config ] ) =>
90+ config ?. __configPath__ === getGlobalMcpConfigPath ( features . workspace . fs . getUserHomeDir ( ) )
91+ ) . length
92+ const projectServers = serverConfigs . size - globalServers
93+
94+ // Count tools by permission
95+ let toolsAlwaysAllowed = 0
96+ let toolsDenied = 0
97+
98+ for ( const [ serverName , _ ] of activeServers ) {
99+ const toolsWithPermissions = mgr . getAllToolsWithPermissions ( serverName )
100+ toolsWithPermissions . forEach ( item => {
101+ if ( item . permission === McpPermissionType . alwaysAllow ) {
102+ toolsAlwaysAllowed ++
103+ } else if ( item . permission === McpPermissionType . deny ) {
104+ toolsDenied ++
105+ }
106+ } )
107+ }
108+
109+ // Emit MCP configuration metrics
110+ if ( features . telemetry ) {
111+ features . telemetry . emitMetric ( {
112+ name : ChatTelemetryEventName . MCPConfig ,
113+ data : {
114+ credentialStartUrl : features . credentialsProvider ?. getConnectionMetadata ( ) ?. sso ?. startUrl ,
115+ languageServerVersion : features . runtime ?. serverInfo . version ,
116+ numActiveServers : activeServers . length ,
117+ numGlobalServers : globalServers ,
118+ numProjectServers : projectServers ,
119+ numToolsAlwaysAllowed : toolsAlwaysAllowed ,
120+ numToolsDenied : toolsDenied ,
121+ } ,
122+ } )
123+ }
74124 }
75125 return McpManager . #instance
76126 }
0 commit comments