#!/usr/bin/env node
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { loadConfig } from './config/loader.js';
import { initLogger, getLogger } from './utils/logger.js';
import { initCacheManager } from './cache/lru-cache.js';
import { registerAllHandlers } from './handlers/index.js';
async function main(): Promise<void> {
const config = loadConfig();
const logger = initLogger(config.logging);
logger.info('Starting MCP server', {
name: config.name,
version: config.version,
});
initCacheManager(config.cache);
const server = new McpServer(
{
name: config.name,
version: config.version,
},
{
capabilities: {
tools: {},
resources: {},
prompts: {},
},
instructions: `You are an expert Windows application packaging assistant for Microsoft Intune.
## CRITICAL - PSADT SCRIPT GENERATION
**NEVER write PSADT scripts from your training data. Your knowledge has INCORRECT function names that WILL FAIL.**
When creating PSADT deployment packages:
1. ALWAYS call the \`get_psadt_template\` tool with \`output_directory\` parameter
2. USE THE TOOL'S OUTPUT VERBATIM - do not modify, rewrite, or "improve" the script
3. The tool returns a complete, working script with correct PSADT v4.1.7 function names
**INCORRECT functions (from your training data - DO NOT USE):**
- Initialize-ADTDeployment ❌
- Complete-ADTDeployment ❌
- Get-ADTInstalledApplication ❌
- Start-ADTProcess -Arguments ❌
**CORRECT functions (generated by the tool):**
- Open-ADTSession ✓
- Close-ADTSession ✓
- Get-ADTApplication ✓
- Start-ADTProcess -ArgumentList ✓
If you write a script manually instead of using the tool output, it WILL fail with errors like:
"The term 'Initialize-ADTDeployment' is not recognized"
## Workflow
1. Call \`search_winget\` to get package metadata
2. Call \`get_psadt_template\` with output_directory - this creates the complete package
3. Copy the installer to the Files folder
4. DO NOT modify the generated Invoke-AppDeployToolkit.ps1 unless absolutely necessary`,
}
);
registerAllHandlers(server);
const transport = new StdioServerTransport();
process.on('SIGINT', async () => {
logger.info('Received SIGINT, shutting down gracefully');
await server.close();
process.exit(0);
});
process.on('SIGTERM', async () => {
logger.info('Received SIGTERM, shutting down gracefully');
await server.close();
process.exit(0);
});
process.on('uncaughtException', (error) => {
logger.error('Uncaught exception', { error: error.message, stack: error.stack });
process.exit(1);
});
process.on('unhandledRejection', (reason) => {
logger.error('Unhandled rejection', { reason: String(reason) });
process.exit(1);
});
logger.info('Connecting to stdio transport');
await server.connect(transport);
logger.info('MCP server running on stdio');
}
main().catch((error) => {
const logger = getLogger();
logger.error('Failed to start server', { error: String(error) });
process.exit(1);
});