@mikoto_zero/minigame-open-mcp
Version:
TapTap Open API MCP Server - Documentation and Management APIs for TapTap Minigame and H5 Games (Leaderboard, and more features coming)
192 lines • 6.75 kB
JavaScript
/**
* Logger utility for TapTap Minigame MCP Server
* Controlled by TAPTAP_MINIGAME_MCP_VERBOSE environment variable
*/
import process from 'node:process';
/**
* Check if verbose logging is enabled
*/
function isVerboseEnabled() {
return process.env.TAPTAP_MINIGAME_MCP_VERBOSE === 'true' || process.env.TAPTAP_MINIGAME_MCP_VERBOSE === '1';
}
/**
* Format object for logging
*/
function formatObject(obj) {
try {
return JSON.stringify(obj, null, 2);
}
catch (error) {
return String(obj);
}
}
/**
* Get current timestamp
*/
function getTimestamp() {
return new Date().toISOString();
}
/**
* Logger class for structured logging
*/
export class Logger {
constructor() {
this.verbose = isVerboseEnabled();
}
/**
* Log informational message
*/
info(message, data) {
if (!this.verbose)
return;
process.stderr.write(`[${getTimestamp()}] [INFO] ${message}\n`);
if (data !== undefined) {
process.stderr.write(`${formatObject(data)}\n`);
}
}
/**
* Log error message
*/
error(message, error) {
if (!this.verbose)
return;
process.stderr.write(`[${getTimestamp()}] [ERROR] ${message}\n`);
if (error !== undefined) {
if (error instanceof Error) {
process.stderr.write(`${error.message}\n${error.stack || ''}\n`);
}
else {
process.stderr.write(`${formatObject(error)}\n`);
}
}
}
/**
* Log debug message
*/
debug(message, data) {
if (!this.verbose)
return;
process.stderr.write(`[${getTimestamp()}] [DEBUG] ${message}\n`);
if (data !== undefined) {
process.stderr.write(`${formatObject(data)}\n`);
}
}
/**
* Log tool call with input arguments
*/
logToolCall(toolName, args) {
if (!this.verbose)
return;
process.stderr.write(`\n${'='.repeat(80)}\n`);
process.stderr.write(`[${getTimestamp()}] [TOOL CALL] ${toolName}\n`);
process.stderr.write(`${'='.repeat(80)}\n`);
process.stderr.write(`📥 Input:\n${formatObject(args)}\n`);
}
/**
* Log tool response with output
*/
logToolResponse(toolName, output, success = true) {
if (!this.verbose)
return;
process.stderr.write(`\n${'-'.repeat(80)}\n`);
process.stderr.write(`[${getTimestamp()}] [TOOL RESPONSE] ${toolName} - ${success ? '✅ SUCCESS' : '❌ FAILED'}\n`);
process.stderr.write(`${'-'.repeat(80)}\n`);
process.stderr.write(`📤 Output:\n${typeof output === 'string' ? output.substring(0, 500) + (output.length > 500 ? '...(truncated)' : '') : formatObject(output)}\n`);
process.stderr.write(`${'='.repeat(80)}\n\n`);
}
/**
* Log HTTP request
*/
logRequest(method, url, headers, body) {
if (!this.verbose)
return;
process.stderr.write(`\n${'='.repeat(100)}\n`);
process.stderr.write(`[${getTimestamp()}] [HTTP REQUEST]\n`);
process.stderr.write(`${'='.repeat(100)}\n`);
// 请求基本信息
process.stderr.write(`📤 Method: ${method}\n`);
process.stderr.write(`📤 URL: ${url}\n`);
process.stderr.write(`\n`);
// 过滤敏感信息
const safeHeaders = { ...headers };
if (safeHeaders['Authorization']) {
const authHeader = safeHeaders['Authorization'];
// 保留完整的 Authorization header 结构,只隐藏 mac 签名
safeHeaders['Authorization'] = authHeader.replace(/mac="[^"]+"/g, 'mac="***REDACTED***"');
// 显示原始的 Authorization(脱敏后)
process.stderr.write(`🔐 Authorization:\n${safeHeaders['Authorization']}\n\n`);
}
if (safeHeaders['X-Tap-Sign']) {
safeHeaders['X-Tap-Sign'] = '***REDACTED***';
}
// 完整的 Headers
process.stderr.write(`📋 Headers (${Object.keys(headers).length} total):\n`);
process.stderr.write(`${formatObject(safeHeaders)}\n`);
// Body 内容
if (body) {
let parsedBody;
try {
parsedBody = JSON.parse(body);
process.stderr.write(`\n📦 Request Body (JSON):\n`);
process.stderr.write(`${formatObject(parsedBody)}\n`);
}
catch {
process.stderr.write(`\n📦 Request Body (Raw):\n`);
process.stderr.write(`${body}\n`);
}
}
else {
process.stderr.write(`\n📦 Request Body: (empty)\n`);
}
}
/**
* Log HTTP response
*/
logResponse(method, url, status, statusText, body, success = true, responseHeaders) {
if (!this.verbose)
return;
process.stderr.write(`\n${'-'.repeat(100)}\n`);
process.stderr.write(`[${getTimestamp()}] [HTTP RESPONSE] ${success ? '✅ SUCCESS' : '❌ FAILED'}\n`);
process.stderr.write(`${'-'.repeat(100)}\n`);
// 响应基本信息
process.stderr.write(`📥 Method: ${method}\n`);
process.stderr.write(`📥 URL: ${url}\n`);
process.stderr.write(`📥 Status: ${status} ${statusText}\n`);
process.stderr.write(`\n`);
// 响应头(如果提供)
if (responseHeaders && Object.keys(responseHeaders).length > 0) {
process.stderr.write(`📋 Response Headers (${Object.keys(responseHeaders).length} total):\n`);
process.stderr.write(`${formatObject(responseHeaders)}\n\n`);
}
// 响应体
if (typeof body === 'string') {
// 尝试解析为 JSON
try {
const parsedBody = JSON.parse(body);
process.stderr.write(`📦 Response Body (JSON):\n`);
process.stderr.write(`${formatObject(parsedBody)}\n`);
}
catch {
process.stderr.write(`📦 Response Body (Text):\n`);
process.stderr.write(`${body}\n`);
}
}
else if (body !== undefined && body !== null) {
process.stderr.write(`📦 Response Body (Object):\n`);
process.stderr.write(`${formatObject(body)}\n`);
}
else {
process.stderr.write(`📦 Response Body: (empty)\n`);
}
process.stderr.write(`${'='.repeat(100)}\n\n`);
}
/**
* Check if verbose mode is enabled
*/
isVerbose() {
return this.verbose;
}
}
// Export singleton instance
export const logger = new Logger();
//# sourceMappingURL=logger.js.map