create-mcp-i-app
Version:
Bootstrap MCP applications with identity features (temporary - use create-mcpi-app after Oct 7)
150 lines ⢠6.13 kB
JavaScript
import path from "path";
import fs from "fs-extra";
import { fileURLToPath } from "url";
import { fetchXMCPTemplate } from "./fetch-xmcp-template.js";
import { applyIdentityPreset } from "./apply-identity-preset.js";
import { renameFiles } from "./rename.js";
import { install } from "./install.js";
import { generateConfig } from "./generate-config.js";
import { validateProjectStructure, ensureLockfile, } from "./validate-project-structure.js";
import chalk from "chalk";
import crypto from "crypto";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Function to generate claim URL
function generateClaimUrl(did, privateKeyBase64) {
try {
const timestamp = Date.now();
const message = `${did}:${timestamp}`;
const privateKeyBuffer = Buffer.from(privateKeyBase64, "base64");
const privateKeyBytes = privateKeyBuffer.length === 64
? privateKeyBuffer.subarray(0, 32)
: privateKeyBuffer;
const privateKey = crypto.createPrivateKey({
key: Buffer.concat([
Buffer.from("302e020100300506032b657004220420", "hex"),
privateKeyBytes,
]),
format: "der",
type: "pkcs8",
});
const signature = crypto.sign(null, Buffer.from(message), privateKey);
const signatureBase64 = signature.toString("base64");
const params = new URLSearchParams({
did: did,
timestamp: timestamp.toString(),
signature: signatureBase64,
});
return `https://knowthat.ai/agents/claim?${params.toString()}`;
}
catch (error) {
console.error("Error generating claim URL:", error);
return "";
}
}
/**
* Create necessary project directories
*/
function createProjectDirectories(projectPath) {
fs.ensureDirSync(path.join(projectPath, ".xmcp"));
}
/**
* Create a new xmcp project with identity features
*/
export async function createProject(options) {
const { projectPath, projectName, packageManager, transports, packageVersion, useLocalXmcp, xmcpVersion, xmcpChannel, deployToVercel, skipInstall, agentName = projectName, agentDescription = "XMCP-I server with identity features", agentRepository = "", skipIdentity = false, skipAnimation = false, fastAnimation = false, } = options;
const warnings = [];
let resolvedXmcpVersion = xmcpVersion;
try {
// Ensure the project directory exists
fs.ensureDirSync(projectPath);
// Fetch XMCP template from npm instead of using local templates
console.log(chalk.blue("\nš Scaffolding project..."));
await fetchXMCPTemplate(projectPath, {
xmcpVersion,
xmcpChannel,
packageManager,
});
// Capture the resolved version for the result
const packageJsonPath = path.join(projectPath, "package.json");
if (fs.existsSync(packageJsonPath)) {
const packageJson = fs.readJsonSync(packageJsonPath);
// Try to extract version from dependencies
resolvedXmcpVersion =
packageJson.dependencies?.xmcp || xmcpVersion || "unknown";
}
// Rename special files (e.g., _gitignore to .gitignore)
renameFiles(projectPath);
// Apply identity preset on top of XMCP template
await applyIdentityPreset({
projectPath,
projectName,
transports,
noIdentity: skipIdentity,
});
// Generate xmcp.config.ts based on selected transports
generateConfig(projectPath, transports);
// Add vercel.json if deployToVercel is true
if (deployToVercel) {
// Create a basic vercel.json for XMCP-I deployment
const vercelConfig = {
functions: {
"src/server.ts": {
runtime: "@vercel/node@3",
},
},
rewrites: [
{
source: "/(.*)",
destination: "/src/server.ts",
},
],
};
fs.writeJsonSync(path.join(projectPath, "vercel.json"), vercelConfig, {
spaces: 2,
});
}
// Create necessary project directories
createProjectDirectories(projectPath);
// Install project dependencies
if (!skipInstall) {
install(projectPath, packageManager, packageVersion);
// Ensure lockfile is properly created
ensureLockfile(projectPath, packageManager);
}
// Validate project structure meets requirements
const validation = validateProjectStructure(projectPath, !skipIdentity);
if (!validation.valid) {
console.warn(chalk.yellow("ā ļø Project structure validation issues:"));
for (const issue of validation.issues) {
console.warn(chalk.yellow(` - ${issue}`));
warnings.push(...validation.issues);
}
}
// Identity setup is now handled by the CLI after scaffolding
if (!skipIdentity) {
console.log(chalk.blue("\nš Identity setup will be handled by the CLI"));
console.log(chalk.gray(" Run 'mcpi init' after scaffolding to set up identity"));
}
return {
success: true,
projectPath,
xmcpVersion: resolvedXmcpVersion || "unknown",
identityEnabled: !skipIdentity,
warnings: warnings.length > 0 ? warnings : undefined,
};
}
catch (error) {
console.error(chalk.red("Failed to create project:"), error);
return {
success: false,
projectPath,
xmcpVersion: resolvedXmcpVersion || "unknown",
identityEnabled: !skipIdentity,
warnings: [
`Project creation failed: ${error instanceof Error ? error.message : String(error)}`,
],
};
}
}
//# sourceMappingURL=create.js.map