@codacy/codacy-mcp
Version:
Codacy MCP server
170 lines (169 loc) • 5.98 kB
JavaScript
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
import { OpenAPI } from './src/api/client/index.js';
import * as Tools from './src/tools/index.js';
import * as Handlers from './src/handlers/index.js';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { applyProxyConfig } from './src/proxy.js';
// Apply proxy / SSL configuration before any outbound requests are made.
applyProxyConfig();
// Check for API key
const CODACY_ACCOUNT_TOKEN = process.env.CODACY_ACCOUNT_TOKEN;
OpenAPI.BASE = 'https://app.codacy.com/api/v3';
OpenAPI.HEADERS = {
'api-token': CODACY_ACCOUNT_TOKEN || '',
'X-Codacy-Origin': 'mcp-server',
};
const mcpServer = new McpServer({
name: 'codacy-mcp-server',
version: '0.1.0',
}, {
capabilities: {
tools: {},
resources: {},
},
});
const toolDefinitions = {
codacy_list_organization_repositories: {
tool: Tools.listOrganizationRepositoriesTool,
handler: Handlers.listOrganizationRepositoriesHandler,
},
codacy_search_organization_srm_items: {
tool: Tools.searchOrganizationSecurityItemsTool,
handler: Handlers.searchSecurityItemsHandler,
},
codacy_search_repository_srm_items: {
tool: Tools.searchRepositorySecurityItemsTool,
handler: Handlers.searchRepositorySecurityItemsHandler,
},
codacy_list_repository_issues: {
tool: Tools.searchRepositoryIssuesTool,
handler: Handlers.searchRepositoryIssuesHandler,
},
codacy_list_repository_pull_requests: {
tool: Tools.listRepositoryPullRequestsTool,
handler: Handlers.listRepositoryPullRequestsHandler,
},
codacy_list_files: {
tool: Tools.listFilesTool,
handler: Handlers.listFilesHandler,
},
codacy_get_file_issues: {
tool: Tools.listFileIssuesTool,
handler: Handlers.getFileIssuesHandler,
},
codacy_get_file_coverage: {
tool: Tools.getFileCoverageTool,
handler: Handlers.getFileCoverageHandler,
},
codacy_get_pull_request_files_coverage: {
tool: Tools.getRepositoryPullRequestFilesCoverageTool,
handler: Handlers.getRepositoryPullRequestFilesCoverageHandler,
},
codacy_get_pull_request_git_diff: {
tool: Tools.getPullRequestGitDiffTool,
handler: Handlers.getPullRequestGitDiffHandler,
},
codacy_list_pull_request_issues: {
tool: Tools.listPullRequestIssuesTool,
handler: Handlers.listPullRequestIssuesHandler,
},
codacy_get_repository_with_analysis: {
tool: Tools.getRepositoryWithAnalysisTool,
handler: Handlers.getRepositoryWithAnalysisHandler,
},
codacy_get_file_with_analysis: {
tool: Tools.getFileWithAnalysisTool,
handler: Handlers.getFileWithAnalysisHandler,
},
codacy_get_file_clones: {
tool: Tools.getFileClonesTool,
handler: Handlers.getFileClonesHandler,
},
codacy_get_repository_pull_request: {
tool: Tools.getRepositoryPullRequestTool,
handler: Handlers.getRepositoryPullRequestHandler,
},
codacy_get_issue: {
tool: Tools.getIssueTool,
handler: Handlers.getIssueHandler,
},
codacy_get_pattern: {
tool: Tools.getPatternTool,
handler: Handlers.getPatternHandler,
noAuth: true,
},
codacy_list_repository_tool_patterns: {
tool: Tools.listRepositoryToolPatternsTool,
handler: Handlers.listRepositoryToolPatternsHandler,
},
codacy_list_tools: {
tool: Tools.listToolsTool,
handler: Handlers.listToolsHandler,
noAuth: true,
},
codacy_list_repository_tools: {
tool: Tools.listRepositoryToolsTool,
handler: Handlers.listRepositoryToolsHandler,
},
codacy_list_organizations: {
tool: Tools.listOrganizationsTool,
handler: Handlers.listOrganizationsHandler,
},
codacy_cli_analyze: {
tool: Tools.cliAnalyzeTool,
handler: Handlers.cliAnalyzeHandler,
noAuth: true,
},
codacy_cli_install: {
tool: Tools.cliInstallTool,
handler: Handlers.cliInstallHandler,
noAuth: true,
},
codacy_setup_repository: {
tool: Tools.setupRepositoryTool,
handler: Handlers.setupRepositoryHandler,
},
};
// Register tools
mcpServer.server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: Object.values(toolDefinitions)
.filter(({ noAuth }) => CODACY_ACCOUNT_TOKEN || noAuth)
.map(({ tool }) => tool),
}));
// Register request handlers
mcpServer.server.setRequestHandler(CallToolRequestSchema, async (request) => {
try {
if (!request.params.arguments) {
throw new Error('Arguments are required');
}
const toolDefinition = toolDefinitions[request.params.name];
if (!toolDefinition)
throw new Error(`Unknown tool: ${request.params.name}`);
// Validate required arguments
const requiredArguments = (toolDefinition.tool.inputSchema.required || []);
requiredArguments.forEach(required => {
if (!request.params.arguments?.[required]) {
throw new Error(`Argument ${required} is required`);
}
});
const result = await toolDefinition.handler(request.params.arguments);
return {
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
};
}
catch (error) {
console.error(error);
throw error;
}
});
async function runServer() {
const transport = new StdioServerTransport();
await mcpServer.connect(transport);
console.error('Codacy MCP Server running on stdio');
}
runServer().catch(error => {
console.error('Fatal error in main():', error);
process.exit(1);
});