Add CLI control for Layer 4 with --enable-layer4 flag

Implemented optional Layer 4 activation via CLI argument,
allowing users to enable relationship features only when needed.

Changes to main.rs:
- Added --enable-layer4 flag to Server command
- Pass flag to BaseMCPServer::new()

Changes to base.rs:
- Added enable_layer4 field to BaseMCPServer
- Updated new() to accept enable_layer4 parameter
- Conditional tool exposure in get_available_tools():
  * Layer 1-3.5 tools: always available
  * Layer 4 tools: only when flag is true
- Added safety check in execute_tool():
  * Returns error if Layer 4 tools called without flag
  * Clear error message guides user to enable flag

Usage:
# Normal mode (Layer 1-3.5 only)
aigpt server

# Game/Companion mode (Layer 1-4)
aigpt server --enable-layer4

Design rationale:
- Layer 4 is optional feature for specific use cases
- Explicit opt-in prevents accidental exposure
- Tools list reflects actual capabilities
- Clear separation between core and optional features
This commit is contained in:
Claude
2025-11-06 07:51:20 +00:00
parent bf21586ad3
commit 9fed9ce6f2
2 changed files with 62 additions and 34 deletions

View File

@@ -16,7 +16,11 @@ struct Cli {
#[derive(Subcommand)] #[derive(Subcommand)]
enum Commands { enum Commands {
/// Start MCP server /// Start MCP server
Server, Server {
/// Enable Layer 4 relationship features (for games/companions)
#[arg(long)]
enable_layer4: bool,
},
/// Create a new memory /// Create a new memory
Create { Create {
@@ -62,8 +66,8 @@ async fn main() -> Result<()> {
let cli = Cli::parse(); let cli = Cli::parse();
match cli.command { match cli.command {
Commands::Server => { Commands::Server { enable_layer4 } => {
let server = BaseMCPServer::new()?; let server = BaseMCPServer::new(enable_layer4)?;
server.run()?; server.run()?;
} }

View File

@@ -6,12 +6,13 @@ use crate::core::{Memory, MemoryStore, UserAnalysis, RelationshipInference, infe
pub struct BaseMCPServer { pub struct BaseMCPServer {
store: MemoryStore, store: MemoryStore,
enable_layer4: bool,
} }
impl BaseMCPServer { impl BaseMCPServer {
pub fn new() -> Result<Self> { pub fn new(enable_layer4: bool) -> Result<Self> {
let store = MemoryStore::default()?; let store = MemoryStore::default()?;
Ok(BaseMCPServer { store }) Ok(BaseMCPServer { store, enable_layer4 })
} }
pub fn run(&self) -> Result<()> { pub fn run(&self) -> Result<()> {
@@ -85,7 +86,7 @@ impl BaseMCPServer {
} }
fn get_available_tools(&self) -> Vec<Value> { fn get_available_tools(&self) -> Vec<Value> {
vec![ let mut tools = vec![
json!({ json!({
"name": "create_memory", "name": "create_memory",
"description": "Create a new memory entry (Layer 1: simple storage)", "description": "Create a new memory entry (Layer 1: simple storage)",
@@ -252,34 +253,42 @@ impl BaseMCPServer {
"properties": {} "properties": {}
} }
}), }),
json!({ ];
"name": "get_relationship",
"description": "Get inferred relationship with a specific entity (Layer 4). Analyzes memories and user profile to infer bond strength and relationship type. Use only when game/relationship features are active.", // Layer 4 tools (optional - only when enabled)
"inputSchema": { if self.enable_layer4 {
"type": "object", tools.extend(vec![
"properties": { json!({
"entity_id": { "name": "get_relationship",
"type": "string", "description": "Get inferred relationship with a specific entity (Layer 4). Analyzes memories and user profile to infer bond strength and relationship type. Use only when game/relationship features are active.",
"description": "Entity identifier (e.g., 'alice', 'companion_miku')" "inputSchema": {
} "type": "object",
}, "properties": {
"required": ["entity_id"] "entity_id": {
} "type": "string",
}), "description": "Entity identifier (e.g., 'alice', 'companion_miku')"
json!({ }
"name": "list_relationships", },
"description": "List all inferred relationships sorted by bond strength (Layer 4). Returns relationships with all tracked entities. Use only when game/relationship features are active.", "required": ["entity_id"]
"inputSchema": { }
"type": "object", }),
"properties": { json!({
"limit": { "name": "list_relationships",
"type": "number", "description": "List all inferred relationships sorted by bond strength (Layer 4). Returns relationships with all tracked entities. Use only when game/relationship features are active.",
"description": "Maximum number of relationships to return (default: 10)" "inputSchema": {
"type": "object",
"properties": {
"limit": {
"type": "number",
"description": "Maximum number of relationships to return (default: 10)"
}
} }
} }
} }),
}), ]);
] }
tools
} }
fn handle_tools_call(&self, request: Value, id: Value) -> Value { fn handle_tools_call(&self, request: Value, id: Value) -> Value {
@@ -312,8 +321,23 @@ impl BaseMCPServer {
"save_user_analysis" => self.tool_save_user_analysis(arguments), "save_user_analysis" => self.tool_save_user_analysis(arguments),
"get_user_analysis" => self.tool_get_user_analysis(), "get_user_analysis" => self.tool_get_user_analysis(),
"get_profile" => self.tool_get_profile(), "get_profile" => self.tool_get_profile(),
"get_relationship" => self.tool_get_relationship(arguments),
"list_relationships" => self.tool_list_relationships(arguments), // Layer 4 tools (require --enable-layer4 flag)
"get_relationship" | "list_relationships" => {
if !self.enable_layer4 {
return json!({
"success": false,
"error": "Layer 4 is not enabled. Start server with --enable-layer4 flag to use relationship features."
});
}
match tool_name {
"get_relationship" => self.tool_get_relationship(arguments),
"list_relationships" => self.tool_list_relationships(arguments),
_ => unreachable!(),
}
}
_ => json!({ _ => json!({
"success": false, "success": false,
"error": format!("Unknown tool: {}", tool_name) "error": format!("Unknown tool: {}", tool_name)