refactor(tamagotchi): use top-level cargo workspace, move tauri-plugin-mcp (#152)
This commit is contained in:
@@ -15,6 +15,16 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
with:
|
||||||
|
components: rustfmt,clippy
|
||||||
|
|
||||||
|
- name: Install system dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y libwebkit2gtk-4.1-dev
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v3
|
- uses: pnpm/action-setup@v3
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
@@ -25,13 +35,22 @@ jobs:
|
|||||||
run: pnpm install
|
run: pnpm install
|
||||||
|
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: pnpm run lint
|
run: |
|
||||||
|
pnpm run lint
|
||||||
|
pnpm run lint:rust
|
||||||
|
|
||||||
build-test:
|
build-test:
|
||||||
name: Build Test
|
name: Build Test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
||||||
|
- name: Install system dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y libwebkit2gtk-4.1-dev
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v3
|
- uses: pnpm/action-setup@v3
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
@@ -45,6 +64,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
pnpm run packages:build
|
pnpm run packages:build
|
||||||
pnpm run apps:build
|
pnpm run apps:build
|
||||||
|
pnpm run crates:build
|
||||||
|
|
||||||
typecheck:
|
typecheck:
|
||||||
name: Type Check
|
name: Type Check
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
name: Release Crates
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
|
||||||
|
env:
|
||||||
|
STORE_PATH: ''
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
id-token: write
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
name: Release
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
||||||
|
- name: Login to crates.io
|
||||||
|
run: |
|
||||||
|
echo ${{ secrets.CRATES_IO_API_TOKEN }} | cargo login
|
||||||
|
|
||||||
|
# TODO: cargo publish --workspace is still experimental
|
||||||
|
- name: Crates publish
|
||||||
|
run: |
|
||||||
|
cargo publish -p tauri-plugin-mcp
|
||||||
@@ -48,3 +48,6 @@ twitter-session.json
|
|||||||
.envrc
|
.envrc
|
||||||
.devenv*
|
.devenv*
|
||||||
devenv.*
|
devenv.*
|
||||||
|
|
||||||
|
target/
|
||||||
|
crates/*/target/
|
||||||
|
|||||||
Vendored
+2
-1
@@ -12,6 +12,7 @@
|
|||||||
"antfu.unocss",
|
"antfu.unocss",
|
||||||
"Vue.volar",
|
"Vue.volar",
|
||||||
"vitest.explorer",
|
"vitest.explorer",
|
||||||
"redhat.vscode-yaml"
|
"redhat.vscode-yaml",
|
||||||
|
"rust-lang.rust-analyzer"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+5
-1
@@ -55,5 +55,9 @@
|
|||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
"appimage",
|
"appimage",
|
||||||
"localforage"
|
"localforage"
|
||||||
]
|
],
|
||||||
|
"[rust]": {
|
||||||
|
"editor.defaultFormatter": "rust-lang.rust-analyzer",
|
||||||
|
"editor.formatOnSave": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+5142
File diff suppressed because it is too large
Load Diff
+12
@@ -0,0 +1,12 @@
|
|||||||
|
[workspace]
|
||||||
|
members = [
|
||||||
|
"crates/*",
|
||||||
|
"apps/stage-tamagotchi/src-tauri"
|
||||||
|
]
|
||||||
|
resolver = "2"
|
||||||
|
|
||||||
|
[workspace.package]
|
||||||
|
version = "0.4.25"
|
||||||
|
|
||||||
|
[workspace.dependencies]
|
||||||
|
tauri-plugin-mcp = { path = "./crates/tauri-plugin-mcp" }
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
"@pixiv/three-vrm-core": "^3.4.0",
|
"@pixiv/three-vrm-core": "^3.4.0",
|
||||||
"@proj-airi/drizzle-duckdb-wasm": "catalog:",
|
"@proj-airi/drizzle-duckdb-wasm": "catalog:",
|
||||||
"@proj-airi/stage-ui": "workspace:^",
|
"@proj-airi/stage-ui": "workspace:^",
|
||||||
|
"@proj-airi/tauri-plugin-mcp": "workspace:^",
|
||||||
"@proj-airi/ui": "workspace:^",
|
"@proj-airi/ui": "workspace:^",
|
||||||
"@ricky0123/vad-web": "^0.0.22",
|
"@ricky0123/vad-web": "^0.0.22",
|
||||||
"@tauri-apps/api": "^2.5.0",
|
"@tauri-apps/api": "^2.5.0",
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "app"
|
name = "app"
|
||||||
version = "0.1.0"
|
version.workspace = true
|
||||||
description = "Airi tamagotchi app built with Tauri"
|
description = "Airi tamagotchi app built with Tauri"
|
||||||
authors = [ "LemonNekoGH <self@lemonneko.moe>" ]
|
authors = [ "LemonNekoGH <self@lemonneko.moe>" ]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/moeru-ai/airi"
|
repository = "https://github.com/moeru-ai/airi"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.77.2"
|
rust-version = "1.77.2"
|
||||||
|
publish = false
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "app_lib"
|
name = "app_lib"
|
||||||
@@ -30,9 +31,4 @@ tauri = { version = "2.3.1", features = [
|
|||||||
] }
|
] }
|
||||||
tauri-plugin-log = "2.0.0-rc"
|
tauri-plugin-log = "2.0.0-rc"
|
||||||
tauri-plugin-os = "2"
|
tauri-plugin-os = "2"
|
||||||
tauri-plugin-mcp = { path = "./tauri-plugin-mcp" }
|
tauri-plugin-mcp = { workspace = true }
|
||||||
|
|
||||||
[workspace]
|
|
||||||
members = [
|
|
||||||
"tauri-plugin-mcp"
|
|
||||||
]
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use tauri::{WebviewUrl, WebviewWindowBuilder, Manager};
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use tauri::{Manager, WebviewUrl, WebviewWindowBuilder};
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn open_settings_window(app: tauri::AppHandle) {
|
pub fn open_settings_window(app: tauri::AppHandle) {
|
||||||
@@ -8,9 +8,13 @@ pub fn open_settings_window(app: tauri::AppHandle) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = WebviewWindowBuilder::new(&app, "settings", WebviewUrl::App(Path::new("#/settings").to_path_buf()))
|
let _ = WebviewWindowBuilder::new(
|
||||||
.title("settings")
|
&app,
|
||||||
.inner_size(600.0, 800.0)
|
"settings",
|
||||||
.build()
|
WebviewUrl::App(Path::new("#/settings").to_path_buf()),
|
||||||
.unwrap();
|
)
|
||||||
|
.title("settings")
|
||||||
|
.inner_size(600.0, 800.0)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
use tauri::{WebviewUrl, WebviewWindowBuilder, Manager};
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
use tauri::{ActivationPolicy,TitleBarStyle};
|
|
||||||
use tauri::tray::TrayIconBuilder;
|
|
||||||
use tauri::menu::{Menu, MenuItem};
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use tauri::menu::{Menu, MenuItem};
|
||||||
|
use tauri::tray::TrayIconBuilder;
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
use tauri::{ActivationPolicy, TitleBarStyle};
|
||||||
|
use tauri::{Manager, WebviewUrl, WebviewWindowBuilder};
|
||||||
|
|
||||||
mod commands;
|
mod commands;
|
||||||
|
|
||||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
pub fn run() {
|
pub fn run() {
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.plugin(tauri_plugin_mcp::Builder::default().build())
|
.plugin(tauri_plugin_mcp::Builder.build())
|
||||||
.plugin(tauri_plugin_os::init())
|
.plugin(tauri_plugin_os::init())
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
let mut builder = WebviewWindowBuilder::new(app, "main", WebviewUrl::default())
|
let mut builder = WebviewWindowBuilder::new(app, "main", WebviewUrl::default())
|
||||||
@@ -26,9 +26,7 @@ pub fn run() {
|
|||||||
builder = builder.title_bar_style(TitleBarStyle::Transparent);
|
builder = builder.title_bar_style(TitleBarStyle::Transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = builder
|
let _ = builder.build().unwrap();
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
app.set_activation_policy(ActivationPolicy::Accessory); // hide dock icon
|
app.set_activation_policy(ActivationPolicy::Accessory); // hide dock icon
|
||||||
@@ -61,11 +59,15 @@ pub fn run() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = WebviewWindowBuilder::new(app, "settings", WebviewUrl::App(Path::new("#/settings").to_path_buf()))
|
let _ = WebviewWindowBuilder::new(
|
||||||
.title("settings")
|
app,
|
||||||
.inner_size(600.0, 800.0)
|
"settings",
|
||||||
.build()
|
WebviewUrl::App(Path::new("#/settings").to_path_buf()),
|
||||||
.unwrap();
|
)
|
||||||
|
.title("settings")
|
||||||
|
.inner_size(600.0, 800.0)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
"hide" => {
|
"hide" => {
|
||||||
if let Some(window) = app.get_webview_window("main") {
|
if let Some(window) = app.get_webview_window("main") {
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
# `tauri-plugin-mcp`
|
|
||||||
|
|
||||||
A Tauri plugin for MCP.
|
|
||||||
|
|
||||||
These files are generated from `tauri-plugin` crate:
|
|
||||||
|
|
||||||
- `permissions/autogenerated`
|
|
||||||
- `permissions/schemas`
|
|
||||||
|
|
||||||
## TODO List
|
|
||||||
|
|
||||||
- [ ] Move to a single repository
|
|
||||||
- [ ] Server connection
|
|
||||||
- [ ] stdio
|
|
||||||
- [ ] SSE
|
|
||||||
- [x] Tools
|
|
||||||
- [x] List tools
|
|
||||||
- [x] Simple: Names only
|
|
||||||
- [ ] With description, parameters, returns
|
|
||||||
- [x] Call tool
|
|
||||||
- [x] Simple: Name only
|
|
||||||
- [x] With parameters
|
|
||||||
- [x] Returns
|
|
||||||
- [ ] Image returns
|
|
||||||
- [ ] Prompts...
|
|
||||||
- [ ] Resources...
|
|
||||||
- [ ] JavaScript package to call commands conveniently
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { WidgetStage } from '@proj-airi/stage-ui/components'
|
import { WidgetStage } from '@proj-airi/stage-ui/components'
|
||||||
import { useMcpStore } from '@proj-airi/stage-ui/stores'
|
import { useMcpStore } from '@proj-airi/stage-ui/stores'
|
||||||
import { connectServer } from '@proj-airi/stage-ui/utils/tauri-plugin-mcp'
|
import { connectServer } from '@proj-airi/tauri-plugin-mcp'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { computed, onMounted } from 'vue'
|
import { computed, onMounted } from 'vue'
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Tool } from '@proj-airi/stage-ui/utils/tauri-plugin-mcp'
|
import type { Tool } from '@proj-airi/tauri-plugin-mcp'
|
||||||
|
|
||||||
import { useMcpStore } from '@proj-airi/stage-ui/stores'
|
import { useMcpStore } from '@proj-airi/stage-ui/stores'
|
||||||
import { connectServer, disconnectServer, listTools } from '@proj-airi/stage-ui/utils/tauri-plugin-mcp'
|
import { connectServer, disconnectServer, listTools } from '@proj-airi/tauri-plugin-mcp'
|
||||||
import {
|
import {
|
||||||
FieldInput,
|
FieldInput,
|
||||||
} from '@proj-airi/ui'
|
} from '@proj-airi/ui'
|
||||||
|
|||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "tauri-plugin-mcp"
|
name = "tauri-plugin-mcp"
|
||||||
version = "0.1.0"
|
version.workspace = true
|
||||||
description = "A Tauri plugin for interacting with MCP servers"
|
description = "A Tauri plugin for interacting with MCP servers"
|
||||||
authors = [ "LemonNekoGH <self@lemonneko.moe>" ]
|
authors = [ "LemonNekoGH <self@lemonneko.moe>" ]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
# `tauri-plugin-mcp`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
A Tauri plugin for interacting with MCP servers.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
This plugin requires a Rust version of at least 1.77.2
|
||||||
|
|
||||||
|
`src-tauri/Cargo.toml`
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[dependencies]
|
||||||
|
tauri-plugin-mcp = { version = "0.4.25" }
|
||||||
|
# or
|
||||||
|
tauri-plugin-mcp = { git = "https://github.com/moeru-ai/airi", tag = "0.4.25" }
|
||||||
|
```
|
||||||
|
|
||||||
|
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm add @proj-airi/tauri-plugin-mcp
|
||||||
|
# or use @antfu/ni
|
||||||
|
ni @proj-airi/tauri-plugin-mcp
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
First, you need to register the plugin with Tauri:
|
||||||
|
|
||||||
|
`src-tauri/src/lib.rs`
|
||||||
|
|
||||||
|
```rust
|
||||||
|
fn main() {
|
||||||
|
tauri::Builder::default()
|
||||||
|
.plugin(tauri_plugin_mcp::Builder.build())
|
||||||
|
.run(tauri::generate_context!())
|
||||||
|
.expect("error while running tauri application");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { callTool, connectServer, disconnectServer, listTools } from '@proj-airi/tauri-plugin-mcp'
|
||||||
|
|
||||||
|
// Sample: Connect to a container running Airi Android
|
||||||
|
await connectServer('docker', 'run -i --rm -e ADB_HOST=host.docker.internal ghcr.io/lemonnekogh/airi-android:v0.1.0')
|
||||||
|
|
||||||
|
console.log(await listTools())
|
||||||
|
// [
|
||||||
|
// {
|
||||||
|
// description: 'Get the battery level of the device',
|
||||||
|
// inputSchema: {
|
||||||
|
// required: [],
|
||||||
|
// title: 'battery_level',
|
||||||
|
// type: 'object',
|
||||||
|
// },
|
||||||
|
// name: 'battery_level',
|
||||||
|
// },
|
||||||
|
// ]
|
||||||
|
|
||||||
|
console.log(await callTool('battery_level', {}))
|
||||||
|
// {
|
||||||
|
// content: [
|
||||||
|
// {
|
||||||
|
// type: 'text',
|
||||||
|
// text: '100',
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// isError: false,
|
||||||
|
// }
|
||||||
|
|
||||||
|
await disconnectServer()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
Source code of JavaScript bindings is located in [packages/tauri-plugin-mcp](../../packages/tauri-plugin-mcp/src/index.ts).
|
||||||
|
|
||||||
|
These files are generated from `tauri-plugin` crate:
|
||||||
|
|
||||||
|
- `permissions/autogenerated`
|
||||||
|
- `permissions/schemas`
|
||||||
|
|
||||||
|
## TODO List
|
||||||
|
|
||||||
|
- [x] Move to a single repository
|
||||||
|
- [ ] Server connection
|
||||||
|
- [x] stdio
|
||||||
|
- [ ] SSE
|
||||||
|
- [x] Tools
|
||||||
|
- [x] List tools
|
||||||
|
- [x] Simple: Names only
|
||||||
|
- [ ] With description, parameters, returns
|
||||||
|
- [x] Call tool
|
||||||
|
- [x] Simple: Name only
|
||||||
|
- [x] With parameters
|
||||||
|
- [x] Returns
|
||||||
|
- [ ] Image returns
|
||||||
|
- [ ] Prompts...
|
||||||
|
- [ ] Resources...
|
||||||
|
- [x] JavaScript package to call commands conveniently
|
||||||
+37
-17
@@ -1,26 +1,36 @@
|
|||||||
use rmcp::{model::{CallToolResult, Tool}, service::RunningService, transport::TokioChildProcess, RoleClient, ServiceExt};
|
|
||||||
use serde_json::{Map, Value};
|
|
||||||
use tauri::{plugin::{self, TauriPlugin}, Manager, Runtime};
|
|
||||||
use tokio::sync::Mutex;
|
|
||||||
use rmcp::model::CallToolRequestParam;
|
use rmcp::model::CallToolRequestParam;
|
||||||
|
use rmcp::{
|
||||||
|
model::{CallToolResult, Tool},
|
||||||
|
service::RunningService,
|
||||||
|
transport::TokioChildProcess,
|
||||||
|
RoleClient, ServiceExt,
|
||||||
|
};
|
||||||
|
use serde_json::{Map, Value};
|
||||||
use tauri::State;
|
use tauri::State;
|
||||||
|
use tauri::{
|
||||||
|
plugin::{self, TauriPlugin},
|
||||||
|
Manager, Runtime,
|
||||||
|
};
|
||||||
use tokio::process::Command;
|
use tokio::process::Command;
|
||||||
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
pub struct McpState {
|
pub struct McpState {
|
||||||
pub client: Option<RunningService<RoleClient, ()>>,
|
pub client: Option<RunningService<RoleClient, ()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn connect_server(state: State<'_, Mutex<McpState>>, command: String, args: Vec<String>) -> Result<(), String> {
|
async fn connect_server(
|
||||||
|
state: State<'_, Mutex<McpState>>,
|
||||||
|
command: String,
|
||||||
|
args: Vec<String>,
|
||||||
|
) -> Result<(), String> {
|
||||||
let mut state = state.lock().await;
|
let mut state = state.lock().await;
|
||||||
|
|
||||||
if state.client.is_some() {
|
if state.client.is_some() {
|
||||||
return Err("Client already connected".to_string());
|
return Err("Client already connected".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let child_process = TokioChildProcess::new(
|
let child_process = TokioChildProcess::new(Command::new(command).args(args)).unwrap();
|
||||||
Command::new(command).args(args)
|
|
||||||
).unwrap();
|
|
||||||
|
|
||||||
let service: RunningService<RoleClient, ()> = ().serve(child_process).await.unwrap();
|
let service: RunningService<RoleClient, ()> = ().serve(child_process).await.unwrap();
|
||||||
|
|
||||||
@@ -50,14 +60,22 @@ async fn list_tools(state: State<'_, Mutex<McpState>>) -> Result<Vec<Tool>, Stri
|
|||||||
return Err("Client not connected".to_string());
|
return Err("Client not connected".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let list_tools_result = client.unwrap().list_tools(Default::default()).await.unwrap();
|
let list_tools_result = client
|
||||||
|
.unwrap()
|
||||||
|
.list_tools(Default::default())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
let tools = list_tools_result.tools;
|
let tools = list_tools_result.tools;
|
||||||
|
|
||||||
Ok(tools)
|
Ok(tools)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn call_tool(state: State<'_, Mutex<McpState>>, name: String, args: Option<Map<String, Value>>) -> Result<CallToolResult, String> {
|
async fn call_tool(
|
||||||
|
state: State<'_, Mutex<McpState>>,
|
||||||
|
name: String,
|
||||||
|
args: Option<Map<String, Value>>,
|
||||||
|
) -> Result<CallToolResult, String> {
|
||||||
println!("Calling tool: {:?}", name);
|
println!("Calling tool: {:?}", name);
|
||||||
println!("Arguments: {:?}", args);
|
println!("Arguments: {:?}", args);
|
||||||
|
|
||||||
@@ -67,21 +85,23 @@ async fn call_tool(state: State<'_, Mutex<McpState>>, name: String, args: Option
|
|||||||
return Err("Client not connected".to_string());
|
return Err("Client not connected".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let call_tool_result = client.unwrap().call_tool(CallToolRequestParam { name: name.into(), arguments: args }).await.unwrap();
|
let call_tool_result = client
|
||||||
|
.unwrap()
|
||||||
|
.call_tool(CallToolRequestParam {
|
||||||
|
name: name.into(),
|
||||||
|
arguments: args,
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
println!("Tool result: {:?}", call_tool_result);
|
println!("Tool result: {:?}", call_tool_result);
|
||||||
|
|
||||||
Ok(call_tool_result)
|
Ok(call_tool_result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct Builder;
|
pub struct Builder;
|
||||||
|
|
||||||
impl Default for Builder {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Builder {
|
impl Builder {
|
||||||
pub fn build<R: Runtime>(self) -> TauriPlugin<R> {
|
pub fn build<R: Runtime>(self) -> TauriPlugin<R> {
|
||||||
println!("Building MCP plugin");
|
println!("Building MCP plugin");
|
||||||
@@ -10,6 +10,7 @@ export default antfu(
|
|||||||
'**/assets/live2d/models/**',
|
'**/assets/live2d/models/**',
|
||||||
'apps/stage-tamagotchi/out/**',
|
'apps/stage-tamagotchi/out/**',
|
||||||
'apps/stage-tamagotchi/src-tauri/**',
|
'apps/stage-tamagotchi/src-tauri/**',
|
||||||
|
'crates/**',
|
||||||
'**/drizzle/**',
|
'**/drizzle/**',
|
||||||
'**/.astro/**',
|
'**/.astro/**',
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -23,10 +23,12 @@
|
|||||||
"packages:dev": "pnpm -rF=\"./packages/*\" --parallel run dev",
|
"packages:dev": "pnpm -rF=\"./packages/*\" --parallel run dev",
|
||||||
"packages:stub": "pnpm -rF=\"./packages/*\" run --parallel stub",
|
"packages:stub": "pnpm -rF=\"./packages/*\" run --parallel stub",
|
||||||
"packages:build": "pnpm -rF=\"./packages/*\" run build",
|
"packages:build": "pnpm -rF=\"./packages/*\" run build",
|
||||||
|
"crates:build": "cargo build --workspace",
|
||||||
"test": "vitest --coverage",
|
"test": "vitest --coverage",
|
||||||
"test:run": "vitest run",
|
"test:run": "vitest run",
|
||||||
"lint": "eslint --cache .",
|
"lint": "eslint --cache .",
|
||||||
"lint:fix": "eslint --cache --fix .",
|
"lint:fix": "eslint --cache --fix .",
|
||||||
|
"lint:rust": "cargo fmt --check && cargo clippy --workspace",
|
||||||
"typecheck": "pnpm -rF=\"./packages/*\" -F=\"./apps/*\" -F run --parallel typecheck",
|
"typecheck": "pnpm -rF=\"./packages/*\" -F=\"./apps/*\" -F run --parallel typecheck",
|
||||||
"sizecheck": "npx vite-bundle-visualizer",
|
"sizecheck": "npx vite-bundle-visualizer",
|
||||||
"up": "taze major -I",
|
"up": "taze major -I",
|
||||||
|
|||||||
@@ -91,6 +91,7 @@
|
|||||||
"@proj-airi/font-cjkfonts-allseto": "workspace:^",
|
"@proj-airi/font-cjkfonts-allseto": "workspace:^",
|
||||||
"@proj-airi/font-xiaolai": "workspace:^",
|
"@proj-airi/font-xiaolai": "workspace:^",
|
||||||
"@proj-airi/server-sdk": "workspace:^",
|
"@proj-airi/server-sdk": "workspace:^",
|
||||||
|
"@proj-airi/tauri-plugin-mcp": "workspace:^",
|
||||||
"@proj-airi/ui": "workspace:^",
|
"@proj-airi/ui": "workspace:^",
|
||||||
"@vueuse/core": "^13.1.0",
|
"@vueuse/core": "^13.1.0",
|
||||||
"@vueuse/motion": "^3.0.3",
|
"@vueuse/motion": "^3.0.3",
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
|
import { callTool, connectServer, disconnectServer, listTools } from '@proj-airi/tauri-plugin-mcp'
|
||||||
import { tool } from '@xsai/tool'
|
import { tool } from '@xsai/tool'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
|
||||||
import { callTool, connectServer, disconnectServer, listTools } from '../utils/tauri-plugin-mcp'
|
|
||||||
|
|
||||||
const tools = [
|
const tools = [
|
||||||
tool({
|
tool({
|
||||||
name: 'mcp_list_tools',
|
name: 'mcp_list_tools',
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# tauri-plugin-mcp
|
||||||
|
|
||||||
|
[Docs here](../../crates/tauri-plugin-mcp/README.md)
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"name": "@proj-airi/tauri-plugin-mcp",
|
||||||
|
"type": "module",
|
||||||
|
"version": "0.4.25",
|
||||||
|
"packageManager": "pnpm@10.9.0",
|
||||||
|
"description": "A Tauri plugin for interacting with MCP servers.",
|
||||||
|
"author": {
|
||||||
|
"name": "LemonNekoGH",
|
||||||
|
"email": "self@lemonnekogh.moe",
|
||||||
|
"url": "https://github.com/LemonNekoGH"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/moeru-ai/airi.git",
|
||||||
|
"directory": "packages/tauri-plugin-mcp"
|
||||||
|
},
|
||||||
|
"exports": {
|
||||||
|
".": "./src/index.ts"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"README.md",
|
||||||
|
"dist",
|
||||||
|
"package.json"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"build": "pkgroll"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@tauri-apps/api": "^2.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"pkgroll": "^2.12.2"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"default": "./dist/index.js"
|
||||||
|
},
|
||||||
|
"main": "./dist/index.js",
|
||||||
|
"module": "./dist/index.js",
|
||||||
|
"types": "./dist/index.d.ts"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
-2
@@ -1,5 +1,3 @@
|
|||||||
// TODO: move to plugin package when it's ready
|
|
||||||
|
|
||||||
import { invoke } from '@tauri-apps/api/core'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
export interface ToolInputSchema {
|
export interface ToolInputSchema {
|
||||||
Generated
+92
-2
@@ -242,6 +242,9 @@ importers:
|
|||||||
'@proj-airi/stage-ui':
|
'@proj-airi/stage-ui':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
version: link:../../packages/stage-ui
|
version: link:../../packages/stage-ui
|
||||||
|
'@proj-airi/tauri-plugin-mcp':
|
||||||
|
specifier: workspace:^
|
||||||
|
version: link:../../packages/tauri-plugin-mcp
|
||||||
'@proj-airi/ui':
|
'@proj-airi/ui':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
version: link:../../packages/ui
|
version: link:../../packages/ui
|
||||||
@@ -957,6 +960,9 @@ importers:
|
|||||||
'@proj-airi/server-sdk':
|
'@proj-airi/server-sdk':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
version: link:../server-sdk
|
version: link:../server-sdk
|
||||||
|
'@proj-airi/tauri-plugin-mcp':
|
||||||
|
specifier: workspace:^
|
||||||
|
version: link:../tauri-plugin-mcp
|
||||||
'@proj-airi/ui':
|
'@proj-airi/ui':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
version: link:../ui
|
version: link:../ui
|
||||||
@@ -1019,6 +1025,16 @@ importers:
|
|||||||
specifier: ^6.3.3
|
specifier: ^6.3.3
|
||||||
version: 6.3.3(@types/node@22.15.2)(jiti@2.4.2)(less@4.3.0)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0)
|
version: 6.3.3(@types/node@22.15.2)(jiti@2.4.2)(less@4.3.0)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0)
|
||||||
|
|
||||||
|
packages/tauri-plugin-mcp:
|
||||||
|
dependencies:
|
||||||
|
'@tauri-apps/api':
|
||||||
|
specifier: ^2.0.0
|
||||||
|
version: 2.5.0
|
||||||
|
devDependencies:
|
||||||
|
pkgroll:
|
||||||
|
specifier: ^2.12.2
|
||||||
|
version: 2.12.2(typescript@5.8.3)
|
||||||
|
|
||||||
packages/ui:
|
packages/ui:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vueuse/core':
|
'@vueuse/core':
|
||||||
@@ -3982,6 +3998,24 @@ packages:
|
|||||||
rollup:
|
rollup:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@rollup/plugin-dynamic-import-vars@2.1.5':
|
||||||
|
resolution: {integrity: sha512-Mymi24fd9hlRifdZV/jYIFj1dn99F34imiYu3KzlAcgBcRi3i9SucgW/VRo5SQ9K4NuQ7dCep6pFWgNyhRdFHQ==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
rollup:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@rollup/plugin-inject@5.0.5':
|
||||||
|
resolution: {integrity: sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
rollup:
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@rollup/plugin-json@6.1.0':
|
'@rollup/plugin-json@6.1.0':
|
||||||
resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==}
|
resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
@@ -6949,6 +6983,9 @@ packages:
|
|||||||
estree-util-visit@2.0.0:
|
estree-util-visit@2.0.0:
|
||||||
resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==}
|
resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==}
|
||||||
|
|
||||||
|
estree-walker@0.6.1:
|
||||||
|
resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==}
|
||||||
|
|
||||||
estree-walker@1.0.1:
|
estree-walker@1.0.1:
|
||||||
resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==}
|
resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==}
|
||||||
|
|
||||||
@@ -9275,6 +9312,16 @@ packages:
|
|||||||
pkg-types@2.1.0:
|
pkg-types@2.1.0:
|
||||||
resolution: {integrity: sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==}
|
resolution: {integrity: sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==}
|
||||||
|
|
||||||
|
pkgroll@2.12.2:
|
||||||
|
resolution: {integrity: sha512-Vl1hJ6jQj6YY9xvhuH8qNVf4qEZng9qC5jfqUKIR4+k5HaGdt6TCXj3lI5uNs+Z3ljtdlwMigi5re1YyDDhVxA==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
hasBin: true
|
||||||
|
peerDependencies:
|
||||||
|
typescript: ^4.1 || ^5.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
typescript:
|
||||||
|
optional: true
|
||||||
|
|
||||||
platform@1.3.6:
|
platform@1.3.6:
|
||||||
resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==}
|
resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==}
|
||||||
|
|
||||||
@@ -10023,6 +10070,9 @@ packages:
|
|||||||
rollup:
|
rollup:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
rollup-pluginutils@2.8.2:
|
||||||
|
resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==}
|
||||||
|
|
||||||
rollup@2.79.1:
|
rollup@2.79.1:
|
||||||
resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==}
|
resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==}
|
||||||
engines: {node: '>=10.0.0'}
|
engines: {node: '>=10.0.0'}
|
||||||
@@ -14765,6 +14815,24 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
rollup: 4.40.0
|
rollup: 4.40.0
|
||||||
|
|
||||||
|
'@rollup/plugin-dynamic-import-vars@2.1.5(rollup@4.40.0)':
|
||||||
|
dependencies:
|
||||||
|
'@rollup/pluginutils': 5.1.4(rollup@4.40.0)
|
||||||
|
astring: 1.9.0
|
||||||
|
estree-walker: 2.0.2
|
||||||
|
fast-glob: 3.3.3
|
||||||
|
magic-string: 0.30.17
|
||||||
|
optionalDependencies:
|
||||||
|
rollup: 4.40.0
|
||||||
|
|
||||||
|
'@rollup/plugin-inject@5.0.5(rollup@4.40.0)':
|
||||||
|
dependencies:
|
||||||
|
'@rollup/pluginutils': 5.1.4(rollup@4.40.0)
|
||||||
|
estree-walker: 2.0.2
|
||||||
|
magic-string: 0.30.17
|
||||||
|
optionalDependencies:
|
||||||
|
rollup: 4.40.0
|
||||||
|
|
||||||
'@rollup/plugin-json@6.1.0(rollup@4.40.0)':
|
'@rollup/plugin-json@6.1.0(rollup@4.40.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rollup/pluginutils': 5.1.4(rollup@4.40.0)
|
'@rollup/pluginutils': 5.1.4(rollup@4.40.0)
|
||||||
@@ -16463,8 +16531,8 @@ snapshots:
|
|||||||
'@xsai-transformers/shared@0.0.5':
|
'@xsai-transformers/shared@0.0.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@huggingface/transformers': 3.5.0
|
'@huggingface/transformers': 3.5.0
|
||||||
'@xsai-ext/shared-providers': 0.2.0-beta.5
|
'@xsai-ext/shared-providers': 0.2.0-beta.6
|
||||||
'@xsai/shared': 0.2.0-beta.5
|
'@xsai/shared': 0.2.0-beta.6
|
||||||
defu: 6.1.4
|
defu: 6.1.4
|
||||||
onnxruntime-common: 1.21.1
|
onnxruntime-common: 1.21.1
|
||||||
|
|
||||||
@@ -18319,6 +18387,8 @@ snapshots:
|
|||||||
'@types/estree-jsx': 1.0.5
|
'@types/estree-jsx': 1.0.5
|
||||||
'@types/unist': 3.0.0
|
'@types/unist': 3.0.0
|
||||||
|
|
||||||
|
estree-walker@0.6.1: {}
|
||||||
|
|
||||||
estree-walker@1.0.1: {}
|
estree-walker@1.0.1: {}
|
||||||
|
|
||||||
estree-walker@2.0.2: {}
|
estree-walker@2.0.2: {}
|
||||||
@@ -21454,6 +21524,22 @@ snapshots:
|
|||||||
exsolve: 1.0.1
|
exsolve: 1.0.1
|
||||||
pathe: 2.0.3
|
pathe: 2.0.3
|
||||||
|
|
||||||
|
pkgroll@2.12.2(typescript@5.8.3):
|
||||||
|
dependencies:
|
||||||
|
'@rollup/plugin-alias': 5.1.1(rollup@4.40.0)
|
||||||
|
'@rollup/plugin-commonjs': 28.0.3(rollup@4.40.0)
|
||||||
|
'@rollup/plugin-dynamic-import-vars': 2.1.5(rollup@4.40.0)
|
||||||
|
'@rollup/plugin-inject': 5.0.5(rollup@4.40.0)
|
||||||
|
'@rollup/plugin-json': 6.1.0(rollup@4.40.0)
|
||||||
|
'@rollup/plugin-node-resolve': 16.0.1(rollup@4.40.0)
|
||||||
|
'@rollup/pluginutils': 5.1.4(rollup@4.40.0)
|
||||||
|
esbuild: 0.25.2
|
||||||
|
magic-string: 0.30.17
|
||||||
|
rollup: 4.40.0
|
||||||
|
rollup-pluginutils: 2.8.2
|
||||||
|
optionalDependencies:
|
||||||
|
typescript: 5.8.3
|
||||||
|
|
||||||
platform@1.3.6: {}
|
platform@1.3.6: {}
|
||||||
|
|
||||||
playwright-core@1.50.1: {}
|
playwright-core@1.50.1: {}
|
||||||
@@ -22388,6 +22474,10 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
rollup: 4.40.0
|
rollup: 4.40.0
|
||||||
|
|
||||||
|
rollup-pluginutils@2.8.2:
|
||||||
|
dependencies:
|
||||||
|
estree-walker: 0.6.1
|
||||||
|
|
||||||
rollup@2.79.1:
|
rollup@2.79.1:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
tab_spaces = 2
|
||||||
Reference in New Issue
Block a user