Skip to main content
Glama
schemas.ts7.78 kB
// Zod schemas for validation of shared types import { z } from 'zod'; /** * MCP Query schemas */ export const MCPQuerySchema = z.object({ method: z.string(), data: z.unknown().optional(), }); export const MCPResponseSchema = z.object({ success: z.boolean(), data: z.unknown().optional(), error: z.string().optional(), }); /** * Character schemas */ export const CharacterItemSchema = z.object({ id: z.string(), name: z.string(), type: z.string(), img: z.string().optional(), system: z.record(z.unknown()), }); export const CharacterEffectSchema = z.object({ id: z.string(), name: z.string(), icon: z.string().optional(), disabled: z.boolean(), duration: z.object({ type: z.string(), duration: z.number().optional(), remaining: z.number().optional(), }).optional(), }); export const CharacterInfoSchema = z.object({ id: z.string(), name: z.string(), type: z.string(), img: z.string().optional(), system: z.record(z.unknown()), items: z.array(CharacterItemSchema), effects: z.array(CharacterEffectSchema), }); /** * Compendium schemas */ export const CompendiumSearchResultSchema = z.object({ id: z.string(), name: z.string(), type: z.string(), img: z.string().optional(), pack: z.string(), packLabel: z.string(), system: z.record(z.unknown()).optional(), }); export const CompendiumPackSchema = z.object({ id: z.string(), label: z.string(), type: z.string(), system: z.string(), private: z.boolean(), }); /** * Scene schemas */ export const SceneTokenSchema = z.object({ id: z.string(), name: z.string(), x: z.number(), y: z.number(), width: z.number(), height: z.number(), actorId: z.string().optional(), img: z.string(), hidden: z.boolean(), disposition: z.number(), }); export const SceneNoteSchema = z.object({ id: z.string(), text: z.string(), x: z.number(), y: z.number(), }); export const SceneInfoSchema = z.object({ id: z.string(), name: z.string(), img: z.string().optional(), background: z.string().optional(), width: z.number(), height: z.number(), padding: z.number(), active: z.boolean(), navigation: z.boolean(), tokens: z.array(SceneTokenSchema), walls: z.number(), lights: z.number(), sounds: z.number(), notes: z.array(SceneNoteSchema), }); /** * Token Manipulation schemas */ export const TokenUpdateSchema = z.object({ tokenId: z.string(), updates: z.object({ x: z.number().optional(), y: z.number().optional(), width: z.number().positive().optional(), height: z.number().positive().optional(), rotation: z.number().min(0).max(360).optional(), hidden: z.boolean().optional(), disposition: z.union([z.literal(-1), z.literal(0), z.literal(1)]).optional(), name: z.string().optional(), elevation: z.number().optional(), lockRotation: z.boolean().optional(), }), }); export const TokenMoveRequestSchema = z.object({ tokenId: z.string(), x: z.number(), y: z.number(), animate: z.boolean().optional().default(false), }); export const TokenUpdateResultSchema = z.object({ success: z.boolean(), tokenId: z.string(), updated: z.boolean(), error: z.string().optional(), }); export const TokenDeleteResultSchema = z.object({ success: z.boolean(), deletedCount: z.number(), tokenIds: z.array(z.string()), errors: z.array(z.string()).optional(), }); export const TokenDetailsSchema = SceneTokenSchema.extend({ rotation: z.number(), elevation: z.number(), lockRotation: z.boolean(), scale: z.number(), alpha: z.number(), actorLink: z.boolean(), actorData: z.object({ name: z.string(), type: z.string(), img: z.string().optional(), }).optional(), }); /** * Configuration schemas */ export const FoundryMCPConfigSchema = z.object({ enabled: z.boolean(), mcpHost: z.string(), mcpPort: z.number().min(1024).max(65535), connectionTimeout: z.number().min(5).max(60), debugLogging: z.boolean(), }); export const MCPServerConfigSchema = z.object({ logLevel: z.enum(['error', 'warn', 'info', 'debug']), foundry: z.object({ host: z.string(), port: z.number().min(1024).max(65535), namespace: z.string(), reconnectAttempts: z.number().min(1).max(10), reconnectDelay: z.number().min(100).max(10000), }), }); /** * World info schemas */ export const WorldUserSchema = z.object({ id: z.string(), name: z.string(), active: z.boolean(), isGM: z.boolean(), }); export const WorldInfoSchema = z.object({ id: z.string(), title: z.string(), system: z.string(), systemVersion: z.string(), foundryVersion: z.string(), users: z.array(WorldUserSchema), }); /** * Bridge status schema */ export const BridgeStatusSchema = z.object({ isRunning: z.boolean(), config: FoundryMCPConfigSchema, timestamp: z.number(), }); /** * Multipart Campaign schemas */ export const CampaignPartStatusSchema = z.enum([ 'not_started', 'in_progress', 'completed', 'skipped' ]); export const CampaignPartTypeSchema = z.enum([ 'main_part', 'sub_part', 'chapter', 'session', 'optional' ]); export const LevelRecommendationSchema = z.object({ start: z.number().min(1).max(20), end: z.number().min(1).max(20), }); export const NPCReferenceSchema = z.object({ id: z.string(), name: z.string(), actorId: z.string().optional(), }); export const ScalingOptionsSchema = z.object({ adjustForPartySize: z.boolean().default(true), adjustForLevel: z.boolean().default(true), difficultyModifier: z.number().min(-2).max(2).default(0), }); // Sub-part schema (no further nesting) export const CampaignSubPartSchema = z.object({ id: z.string(), title: z.string().min(1), description: z.string(), type: CampaignPartTypeSchema, status: CampaignPartStatusSchema.default('not_started'), journalId: z.string().optional(), createdAt: z.number().optional(), completedAt: z.number().optional(), }); // Main campaign part schema with optional sub-parts export const CampaignPartSchema = z.object({ id: z.string(), title: z.string().min(1), description: z.string(), type: CampaignPartTypeSchema, status: CampaignPartStatusSchema.default('not_started'), dependencies: z.array(z.string()).default([]), subParts: z.array(CampaignSubPartSchema).optional(), questGiver: NPCReferenceSchema.optional(), levelRecommendation: LevelRecommendationSchema, gmNotes: z.string().default(''), playerContent: z.string().default(''), scaling: ScalingOptionsSchema.default({}), journalId: z.string().optional(), createdAt: z.number().optional(), completedAt: z.number().optional(), }); export const CampaignMetadataSchema = z.object({ defaultQuestGiver: NPCReferenceSchema.optional(), defaultLocation: z.string().optional(), theme: z.string().optional(), estimatedSessions: z.number().optional(), targetLevelRange: LevelRecommendationSchema.optional(), tags: z.array(z.string()).default([]), }); export const CampaignStructureSchema = z.object({ id: z.string(), title: z.string().min(1), description: z.string(), parts: z.array(CampaignPartSchema), metadata: CampaignMetadataSchema, dashboardJournalId: z.string().optional(), createdAt: z.number(), updatedAt: z.number(), }); export const CampaignTemplateSchema = z.object({ id: z.string(), name: z.string(), description: z.string(), parts: z.array(z.object({ title: z.string(), description: z.string(), type: CampaignPartTypeSchema, dependencies: z.array(z.string()).default([]), subParts: z.array(z.object({ title: z.string(), description: z.string(), type: CampaignPartTypeSchema, })).optional(), levelRecommendation: LevelRecommendationSchema, })), metadata: CampaignMetadataSchema.partial(), });

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/adambdooley/foundry-vtt-mcp'

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