@@ -2,13 +2,14 @@ import { McpAgent } from "agents/mcp";
22import OAuthProvider from "@cloudflare/workers-oauth-provider" ;
33import { isAPITokenRequest , isValidAPIToken } from "./auth" ;
44import app from "./app" ;
5- import { MCP_CONFIG , OAUTH_CONFIG } from "./config" ;
5+ import { MCP_CONFIG , OAUTH_CONFIG , MCPCAT_CONFIG } from "./config" ;
66import type { GlobalpingEnv , Props , State } from "./types" ;
77import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" ;
88import { z } from "zod" ;
99import { registerGlobalpingTools } from "./mcp" ;
1010import { sanitizeToken } from "./auth" ;
1111import { validateOrigin , validateHost , getCorsOptionsForRequest } from "./lib" ;
12+ import * as mcpcat from "mcpcat" ;
1213
1314export class GlobalpingMCP extends McpAgent < GlobalpingEnv , State , Props > {
1415 server = new McpServer ( {
@@ -51,6 +52,24 @@ Key guidelines:
5152 async init ( ) {
5253 console . log ( "Initializing Globalping MCP..." ) ;
5354
55+ // Initialize MCPcat tracking if project ID is configured
56+ if ( this . env . MCPCAT_PROJECT_ID && MCPCAT_CONFIG . ENABLED ) {
57+ try {
58+ mcpcat . track ( this . server , this . env . MCPCAT_PROJECT_ID , {
59+ // Identify users with generic labels
60+ identify : async ( ) => {
61+ return this . getUserIdentification ( ) ;
62+ } ,
63+ } ) ;
64+
65+ console . log ( "✓ MCPcat tracking initialized" ) ;
66+ } catch ( error ) {
67+ console . warn ( "⚠ MCPcat tracking initialization failed (non-fatal):" , error ) ;
68+ }
69+ } else {
70+ console . log ( "✗ MCPcat tracking disabled (no project ID or disabled in config)" ) ;
71+ }
72+
5473 // Register all the Globalping tools
5574 registerGlobalpingTools ( this , ( ) => {
5675 const raw = this . getToken ( ) ?? "" ;
@@ -114,7 +133,6 @@ Key guidelines:
114133 annotations : {
115134 readOnlyHint : true ,
116135 } ,
117- inputSchema : { } ,
118136 outputSchema : {
119137 guide : z . string ( ) ,
120138 } ,
@@ -174,7 +192,6 @@ This approach allows for direct side-by-side comparisons of different targets us
174192 annotations : {
175193 readOnlyHint : true ,
176194 } ,
177- inputSchema : { } ,
178195 outputSchema : {
179196 helpText : z . string ( ) ,
180197 } ,
@@ -277,7 +294,6 @@ For more information, visit: https://www.globalping.io
277294 annotations : {
278295 readOnlyHint : true ,
279296 } ,
280- inputSchema : { } ,
281297 outputSchema : {
282298 authenticated : z . boolean ( ) ,
283299 status : z . string ( ) ,
@@ -359,6 +375,50 @@ For more information, visit: https://www.globalping.io
359375 return this . props ?. accessToken ;
360376 }
361377
378+ /**
379+ * Returns generic user identification for MCPcat analytics
380+ * Does not expose PII - uses generic labels only
381+ */
382+ private getUserIdentification ( ) : {
383+ userId : string ;
384+ userName : string ;
385+ userData : Record < string , any > ;
386+ } {
387+ const isAuth = this . props ?. isAuthenticated ;
388+ const hasAPIToken = ! this . props ?. isOAuth ;
389+
390+ // Check API token first (most specific) to prevent misclassification
391+ // as OAuth when API token flow sets isAuthenticated and userName
392+ if ( hasAPIToken ) {
393+ return {
394+ userId : "api_token_user" ,
395+ userName : "API Token User" ,
396+ userData : {
397+ authMethod : "api_token" ,
398+ } ,
399+ } ;
400+ }
401+
402+ if ( isAuth && this . props ?. userName ) {
403+ return {
404+ userId : "oauth_user" ,
405+ userName : "OAuth User" ,
406+ userData : {
407+ authMethod : "oauth" ,
408+ clientId : this . props . clientId || "unknown" ,
409+ } ,
410+ } ;
411+ }
412+
413+ return {
414+ userId : "anonymous_user" ,
415+ userName : "Anonymous User" ,
416+ userData : {
417+ authMethod : "none" ,
418+ } ,
419+ } ;
420+ }
421+
362422 setIsAuthenticated ( isAuthenticated : boolean ) : void {
363423 if ( ! this . props ) return ;
364424 this . props . isAuthenticated = isAuthenticated ;
@@ -490,6 +550,7 @@ async function handleAPITokenRequest<
490550 userName : "API Token User" ,
491551 clientId : "" ,
492552 isAuthenticated : true ,
553+ isOAuth : false ,
493554 } satisfies Props ;
494555
495556 if ( pathname === MCP_CONFIG . ROUTES . SSE || pathname === MCP_CONFIG . ROUTES . SSE_MESSAGE ) {
0 commit comments