Skip to main content

voidcrawl_mcp/tools/
profile_registry.rs

1//! MCP tools for VoidCrawl-managed Chromium profile metadata and pools.
2
3#![allow(clippy::unused_async)]
4
5use rmcp::ErrorData;
6use schemars::JsonSchema;
7use serde::{Deserialize, Serialize};
8use void_crawl_core::{
9    ManagedProfileDescription, ProfilePool, ProfileRegistry, ResolvedProfilePool,
10};
11
12use crate::{errors::map_err, server::VoidCrawlServer};
13
14#[derive(Debug, Deserialize, JsonSchema, Default)]
15pub struct ProfileListArgs {}
16
17#[derive(Debug, Serialize, JsonSchema)]
18pub struct ProfileListResult {
19    pub profiles: Vec<ManagedProfileDescription>,
20}
21
22#[derive(Debug, Deserialize, JsonSchema, Default)]
23pub struct ProfileCreateArgs {
24    pub id:          String,
25    #[serde(default)]
26    pub description: Option<String>,
27    #[serde(default)]
28    pub labels:      Vec<String>,
29}
30
31#[derive(Debug, Deserialize, JsonSchema, Default)]
32pub struct ProfileDescribeArgs {
33    pub id: String,
34}
35
36#[derive(Debug, Deserialize, JsonSchema, Default)]
37pub struct ProfileCloneArgs {
38    pub source_id_or_path: String,
39    pub id:                String,
40    #[serde(default)]
41    pub description:       Option<String>,
42    #[serde(default)]
43    pub labels:            Vec<String>,
44}
45
46#[derive(Debug, Deserialize, JsonSchema, Default)]
47pub struct ProfileDeleteArgs {
48    pub id: String,
49}
50
51#[derive(Debug, Serialize, JsonSchema)]
52pub struct ProfileDeleteResult {
53    pub deleted: bool,
54}
55
56#[derive(Debug, Deserialize, JsonSchema, Default)]
57pub struct ProfilePoolListArgs {}
58
59#[derive(Debug, Serialize, JsonSchema)]
60pub struct ProfilePoolListResult {
61    pub pools: Vec<ProfilePool>,
62}
63
64#[derive(Debug, Deserialize, JsonSchema, Default)]
65pub struct ProfilePoolCreateArgs {
66    pub name:        String,
67    pub profile_ids: Vec<String>,
68    #[serde(default = "default_max_active")]
69    pub max_active:  usize,
70}
71
72#[derive(Debug, Deserialize, JsonSchema, Default)]
73pub struct ProfilePoolDescribeArgs {
74    pub name: String,
75}
76
77fn default_max_active() -> usize {
78    3
79}
80
81pub async fn list(_: &VoidCrawlServer, _: ProfileListArgs) -> Result<ProfileListResult, ErrorData> {
82    ProfileRegistry::default()
83        .list_profiles()
84        .map(|profiles| ProfileListResult { profiles })
85        .map_err(map_err)
86}
87
88pub async fn create(
89    _: &VoidCrawlServer,
90    args: ProfileCreateArgs,
91) -> Result<ManagedProfileDescription, ErrorData> {
92    ProfileRegistry::default()
93        .create_profile(&args.id, args.description, args.labels)
94        .map_err(map_err)
95}
96
97pub async fn describe(
98    _: &VoidCrawlServer,
99    args: ProfileDescribeArgs,
100) -> Result<ManagedProfileDescription, ErrorData> {
101    ProfileRegistry::default().describe_profile(&args.id).map_err(map_err)
102}
103
104pub async fn clone(
105    _: &VoidCrawlServer,
106    args: ProfileCloneArgs,
107) -> Result<ManagedProfileDescription, ErrorData> {
108    ProfileRegistry::default()
109        .clone_profile(&args.source_id_or_path, &args.id, args.description, args.labels)
110        .map_err(map_err)
111}
112
113pub async fn delete(
114    _: &VoidCrawlServer,
115    args: ProfileDeleteArgs,
116) -> Result<ProfileDeleteResult, ErrorData> {
117    ProfileRegistry::default()
118        .delete_profile(&args.id)
119        .map(|deleted| ProfileDeleteResult { deleted })
120        .map_err(map_err)
121}
122
123pub async fn pool_list(
124    _: &VoidCrawlServer,
125    _: ProfilePoolListArgs,
126) -> Result<ProfilePoolListResult, ErrorData> {
127    ProfileRegistry::default()
128        .list_pools()
129        .map(|pools| ProfilePoolListResult { pools })
130        .map_err(map_err)
131}
132
133pub async fn pool_create(
134    _: &VoidCrawlServer,
135    args: ProfilePoolCreateArgs,
136) -> Result<ProfilePool, ErrorData> {
137    ProfileRegistry::default()
138        .create_pool(&args.name, args.profile_ids, args.max_active)
139        .map_err(map_err)
140}
141
142pub async fn pool_describe(
143    _: &VoidCrawlServer,
144    args: ProfilePoolDescribeArgs,
145) -> Result<ResolvedProfilePool, ErrorData> {
146    ProfileRegistry::default().resolve_pool(&args.name).map_err(map_err)
147}