UNPKG

@rashidazarang/aptly-mcp

Version:

Model Context Protocol server for Aptly package repository management - enables AI assistants to manage Debian repositories

196 lines 8.84 kB
import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ErrorCode, ListResourcesRequestSchema, ListToolsRequestSchema, McpError, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import { AptlyClient } from './utils/aptly-client.js'; import { createRepositoryTools, handleRepositoryTool } from './tools/repository-tools.js'; import { createPackageTools, handlePackageTool } from './tools/package-tools.js'; import { createSnapshotTools, handleSnapshotTool } from './tools/snapshot-tools.js'; import { createPublishTools, handlePublishTool } from './tools/publish-tools.js'; import { createMirrorTools, handleMirrorTool } from './tools/mirror-tools.js'; export class AptlyMcpServer { server; client; constructor() { // Initialize Aptly client from environment const aptlyURL = process.env.APTLY_API_URL || 'http://localhost:8080'; const authToken = process.env.APTLY_AUTH_TOKEN; this.client = new AptlyClient({ baseURL: aptlyURL, authToken }); // Initialize MCP server this.server = new Server({ name: 'aptly-mcp', version: '1.1.0', }, { capabilities: { resources: {}, tools: {}, }, }); this.setupHandlers(); } setupHandlers() { // List available tools this.server.setRequestHandler(ListToolsRequestSchema, async () => { const repoTools = createRepositoryTools(this.client); const packageTools = createPackageTools(this.client); const snapshotTools = createSnapshotTools(this.client); const publishTools = createPublishTools(this.client); const mirrorTools = createMirrorTools(this.client); const allTools = [ ...repoTools, ...packageTools, ...snapshotTools, ...publishTools, ...mirrorTools, { name: 'aptly_health_check', description: 'Check if Aptly server is running and accessible', inputSchema: { type: 'object', properties: {}, required: [] } } ]; return { tools: allTools }; }); // Handle tool calls this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { // Health check tool if (name === 'aptly_health_check') { const isHealthy = await this.client.ping(); return { content: [{ type: 'text', text: isHealthy ? '✅ Aptly server is running and accessible' : '❌ Aptly server is not accessible' }] }; } // Repository tools if (['aptly_create_repo', 'aptly_list_repos', 'aptly_get_repo', 'aptly_delete_repo'].includes(name)) { return await handleRepositoryTool(this.client, name, args); } // Package tools if (['aptly_list_packages', 'aptly_search_packages', 'aptly_add_packages', 'aptly_list_uploaded_files', 'aptly_delete_uploaded_files'].includes(name)) { return await handlePackageTool(this.client, name, args); } // Snapshot tools if (['aptly_list_snapshots', 'aptly_create_snapshot'].includes(name)) { return await handleSnapshotTool(this.client, name, args); } // Publish tools if (['aptly_list_published', 'aptly_publish_repo', 'aptly_publish_snapshot'].includes(name)) { return await handlePublishTool(this.client, name, args); } // Mirror tools if (['aptly_list_mirrors', 'aptly_create_mirror', 'aptly_update_mirror', 'aptly_get_mirror'].includes(name)) { return await handleMirrorTool(this.client, name, args); } throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); throw new McpError(ErrorCode.InternalError, `Tool execution failed: ${errorMessage}`); } }); // List available resources this.server.setRequestHandler(ListResourcesRequestSchema, async () => { return { resources: [ { uri: 'aptly://repositories', mimeType: 'application/json', name: 'Repositories', description: 'List of all local repositories' }, { uri: 'aptly://mirrors', mimeType: 'application/json', name: 'Mirrors', description: 'List of all configured mirrors' }, { uri: 'aptly://snapshots', mimeType: 'application/json', name: 'Snapshots', description: 'List of all snapshots' }, { uri: 'aptly://published', mimeType: 'application/json', name: 'Published Repositories', description: 'List of all published repositories' } ] }; }); // Handle resource reads this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => { const { uri } = request.params; try { switch (uri) { case 'aptly://repositories': { const repos = await this.client.listRepositories(); return { contents: [{ uri, mimeType: 'application/json', text: JSON.stringify(repos, null, 2) }] }; } case 'aptly://mirrors': { const mirrors = await this.client.listMirrors(); return { contents: [{ uri, mimeType: 'application/json', text: JSON.stringify(mirrors, null, 2) }] }; } case 'aptly://snapshots': { const snapshots = await this.client.listSnapshots(); return { contents: [{ uri, mimeType: 'application/json', text: JSON.stringify(snapshots, null, 2) }] }; } case 'aptly://published': { const published = await this.client.listPublishedRepositories(); return { contents: [{ uri, mimeType: 'application/json', text: JSON.stringify(published, null, 2) }] }; } default: throw new McpError(ErrorCode.InvalidRequest, `Unknown resource: ${uri}`); } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); throw new McpError(ErrorCode.InternalError, `Failed to read resource: ${errorMessage}`); } }); } async run() { const transport = new StdioServerTransport(); await this.server.connect(transport); } getServer() { return this.server; } } //# sourceMappingURL=server.js.map