deepsource-mcp-server
Version:
Model Context Protocol server for DeepSource
351 lines • 12.8 kB
JavaScript
/**
* @fileoverview Tool registration module for DeepSource MCP tools
*
* This module handles the registration of all DeepSource tools with the
* MCP server. It centralizes tool registration logic and provides a
* clean interface for registering tools.
*
* @packageDocumentation
*/
import { toolSchemas } from './tool-definitions.js';
import { handleProjects, handleDeepsourceQualityMetrics, handleDeepsourceUpdateMetricThreshold, handleDeepsourceUpdateMetricSetting, handleDeepsourceComplianceReport, handleDeepsourceProjectIssues, handleDeepsourceProjectRuns, handleDeepsourceRun, handleDeepsourceRecentRunIssues, handleDeepsourceDependencyVulnerabilities, } from '../handlers/index.js';
import { createLogger } from '../utils/logging/logger.js';
const logger = createLogger('ToolRegistration');
/**
* Handler mapping for tool schemas
*/
const TOOL_HANDLERS = {
projects: async (params) => {
logger.info('=== PROJECTS HANDLER START ===');
logger.info('Projects handler called with params:', { params, type: typeof params });
try {
// Params currently unused but may be used for future filtering
const result = await handleProjects();
logger.info('=== PROJECTS HANDLER SUCCESS ===', { result });
return result;
}
catch (error) {
logger.error('=== PROJECTS HANDLER ERROR ===', {
error,
message: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
});
throw error;
}
},
quality_metrics: async (params) => {
const typedParams = params;
const metricsParams = {
projectKey: typedParams.projectKey,
};
const shortcodeIn = typedParams.shortcodeIn;
if (shortcodeIn) {
metricsParams.shortcodeIn = shortcodeIn;
}
return handleDeepsourceQualityMetrics(metricsParams);
},
update_metric_threshold: async (params) => {
const typedParams = params;
const thresholdParams = {
projectKey: typedParams.projectKey,
repositoryId: typedParams.repositoryId,
metricShortcode: typedParams.metricShortcode,
metricKey: typedParams.metricKey,
};
const thresholdValue = typedParams.thresholdValue;
if (thresholdValue !== undefined) {
thresholdParams.thresholdValue = thresholdValue;
}
return handleDeepsourceUpdateMetricThreshold(thresholdParams);
},
update_metric_setting: async (params) => {
const typedParams = params;
return handleDeepsourceUpdateMetricSetting({
projectKey: typedParams.projectKey,
repositoryId: typedParams.repositoryId,
metricShortcode: typedParams.metricShortcode,
isReported: typedParams.isReported,
isThresholdEnforced: typedParams.isThresholdEnforced,
});
},
compliance_report: async (params) => {
const typedParams = params;
return handleDeepsourceComplianceReport({
projectKey: typedParams.projectKey,
reportType: typedParams.reportType,
});
},
project_issues: async (params) => {
const typedParams = params;
const issuesParams = {
projectKey: typedParams.projectKey,
};
if (typeof typedParams.path === 'string') {
issuesParams.path = typedParams.path;
}
if (Array.isArray(typedParams.analyzerIn)) {
issuesParams.analyzerIn = typedParams.analyzerIn;
}
if (Array.isArray(typedParams.tags)) {
issuesParams.tags = typedParams.tags;
}
if (typeof typedParams.first === 'number') {
issuesParams.first = typedParams.first;
}
if (typeof typedParams.last === 'number') {
issuesParams.last = typedParams.last;
}
if (typeof typedParams.after === 'string') {
issuesParams.after = typedParams.after;
}
if (typeof typedParams.before === 'string') {
issuesParams.before = typedParams.before;
}
return handleDeepsourceProjectIssues(issuesParams);
},
runs: async (params) => {
const typedParams = params;
const runsParams = {
projectKey: typedParams.projectKey,
analyzerIn: typedParams.analyzerIn,
};
if (typeof typedParams.first === 'number') {
runsParams.first = typedParams.first;
}
if (typeof typedParams.last === 'number') {
runsParams.last = typedParams.last;
}
if (typeof typedParams.after === 'string') {
runsParams.after = typedParams.after;
}
if (typeof typedParams.before === 'string') {
runsParams.before = typedParams.before;
}
return handleDeepsourceProjectRuns(runsParams);
},
run: async (params) => {
const typedParams = params;
const runParams = {
projectKey: typedParams.projectKey,
runIdentifier: typedParams.runIdentifier,
};
if (typeof typedParams.isCommitOid === 'boolean') {
runParams.isCommitOid = typedParams.isCommitOid;
}
return handleDeepsourceRun(runParams);
},
recent_run_issues: async (params) => {
const typedParams = params;
const recentRunParams = {
projectKey: typedParams.projectKey,
branchName: typedParams.branchName,
};
if (typeof typedParams.first === 'number') {
recentRunParams.first = typedParams.first;
}
if (typeof typedParams.last === 'number') {
recentRunParams.last = typedParams.last;
}
if (typeof typedParams.after === 'string') {
recentRunParams.after = typedParams.after;
}
if (typeof typedParams.before === 'string') {
recentRunParams.before = typedParams.before;
}
return handleDeepsourceRecentRunIssues(recentRunParams);
},
dependency_vulnerabilities: async (params) => {
const typedParams = params;
const vulnParams = {
projectKey: typedParams.projectKey,
};
if (typeof typedParams.first === 'number') {
vulnParams.first = typedParams.first;
}
if (typeof typedParams.last === 'number') {
vulnParams.last = typedParams.last;
}
if (typeof typedParams.after === 'string') {
vulnParams.after = typedParams.after;
}
if (typeof typedParams.before === 'string') {
vulnParams.before = typedParams.before;
}
return handleDeepsourceDependencyVulnerabilities(vulnParams);
},
};
/**
* Creates a tool definition from a schema and handler
*
* @param schema - The tool schema
* @param handler - The tool handler function
* @returns The tool definition
*/
function createToolDefinition(schema, handler) {
logger.debug(`Creating tool definition for ${schema.name}`, {
hasInputSchema: Boolean(schema.inputSchema),
inputSchemaType: typeof schema.inputSchema,
inputSchema: schema.inputSchema,
});
return {
name: schema.name,
description: schema.description,
inputSchema: schema.inputSchema,
outputSchema: schema.outputSchema,
handler,
};
}
/**
* Registers all DeepSource tools with the tool registry
*
* @param registry - The tool registry to register tools with
*/
export function registerDeepSourceTools(registry) {
logger.info('=== REGISTER DEEPSOURCE TOOLS START ===');
logger.info('Registering DeepSource tools', {
toolSchemasType: typeof toolSchemas,
toolSchemasIsArray: Array.isArray(toolSchemas),
toolSchemasLength: Array.isArray(toolSchemas) ? toolSchemas.length : 'not an array',
toolSchemaNames: Array.isArray(toolSchemas) ? toolSchemas.map((s) => s.name) : 'not an array',
});
const toolDefinitions = [];
// Create tool definitions from schemas and handlers
for (const schema of toolSchemas) {
logger.debug(`Processing schema: ${schema.name}`);
const handler = TOOL_HANDLERS[schema.name];
if (!handler) {
logger.warn(`No handler found for tool: ${schema.name}`);
continue;
}
logger.debug(`Creating tool definition for: ${schema.name}`);
const toolDef = createToolDefinition(schema, handler);
toolDefinitions.push(toolDef);
logger.debug(`Successfully created tool definition for: ${schema.name}`);
}
logger.info(`Prepared ${toolDefinitions.length} tool definitions for registration`);
// Register all tools
registry.registerTools(toolDefinitions);
logger.info('=== REGISTER DEEPSOURCE TOOLS COMPLETE ===', {
registeredCount: toolDefinitions.length,
registeredTools: toolDefinitions.map((t) => t.name),
});
}
/**
* Tool categories for organization
*/
export var ToolCategory;
(function (ToolCategory) {
ToolCategory["PROJECT_MANAGEMENT"] = "project_management";
ToolCategory["CODE_QUALITY"] = "code_quality";
ToolCategory["SECURITY"] = "security";
ToolCategory["ANALYSIS"] = "analysis";
ToolCategory["DEPENDENCIES"] = "dependencies";
})(ToolCategory || (ToolCategory = {}));
/**
* Metadata for all DeepSource tools
*/
export const TOOL_METADATA = {
projects: {
category: ToolCategory.PROJECT_MANAGEMENT,
tags: ['projects', 'list', 'discovery'],
requiresAuth: true,
supportsFiltering: false,
supportsPagination: false,
},
quality_metrics: {
category: ToolCategory.CODE_QUALITY,
tags: ['metrics', 'quality', 'code', 'statistics'],
requiresAuth: true,
supportsFiltering: true,
supportsPagination: false,
},
update_metric_threshold: {
category: ToolCategory.CODE_QUALITY,
tags: ['metrics', 'quality', 'threshold', 'update', 'mutation'],
requiresAuth: true,
supportsFiltering: false,
supportsPagination: false,
},
update_metric_setting: {
category: ToolCategory.CODE_QUALITY,
tags: ['metrics', 'quality', 'settings', 'update', 'mutation'],
requiresAuth: true,
supportsFiltering: false,
supportsPagination: false,
},
compliance_report: {
category: ToolCategory.SECURITY,
tags: ['compliance', 'security', 'report', 'owasp', 'sans'],
requiresAuth: true,
supportsFiltering: false,
supportsPagination: false,
},
project_issues: {
category: ToolCategory.CODE_QUALITY,
tags: ['issues', 'problems', 'code', 'quality', 'list'],
requiresAuth: true,
supportsFiltering: true,
supportsPagination: true,
},
runs: {
category: ToolCategory.ANALYSIS,
tags: ['runs', 'analysis', 'history', 'list'],
requiresAuth: true,
supportsFiltering: true,
supportsPagination: true,
},
run: {
category: ToolCategory.ANALYSIS,
tags: ['run', 'analysis', 'details', 'single'],
requiresAuth: true,
supportsFiltering: false,
supportsPagination: false,
},
recent_run_issues: {
category: ToolCategory.ANALYSIS,
tags: ['issues', 'run', 'recent', 'branch', 'analysis'],
requiresAuth: true,
supportsFiltering: false,
supportsPagination: true,
},
dependency_vulnerabilities: {
category: ToolCategory.DEPENDENCIES,
tags: ['dependencies', 'vulnerabilities', 'security', 'cve', 'list'],
requiresAuth: true,
supportsFiltering: false,
supportsPagination: true,
},
};
/**
* Gets tools by category
*
* @param category - The tool category
* @returns Array of tool names in the category
*/
export function getToolsByCategory(category) {
return Object.entries(TOOL_METADATA)
.filter(([, metadata]) => metadata.category === category)
.map(([name]) => name);
}
/**
* Gets tools by tag
*
* @param tag - The tag to filter by
* @returns Array of tool names with the tag
*/
export function getToolsByTag(tag) {
return Object.entries(TOOL_METADATA)
.filter(([, metadata]) => metadata.tags.includes(tag))
.map(([name]) => name);
}
/**
* Gets paginated tools
*
* @returns Array of tool names that support pagination
*/
export function getPaginatedTools() {
return Object.entries(TOOL_METADATA)
.filter(([, metadata]) => metadata.supportsPagination)
.map(([name]) => name);
}
//# sourceMappingURL=tool-registration.js.map