mirror of
https://github.com/aljazceru/goose.git
synced 2026-02-01 12:44:21 +01:00
Remove mcp_macros and unused types (#3581)
This commit is contained in:
17
Cargo.lock
generated
17
Cargo.lock
generated
@@ -5428,22 +5428,6 @@ dependencies = [
|
||||
"utoipa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mcp-macros"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"convert_case",
|
||||
"mcp-core",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn 2.0.99",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mcp-server"
|
||||
version = "0.1.0"
|
||||
@@ -5452,7 +5436,6 @@ dependencies = [
|
||||
"async-trait",
|
||||
"futures",
|
||||
"mcp-core",
|
||||
"mcp-macros",
|
||||
"pin-project",
|
||||
"rmcp",
|
||||
"schemars",
|
||||
|
||||
@@ -11,7 +11,6 @@ use goose::permission::permission_confirmation::PrincipalType;
|
||||
use goose::providers::base::{ConfigKey, ModelInfo, ProviderMetadata};
|
||||
use goose::session::info::SessionInfo;
|
||||
use goose::session::SessionMetadata;
|
||||
use mcp_core::handler::ToolResultSchema;
|
||||
use mcp_core::tool::{Tool, ToolAnnotations};
|
||||
use rmcp::model::ResourceContents;
|
||||
use rmcp::model::{Annotations, Content, EmbeddedResource, ImageContent, Role, TextContent};
|
||||
@@ -348,7 +347,6 @@ derive_utoipa!(ResourceContents as ResourceContentsSchema);
|
||||
TextContentSchema,
|
||||
ToolResponse,
|
||||
ToolRequest,
|
||||
ToolResultSchema,
|
||||
ToolConfirmationRequest,
|
||||
ThinkingContent,
|
||||
RedactedThinkingContent,
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
use async_trait::async_trait;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
#[allow(unused_imports)] // this is used in schema below
|
||||
use serde_json::json;
|
||||
use serde_json::Value;
|
||||
use thiserror::Error;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
#[non_exhaustive]
|
||||
#[derive(Error, Debug, Clone, Deserialize, Serialize, PartialEq)]
|
||||
@@ -22,18 +18,6 @@ pub enum ToolError {
|
||||
|
||||
pub type ToolResult<T> = std::result::Result<T, ToolError>;
|
||||
|
||||
// Define schema manually without generics issues
|
||||
#[derive(ToSchema)]
|
||||
#[schema(example = json!({"success": true, "data": {}}))]
|
||||
pub struct ToolResultSchema {
|
||||
#[schema(example = "Operation completed successfully")]
|
||||
pub message: Option<String>,
|
||||
#[schema(example = true)]
|
||||
pub success: bool,
|
||||
#[schema(value_type = Object)]
|
||||
pub data: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ResourceError {
|
||||
#[error("Execution failed: {0}")]
|
||||
@@ -51,38 +35,3 @@ pub enum PromptError {
|
||||
#[error("Prompt not found: {0}")]
|
||||
NotFound(String),
|
||||
}
|
||||
|
||||
/// Trait for implementing MCP tools
|
||||
#[async_trait]
|
||||
pub trait ToolHandler: Send + Sync + 'static {
|
||||
/// The name of the tool
|
||||
fn name(&self) -> &'static str;
|
||||
|
||||
/// A description of what the tool does
|
||||
fn description(&self) -> &'static str;
|
||||
|
||||
/// JSON schema describing the tool's parameters
|
||||
fn schema(&self) -> Value;
|
||||
|
||||
/// Execute the tool with the given parameters
|
||||
async fn call(&self, params: Value) -> ToolResult<Value>;
|
||||
}
|
||||
|
||||
/// Trait for implementing MCP resources
|
||||
#[async_trait]
|
||||
pub trait ResourceTemplateHandler: Send + Sync + 'static {
|
||||
/// The URL template for this resource
|
||||
fn template() -> &'static str;
|
||||
|
||||
/// JSON schema describing the resource parameters
|
||||
fn schema() -> Value;
|
||||
|
||||
/// Get the resource value
|
||||
async fn get(&self, params: Value) -> ToolResult<String>;
|
||||
}
|
||||
|
||||
/// Helper function to generate JSON schema for a type
|
||||
pub fn generate_schema<T: JsonSchema>() -> ToolResult<Value> {
|
||||
let schema = schemars::schema_for!(T);
|
||||
serde_json::to_value(schema).map_err(|e| ToolError::SchemaError(e.to_string()))
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
[package]
|
||||
name = "mcp-macros"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
syn = { version = "2.0", features = ["full", "extra-traits"] }
|
||||
quote = "1.0"
|
||||
proc-macro2 = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
mcp-core = { path = "../mcp-core" }
|
||||
async-trait = "0.1"
|
||||
schemars = "0.8"
|
||||
convert_case = "0.6.0"
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1.43", features = ["full"] }
|
||||
async-trait = "0.1"
|
||||
serde_json = "1.0"
|
||||
schemars = "0.8"
|
||||
@@ -1,53 +0,0 @@
|
||||
use mcp_core::handler::{ToolError, ToolHandler};
|
||||
use mcp_macros::tool;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
|
||||
// Create an instance of our tool
|
||||
let calculator = Calculator;
|
||||
|
||||
// Print tool information
|
||||
println!("Tool name: {}", calculator.name());
|
||||
println!("Tool description: {}", calculator.description());
|
||||
println!("Tool schema: {}", calculator.schema());
|
||||
|
||||
// Test the tool with some sample input
|
||||
let input = serde_json::json!({
|
||||
"x": 5,
|
||||
"y": 3,
|
||||
"operation": "multiply"
|
||||
});
|
||||
|
||||
let result = calculator.call(input).await?;
|
||||
println!("Result: {}", result);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tool(
|
||||
name = "calculator",
|
||||
description = "Perform basic arithmetic operations",
|
||||
params(
|
||||
x = "First number in the calculation",
|
||||
y = "Second number in the calculation",
|
||||
operation = "The operation to perform (add, subtract, multiply, divide)"
|
||||
)
|
||||
)]
|
||||
async fn calculator(x: i32, y: i32, operation: String) -> Result<i32, ToolError> {
|
||||
match operation.as_str() {
|
||||
"add" => Ok(x + y),
|
||||
"subtract" => Ok(x - y),
|
||||
"multiply" => Ok(x * y),
|
||||
"divide" => {
|
||||
if y == 0 {
|
||||
Err(ToolError::ExecutionError("Division by zero".into()))
|
||||
} else {
|
||||
Ok(x / y)
|
||||
}
|
||||
}
|
||||
_ => Err(ToolError::InvalidParameters(format!(
|
||||
"Unknown operation: {}",
|
||||
operation
|
||||
))),
|
||||
}
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
use convert_case::{Case, Casing};
|
||||
use proc_macro::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use std::collections::HashMap;
|
||||
use syn::{
|
||||
parse::Parse, parse::ParseStream, parse_macro_input, punctuated::Punctuated, Expr, ExprLit,
|
||||
FnArg, ItemFn, Lit, Meta, Pat, PatType, Token,
|
||||
};
|
||||
|
||||
struct MacroArgs {
|
||||
name: Option<String>,
|
||||
description: Option<String>,
|
||||
param_descriptions: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl Parse for MacroArgs {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
let mut name = None;
|
||||
let mut description = None;
|
||||
let mut param_descriptions = HashMap::new();
|
||||
|
||||
let meta_list: Punctuated<Meta, Token![,]> = Punctuated::parse_terminated(input)?;
|
||||
|
||||
for meta in meta_list {
|
||||
match meta {
|
||||
Meta::NameValue(nv) => {
|
||||
let ident = nv.path.get_ident().unwrap().to_string();
|
||||
if let Expr::Lit(ExprLit {
|
||||
lit: Lit::Str(lit_str),
|
||||
..
|
||||
}) = nv.value
|
||||
{
|
||||
match ident.as_str() {
|
||||
"name" => name = Some(lit_str.value()),
|
||||
"description" => description = Some(lit_str.value()),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
Meta::List(list) if list.path.is_ident("params") => {
|
||||
let nested: Punctuated<Meta, Token![,]> =
|
||||
list.parse_args_with(Punctuated::parse_terminated)?;
|
||||
|
||||
for meta in nested {
|
||||
if let Meta::NameValue(nv) = meta {
|
||||
if let Expr::Lit(ExprLit {
|
||||
lit: Lit::Str(lit_str),
|
||||
..
|
||||
}) = nv.value
|
||||
{
|
||||
let param_name = nv.path.get_ident().unwrap().to_string();
|
||||
param_descriptions.insert(param_name, lit_str.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(MacroArgs {
|
||||
name,
|
||||
description,
|
||||
param_descriptions,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn tool(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let args = parse_macro_input!(args as MacroArgs);
|
||||
let input_fn = parse_macro_input!(input as ItemFn);
|
||||
|
||||
// Extract function details
|
||||
let fn_name = &input_fn.sig.ident;
|
||||
let fn_name_str = fn_name.to_string();
|
||||
|
||||
// Generate PascalCase struct name from the function name
|
||||
let struct_name = format_ident!("{}", { fn_name_str.to_case(Case::Pascal) });
|
||||
|
||||
// Use provided name or function name as default
|
||||
let tool_name = args.name.unwrap_or(fn_name_str);
|
||||
let tool_description = args.description.unwrap_or_default();
|
||||
|
||||
// Extract parameter names, types, and descriptions
|
||||
let mut param_defs = Vec::new();
|
||||
let mut param_names = Vec::new();
|
||||
|
||||
for arg in input_fn.sig.inputs.iter() {
|
||||
if let FnArg::Typed(PatType { pat, ty, .. }) = arg {
|
||||
if let Pat::Ident(param_ident) = &**pat {
|
||||
let param_name = ¶m_ident.ident;
|
||||
let param_name_str = param_name.to_string();
|
||||
let description = args
|
||||
.param_descriptions
|
||||
.get(¶m_name_str)
|
||||
.map(|s| s.as_str())
|
||||
.unwrap_or("");
|
||||
|
||||
param_names.push(param_name);
|
||||
param_defs.push(quote! {
|
||||
#[schemars(description = #description)]
|
||||
#param_name: #ty
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the implementation
|
||||
let params_struct_name = format_ident!("{}Parameters", struct_name);
|
||||
let expanded = quote! {
|
||||
#[derive(serde::Deserialize, schemars::JsonSchema)]
|
||||
struct #params_struct_name {
|
||||
#(#param_defs,)*
|
||||
}
|
||||
|
||||
#input_fn
|
||||
|
||||
#[derive(Default)]
|
||||
struct #struct_name;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl mcp_core::handler::ToolHandler for #struct_name {
|
||||
fn name(&self) -> &'static str {
|
||||
#tool_name
|
||||
}
|
||||
|
||||
fn description(&self) -> &'static str {
|
||||
#tool_description
|
||||
}
|
||||
|
||||
fn schema(&self) -> serde_json::Value {
|
||||
mcp_core::handler::generate_schema::<#params_struct_name>()
|
||||
.expect("Failed to generate schema")
|
||||
}
|
||||
|
||||
async fn call(&self, params: serde_json::Value) -> Result<serde_json::Value, mcp_core::handler::ToolError> {
|
||||
let params: #params_struct_name = serde_json::from_value(params)
|
||||
.map_err(|e| mcp_core::handler::ToolError::InvalidParameters(e.to_string()))?;
|
||||
|
||||
// Extract parameters and call the function
|
||||
let result = #fn_name(#(params.#param_names,)*).await
|
||||
.map_err(|e| mcp_core::handler::ToolError::ExecutionError(e.to_string()))?;
|
||||
|
||||
Ok(serde_json::to_value(result).expect("should serialize"))
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TokenStream::from(expanded)
|
||||
}
|
||||
@@ -10,7 +10,6 @@ workspace = true
|
||||
anyhow = "1.0.94"
|
||||
thiserror = "1.0"
|
||||
mcp-core = { path = "../mcp-core" }
|
||||
mcp-macros = { path = "../mcp-macros" }
|
||||
rmcp = { workspace = true }
|
||||
serde = { version = "1.0.216", features = ["derive"] }
|
||||
serde_json = "1.0.133"
|
||||
|
||||
@@ -2975,31 +2975,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"ToolResultSchema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"success",
|
||||
"data"
|
||||
],
|
||||
"properties": {
|
||||
"data": {
|
||||
"type": "object"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"example": "Operation completed successfully",
|
||||
"nullable": true
|
||||
},
|
||||
"success": {
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"data": {},
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
"UpdateScheduleRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
||||
@@ -763,14 +763,6 @@ export type ToolResponse = {
|
||||
};
|
||||
};
|
||||
|
||||
export type ToolResultSchema = {
|
||||
data: {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
message?: string | null;
|
||||
success: boolean;
|
||||
};
|
||||
|
||||
export type UpdateScheduleRequest = {
|
||||
cron: string;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user