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 fn db_conn(&self) -> crate::function::DbConn<'_> {
69 crate::function::DbConn::Pool(self.db_pool.clone())
70 }
71
72 pub async fn conn(&self) -> sqlx::Result<crate::function::ForgeConn<'static>> {
74 Ok(crate::function::ForgeConn::Pool(
75 self.db_pool.acquire().await?,
76 ))
77 }
78
79 pub fn user_id(&self) -> Result<Uuid> {
81 self.auth.require_user_id()
82 }
83
84 pub fn tenant_id(&self) -> Option<Uuid> {
86 self.auth.tenant_id()
87 }
88
89 pub async fn dispatch_job<T: serde::Serialize>(&self, job_type: &str, args: T) -> Result<Uuid> {
91 let dispatcher = self.job_dispatch.as_ref().ok_or_else(|| {
92 crate::error::ForgeError::Internal("Job dispatch not available".to_string())
93 })?;
94
95 let args_json = serde_json::to_value(args)?;
96 dispatcher
97 .dispatch_by_name(job_type, args_json, self.auth.principal_id())
98 .await
99 }
100
101 pub async fn start_workflow<T: serde::Serialize>(
103 &self,
104 workflow_name: &str,
105 input: T,
106 ) -> Result<Uuid> {
107 let dispatcher = self.workflow_dispatch.as_ref().ok_or_else(|| {
108 crate::error::ForgeError::Internal("Workflow dispatch not available".to_string())
109 })?;
110
111 let input_json = serde_json::to_value(input)?;
112 dispatcher
113 .start_by_name(workflow_name, input_json, self.auth.principal_id())
114 .await
115 }
116}
117
118impl EnvAccess for McpToolContext {
119 fn env_provider(&self) -> &dyn EnvProvider {
120 self.env_provider.as_ref()
121 }
122}