@utaba/ucm-mcp-server
Version:
Universal Context Manager MCP Server - AI Productivity Platform
114 lines • 5.32 kB
JavaScript
/**
* SharePointSignOutTool
* Revoke user's OnBehalfOf authorization for a SharePoint connection
*/
import { BaseToolController } from '../base/BaseToolController.js';
import { McpError, McpErrorCode } from '../../utils/McpErrorHandler.js';
export class SharePointSignOutTool extends BaseToolController {
constructor(ucmClient, logger, publishingAuthorId) {
super(ucmClient, logger, publishingAuthorId);
}
get name() {
return 'ucm_sharepoint_signout';
}
get description() {
return 'This signs the user out only for connections with user-delegated permissions.';
}
get inputSchema() {
return {
type: 'object',
properties: {
connectionId: {
type: 'string',
description: 'SharePoint connection ID to revoke authorization for (get this from list_connections)',
minLength: 36,
maxLength: 36
}
},
required: ['connectionId']
};
}
validateParams(params) {
super.validateParams(params);
// Validate connectionId
if (!params.connectionId || typeof params.connectionId !== 'string') {
throw new McpError(McpErrorCode.InvalidParams, 'connectionId is required and must be a string');
}
if (params.connectionId.length !== 36) {
throw new McpError(McpErrorCode.InvalidParams, 'connectionId must be a valid UUID (36 characters)');
}
}
async handleExecute(params) {
this.logger.info('SharePointSignOutTool', `Revoking SharePoint authorization for connection ${params.connectionId}`);
try {
// Call API to revoke authorization
const result = await this.ucmClient.sharePointSignOut(params.connectionId);
this.logger.info('SharePointSignOutTool', 'Authorization revoked successfully', '', {
connectionId: params.connectionId,
success: result.success
});
// Return structured markdown response
const markdown = this.formatSignOutResponse(result);
return markdown;
}
catch (error) {
// Sanitize error for logging to avoid circular reference issues
const sanitizedError = {
message: error?.message,
status: error?.response?.status,
data: error?.response?.data
};
this.logger.error('SharePointSignOutTool', 'Failed to revoke authorization', '', sanitizedError);
if (error instanceof McpError) {
throw error;
}
// Handle API errors
if (error.response) {
const status = error.response.status;
const errorData = error.response.data;
if (status === 401 || status === 403) {
throw new McpError(McpErrorCode.InvalidRequest, `Access denied: ${errorData?.message || 'Not authorized to revoke SharePoint authorization'}`);
}
if (status === 404) {
throw new McpError(McpErrorCode.InvalidRequest, `Connection not found: ${errorData?.message || 'SharePoint connection does not exist'}`);
}
if (status === 400 && errorData?.error === 'INVALID_AUTH_TYPE') {
throw new McpError(McpErrorCode.InvalidRequest, `Invalid operation: Only OnBehalfOf (user-delegated) connections support user authorization. This connection uses ServicePrincipal authentication.`);
}
throw new McpError(McpErrorCode.InternalError, `API error: ${errorData?.message || error.message}`);
}
throw new McpError(McpErrorCode.InternalError, `Failed to revoke SharePoint authorization: ${error.message}`);
}
}
/**
* Format sign out response as markdown
*/
formatSignOutResponse(result) {
const lines = [];
lines.push('# SharePoint Authorization Revoked\n');
if (result.success) {
lines.push('✅ **Status**: Authorization successfully revoked\n');
lines.push(`**Connection ID**: ${result.connectionId}\n`);
if (result.revokedAt) {
lines.push(`**Revoked At**: ${new Date(result.revokedAt).toLocaleString()}\n`);
}
lines.push('\n## What This Means\n');
lines.push('- Your access tokens have been deleted from the system');
lines.push('- You are now signed out of this SharePoint connection');
lines.push('- To access SharePoint files again, you must re-authorize\n');
if (result._links?.authorize) {
lines.push('\n## Re-authorize Access\n');
lines.push(`To grant access again, visit: ${result._links.authorize.href}\n`);
}
}
else {
lines.push('⚠️ **Status**: Revocation failed or not needed\n');
lines.push(`**Message**: ${result.message}\n`);
if (result.details?.reason) {
lines.push(`**Reason**: ${result.details.reason}\n`);
}
}
return lines.join('\n');
}
}
//# sourceMappingURL=SharePointSignOutTool.js.map