Skip to main content
Glama
nickytonline

Pimp My Ride MCP Server

by nickytonline
builds.ts6.95 kB
/** * Build management tools for Pomeranian Kart MCP Server * Handles car configuration, driver profiles, and build persistence */ import type { KV } from "../storage/index.ts"; import { KVHelpers } from "../storage/index.ts"; import type { UserIdentity } from "../auth/pomerium.ts"; import { canAccessBuild } from "../auth/pomerium.ts"; import { type Build, type BuildMetadata, type CarConfigUpdate, type DriverProfileUpdate, CarConfigUpdateSchema, DriverProfileUpdateSchema, createBuild, calculatePerformanceScore, } from "../domain/models.ts"; const BUILDS_NAMESPACE = "builds"; const ACTIVE_BUILD_KEY = "active"; /** * Build storage key format: ${userId}:${buildId} */ function buildKey(userId: string, buildId: string): string { return `${userId}:${buildId}`; } /** * Get the current active build for a user, creating one if it doesn't exist */ export async function getCurrentBuild( kv: KV, identity: UserIdentity, ): Promise<Build> { const key = buildKey(identity.userId, ACTIVE_BUILD_KEY); // Try to get existing active build const result = await KVHelpers.getJSON<Build>(kv, BUILDS_NAMESPACE, key); if (result) { return result.value; } // Create a new default build const newBuild = createBuild(ACTIVE_BUILD_KEY); await KVHelpers.setJSON(kv, BUILDS_NAMESPACE, key, newBuild); return newBuild; } /** * Update car configuration for the active build */ export async function updateCarConfig( kv: KV, identity: UserIdentity, updates: CarConfigUpdate, ): Promise<Build> { // Validate updates const validatedUpdates = CarConfigUpdateSchema.parse(updates); // Get current build const build = await getCurrentBuild(kv, identity); // Apply updates build.car = { ...build.car, ...validatedUpdates }; build.updatedAt = Date.now(); // Save updated build const key = buildKey(identity.userId, ACTIVE_BUILD_KEY); await KVHelpers.setJSON(kv, BUILDS_NAMESPACE, key, build); return build; } /** * Update driver profile for the active build */ export async function updateDriverProfile( kv: KV, identity: UserIdentity, updates: DriverProfileUpdate, ): Promise<Build> { // Validate updates const validatedUpdates = DriverProfileUpdateSchema.parse(updates); // Get current build const build = await getCurrentBuild(kv, identity); // Apply updates build.driver = { ...build.driver, ...validatedUpdates }; build.updatedAt = Date.now(); // Save updated build const key = buildKey(identity.userId, ACTIVE_BUILD_KEY); await KVHelpers.setJSON(kv, BUILDS_NAMESPACE, key, build); return build; } /** * Save the active build under a specific name */ export async function saveBuild( kv: KV, identity: UserIdentity, name: string, ): Promise<Build> { // Get current active build const activeBuild = await getCurrentBuild(kv, identity); // Create a new build ID based on the name (sanitized) const buildId = sanitizeBuildId(name); // Check if a build with this name already exists const existingKey = buildKey(identity.userId, buildId); const existing = await KVHelpers.getJSON<Build>( kv, BUILDS_NAMESPACE, existingKey, ); if (existing) { throw new Error(`A build named "${name}" already exists`); } // Create the saved build const savedBuild: Build = { ...activeBuild, id: buildId, name, createdAt: activeBuild.createdAt, updatedAt: Date.now(), }; // Save the build await KVHelpers.setJSON(kv, BUILDS_NAMESPACE, existingKey, savedBuild); return savedBuild; } /** * Load a saved build and make it the active build */ export async function loadBuild( kv: KV, identity: UserIdentity, buildId: string, ): Promise<Build> { const key = buildKey(identity.userId, buildId); // Get the build const result = await KVHelpers.getJSON<Build>(kv, BUILDS_NAMESPACE, key); if (!result) { throw new Error(`Build "${buildId}" not found`); } const build = result.value; // Verify the user owns this build if (!canAccessBuild(identity, identity.userId)) { throw new Error("Access denied"); } // Copy to active build const activeBuild: Build = { ...build, id: ACTIVE_BUILD_KEY, updatedAt: Date.now(), }; const activeKey = buildKey(identity.userId, ACTIVE_BUILD_KEY); await KVHelpers.setJSON(kv, BUILDS_NAMESPACE, activeKey, activeBuild); return activeBuild; } /** * List all saved builds for a user */ export async function listBuilds( kv: KV, identity: UserIdentity, options?: { limit?: number; cursor?: string }, ): Promise<{ builds: BuildMetadata[]; cursor: string | null }> { const { limit = 50, cursor } = options || {}; // List all keys for this user const prefix = `${identity.userId}:`; const result = await kv.list(BUILDS_NAMESPACE, { prefix, limit, cursor, }); // Fetch metadata for each build (excluding the active build) const builds: BuildMetadata[] = []; for (const fullKey of result.keys) { // Extract buildId from the key const buildId = fullKey.substring(prefix.length); // Skip the active build if (buildId === ACTIVE_BUILD_KEY) { continue; } // Get the build const buildResult = await KVHelpers.getJSON<Build>( kv, BUILDS_NAMESPACE, fullKey, ); if (buildResult) { const build = buildResult.value; builds.push({ id: build.id, name: build.name, createdAt: build.createdAt, updatedAt: build.updatedAt, }); } } return { builds, cursor: result.cursor, }; } /** * Delete a saved build */ export async function deleteBuild( kv: KV, identity: UserIdentity, buildId: string, ): Promise<boolean> { // Prevent deleting the active build if (buildId === ACTIVE_BUILD_KEY) { throw new Error("Cannot delete the active build"); } const key = buildKey(identity.userId, buildId); return await kv.delete(BUILDS_NAMESPACE, key); } /** * Get build details including performance score */ export async function getBuildDetails( kv: KV, identity: UserIdentity, buildId: string = ACTIVE_BUILD_KEY, ): Promise<Build & { performanceScore: number }> { const key = buildKey(identity.userId, buildId); const result = await KVHelpers.getJSON<Build>(kv, BUILDS_NAMESPACE, key); if (!result) { if (buildId === ACTIVE_BUILD_KEY) { // Create default build for active return { ...createBuild(ACTIVE_BUILD_KEY), performanceScore: 50, }; } throw new Error(`Build "${buildId}" not found`); } const build = result.value; const performanceScore = calculatePerformanceScore(build.car); return { ...build, performanceScore, }; } /** * Sanitize a build name to create a safe build ID */ function sanitizeBuildId(name: string): string { return name .toLowerCase() .replace(/[^a-z0-9]+/g, "_") .replace(/^_+|_+$/g, "") .substring(0, 50); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/nickytonline/pimp-my-ride-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server