44//! notifications to AI agents, bots, and scripts. The agent binary is a
55//! first-class Willow peer with its own Ed25519 identity.
66
7- use clap:: Parser ;
7+ use clap:: { Parser , ValueEnum } ;
8+ use willow_agent:: scopes:: TokenScope ;
89use willow_agent:: { auth, server} ;
910use willow_client:: { ClientConfig , ClientHandle } ;
1011use willow_identity:: Identity ;
@@ -57,6 +58,10 @@ struct Cli {
5758 #[ arg( long, default_value = "info" ) ]
5859 log_level : String ,
5960
61+ /// Token scope for HTTP transport (least-privilege default).
62+ #[ arg( long, value_enum, default_value_t = ScopeArg :: Messaging ) ]
63+ scope : ScopeArg ,
64+
6065 /// Generate a new identity and exit.
6166 #[ arg( long) ]
6267 generate_identity : bool ,
@@ -66,6 +71,27 @@ struct Cli {
6671 print_peer_id : bool ,
6772}
6873
74+ /// CLI-friendly enum for `--scope`. Maps to `TokenScope`.
75+ #[ derive( Copy , Clone , Debug , ValueEnum ) ]
76+ enum ScopeArg {
77+ /// Messaging tools only (least-privilege default).
78+ Messaging ,
79+ /// Read-only: no tools, all resources.
80+ Read ,
81+ /// Full access: all tools, all resources.
82+ Full ,
83+ }
84+
85+ impl From < ScopeArg > for TokenScope {
86+ fn from ( s : ScopeArg ) -> Self {
87+ match s {
88+ ScopeArg :: Messaging => TokenScope :: Messaging ,
89+ ScopeArg :: Read => TokenScope :: ReadOnly ,
90+ ScopeArg :: Full => TokenScope :: Full ,
91+ }
92+ }
93+ }
94+
6995#[ tokio:: main]
7096async fn main ( ) -> anyhow:: Result < ( ) > {
7197 let cli = Cli :: parse ( ) ;
@@ -148,7 +174,7 @@ async fn main() -> anyhow::Result<()> {
148174 }
149175 "http" => {
150176 tracing:: info!( "starting MCP HTTP server on {}" , cli. bind) ;
151- server:: serve_http ( client, & cli. bind , Default :: default ( ) , token) . await ?;
177+ server:: serve_http ( client, & cli. bind , cli . scope . into ( ) , token) . await ?;
152178 }
153179 other => {
154180 anyhow:: bail!( "unsupported transport: {other} (supported: 'stdio', 'http')" ) ;
0 commit comments