mcp-use
Version:
Opinionated MCP Framework for TypeScript (@modelcontextprotocol/sdk compatible) - Build MCP Agents, Clients and Servers with support for ChatGPT Apps, Code Mode, OAuth, Notifications, Sampling, Observability and more.
1,183 lines (1,176 loc) • 36.2 kB
JavaScript
import {
logger
} from "./chunk-FRUZDWXH.js";
import {
__name,
__require
} from "./chunk-3GQAWCBQ.js";
// src/server/utils/runtime.ts
var isDeno = typeof globalThis.Deno !== "undefined";
function getEnv(key) {
if (isDeno) {
return globalThis.Deno.env.get(key);
}
return process.env[key];
}
__name(getEnv, "getEnv");
function getCwd() {
if (isDeno) {
return globalThis.Deno.cwd();
}
return process.cwd();
}
__name(getCwd, "getCwd");
var fsHelpers = {
async readFileSync(path, encoding = "utf8") {
if (isDeno) {
return await globalThis.Deno.readTextFile(path);
}
const { readFileSync } = await import("fs");
const result = readFileSync(path, encoding);
return typeof result === "string" ? result : result.toString(encoding);
},
async readFile(path) {
if (isDeno) {
const data = await globalThis.Deno.readFile(path);
return data.buffer;
}
const { readFileSync } = await import("fs");
const buffer = readFileSync(path);
return buffer.buffer.slice(
buffer.byteOffset,
buffer.byteOffset + buffer.byteLength
);
},
async existsSync(path) {
if (isDeno) {
try {
await globalThis.Deno.stat(path);
return true;
} catch {
return false;
}
}
const { existsSync } = await import("fs");
return existsSync(path);
},
async readdirSync(path) {
if (isDeno) {
const entries = [];
for await (const entry of globalThis.Deno.readDir(path)) {
entries.push(entry.name);
}
return entries;
}
const { readdirSync } = await import("fs");
return readdirSync(path);
}
};
var pathHelpers = {
join(...paths) {
if (isDeno) {
return paths.join("/").replace(/\/+/g, "/");
}
return paths.join("/").replace(/\/+/g, "/");
},
relative(from, to) {
const fromParts = from.split("/").filter((p) => p);
const toParts = to.split("/").filter((p) => p);
let i = 0;
while (i < fromParts.length && i < toParts.length && fromParts[i] === toParts[i]) {
i++;
}
const upCount = fromParts.length - i;
const relativeParts = [...Array(upCount).fill(".."), ...toParts.slice(i)];
return relativeParts.join("/");
}
};
function generateUUID() {
return globalThis.crypto.randomUUID();
}
__name(generateUUID, "generateUUID");
// src/version.ts
var VERSION = "1.11.2";
function getPackageVersion() {
return VERSION;
}
__name(getPackageVersion, "getPackageVersion");
// src/telemetry/events.ts
var BaseTelemetryEvent = class {
static {
__name(this, "BaseTelemetryEvent");
}
};
var MCPAgentExecutionEvent = class extends BaseTelemetryEvent {
constructor(data) {
super();
this.data = data;
}
static {
__name(this, "MCPAgentExecutionEvent");
}
get name() {
return "mcp_agent_execution";
}
get properties() {
return {
// Core execution info
execution_method: this.data.executionMethod,
query: this.data.query,
query_length: this.data.query.length,
success: this.data.success,
// Agent configuration
model_provider: this.data.modelProvider,
model_name: this.data.modelName,
server_count: this.data.serverCount,
server_identifiers: this.data.serverIdentifiers,
total_tools_available: this.data.totalToolsAvailable,
tools_available_names: this.data.toolsAvailableNames,
max_steps_configured: this.data.maxStepsConfigured,
memory_enabled: this.data.memoryEnabled,
use_server_manager: this.data.useServerManager,
// Execution parameters (always include, even if null)
max_steps_used: this.data.maxStepsUsed,
manage_connector: this.data.manageConnector,
external_history_used: this.data.externalHistoryUsed,
// Execution results (always include, even if null)
steps_taken: this.data.stepsTaken ?? null,
tools_used_count: this.data.toolsUsedCount ?? null,
tools_used_names: this.data.toolsUsedNames ?? null,
response: this.data.response ?? null,
response_length: this.data.response ? this.data.response.length : null,
execution_time_ms: this.data.executionTimeMs ?? null,
error_type: this.data.errorType ?? null,
conversation_history_length: this.data.conversationHistoryLength ?? null
};
}
};
function createServerRunEventData(server, transport) {
const toolRegistrations = Array.from(server.registrations.tools.values());
const promptRegistrations = Array.from(server.registrations.prompts.values());
const resourceRegistrations = Array.from(
server.registrations.resources.values()
);
const templateRegistrations = Array.from(
server.registrations.resourceTemplates.values()
);
const allResources = resourceRegistrations.map((r) => ({
name: r.config.name,
title: r.config.title ?? null,
description: r.config.description ?? null,
uri: r.config.uri ?? null,
mime_type: r.config.mimeType ?? null
}));
const appsSdkResources = allResources.filter(
(r) => r.mime_type === "text/html+skybridge"
);
const mcpUiResources = allResources.filter(
(r) => r.mime_type === "text/uri-list" || r.mime_type === "text/html"
);
const mcpAppsResources = allResources.filter(
(r) => r.mime_type === "text/html+mcp"
);
return {
transport,
toolsNumber: server.registeredTools.length,
resourcesNumber: server.registeredResources.length,
promptsNumber: server.registeredPrompts.length,
auth: !!server.oauthProvider,
name: server.config.name,
description: server.config.description ?? null,
baseUrl: server.serverBaseUrl ?? null,
toolNames: server.registeredTools.length > 0 ? server.registeredTools : null,
resourceNames: server.registeredResources.length > 0 ? server.registeredResources : null,
promptNames: server.registeredPrompts.length > 0 ? server.registeredPrompts : null,
tools: toolRegistrations.length > 0 ? toolRegistrations.map((r) => ({
name: r.config.name,
title: r.config.title ?? null,
description: r.config.description ?? null,
input_schema: r.config.schema ? JSON.stringify(r.config.schema) : null,
output_schema: r.config.outputSchema ? JSON.stringify(r.config.outputSchema) : null
})) : null,
resources: allResources.length > 0 ? allResources : null,
prompts: promptRegistrations.length > 0 ? promptRegistrations.map((r) => ({
name: r.config.name,
title: r.config.title ?? null,
description: r.config.description ?? null,
args: r.config.args ? JSON.stringify(r.config.args) : null
})) : null,
templates: templateRegistrations.length > 0 ? templateRegistrations.map((r) => ({
name: r.config.name,
title: r.config.title ?? null,
description: r.config.description ?? null
})) : null,
capabilities: {
logging: true,
resources: { subscribe: true, listChanged: true }
},
appsSdkResources: appsSdkResources.length > 0 ? appsSdkResources : null,
appsSdkResourcesNumber: appsSdkResources.length,
mcpUiResources: mcpUiResources.length > 0 ? mcpUiResources : null,
mcpUiResourcesNumber: mcpUiResources.length,
mcpAppsResources: mcpAppsResources.length > 0 ? mcpAppsResources : null,
mcpAppsResourcesNumber: mcpAppsResources.length
};
}
__name(createServerRunEventData, "createServerRunEventData");
var ServerRunEvent = class extends BaseTelemetryEvent {
constructor(data) {
super();
this.data = data;
}
static {
__name(this, "ServerRunEvent");
}
get name() {
return "server_run";
}
get properties() {
return {
transport: this.data.transport,
tools_number: this.data.toolsNumber,
resources_number: this.data.resourcesNumber,
prompts_number: this.data.promptsNumber,
auth: this.data.auth,
name: this.data.name,
description: this.data.description ?? null,
base_url: this.data.baseUrl ?? null,
tool_names: this.data.toolNames ?? null,
resource_names: this.data.resourceNames ?? null,
prompt_names: this.data.promptNames ?? null,
tools: this.data.tools ?? null,
resources: this.data.resources ?? null,
prompts: this.data.prompts ?? null,
templates: this.data.templates ?? null,
capabilities: this.data.capabilities ? JSON.stringify(this.data.capabilities) : null,
apps_sdk_resources: this.data.appsSdkResources ? JSON.stringify(this.data.appsSdkResources) : null,
apps_sdk_resources_number: this.data.appsSdkResourcesNumber ?? 0,
mcp_ui_resources: this.data.mcpUiResources ? JSON.stringify(this.data.mcpUiResources) : null,
mcp_ui_resources_number: this.data.mcpUiResourcesNumber ?? 0,
mcp_apps_resources: this.data.mcpAppsResources ? JSON.stringify(this.data.mcpAppsResources) : null,
mcp_apps_resources_number: this.data.mcpAppsResourcesNumber ?? 0
};
}
};
var ServerInitializeEvent = class extends BaseTelemetryEvent {
constructor(data) {
super();
this.data = data;
}
static {
__name(this, "ServerInitializeEvent");
}
get name() {
return "server_initialize_call";
}
get properties() {
return {
protocol_version: this.data.protocolVersion,
client_info: JSON.stringify(this.data.clientInfo),
client_capabilities: JSON.stringify(this.data.clientCapabilities),
session_id: this.data.sessionId ?? null
};
}
};
var ServerToolCallEvent = class extends BaseTelemetryEvent {
constructor(data) {
super();
this.data = data;
}
static {
__name(this, "ServerToolCallEvent");
}
get name() {
return "server_tool_call";
}
get properties() {
return {
tool_name: this.data.toolName,
length_input_argument: this.data.lengthInputArgument,
success: this.data.success,
error_type: this.data.errorType ?? null,
execution_time_ms: this.data.executionTimeMs ?? null
};
}
};
var ServerResourceCallEvent = class extends BaseTelemetryEvent {
constructor(data) {
super();
this.data = data;
}
static {
__name(this, "ServerResourceCallEvent");
}
get name() {
return "server_resource_call";
}
get properties() {
return {
name: this.data.name,
description: this.data.description,
contents: this.data.contents,
success: this.data.success,
error_type: this.data.errorType ?? null
};
}
};
var ServerPromptCallEvent = class extends BaseTelemetryEvent {
constructor(data) {
super();
this.data = data;
}
static {
__name(this, "ServerPromptCallEvent");
}
get name() {
return "server_prompt_call";
}
get properties() {
return {
name: this.data.name,
description: this.data.description,
success: this.data.success,
error_type: this.data.errorType ?? null
};
}
};
var ServerContextEvent = class extends BaseTelemetryEvent {
constructor(data) {
super();
this.data = data;
}
static {
__name(this, "ServerContextEvent");
}
get name() {
return `server_context_${this.data.contextType}`;
}
get properties() {
return {
context_type: this.data.contextType,
notification_type: this.data.notificationType ?? null
};
}
};
var MCPClientInitEvent = class extends BaseTelemetryEvent {
constructor(data) {
super();
this.data = data;
}
static {
__name(this, "MCPClientInitEvent");
}
get name() {
return "mcpclient_init";
}
get properties() {
return {
code_mode: this.data.codeMode,
sandbox: this.data.sandbox,
all_callbacks: this.data.allCallbacks,
verify: this.data.verify,
servers: this.data.servers,
num_servers: this.data.numServers,
is_browser: this.data.isBrowser
};
}
};
var ConnectorInitEvent = class extends BaseTelemetryEvent {
constructor(data) {
super();
this.data = data;
}
static {
__name(this, "ConnectorInitEvent");
}
get name() {
return "connector_init";
}
get properties() {
return {
connector_type: this.data.connectorType,
server_command: this.data.serverCommand ?? null,
server_args: this.data.serverArgs ?? null,
server_url: this.data.serverUrl ?? null,
public_identifier: this.data.publicIdentifier ?? null
};
}
};
var ClientAddServerEvent = class extends BaseTelemetryEvent {
constructor(data) {
super();
this.data = data;
}
static {
__name(this, "ClientAddServerEvent");
}
get name() {
return "client_add_server";
}
get properties() {
const { serverName, serverConfig } = this.data;
const url = serverConfig.url;
return {
server_name: serverName,
server_url_domain: url ? this._extractHostname(url) : null,
transport: serverConfig.transport ?? null,
has_auth: !!(serverConfig.authToken || serverConfig.authProvider)
};
}
_extractHostname(url) {
try {
return new URL(url).hostname;
} catch {
return null;
}
}
};
var ClientRemoveServerEvent = class extends BaseTelemetryEvent {
constructor(data) {
super();
this.data = data;
}
static {
__name(this, "ClientRemoveServerEvent");
}
get name() {
return "client_remove_server";
}
get properties() {
return {
server_name: this.data.serverName
};
}
};
// src/telemetry/utils.ts
function getModelProvider(llm) {
return llm._llm_type || llm.constructor.name.toLowerCase();
}
__name(getModelProvider, "getModelProvider");
function getModelName(llm) {
if ("_identifyingParams" in llm) {
const identifyingParams = llm._identifyingParams;
if (typeof identifyingParams === "object" && identifyingParams !== null) {
for (const key of [
"model",
"modelName",
"model_name",
"modelId",
"model_id",
"deploymentName",
"deployment_name"
]) {
if (key in identifyingParams) {
return String(identifyingParams[key]);
}
}
}
}
return llm.model || llm.modelName || llm.constructor.name;
}
__name(getModelName, "getModelName");
function extractModelInfo(llm) {
return [getModelProvider(llm), getModelName(llm)];
}
__name(extractModelInfo, "extractModelInfo");
// src/telemetry/telemetry.ts
function secureRandomString() {
if (typeof window !== "undefined" && window.crypto && typeof window.crypto.getRandomValues === "function") {
const array = new Uint8Array(8);
window.crypto.getRandomValues(array);
return Array.from(array, (v) => v.toString(16).padStart(2, "0")).join("");
}
try {
const crypto = __require("crypto");
return crypto.randomBytes(8).toString("hex");
} catch (e) {
return Math.random().toString(36).substring(2, 15);
}
}
__name(secureRandomString, "secureRandomString");
var USER_ID_STORAGE_KEY = "mcp_use_user_id";
function detectRuntimeEnvironment() {
try {
if (typeof globalThis.Bun !== "undefined") {
return "bun";
}
if (typeof globalThis.Deno !== "undefined") {
return "deno";
}
if (typeof navigator !== "undefined" && navigator.userAgent?.includes("Cloudflare-Workers")) {
return "cloudflare-workers";
}
if (typeof globalThis.EdgeRuntime !== "undefined") {
return "edge";
}
if (typeof window !== "undefined" && typeof document !== "undefined") {
return "browser";
}
if (typeof process !== "undefined" && typeof process.versions?.node !== "undefined") {
return "node";
}
return "unknown";
} catch {
return "unknown";
}
}
__name(detectRuntimeEnvironment, "detectRuntimeEnvironment");
function getStorageCapability(env) {
switch (env) {
case "node":
case "bun":
return "filesystem";
case "browser":
try {
if (typeof localStorage !== "undefined") {
localStorage.setItem("__mcp_use_test__", "1");
localStorage.removeItem("__mcp_use_test__");
return "localStorage";
}
} catch {
}
return "session-only";
case "deno":
return "session-only";
default:
return "session-only";
}
}
__name(getStorageCapability, "getStorageCapability");
var cachedEnvironment = null;
function getRuntimeEnvironment() {
if (cachedEnvironment === null) {
cachedEnvironment = detectRuntimeEnvironment();
}
return cachedEnvironment;
}
__name(getRuntimeEnvironment, "getRuntimeEnvironment");
var ScarfEventLogger = class {
static {
__name(this, "ScarfEventLogger");
}
endpoint;
timeout;
constructor(endpoint, timeout = 3e3) {
this.endpoint = endpoint;
this.timeout = timeout;
}
async logEvent(properties) {
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
const response = await fetch(this.endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(properties),
signal: controller.signal
});
clearTimeout(timeoutId);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
} catch (error) {
logger.debug(`Failed to send Scarf event: ${error}`);
}
}
};
var Telemetry = class _Telemetry {
static {
__name(this, "Telemetry");
}
static instance = null;
PROJECT_API_KEY = "phc_lyTtbYwvkdSbrcMQNPiKiiRWrrM1seyKIMjycSvItEI";
HOST = "https://eu.i.posthog.com";
SCARF_GATEWAY_URL = "https://mcpuse.gateway.scarf.sh/events-ts";
UNKNOWN_USER_ID = "UNKNOWN_USER_ID";
_currUserId = null;
_posthogNodeClient = null;
_posthogBrowserClient = null;
_posthogLoading = null;
_scarfClient = null;
_runtimeEnvironment;
_storageCapability;
_source;
// Node.js specific paths (lazily computed)
_userIdPath = null;
_versionDownloadPath = null;
constructor() {
this._runtimeEnvironment = getRuntimeEnvironment();
this._storageCapability = getStorageCapability(this._runtimeEnvironment);
this._source = typeof process !== "undefined" && process.env?.MCP_USE_TELEMETRY_SOURCE || this._runtimeEnvironment;
const telemetryDisabled = this._checkTelemetryDisabled();
const canSupportTelemetry = this._runtimeEnvironment !== "unknown";
if (telemetryDisabled) {
this._posthogNodeClient = null;
this._posthogBrowserClient = null;
this._scarfClient = null;
logger.debug("Telemetry disabled via environment/localStorage");
} else if (!canSupportTelemetry) {
this._posthogNodeClient = null;
this._posthogBrowserClient = null;
this._scarfClient = null;
logger.debug(
`Telemetry disabled - unknown environment: ${this._runtimeEnvironment}`
);
} else {
logger.info(
"Anonymized telemetry enabled. Set MCP_USE_ANONYMIZED_TELEMETRY=false to disable."
);
this._posthogLoading = this._initPostHog();
if (this._runtimeEnvironment !== "browser") {
try {
this._scarfClient = new ScarfEventLogger(
this.SCARF_GATEWAY_URL,
3e3
);
} catch (e) {
logger.warn(`Failed to initialize Scarf telemetry: ${e}`);
this._scarfClient = null;
}
} else {
this._scarfClient = null;
}
if (this._storageCapability === "filesystem" && this._scarfClient) {
setTimeout(() => {
this.trackPackageDownload({ triggered_by: "initialization" }).catch(
(e) => logger.debug(`Failed to track package download: ${e}`)
);
}, 0);
}
}
}
_checkTelemetryDisabled() {
if (typeof process !== "undefined" && process.env?.MCP_USE_ANONYMIZED_TELEMETRY?.toLowerCase() === "false") {
return true;
}
if (typeof localStorage !== "undefined" && localStorage.getItem("MCP_USE_ANONYMIZED_TELEMETRY") === "false") {
return true;
}
return false;
}
async _initPostHog() {
const isBrowser = this._runtimeEnvironment === "browser";
if (isBrowser) {
await this._initPostHogBrowser();
} else {
await this._initPostHogNode();
}
}
async _initPostHogBrowser() {
try {
const posthogModule = await import("posthog-js");
const posthog = posthogModule.default || posthogModule.posthog;
if (!posthog || typeof posthog.init !== "function") {
throw new Error("posthog-js module did not export expected interface");
}
posthog.init(this.PROJECT_API_KEY, {
api_host: this.HOST,
persistence: "localStorage",
autocapture: false,
// We only want explicit captures
capture_pageview: false,
// We don't want automatic pageview tracking
disable_session_recording: true,
// No session recording
loaded: /* @__PURE__ */ __name(() => {
logger.debug("PostHog browser client initialized");
}, "loaded")
});
this._posthogBrowserClient = posthog;
} catch (e) {
logger.warn(`Failed to initialize PostHog browser telemetry: ${e}`);
this._posthogBrowserClient = null;
}
}
async _initPostHogNode() {
try {
const { PostHog } = await import("posthog-node");
const isServerlessEnvironment = [
"cloudflare-workers",
"edge",
"deno"
].includes(this._runtimeEnvironment);
const posthogOptions = {
host: this.HOST,
disableGeoip: false
};
if (isServerlessEnvironment) {
posthogOptions.flushAt = 1;
posthogOptions.flushInterval = 0;
}
this._posthogNodeClient = new PostHog(
this.PROJECT_API_KEY,
posthogOptions
);
logger.debug("PostHog Node.js client initialized");
} catch (e) {
logger.warn(`Failed to initialize PostHog Node.js telemetry: ${e}`);
this._posthogNodeClient = null;
}
}
/**
* Get the detected runtime environment
*/
get runtimeEnvironment() {
return this._runtimeEnvironment;
}
/**
* Get the storage capability for this environment
*/
get storageCapability() {
return this._storageCapability;
}
static getInstance() {
if (!_Telemetry.instance) {
_Telemetry.instance = new _Telemetry();
}
return _Telemetry.instance;
}
/**
* Set the source identifier for telemetry events.
* This allows tracking usage from different applications.
* @param source - The source identifier (e.g., "my-app", "cli", "vs-code-extension")
*/
setSource(source) {
this._source = source;
logger.debug(`Telemetry source set to: ${source}`);
}
/**
* Get the current source identifier.
*/
getSource() {
return this._source;
}
/**
* Check if telemetry is enabled.
*/
get isEnabled() {
return this._posthogNodeClient !== null || this._posthogBrowserClient !== null || this._scarfClient !== null;
}
get userId() {
if (this._currUserId) {
return this._currUserId;
}
try {
switch (this._storageCapability) {
case "filesystem":
this._currUserId = this._getUserIdFromFilesystem();
break;
case "localStorage":
this._currUserId = this._getUserIdFromLocalStorage();
break;
case "session-only":
default:
try {
this._currUserId = `session-${generateUUID()}`;
} catch (uuidError) {
this._currUserId = `session-${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;
}
break;
}
} catch (e) {
this._currUserId = this.UNKNOWN_USER_ID;
}
return this._currUserId;
}
/**
* Get or create user ID from filesystem (Node.js/Bun)
* Falls back to session ID if filesystem operations fail
*/
_getUserIdFromFilesystem() {
try {
let fs, os, path;
try {
fs = __require("fs");
os = __require("os");
path = __require("path");
} catch (requireError) {
try {
const sessionId = `session-${generateUUID()}`;
return sessionId;
} catch (uuidError) {
return `session-${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;
}
}
if (!this._userIdPath) {
this._userIdPath = path.join(
this._getCacheHome(os, path),
"mcp_use_3",
"telemetry_user_id"
);
}
const isFirstTime = !fs.existsSync(this._userIdPath);
if (isFirstTime) {
fs.mkdirSync(path.dirname(this._userIdPath), { recursive: true });
let newUserId;
try {
newUserId = generateUUID();
} catch (uuidError) {
newUserId = `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;
}
fs.writeFileSync(this._userIdPath, newUserId);
return newUserId;
}
const userId = fs.readFileSync(this._userIdPath, "utf-8").trim();
return userId;
} catch (e) {
try {
return `session-${generateUUID()}`;
} catch (uuidError) {
return `session-${Date.now()}-${secureRandomString()}`;
}
}
}
/**
* Get or create user ID from localStorage (Browser)
*/
_getUserIdFromLocalStorage() {
try {
let userId = localStorage.getItem(USER_ID_STORAGE_KEY);
if (!userId) {
try {
userId = generateUUID();
} catch (uuidError) {
userId = `${Date.now()}-${secureRandomString()}`;
}
localStorage.setItem(USER_ID_STORAGE_KEY, userId);
}
return userId;
} catch (e) {
let sessionId;
try {
sessionId = `session-${generateUUID()}`;
} catch (uuidError) {
sessionId = `session-${Date.now()}-${secureRandomString()}`;
}
return sessionId;
}
}
_getCacheHome(os, path) {
const envVar = process.env.XDG_CACHE_HOME;
if (envVar && path.isAbsolute(envVar)) {
return envVar;
}
const platform = process.platform;
const homeDir = os.homedir();
if (platform === "win32") {
const appdata = process.env.LOCALAPPDATA || process.env.APPDATA;
if (appdata) {
return appdata;
}
return path.join(homeDir, "AppData", "Local");
} else if (platform === "darwin") {
return path.join(homeDir, "Library", "Caches");
} else {
return path.join(homeDir, ".cache");
}
}
async capture(event) {
if (this._posthogLoading) {
await this._posthogLoading;
}
if (!this._posthogNodeClient && !this._posthogBrowserClient && !this._scarfClient) {
return;
}
const currentUserId = this.userId;
const properties = { ...event.properties };
properties.mcp_use_version = getPackageVersion();
properties.language = "typescript";
properties.source = this._source;
properties.runtime = this._runtimeEnvironment;
if (this._posthogNodeClient) {
try {
this._posthogNodeClient.capture({
distinctId: currentUserId,
event: event.name,
properties
});
} catch (e) {
logger.debug(`Failed to track PostHog Node event ${event.name}: ${e}`);
}
}
if (this._posthogBrowserClient) {
try {
this._posthogBrowserClient.capture(event.name, {
...properties,
distinct_id: currentUserId
});
} catch (e) {
logger.debug(
`Failed to track PostHog Browser event ${event.name}: ${e}`
);
}
}
if (this._scarfClient) {
try {
const scarfProperties = {
...properties,
user_id: currentUserId,
event: event.name
};
await this._scarfClient.logEvent(scarfProperties);
} catch (e) {
logger.debug(`Failed to track Scarf event ${event.name}: ${e}`);
}
}
}
// ============================================================================
// Package Download Tracking (Node.js only)
// ============================================================================
/**
* Track package download event.
* This is a public wrapper that safely accesses userId.
*/
async trackPackageDownload(properties) {
return this._trackPackageDownloadInternal(this.userId, properties);
}
/**
* Internal method to track package download with explicit userId.
*/
async _trackPackageDownloadInternal(userId, properties) {
if (!this._scarfClient) {
return;
}
if (this._storageCapability !== "filesystem") {
return;
}
try {
const fs = __require("fs");
const path = __require("path");
const os = __require("os");
if (!this._versionDownloadPath) {
this._versionDownloadPath = path.join(
this._getCacheHome(os, path),
"mcp_use",
"download_version"
);
}
const currentVersion = getPackageVersion();
let shouldTrack = false;
let firstDownload = false;
if (!fs.existsSync(this._versionDownloadPath)) {
shouldTrack = true;
firstDownload = true;
fs.mkdirSync(path.dirname(this._versionDownloadPath), {
recursive: true
});
fs.writeFileSync(this._versionDownloadPath, currentVersion);
} else {
const savedVersion = fs.readFileSync(this._versionDownloadPath, "utf-8").trim();
if (currentVersion > savedVersion) {
shouldTrack = true;
firstDownload = false;
fs.writeFileSync(this._versionDownloadPath, currentVersion);
}
}
if (shouldTrack) {
logger.debug(
`Tracking package download event with properties: ${JSON.stringify(properties)}`
);
const eventProperties = { ...properties || {} };
eventProperties.mcp_use_version = currentVersion;
eventProperties.user_id = userId;
eventProperties.event = "package_download";
eventProperties.first_download = firstDownload;
eventProperties.language = "typescript";
eventProperties.source = this._source;
eventProperties.runtime = this._runtimeEnvironment;
await this._scarfClient.logEvent(eventProperties);
}
} catch (e) {
logger.debug(`Failed to track Scarf package_download event: ${e}`);
}
}
// ============================================================================
// Agent Events
// ============================================================================
async trackAgentExecution(data) {
if (!this.isEnabled) return;
const event = new MCPAgentExecutionEvent(data);
await this.capture(event);
}
// ============================================================================
// Server Events
// ============================================================================
/**
* Track server run event directly from an MCPServer instance.
*/
async trackServerRunFromServer(server, transport) {
if (!this.isEnabled) return;
const data = createServerRunEventData(server, transport);
const event = new ServerRunEvent(data);
await this.capture(event);
}
async trackServerInitialize(data) {
if (!this.isEnabled) return;
const event = new ServerInitializeEvent(data);
await this.capture(event);
}
async trackServerToolCall(data) {
if (!this.isEnabled) return;
const event = new ServerToolCallEvent(data);
await this.capture(event);
}
async trackServerResourceCall(data) {
if (!this.isEnabled) return;
const event = new ServerResourceCallEvent(data);
await this.capture(event);
}
async trackServerPromptCall(data) {
if (!this.isEnabled) return;
const event = new ServerPromptCallEvent(data);
await this.capture(event);
}
async trackServerContext(data) {
if (!this.isEnabled) return;
const event = new ServerContextEvent(data);
await this.capture(event);
}
// ============================================================================
// Client Events
// ============================================================================
async trackMCPClientInit(data) {
if (!this.isEnabled) return;
const event = new MCPClientInitEvent(data);
await this.capture(event);
}
async trackConnectorInit(data) {
if (!this.isEnabled) return;
const event = new ConnectorInitEvent(data);
await this.capture(event);
}
async trackClientAddServer(serverName, serverConfig) {
if (!this.isEnabled) return;
const event = new ClientAddServerEvent({ serverName, serverConfig });
await this.capture(event);
}
async trackClientRemoveServer(serverName) {
if (!this.isEnabled) return;
const event = new ClientRemoveServerEvent({ serverName });
await this.capture(event);
}
// ============================================================================
// React Hook / Browser specific events
// ============================================================================
async trackUseMcpConnection(data) {
if (!this.isEnabled) return;
await this.capture({
name: "usemcp_connection",
properties: {
url_domain: new URL(data.url).hostname,
// Only domain for privacy
transport_type: data.transportType,
success: data.success,
error_type: data.errorType ?? null,
connection_time_ms: data.connectionTimeMs ?? null,
has_oauth: data.hasOAuth,
has_sampling: data.hasSampling,
has_elicitation: data.hasElicitation
}
});
}
async trackUseMcpToolCall(data) {
if (!this.isEnabled) return;
await this.capture({
name: "usemcp_tool_call",
properties: {
tool_name: data.toolName,
success: data.success,
error_type: data.errorType ?? null,
execution_time_ms: data.executionTimeMs ?? null
}
});
}
async trackUseMcpResourceRead(data) {
if (!this.isEnabled) return;
await this.capture({
name: "usemcp_resource_read",
properties: {
resource_uri_scheme: data.resourceUri.split(":")[0],
// Only scheme for privacy
success: data.success,
error_type: data.errorType ?? null
}
});
}
// ============================================================================
// Browser-specific Methods
// ============================================================================
/**
* Identify the current user (useful for linking sessions)
* Browser only - no-op in Node.js
*/
identify(userId, properties) {
if (this._posthogBrowserClient) {
try {
this._posthogBrowserClient.identify(userId, properties);
} catch (e) {
logger.debug(`Failed to identify user: ${e}`);
}
}
}
/**
* Reset the user identity (useful for logout)
* Browser only - no-op in Node.js
*/
reset() {
if (this._posthogBrowserClient) {
try {
this._posthogBrowserClient.reset();
} catch (e) {
logger.debug(`Failed to reset user: ${e}`);
}
}
this._currUserId = null;
}
// ============================================================================
// Node.js-specific Methods
// ============================================================================
/**
* Flush the telemetry queue (Node.js only)
*/
flush() {
if (this._posthogNodeClient) {
try {
this._posthogNodeClient.flush();
logger.debug("PostHog client telemetry queue flushed");
} catch (e) {
logger.debug(`Failed to flush PostHog client: ${e}`);
}
}
}
/**
* Shutdown the telemetry client (Node.js only)
*/
shutdown() {
if (this._posthogNodeClient) {
try {
this._posthogNodeClient.shutdown();
logger.debug("PostHog client shutdown successfully");
} catch (e) {
logger.debug(`Error shutting down PostHog client: ${e}`);
}
}
}
};
var Tel = Telemetry;
function setTelemetrySource(source) {
Tel.getInstance().setSource(source);
}
__name(setTelemetrySource, "setTelemetrySource");
export {
isDeno,
getEnv,
getCwd,
fsHelpers,
pathHelpers,
generateUUID,
VERSION,
getPackageVersion,
extractModelInfo,
Telemetry,
Tel,
setTelemetrySource
};