resources mcp
This commit is contained in:
70
src/mcp.rs
70
src/mcp.rs
@@ -1,5 +1,11 @@
|
|||||||
use crate::fossil::{Fossil, FossilManager};
|
use crate::fossil::{Fossil, FossilManager};
|
||||||
use crate::matcher::match_lines;
|
use crate::matcher::match_lines;
|
||||||
|
use rmcp::model::{
|
||||||
|
AnnotateAble, ListResourcesResult, PaginatedRequestParam, RawResource,
|
||||||
|
ReadResourceRequestParam, ReadResourceResult, ResourceContents,
|
||||||
|
};
|
||||||
|
use rmcp::service::RequestContext;
|
||||||
|
use rmcp::{ErrorData, RoleServer};
|
||||||
use rmcp::{
|
use rmcp::{
|
||||||
ServerHandler,
|
ServerHandler,
|
||||||
handler::server::{
|
handler::server::{
|
||||||
@@ -9,6 +15,7 @@ use rmcp::{
|
|||||||
model::{ServerCapabilities, ServerInfo},
|
model::{ServerCapabilities, ServerInfo},
|
||||||
schemars, tool, tool_handler, tool_router,
|
schemars, tool, tool_handler, tool_router,
|
||||||
};
|
};
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
#[derive(Debug, serde::Deserialize, schemars::JsonSchema)]
|
#[derive(Debug, serde::Deserialize, schemars::JsonSchema)]
|
||||||
pub struct CreateFossilRequest {
|
pub struct CreateFossilRequest {
|
||||||
@@ -181,6 +188,67 @@ impl FossilEditor {
|
|||||||
|
|
||||||
#[tool_handler]
|
#[tool_handler]
|
||||||
impl ServerHandler for FossilEditor {
|
impl ServerHandler for FossilEditor {
|
||||||
|
async fn list_resources(
|
||||||
|
&self,
|
||||||
|
_request: Option<PaginatedRequestParam>,
|
||||||
|
_: RequestContext<RoleServer>,
|
||||||
|
) -> Result<ListResourcesResult, ErrorData> {
|
||||||
|
let fossils = self.state.fossils.lock().unwrap();
|
||||||
|
let resources: Vec<_> = fossils
|
||||||
|
.keys()
|
||||||
|
.map(|id| {
|
||||||
|
let uri = format!("fossil://{}", id);
|
||||||
|
RawResource::new(uri, id).no_annotation()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(ListResourcesResult {
|
||||||
|
resources,
|
||||||
|
next_cursor: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_resource(
|
||||||
|
&self,
|
||||||
|
ReadResourceRequestParam { uri }: ReadResourceRequestParam,
|
||||||
|
_: RequestContext<RoleServer>,
|
||||||
|
) -> Result<ReadResourceResult, ErrorData> {
|
||||||
|
if let Some(fossil_id) = uri.strip_prefix("fossil://") {
|
||||||
|
let fossils = self.state.fossils.lock().unwrap();
|
||||||
|
if let Some(fossil) = fossils.get(fossil_id) {
|
||||||
|
if let Some(content) = fossil.latest() {
|
||||||
|
Ok(ReadResourceResult {
|
||||||
|
contents: vec![ResourceContents::text(content, uri)],
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Err(ErrorData::resource_not_found(
|
||||||
|
"fossil_empty",
|
||||||
|
Some(json!({
|
||||||
|
"uri": uri,
|
||||||
|
"message": "Fossil exists but has no content"
|
||||||
|
})),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(ErrorData::resource_not_found(
|
||||||
|
"fossil_not_found",
|
||||||
|
Some(json!({
|
||||||
|
"uri": uri,
|
||||||
|
"message": format!("Fossil '{}' not found", fossil_id)
|
||||||
|
})),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(ErrorData::resource_not_found(
|
||||||
|
"invalid_uri",
|
||||||
|
Some(json!({
|
||||||
|
"uri": uri,
|
||||||
|
"message": "URI must start with 'fossil://'"
|
||||||
|
})),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_info(&self) -> ServerInfo {
|
fn get_info(&self) -> ServerInfo {
|
||||||
ServerInfo {
|
ServerInfo {
|
||||||
instructions: Some(
|
instructions: Some(
|
||||||
@@ -197,7 +265,7 @@ impl ServerHandler for FossilEditor {
|
|||||||
- Use `revert` to undo recent edits on a fossil. Specify `steps` to undo multiple (defaults to 1). This rolls back to previous versions without losing history. Preview with `get_version` first if needed.
|
- Use `revert` to undo recent edits on a fossil. Specify `steps` to undo multiple (defaults to 1). This rolls back to previous versions without losing history. Preview with `get_version` first if needed.
|
||||||
- Use `delete_fossil` to clean up and remove unused fossils by ID."#.into(),
|
- Use `delete_fossil` to clean up and remove unused fossils by ID."#.into(),
|
||||||
),
|
),
|
||||||
capabilities: ServerCapabilities::builder().enable_tools().build(),
|
capabilities: ServerCapabilities::builder().enable_tools().enable_resources().build(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user