add fastapi_mcp

This commit is contained in:
2025-05-22 21:30:47 +09:00
parent 9cbf5da3fd
commit 4f55138306
12 changed files with 566 additions and 84 deletions

View File

@ -5,11 +5,16 @@ use serde::Deserialize;
use seahorse::Context;
use crate::config::ConfigPaths;
use crate::metrics::{load_user_data, save_user_data, update_metrics_decay};
//use std::process::Stdio;
//use std::io::Write;
//use std::time::Duration;
//use std::net::TcpStream;
#[derive(Debug, Clone, PartialEq)]
pub enum Provider {
OpenAI,
Ollama,
MCP,
}
impl Provider {
@ -17,6 +22,7 @@ impl Provider {
match s.to_lowercase().as_str() {
"openai" => Some(Provider::OpenAI),
"ollama" => Some(Provider::Ollama),
"mcp" => Some(Provider::MCP),
_ => None,
}
}
@ -25,6 +31,7 @@ impl Provider {
match self {
Provider::OpenAI => "openai",
Provider::Ollama => "ollama",
Provider::MCP => "mcp",
}
}
}
@ -45,19 +52,11 @@ fn load_openai_api_key() -> Option<String> {
pub fn ask_chat(c: &Context, question: &str) -> Option<String> {
let config = ConfigPaths::new();
let base_dir = config.base_dir.join("mcp");
let script_path = base_dir.join("scripts/ask.py");
let user_path = config.base_dir.join("user.json");
let mut user = load_user_data(&user_path);
user.metrics = update_metrics_decay();
// Python 実行パス
let python_path = if cfg!(target_os = "windows") {
base_dir.join(".venv/Scripts/python.exe")
} else {
base_dir.join(".venv/bin/python")
};
// 各種オプション
let ollama_host = c.string_flag("host").ok();
let ollama_model = c.string_flag("model").ok();
@ -67,38 +66,75 @@ pub fn ask_chat(c: &Context, question: &str) -> Option<String> {
println!("🔍 使用プロバイダー: {}", provider.as_str());
// Python コマンド準備
let mut command = Command::new(python_path);
command.arg(script_path).arg(question);
match provider {
Provider::MCP => {
let client = reqwest::blocking::Client::new();
let url = std::env::var("MCP_URL").unwrap_or("http://127.0.0.1:5000/chat".to_string());
let res = client.post(url)
.json(&serde_json::json!({"message": question}))
.send();
if let Some(host) = ollama_host {
command.env("OLLAMA_HOST", host);
}
if let Some(model) = ollama_model {
command.env("OLLAMA_MODEL", model.clone());
command.env("OPENAI_MODEL", model);
}
command.env("PROVIDER", provider.as_str());
match res {
Ok(resp) => {
if resp.status().is_success() {
let json: serde_json::Value = resp.json().ok()?;
let text = json.get("response")?.as_str()?.to_string();
user.metrics.intimacy += 0.01;
user.metrics.last_updated = chrono::Utc::now();
save_user_data(&user_path, &user);
Some(text)
} else {
eprintln!("❌ MCPエラー: HTTP {}", resp.status());
None
}
}
Err(e) => {
eprintln!("❌ MCP接続失敗: {}", e);
None
}
}
}
_ => {
// Python 実行パス
let python_path = if cfg!(target_os = "windows") {
base_dir.join(".venv/Scripts/mcp.exe")
} else {
base_dir.join(".venv/bin/mcp")
};
if let Some(key) = api_key {
command.env("OPENAI_API_KEY", key);
}
let mut command = Command::new(python_path);
command.arg("ask").arg(question);
let output = command.output().expect("❌ MCPチャットスクリプトの実行に失敗しました");
if let Some(host) = ollama_host {
command.env("OLLAMA_HOST", host);
}
if let Some(model) = ollama_model {
command.env("OLLAMA_MODEL", model.clone());
command.env("OPENAI_MODEL", model);
}
command.env("PROVIDER", provider.as_str());
if output.status.success() {
let response = String::from_utf8_lossy(&output.stdout).to_string();
user.metrics.intimacy += 0.01;
user.metrics.last_updated = chrono::Utc::now();
save_user_data(&user_path, &user);
if let Some(key) = api_key {
command.env("OPENAI_API_KEY", key);
}
Some(response)
} else {
eprintln!(
"❌ 実行エラー: {}\n{}",
String::from_utf8_lossy(&output.stderr),
String::from_utf8_lossy(&output.stdout),
);
None
let output = command.output().expect("❌ MCPチャットスクリプトの実行に失敗しました");
if output.status.success() {
let response = String::from_utf8_lossy(&output.stdout).to_string();
user.metrics.intimacy += 0.01;
user.metrics.last_updated = chrono::Utc::now();
save_user_data(&user_path, &user);
Some(response)
} else {
eprintln!(
"❌ 実行エラー: {}\n{}",
String::from_utf8_lossy(&output.stderr),
String::from_utf8_lossy(&output.stdout),
);
None
}
}
}
}

View File

@ -32,8 +32,12 @@ pub fn mcp_setup() {
"cli.py",
"setup.py",
"scripts/ask.py",
"scripts/server.py",
"scripts/config.py",
"scripts/summarize.py",
"scripts/context_loader.py",
"scripts/prompt_template.py",
"scripts/memory_store.py",
];
for rel_path in files_to_copy {
@ -76,6 +80,12 @@ pub fn mcp_setup() {
let output = OtherCommand::new(&pip_path)
.arg("install")
.arg("openai")
.arg("requests")
.arg("fastmcp")
.arg("uvicorn")
.arg("fastapi")
.arg("fastapi_mcp")
.arg("mcp")
.current_dir(&dest_dir)
.output()
.expect("pip install に失敗しました");