get_character
Retrieve D&D 5e character data by ID or name to access stats, inventory, and abilities for gameplay in ChatRPG.
Instructions
Retrieve an existing D&D 5e character by ID
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| characterId | No | ||
| characterName | No | ||
| batch | No |
Implementation Reference
- src/registry.ts:332-354 (registration)Registration of the 'get_character' tool in the central registry, including name, description, input schema conversion, and wrapper handler that validates args with getCharacterSchema and calls the getCharacter implementation.get_character: { name: 'get_character', description: 'Retrieve an existing D&D 5e character by ID', inputSchema: toJsonSchema(getCharacterSchema), handler: async (args) => { try { const validated = getCharacterSchema.parse(args); const result = getCharacter(validated); if (!result.success) { return error(result.error || 'Failed to retrieve character'); } return success(result.markdown); } catch (err) { if (err instanceof z.ZodError) { const messages = err.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(', '); return error(`Validation failed: ${messages}`); } const message = err instanceof Error ? err.message : String(err); return error(message); } },
- src/modules/characters.ts:83-98 (schema)Zod schema for get_character tool input: supports single lookup by characterId or characterName, or batch array of lookups (max 20).const singleGetSchema = z.object({ characterId: z.string().min(1).optional(), characterName: z.string().min(1).optional(), }).refine(data => data.characterId || data.characterName, { message: 'Either characterId or characterName must be provided', }); // Support both single and batch get export const getCharacterSchema = z.union([ singleGetSchema, z.object({ batch: z.array(singleGetSchema).min(1).max(20), }), ]); export type GetCharacterInput = z.infer<typeof getCharacterSchema>;
- src/modules/characters.ts:1174-1244 (handler)Main handler function getCharacter: resolves character by ID or name (via findCharacterByName helper), reads JSON from persistent storage, formats detailed ASCII character sheet with effective stats/conditions, supports batch via getCharacterBatch.export function getCharacter(input: GetCharacterInput): { success: boolean; character?: Character; markdown: string; error?: string; } { // Check if this is a batch operation if ('batch' in input && input.batch) { return getCharacterBatch(input.batch); } // Type assertion: we know it's a single get at this point const singleInput = input as z.infer<typeof singleGetSchema>; const dataDir = path.join(DATA_ROOT, 'characters'); // Resolve character ID (either from direct ID or by name lookup) let characterId: string | undefined = singleInput.characterId; if (!characterId && singleInput.characterName) { const foundId = findCharacterByName(singleInput.characterName); if (!foundId) { return { success: false, markdown: '', error: `Character not found with name: ${singleInput.characterName}`, }; } characterId = foundId; } if (!characterId) { return { success: false, markdown: '', error: 'Character ID or name is required', }; } const filePath = path.join(dataDir, `${characterId}.json`); // Check if file exists if (!fs.existsSync(filePath)) { return { success: false, markdown: '', error: `Character not found: ${characterId}`, }; } // Read and parse character data try { const fileContent = fs.readFileSync(filePath, 'utf-8'); const character: Character = JSON.parse(fileContent); // Format markdown output using the same formatter as create const markdown = formatCharacterSheet(character); return { success: true, character, markdown, }; } catch (err) { const message = err instanceof Error ? err.message : String(err); return { success: false, markdown: '', error: `Failed to read character: ${message}`, }; } }
- src/modules/characters.ts:269-298 (helper)Helper function to find character ID by case-insensitive name search through all stored character JSON files.// Find character by name (returns ID) function findCharacterByName(name: string): string | null { const dataDir = path.join(DATA_ROOT, 'characters'); // Ensure directory exists if (!fs.existsSync(dataDir)) { return null; } try { const files = fs.readdirSync(dataDir); for (const file of files) { if (!file.endsWith('.json')) continue; const filePath = path.join(dataDir, file); const fileContent = fs.readFileSync(filePath, 'utf-8'); const character: Character = JSON.parse(fileContent); // Case-insensitive name match if (character.name.toLowerCase() === name.toLowerCase()) { return character.id; } } return null; } catch (err) { return null; } }