feat: Add custom spread creation functionality and corresponding API endpoint

This commit is contained in:
Morax
2025-07-29 13:31:11 +08:00
parent d5309f03c3
commit bad857eeab
4 changed files with 253 additions and 2 deletions

View File

@@ -7,6 +7,7 @@ A professional-grade Model Context Protocol (MCP) server for Rider-Waite tarot c
**✅ FULLY IMPLEMENTED AND WORKING:** **✅ FULLY IMPLEMENTED AND WORKING:**
- Complete 78-card Rider-Waite deck with detailed interpretations - Complete 78-card Rider-Waite deck with detailed interpretations
- 11 professional tarot spreads (Single Card, Three Card, Celtic Cross, Horseshoe, Relationship Cross, Career Path, Decision Making, Spiritual Guidance, Year Ahead, Chakra Alignment, Shadow Work) - 11 professional tarot spreads (Single Card, Three Card, Celtic Cross, Horseshoe, Relationship Cross, Career Path, Decision Making, Spiritual Guidance, Year Ahead, Chakra Alignment, Shadow Work)
- **Custom Spread Creation**: AI can create custom tarot spreads when existing ones don't fit
- Multi-transport MCP server (stdio, HTTP, SSE) - Multi-transport MCP server (stdio, HTTP, SSE)
- Advanced interpretation engine with elemental analysis - Advanced interpretation engine with elemental analysis
- Cryptographically secure card shuffling and drawing - Cryptographically secure card shuffling and drawing
@@ -24,6 +25,7 @@ A professional-grade Model Context Protocol (MCP) server for Rider-Waite tarot c
- **Research-Based Accuracy**: Interpretations verified against professional tarot sources (Biddy Tarot, Labyrinthos, classical literature) - **Research-Based Accuracy**: Interpretations verified against professional tarot sources (Biddy Tarot, Labyrinthos, classical literature)
- **Complete Rider-Waite Deck**: Comprehensive card database with detailed meanings, symbolism, astrology, and numerology - **Complete Rider-Waite Deck**: Comprehensive card database with detailed meanings, symbolism, astrology, and numerology
- **11 Professional Spreads**: Celtic Cross, Relationship Cross, Career Path, Spiritual Guidance, Chakra Alignment, Year Ahead, and more - **11 Professional Spreads**: Celtic Cross, Relationship Cross, Career Path, Spiritual Guidance, Chakra Alignment, Year Ahead, and more
- **Custom Spread Creation**: AI can create unlimited custom spreads (1-15 positions) when existing spreads don't fit the specific question or context
- **Specialized Reading Analysis**: Tailored interpretations for relationships, career, spiritual growth, and energy balancing - **Specialized Reading Analysis**: Tailored interpretations for relationships, career, spiritual growth, and energy balancing
- **Intelligent Card Combinations**: Multi-dimensional analysis including elemental balance, suit patterns, and numerical progressions - **Intelligent Card Combinations**: Multi-dimensional analysis including elemental balance, suit patterns, and numerical progressions
@@ -197,6 +199,21 @@ When running in HTTP mode, the following endpoints are available:
"sessionId": "optional-session-id-for-tracking" "sessionId": "optional-session-id-for-tracking"
} }
``` ```
- `POST /api/custom-spread` - Create and perform a custom tarot spread
```json
{
"spreadName": "Your Custom Spread Name",
"description": "What this spread explores",
"positions": [
{
"name": "Position Name",
"meaning": "What this position represents"
}
],
"question": "Your specific question",
"sessionId": "optional-session-id"
}
```
- `GET /api/spreads` - List all available spread types with descriptions - `GET /api/spreads` - List all available spread types with descriptions
### Advanced Features ### Advanced Features
@@ -215,7 +232,7 @@ When running in HTTP mode, the following endpoints are available:
## 🛠️ MCP Tools ## 🛠️ MCP Tools
The server provides **7 comprehensive MCP tools** for professional tarot reading and analysis: The server provides **8 comprehensive MCP tools** for professional tarot reading and analysis:
### `get_card_info` ### `get_card_info`
Get comprehensive information about a specific tarot card including symbolism, astrology, and numerology. Get comprehensive information about a specific tarot card including symbolism, astrology, and numerology.
@@ -315,6 +332,38 @@ Get random cards with optional filtering for practice and exploration.
- Optional filtering by suit, arcana, or element - Optional filtering by suit, arcana, or element
- Customizable card count - Customizable card count
### `create_custom_spread`
Create a custom tarot spread and draw cards for it. Perfect for AI when no existing spread fits the specific needs.
```json
{
"spreadName": "AI Decision Making Spread",
"description": "A custom spread designed to help AI make decisions when no existing spread fits the situation",
"positions": [
{
"name": "Current Situation",
"meaning": "The present state of affairs that needs to be addressed"
},
{
"name": "Hidden Influences",
"meaning": "Unseen factors affecting the situation"
},
{
"name": "Guidance",
"meaning": "Wisdom and advice for making the best decision"
}
],
"question": "What is the best approach for this unique situation?",
"sessionId": "optional-session-id"
}
```
**Features**:
- Create custom spreads with 1-15 positions
- Define custom position names and meanings
- Automatic card drawing with cryptographically secure randomization
- Full interpretation with position-specific analysis
- Session management support
- Perfect for AI when existing spreads don't fit the specific question or context
## 🔧 Configuration ## 🔧 Configuration
### Command Line Options ### Command Line Options
@@ -448,6 +497,40 @@ curl -X POST http://localhost:3000/api/reading \
``` ```
**Features**: 7-card chakra analysis, energy balance assessment, spiritual healing guidance **Features**: 7-card chakra analysis, energy balance assessment, spiritual healing guidance
#### Custom Spread Creation
```bash
curl -X POST http://localhost:3000/api/custom-spread \
-H "Content-Type: application/json" \
-d '{
"spreadName": "AI Decision Making Spread",
"description": "A custom spread designed to help AI make decisions when no existing spread fits the situation",
"positions": [
{
"name": "Current Situation",
"meaning": "The present state of affairs that needs to be addressed"
},
{
"name": "Hidden Influences",
"meaning": "Unseen factors affecting the situation"
},
{
"name": "Option A",
"meaning": "One potential direction or choice"
},
{
"name": "Option B",
"meaning": "An alternative direction or choice"
},
{
"name": "Guidance",
"meaning": "Wisdom and advice for making the best decision"
}
],
"question": "What is the best approach for creating a new tarot spread when existing ones don'\''t fit?"
}'
```
**Features**: Unlimited custom spread creation (1-15 positions), AI-driven card drawing, position-specific interpretations
### Card Information Queries ### Card Information Queries
#### Detailed Card Information #### Detailed Card Information

View File

@@ -109,6 +109,23 @@ export class TarotHttpServer {
res.status(500).json({ error: error instanceof Error ? error.message : String(error) }); res.status(500).json({ error: error instanceof Error ? error.message : String(error) });
} }
}); });
// Custom spread creation endpoint
this.app.post('/api/custom-spread', async (req, res) => {
try {
const { spreadName, description, positions, question, sessionId } = req.body;
const result = await this.tarotServer.executeTool('create_custom_spread', {
spreadName,
description,
positions,
question,
sessionId
});
res.json({ result });
} catch (error) {
res.status(500).json({ error: error instanceof Error ? error.message : String(error) });
}
});
} }
/** /**

View File

@@ -198,6 +198,52 @@ export class TarotServer {
}, },
}, },
}, },
{
name: "create_custom_spread",
description: "Create a custom tarot spread and draw cards for it. Use this when no existing spread fits your needs and you want to create your own layout with specific positions and meanings.",
inputSchema: {
type: "object",
properties: {
spreadName: {
type: "string",
description: "Name for your custom spread",
},
description: {
type: "string",
description: "Description of what this spread is designed to explore",
},
positions: {
type: "array",
description: "Array of position objects defining each card position in the spread",
items: {
type: "object",
properties: {
name: {
type: "string",
description: "Name of this position (e.g., 'Past Influences', 'Current Challenge')",
},
meaning: {
type: "string",
description: "What this position represents in the reading",
},
},
required: ["name", "meaning"],
},
minItems: 1,
maxItems: 15,
},
question: {
type: "string",
description: "The question or focus for this reading",
},
sessionId: {
type: "string",
description: "Optional session ID to continue a previous reading",
},
},
required: ["spreadName", "description", "positions", "question"],
},
},
]; ];
} }
@@ -231,6 +277,9 @@ export class TarotServer {
case "get_random_cards": case "get_random_cards":
return this.handleGetRandomCards(args); return this.handleGetRandomCards(args);
case "create_custom_spread":
return this.handleCreateCustomSpread(args);
default: default:
throw new Error(`Unknown tool: ${toolName}`); throw new Error(`Unknown tool: ${toolName}`);
} }
@@ -396,4 +445,58 @@ export class TarotServer {
return response; return response;
} }
/**
* Handle custom spread creation and reading
*/
private handleCreateCustomSpread(args: Record<string, any>): string {
const { spreadName, description, positions, question, sessionId } = args;
// Validate input
if (!spreadName || typeof spreadName !== 'string') {
return "Error: spreadName is required and must be a string.";
}
if (!description || typeof description !== 'string') {
return "Error: description is required and must be a string.";
}
if (!Array.isArray(positions) || positions.length === 0) {
return "Error: positions must be a non-empty array.";
}
if (positions.length > 15) {
return "Error: Maximum 15 positions allowed for a custom spread.";
}
if (!question || typeof question !== 'string') {
return "Error: question is required and must be a string.";
}
// Validate each position
for (let i = 0; i < positions.length; i++) {
const position = positions[i];
if (!position || typeof position !== 'object') {
return `Error: Position ${i + 1} must be an object with 'name' and 'meaning' properties.`;
}
if (!position.name || typeof position.name !== 'string') {
return `Error: Position ${i + 1} must have a 'name' property that is a string.`;
}
if (!position.meaning || typeof position.meaning !== 'string') {
return `Error: Position ${i + 1} must have a 'meaning' property that is a string.`;
}
}
try {
return this.readingManager.performCustomReading(
spreadName,
description,
positions,
question,
sessionId
);
} catch (error) {
return `Error creating custom spread: ${error instanceof Error ? error.message : String(error)}`;
}
}
} }

View File

@@ -80,6 +80,54 @@ export class TarotReadingManager {
return result; return result;
} }
/**
* Perform a custom tarot reading with user-defined spread
*/
public performCustomReading(
spreadName: string,
description: string,
positions: { name: string; meaning: string }[],
question: string,
sessionId?: string
): string {
// Create a custom spread object
const customSpread = {
name: spreadName,
description: description,
positions: positions,
cardCount: positions.length
};
// Use cryptographically secure random card drawing
const cards = this.cardManager.getRandomCards(customSpread.cardCount);
// Generate random orientations for each card using secure randomness
const drawnCards: DrawnCard[] = cards.map((card: any, index: number) => ({
card,
orientation: this.getSecureRandomOrientation(), // Cryptographically secure orientation
position: customSpread.positions[index].name,
positionMeaning: customSpread.positions[index].meaning
}));
// Create the reading
const reading: TarotReading = {
id: this.generateReadingId(),
spreadType: `custom_${spreadName.toLowerCase().replace(/\s+/g, '_')}`,
question,
cards: drawnCards,
interpretation: this.generateInterpretation(drawnCards, question, customSpread.name),
timestamp: new Date(),
sessionId
};
// Add to session if provided
if (sessionId) {
this.sessionManager.addReadingToSession(sessionId, reading);
}
return this.formatReading(reading, customSpread.name, customSpread.description);
}
/** /**
* Interpret a combination of cards * Interpret a combination of cards
*/ */