Skip to main content
Glama

Claude MCP Server Integration

by mokemoke0821
SuspectAI.ts8.15 kB
import { OllamaClient } from '../ollama/OllamaClient'; import { PersonalityManager } from './PersonalityManager'; import { SuspectBackground, SuspectStatus, GamePhase, GameContext, QuestionType, SuspectSpecialAction } from '../types/GameTypes'; export class SuspectAI { private background: SuspectBackground; private status: SuspectStatus; private currentPhase: GamePhase; private ollamaClient: OllamaClient; private conversationHistory: GameContext['conversationHistory']; private secretsRevealed: string[]; private specialActions: SuspectSpecialAction[]; constructor(ollamaModel: string = 'qwen2.5:7b') { this.background = this.generateRandomSuspect(); this.status = this.initializeStatus(); this.currentPhase = GamePhase.PHASE1_CONFIDENT; this.ollamaClient = new OllamaClient(ollamaModel); this.conversationHistory = []; this.secretsRevealed = []; this.specialActions = PersonalityManager.generateSpecialActions(this.background); } /** * ランダムな容疑者を生成 */ private generateRandomSuspect(): SuspectBackground { const names = ['田中太郎', '佐藤花子', '鈴木一郎', '高橋美咲', '渡辺健二']; const occupations = ['会社員', '教師', '医師', '店員', 'フリーランス']; const crimes = ['窃盗', '詐欺', '横領', '暴行', '器物損壊']; const motives = [ '借金返済のため', '家族を守るため', '復讐のため', '金銭的な困窮', '衝動的な行動' ]; const personalities = ['冷静', '感情的', '頑固', '狡猾', '臆病']; const weaknesses = [ '家族への愛情', '罪悪感', '証拠の存在', '共犯者の裏切り', '過去のトラウマ' ]; const suspect: SuspectBackground = { name: names[Math.floor(Math.random() * names.length)] || '名無し', age: 25 + Math.floor(Math.random() * 30), occupation: occupations[Math.floor(Math.random() * occupations.length)] || '無職', crime: crimes[Math.floor(Math.random() * crimes.length)] || '不明', motive: motives[Math.floor(Math.random() * motives.length)] || '不明', personality: personalities[Math.floor(Math.random() * personalities.length)] || '冷静', secretWeakness: weaknesses[Math.floor(Math.random() * weaknesses.length)] || '不明', hiddenTruths: this.generateHiddenTruths() }; return suspect; } /** * 隠された真実を生成 */ private generateHiddenTruths(): string[] { return [ 'アリバイは嘘だった', '共犯者がいる', '証拠を隠している場所がある', '本当の動機は別にある', '被害者との関係を隠している' ].sort(() => Math.random() - 0.5).slice(0, 3); } /** * 初期ステータス設定 */ private initializeStatus(): SuspectStatus { return { mentalLife: 100, alertLevel: 10, trustLevel: 20, confessionRate: 0 }; } /** * 質問タイプを検出 */ detectQuestionType(question: string): QuestionType { return this.ollamaClient.detectQuestionType(question); } /** * 質問に対する応答を生成 */ async generateResponse(playerQuestion: string): Promise<{ response: string; emotion: string; innerThought?: string; specialAction?: SuspectSpecialAction; }> { // 質問タイプ検出 const questionType = this.ollamaClient.detectQuestionType(playerQuestion); // 会話履歴に追加 this.conversationHistory.push({ role: 'player', message: playerQuestion, questionType }); // ゲームコンテキスト作成 const gameContext: GameContext = { suspect: this.background, currentStatus: this.status, currentPhase: this.currentPhase, conversationHistory: this.conversationHistory, turnNumber: this.conversationHistory.length, secretsRevealed: this.secretsRevealed }; // AI応答生成 let response = await this.ollamaClient.generateResponse( gameContext, playerQuestion, questionType ); // 真実の漏洩チェック if (PersonalityManager.shouldRevealTruth(this.currentPhase, this.status.mentalLife)) { const partialTruth = PersonalityManager.generatePartialTruth( this.background.hiddenTruths.filter(t => !this.secretsRevealed.includes(t)) ); if (partialTruth) { response += ` ${partialTruth}`; } } // 自供モードチェック if (this.currentPhase === GamePhase.PHASE4_BREAKDOWN && this.status.confessionRate > 80) { if (Math.random() < 0.3) { response = PersonalityManager.generateConfessionLine(this.background); } } // 感情生成 const emotion = PersonalityManager.generateEmotion(this.currentPhase, this.status.mentalLife); // 内部思考(デバッグ/演出用) const innerThought = PersonalityManager.generateInnerThought(this.currentPhase, this.status); // 特殊アクション判定 const specialAction = this.checkSpecialAction(); // 会話履歴に追加 this.conversationHistory.push({ role: 'suspect', message: response }); return { response, emotion, innerThought, specialAction }; } /** * 特殊アクション判定 */ private checkSpecialAction(): SuspectSpecialAction | undefined { for (const action of this.specialActions) { if (Math.random() < action.probability) { // トリガー条件チェック(簡易実装) if (this.evaluateTrigger(action.trigger)) { return action; } } } return undefined; } /** * トリガー条件評価 */ private evaluateTrigger(trigger: string): boolean { // 簡易的なトリガー評価 if (trigger.includes('alertLevel > 60')) { return this.status.alertLevel > 60; } if (trigger.includes('Life < 30%')) { return this.status.mentalLife < 30; } if (trigger.includes('Life < 20%')) { return this.status.mentalLife < 20; } if (trigger === 'いつでも') { return true; } return false; } /** * ステータス更新 */ updateStatus(changes: Partial<SuspectStatus>): void { this.status = { ...this.status, ...changes }; // フェーズ更新チェック const newPhase = this.determinePhase(); if (newPhase !== this.currentPhase) { this.currentPhase = newPhase; } } /** * フェーズ判定 */ private determinePhase(): GamePhase { if (this.status.mentalLife >= 70) return GamePhase.PHASE1_CONFIDENT; if (this.status.mentalLife >= 40) return GamePhase.PHASE2_NERVOUS; if (this.status.mentalLife >= 20) return GamePhase.PHASE3_CONFUSED; return GamePhase.PHASE4_BREAKDOWN; } /** * 秘密を暴露 */ revealSecret(): string | null { const unrevealed = this.background.hiddenTruths.filter( t => !this.secretsRevealed.includes(t) ); if (unrevealed.length === 0) return null; const secret = unrevealed[Math.floor(Math.random() * unrevealed.length)]; if (secret) { this.secretsRevealed.push(secret); } return secret ?? null; } /** * ゲッター */ getBackground(): SuspectBackground { return this.background; } getStatus(): SuspectStatus { return this.status; } getCurrentPhase(): GamePhase { return this.currentPhase; } getConversationHistory(): GameContext['conversationHistory'] { return this.conversationHistory; } getSecretsRevealed(): string[] { return this.secretsRevealed; } /** * リセット */ reset(): void { this.background = this.generateRandomSuspect(); this.status = this.initializeStatus(); this.currentPhase = GamePhase.PHASE1_CONFIDENT; this.conversationHistory = []; this.secretsRevealed = []; this.specialActions = PersonalityManager.generateSpecialActions(this.background); this.ollamaClient.resetContext(); } }

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/mokemoke0821/claude-mcp-integration'

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