JIRA MCP Server

  • src
#!/usr/bin/env node import * as dotenv from 'dotenv'; import { parseArgs } from 'node:util'; // Load environment variables from .env file as fallback dotenv.config(); import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { ListToolsRequestSchema, CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js"; import { IapticAPI } from "./iaptic-api.js"; import { CustomerTools } from "./tools/customers.js"; import { PurchaseTools } from "./tools/purchases.js"; import { TransactionTools } from "./tools/transactions.js"; import { StatisticsTools } from "./tools/statistics.js"; declare global { namespace NodeJS { interface ProcessEnv { IAPTIC_API_KEY?: string; IAPTIC_APP_NAME?: string; } } } class IapticServer { private server: Server; private api: IapticAPI; private tools: { customers: CustomerTools; purchases: PurchaseTools; transactions: TransactionTools; statistics: StatisticsTools; }; constructor(apiKey: string, appName: string) { console.error('Starting Iaptic MCP Server...'); this.api = new IapticAPI(apiKey, appName); this.tools = { customers: new CustomerTools(this.api), purchases: new PurchaseTools(this.api), transactions: new TransactionTools(this.api), statistics: new StatisticsTools(this.api) }; this.server = new Server( { name: "iaptic-mcp-server", version: "1.0.0" }, { capabilities: { tools: {} } } ); this.setupHandlers(); } private setupHandlers() { // List available tools this.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ ...this.tools.customers.getTools(), ...this.tools.purchases.getTools(), ...this.tools.transactions.getTools(), ...this.tools.statistics.getTools() ] }; }); // Handle tool calls this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { // Route tool calls to appropriate handler if (name.startsWith('customer_')) { return await this.tools.customers.handleTool(name, args); } if (name.startsWith('purchase_')) { return await this.tools.purchases.handleTool(name, args); } if (name.startsWith('transaction_')) { return await this.tools.transactions.handleTool(name, args); } if (name.startsWith('stats_')) { return await this.tools.statistics.handleTool(name, args); } throw new Error(`Unknown tool: ${name}`); } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; return { isError: true, content: [{ type: "text", text: `Error: ${errorMessage}` }] }; } }); } async start() { const transport = new StdioServerTransport(); console.error('Connecting to transport...'); await this.server.connect(transport); console.error('Server ready!'); } } // Parse command line arguments const { values } = parseArgs({ args: process.argv.slice(2), options: { 'api-key': { type: 'string' }, 'app-name': { type: 'string' } } }); // Get credentials from args or fallback to env vars const apiKey = values['api-key'] || process.env.IAPTIC_API_KEY; const appName = values['app-name'] || process.env.IAPTIC_APP_NAME; if (!apiKey) { throw new Error("API key is required. Provide it via --api-key argument or IAPTIC_API_KEY environment variable"); } if (!appName) { throw new Error("App name is required. Provide it via --app-name argument or IAPTIC_APP_NAME environment variable"); } const server = new IapticServer(apiKey, appName); server.start().catch(console.error);