resources.js•5.94 kB
/**
* Google Cloud Logging resources for MCP
*/
import { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
import { getProjectId } from '../../utils/auth.js';
import { GcpMcpError } from '../../utils/error.js';
import { formatLogEntry, getLoggingClient } from './types.js';
/**
* Registers Google Cloud Logging resources with the MCP server
*
* @param server The MCP server instance
*/
export function registerLoggingResources(server) {
// Register a resource for listing recent logs
server.resource('recent-logs', new ResourceTemplate('gcp-logs://{projectId}/recent', { list: undefined }), async (uri, { projectId }, _extra) => {
try {
const actualProjectId = projectId || await getProjectId();
const logging = getLoggingClient();
const defaultFilter = process.env.LOG_FILTER || '';
const [entries] = await logging.getEntries({
pageSize: 50,
filter: defaultFilter
});
if (!entries || entries.length === 0) {
return {
contents: [{
uri: uri.href,
text: 'No log entries found.'
}]
};
}
// Format logs with error handling for each entry
const formattedLogs = entries
.map((entry) => {
try {
return formatLogEntry(entry);
}
catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Unknown error';
return `## Error Formatting Log Entry\n\nAn error occurred while formatting a log entry: ${errorMessage}`;
}
})
.join('\n\n');
return {
contents: [{
uri: uri.href,
text: `# Recent Logs for Project: ${actualProjectId}\n\n${formattedLogs}`
}]
};
}
catch (error) {
// Get project ID safely
let projectIdForError;
try {
projectIdForError = Array.isArray(projectId) ? projectId[0] : (projectId || process.env.GOOGLE_CLOUD_PROJECT || 'unknown');
}
catch {
projectIdForError = 'unknown';
}
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
// Return a user-friendly error message instead of throwing
return {
contents: [{
uri: uri.href,
text: `# Error Fetching Recent Logs\n\nAn error occurred while fetching recent logs for project ${projectIdForError}: ${errorMessage}\n\nPlease check your Google Cloud credentials and project configuration.`
}]
};
}
});
// Register a resource for querying logs with a filter
server.resource('filtered-logs', new ResourceTemplate('gcp-logs://{projectId}/filter/{filter}', { list: undefined }), async (uri, { projectId, filter }, _extra) => {
try {
const actualProjectId = projectId || await getProjectId();
const logging = getLoggingClient();
if (!filter) {
throw new GcpMcpError('Log filter is required', 'INVALID_ARGUMENT', 400);
}
const decodedFilter = Array.isArray(filter) ? decodeURIComponent(filter[0]) : decodeURIComponent(filter);
const [entries] = await logging.getEntries({
pageSize: 50,
filter: decodedFilter
});
if (!entries || entries.length === 0) {
return {
contents: [{
uri: uri.href,
text: `No log entries found matching filter: ${decodedFilter}`
}]
};
}
// Format logs with error handling for each entry
const formattedLogs = entries
.map((entry) => {
try {
return formatLogEntry(entry);
}
catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Unknown error';
return `## Error Formatting Log Entry\n\nAn error occurred while formatting a log entry: ${errorMessage}`;
}
})
.join('\n\n');
return {
contents: [{
uri: uri.href,
text: `# Filtered Logs for Project: ${actualProjectId}\n\nFilter: ${decodedFilter}\n\n${formattedLogs}`
}]
};
}
catch (error) {
// Get project ID and filter safely
let projectIdForError;
let filterForError;
try {
projectIdForError = Array.isArray(projectId) ? projectId[0] : (projectId || process.env.GOOGLE_CLOUD_PROJECT || 'unknown');
filterForError = Array.isArray(filter) ? filter[0] : String(filter || 'unknown');
}
catch {
projectIdForError = 'unknown';
filterForError = 'unknown';
}
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
// Return a user-friendly error message instead of throwing
return {
contents: [{
uri: uri.href,
text: `# Error Fetching Filtered Logs\n\nAn error occurred while fetching logs with filter "${filterForError}" for project ${projectIdForError}: ${errorMessage}\n\nPlease check your filter syntax and Google Cloud credentials.`
}]
};
}
});
}
//# sourceMappingURL=resources.js.map