fix: fix OpenAPI build (#2036)

This commit is contained in:
Alex Hancock
2025-04-04 11:58:57 -04:00
committed by GitHub
parent c3042067a0
commit 3ec0f77ed5
7 changed files with 183 additions and 3 deletions

1
Cargo.lock generated
View File

@@ -3572,6 +3572,7 @@ dependencies = [
"tempfile",
"thiserror 1.0.69",
"url",
"utoipa",
]
[[package]]

View File

@@ -5,6 +5,7 @@ use goose::agents::ExtensionConfig;
use goose::config::ExtensionEntry;
use goose::providers::base::ConfigKey;
use goose::providers::base::ProviderMetadata;
use mcp_core::tool::{Tool, ToolAnnotations};
#[allow(dead_code)] // Used by utoipa for OpenAPI generation
#[derive(OpenApi)]
@@ -32,6 +33,8 @@ use goose::providers::base::ProviderMetadata;
ExtensionConfig,
ConfigKey,
Envs,
Tool,
ToolAnnotations,
))
)]
pub struct ApiDoc;

View File

@@ -1,6 +1,7 @@
use std::collections::HashMap;
use mcp_client::client::Error as ClientError;
use mcp_core::tool::Tool;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use tracing::warn;
@@ -155,7 +156,7 @@ pub enum ExtensionConfig {
/// The name used to identify this extension
name: String,
/// The tools provided by the frontend
tools: Vec<mcp_core::tool::Tool>,
tools: Vec<Tool>,
/// Instructions for how to use these tools
instructions: Option<String>,
},

View File

@@ -13,6 +13,7 @@ anyhow = "1.0"
chrono = { version = "0.4.38", features = ["serde"] }
url = "2.5"
base64 = "0.21"
utoipa = "4.1"
[dev-dependencies]
tempfile = "3.8"

View File

@@ -2,6 +2,7 @@
/// Tool calls represent requests from the client to execute one
use serde::{Deserialize, Serialize};
use serde_json::Value;
use utoipa::ToSchema;
/// Additional properties describing a tool to clients.
///
@@ -11,7 +12,7 @@ use serde_json::Value;
///
/// Clients should never make tool use decisions based on ToolAnnotations
/// received from untrusted servers.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ToolAnnotations {
/// A human-readable title for the tool.
@@ -100,7 +101,7 @@ impl ToolAnnotations {
}
/// A tool that can be used by a model.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct Tool {
/// The name of the tool

View File

@@ -424,6 +424,39 @@
]
}
}
},
{
"type": "object",
"description": "Frontend-provided tools that will be called through the frontend",
"required": [
"name",
"tools",
"type"
],
"properties": {
"instructions": {
"type": "string",
"description": "Instructions for how to use these tools",
"nullable": true
},
"name": {
"type": "string",
"description": "The name used to identify this extension"
},
"tools": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Tool"
},
"description": "The tools provided by the frontend"
},
"type": {
"type": "string",
"enum": [
"frontend"
]
}
}
}
],
"description": "Represents the different types of MCP extensions that can be added to the manager",
@@ -566,6 +599,63 @@
}
}
},
"Tool": {
"type": "object",
"description": "A tool that can be used by a model.",
"required": [
"name",
"description",
"inputSchema"
],
"properties": {
"annotations": {
"allOf": [
{
"$ref": "#/components/schemas/ToolAnnotations"
}
],
"nullable": true
},
"description": {
"type": "string",
"description": "A description of what the tool does"
},
"inputSchema": {
"description": "A JSON Schema object defining the expected parameters for the tool"
},
"name": {
"type": "string",
"description": "The name of the tool"
}
}
},
"ToolAnnotations": {
"type": "object",
"description": "Additional properties describing a tool to clients.\n\nNOTE: all properties in ToolAnnotations are **hints**.\nThey are not guaranteed to provide a faithful description of\ntool behavior (including descriptive properties like `title`).\n\nClients should never make tool use decisions based on ToolAnnotations\nreceived from untrusted servers.",
"properties": {
"destructiveHint": {
"type": "boolean",
"description": "If true, the tool may perform destructive updates to its environment.\nIf false, the tool performs only additive updates.\n\n(This property is meaningful only when `read_only_hint == false`)\n\nDefault: true"
},
"idempotentHint": {
"type": "boolean",
"description": "If true, calling the tool repeatedly with the same arguments\nwill have no additional effect on its environment.\n\n(This property is meaningful only when `read_only_hint == false`)\n\nDefault: false"
},
"openWorldHint": {
"type": "boolean",
"description": "If true, this tool may interact with an \"open world\" of external\nentities. If false, the tool's domain of interaction is closed.\nFor example, the world of a web search tool is open, whereas that\nof a memory tool is not.\n\nDefault: true"
},
"readOnlyHint": {
"type": "boolean",
"description": "If true, the tool does not modify its environment.\n\nDefault: false"
},
"title": {
"type": "string",
"description": "A human-readable title for the tool.",
"nullable": true
}
}
},
"UpsertConfigQuery": {
"type": "object",
"required": [

View File

@@ -52,6 +52,20 @@ export type ExtensionConfig = {
name: string;
timeout?: number | null;
type: 'builtin';
} | {
/**
* Instructions for how to use these tools
*/
instructions?: string | null;
/**
* The name used to identify this extension
*/
name: string;
/**
* The tools provided by the frontend
*/
tools: Array<Tool>;
type: 'frontend';
};
export type ExtensionEntry = ExtensionConfig & {
@@ -121,6 +135,75 @@ export type ProvidersResponse = {
providers: Array<ProviderDetails>;
};
/**
* A tool that can be used by a model.
*/
export type Tool = {
annotations?: ToolAnnotations | null;
/**
* A description of what the tool does
*/
description: string;
/**
* A JSON Schema object defining the expected parameters for the tool
*/
inputSchema: unknown;
/**
* The name of the tool
*/
name: string;
};
/**
* Additional properties describing a tool to clients.
*
* NOTE: all properties in ToolAnnotations are **hints**.
* They are not guaranteed to provide a faithful description of
* tool behavior (including descriptive properties like `title`).
*
* Clients should never make tool use decisions based on ToolAnnotations
* received from untrusted servers.
*/
export type ToolAnnotations = {
/**
* If true, the tool may perform destructive updates to its environment.
* If false, the tool performs only additive updates.
*
* (This property is meaningful only when `read_only_hint == false`)
*
* Default: true
*/
destructiveHint?: boolean;
/**
* If true, calling the tool repeatedly with the same arguments
* will have no additional effect on its environment.
*
* (This property is meaningful only when `read_only_hint == false`)
*
* Default: false
*/
idempotentHint?: boolean;
/**
* If true, this tool may interact with an "open world" of external
* entities. If false, the tool's domain of interaction is closed.
* For example, the world of a web search tool is open, whereas that
* of a memory tool is not.
*
* Default: true
*/
openWorldHint?: boolean;
/**
* If true, the tool does not modify its environment.
*
* Default: false
*/
readOnlyHint?: boolean;
/**
* A human-readable title for the tool.
*/
title?: string | null;
};
export type UpsertConfigQuery = {
is_secret: boolean;
key: string;