skills-mcp
Version:
Bring Claude's Skills pattern to any MCP-compatible agent
91 lines • 3.39 kB
JavaScript
import * as path from 'node:path';
import * as util from 'node:util';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { createServer } from './server.js';
import { getSkillsMCPInstructions, instructionsCommandHelpText, } from './instructions.js';
// Check if this is the instructions command
const isInstructionsCommand = process.argv[2] === 'instructions';
if (isInstructionsCommand) {
// Handle instructions command
const args = util.parseArgs({
// Skip 'node', 'script', and 'instructions'
args: process.argv.slice(3),
allowPositionals: true,
allowNegative: true,
options: {
xml: {
type: 'boolean',
default: true,
},
help: {
type: 'boolean',
default: false,
},
},
});
if (args.values.help) {
console.log(instructionsCommandHelpText);
process.exit(0);
}
console.log(getSkillsMCPInstructions(args.values.xml));
process.exit(0);
}
// Otherwise, parse server arguments
const args = util.parseArgs({
options: {
'skills-dir': {
type: 'string',
multiple: true,
short: 's',
},
},
});
const skillsDirs = args.values['skills-dir'];
async function main() {
// Validate arguments
if (!skillsDirs || !skillsDirs.length) {
console.error('Error: At least one --skills-dir argument is required');
console.error('Usage: npx skills-mcp --skills-dir /path/to/skills');
console.error(' npx skills-mcp --skills-dir /path/to/skills1 --skills-dir /path/to/skills2');
console.error(' npx skills-mcp -s /path/to/skills');
process.exit(1);
}
const nonAbsoluteSkillsDirs = skillsDirs.filter((skillsDir) => !path.isAbsolute(skillsDir));
if (nonAbsoluteSkillsDirs.length) {
console.error('Error: All skills directories must be absolute paths');
console.error('Non-absolute paths found:');
nonAbsoluteSkillsDirs.forEach((skillsDir) => console.error(` - ${skillsDir}`));
process.exit(1);
}
// Log startup information (to stderr to not interfere with stdio transport)
console.error(`Skills MCP starting...`);
console.error(`Skills directories:`);
skillsDirs.forEach((dir) => console.error(` - ${dir}`));
// Create the MCP server
const { server, skillRegistry } = createServer({ skillsDirs });
// Initial scan of skills directory
console.error(`Scanning skills directory...`);
try {
await skillRegistry.scan();
const skillInfos = skillRegistry.getSkillInfos();
console.error(`Loaded ${skillInfos.length} skill(s)`);
skillInfos.forEach((skillInfo) => {
console.error(` - ${skillInfo.id}: ${skillInfo.metadata.name}`);
});
}
catch (error) {
console.error(`Failed to scan skills directory:`, error);
process.exit(1);
}
// Start stdio transport
console.error('Starting stdio transport...');
const transport = new StdioServerTransport();
await server.connect(transport);
console.error('Stdio transport connected and ready');
}
main().catch((error) => {
console.error('Fatal error:', error);
process.exit(1);
});
//# sourceMappingURL=index.js.map