clean(mcp): extract constants, use CARGO_PKG_VERSION, fix unreachable

- extract DEFAULT_DATABASE_URL, DEFAULT_SEARCH_LIMIT, SERVER_NAME
- use env!("CARGO_PKG_VERSION") instead of hardcoded "0.1.0"
- content_type_to_str returns &'static str instead of allocating String
- cfg guard on unreachable pattern in wire_repositories
This commit is contained in:
2026-07-12 04:37:27 +02:00
parent ff5f299a84
commit f6b2481758
3 changed files with 17 additions and 10 deletions

View File

@@ -1,8 +1,8 @@
use std::sync::Arc; use std::sync::Arc;
use domain::ports::{IMediaProvider, IProviderRegistry, ProviderCapabilities, StreamingProtocol}; use domain::ports::{IMediaProvider, IProviderRegistry, ProviderCapabilities, StreamingProtocol};
use domain::{DomainError, DomainResult, MediaFilter, MediaItemId, MediaItem, ScheduleEngineService};
use domain::ports::StreamQuality; use domain::ports::StreamQuality;
use domain::{DomainError, DomainResult, MediaFilter, MediaItem, MediaItemId, ScheduleEngineService};
use infra_wiring::DbPool; use infra_wiring::DbPool;
use tracing::info; use tracing::info;
use uuid::Uuid; use uuid::Uuid;
@@ -13,6 +13,8 @@ mod tools;
use server::KTvMcpServer; use server::KTvMcpServer;
const DEFAULT_DATABASE_URL: &str = "sqlite:data.db?mode=rwc";
#[tokio::main] #[tokio::main]
async fn main() -> anyhow::Result<()> { async fn main() -> anyhow::Result<()> {
let _ = dotenvy::dotenv(); let _ = dotenvy::dotenv();
@@ -26,7 +28,7 @@ async fn main() -> anyhow::Result<()> {
.init(); .init();
let database_url = std::env::var("DATABASE_URL") let database_url = std::env::var("DATABASE_URL")
.unwrap_or_else(|_| "sqlite:data.db?mode=rwc".to_string()); .unwrap_or_else(|_| DEFAULT_DATABASE_URL.to_string());
let owner_id: Uuid = std::env::var("MCP_USER_ID") let owner_id: Uuid = std::env::var("MCP_USER_ID")
.map_err(|_| anyhow::anyhow!("MCP_USER_ID env var is required (UUID of the user)"))? .map_err(|_| anyhow::anyhow!("MCP_USER_ID env var is required (UUID of the user)"))?
@@ -127,6 +129,7 @@ fn wire_repositories(pool: &DbPool) -> anyhow::Result<WireOutput> {
library_query: w.library_query, library_query: w.library_query,
}) })
} }
#[cfg(not(any(feature = "sqlite", feature = "postgres")))]
_ => anyhow::bail!("database backend not compiled into this binary"), _ => anyhow::bail!("database backend not compiled into this binary"),
} }
} }

View File

@@ -16,6 +16,8 @@ use uuid::Uuid;
use crate::tools::{channels, library, schedule}; use crate::tools::{channels, library, schedule};
const SERVER_NAME: &str = "k-tv-mcp";
#[derive(Clone)] #[derive(Clone)]
pub struct KTvMcpServer { pub struct KTvMcpServer {
pub channel_cmd_deps: Arc<ChannelCommandDeps>, pub channel_cmd_deps: Arc<ChannelCommandDeps>,
@@ -191,8 +193,8 @@ impl ServerHandler for KTvMcpServer {
protocol_version: ProtocolVersion::V_2024_11_05, protocol_version: ProtocolVersion::V_2024_11_05,
capabilities: ServerCapabilities::builder().enable_tools().build(), capabilities: ServerCapabilities::builder().enable_tools().build(),
server_info: Implementation { server_info: Implementation {
name: "k-tv-mcp".into(), name: SERVER_NAME.into(),
version: "0.1.0".into(), version: env!("CARGO_PKG_VERSION").into(),
}, },
instructions: Some( instructions: Some(
"K-TV MCP server. Create channels, define programming blocks, generate schedules. \ "K-TV MCP server. Create channels, define programming blocks, generate schedules. \

View File

@@ -7,6 +7,8 @@ use serde::Serialize;
use crate::error::{domain_err, ok_json}; use crate::error::{domain_err, ok_json};
const DEFAULT_SEARCH_LIMIT: u32 = 50;
#[derive(Serialize)] #[derive(Serialize)]
struct CollectionDto { struct CollectionDto {
id: String, id: String,
@@ -38,11 +40,11 @@ struct SearchResult {
total: u32, total: u32,
} }
fn to_content_type_string(ct: &domain::ContentType) -> String { fn content_type_to_str(ct: &domain::ContentType) -> &'static str {
match ct { match ct {
domain::ContentType::Movie => "movie".to_string(), domain::ContentType::Movie => "movie",
domain::ContentType::Episode => "episode".to_string(), domain::ContentType::Episode => "episode",
domain::ContentType::Short => "short".to_string(), domain::ContentType::Short => "short",
} }
} }
@@ -93,7 +95,7 @@ pub async fn search_media(
season_number: None, season_number: None,
decade: None, decade: None,
offset: 0, offset: 0,
limit: 50, limit: DEFAULT_SEARCH_LIMIT,
}; };
match application::library::search::execute(deps, query).await { match application::library::search::execute(deps, query).await {
Ok((items, total)) => { Ok((items, total)) => {
@@ -104,7 +106,7 @@ pub async fn search_media(
provider_id: i.provider_id().to_string(), provider_id: i.provider_id().to_string(),
external_id: i.external_id().to_string(), external_id: i.external_id().to_string(),
title: i.title().to_string(), title: i.title().to_string(),
content_type: to_content_type_string(i.content_type()), content_type: content_type_to_str(i.content_type()).to_string(),
duration_secs: i.duration_secs(), duration_secs: i.duration_secs(),
series_name: i.series_name().map(|s| s.to_string()), series_name: i.series_name().map(|s| s.to_string()),
season_number: i.season_number(), season_number: i.season_number(),