forge_core/mcp/
context.rs1use std::sync::Arc;
2
3use crate::Result;
4use crate::env::{EnvAccess, EnvProvider, RealEnvProvider};
5use crate::function::{AuthContext, JobDispatch, RequestMetadata, WorkflowDispatch};
6use uuid::Uuid;
7
8pub struct McpToolContext {
10 pub auth: AuthContext,
12 pub request: RequestMetadata,
14 db_pool: sqlx::PgPool,
15 job_dispatch: Option<Arc<dyn JobDispatch>>,
16 workflow_dispatch: Option<Arc<dyn WorkflowDispatch>>,
17 env_provider: Arc<dyn EnvProvider>,
18}
19
20impl McpToolContext {
21 pub fn new(db_pool: sqlx::PgPool, auth: AuthContext, request: RequestMetadata) -> Self {
23 Self::with_dispatch(db_pool, auth, request, None, None)
24 }
25
26 pub fn with_dispatch(
28 db_pool: sqlx::PgPool,
29 auth: AuthContext,
30 request: RequestMetadata,
31 job_dispatch: Option<Arc<dyn JobDispatch>>,
32 workflow_dispatch: Option<Arc<dyn WorkflowDispatch>>,
33 ) -> Self {
34 Self::with_env(
35 db_pool,
36 auth,
37 request,
38 job_dispatch,
39 workflow_dispatch,
40 Arc::new(RealEnvProvider::new()),
41 )
42 }
43
44 pub fn with_env(
46 db_pool: sqlx::PgPool,
47 auth: AuthContext,
48 request: RequestMetadata,
49 job_dispatch: Option<Arc<dyn JobDispatch>>,
50 workflow_dispatch: Option<Arc<dyn WorkflowDispatch>>,
51 env_provider: Arc<dyn EnvProvider>,
52 ) -> Self {
53 Self {
54 auth,
55 request,
56 db_pool,
57 job_dispatch,
58 workflow_dispatch,
59 env_provider,
60 }
61 }
62
63 pub fn db(&self) -> crate::function::ForgeDb {
64 crate::function::ForgeDb::from_pool(&self.db_pool)
65 }
66
67 pub async fn conn(&self) -> sqlx::Result<crate::function::ForgeConn<'static>> {
69 Ok(crate::function::ForgeConn::Pool(
70 self.db_pool.acquire().await?,
71 ))
72 }
73
74 pub fn require_user_id(&self) -> Result<Uuid> {
75 self.auth.require_user_id()
76 }
77
78 pub fn require_subject(&self) -> Result<&str> {
79 self.auth.require_subject()
80 }
81
82 pub async fn dispatch_job<T: serde::Serialize>(&self, job_type: &str, args: T) -> Result<Uuid> {
84 let dispatcher = self.job_dispatch.as_ref().ok_or_else(|| {
85 crate::error::ForgeError::Internal("Job dispatch not available".to_string())
86 })?;
87
88 let args_json = serde_json::to_value(args)?;
89 dispatcher
90 .dispatch_by_name(job_type, args_json, self.auth.principal_id())
91 .await
92 }
93
94 pub async fn start_workflow<T: serde::Serialize>(
96 &self,
97 workflow_name: &str,
98 input: T,
99 ) -> Result<Uuid> {
100 let dispatcher = self.workflow_dispatch.as_ref().ok_or_else(|| {
101 crate::error::ForgeError::Internal("Workflow dispatch not available".to_string())
102 })?;
103
104 let input_json = serde_json::to_value(input)?;
105 dispatcher
106 .start_by_name(workflow_name, input_json, self.auth.principal_id())
107 .await
108 }
109}
110
111impl EnvAccess for McpToolContext {
112 fn env_provider(&self) -> &dyn EnvProvider {
113 self.env_provider.as_ref()
114 }
115}