Code Execution Server¶
agora_workbench.code_execution.server
¶
Base Code Execution Server for MCP.
This module provides a base class for creating MCP servers that execute Python code in isolated environments with domain-specific packages.
CodeExecutionServer(server_config, tool_registry=None, session_manager=None, auth_config=None, working_dir=None, tool_search_backend=None, publishers=None, skills=None, states=None)
¶
Bases: BaseMCPServer
Base class for MCP code execution servers.
Subclass this to create execution environments with specific Python interpreters and package sets. Each server exposes an MCP tool for executing code in its isolated environment.
Security features: - Timeout enforcement - Separate process execution - Optional working directory isolation - Configurable resource limits (override in subclass) - Pluggable authentication (Entra ID, no-op/dev, or custom) - Managed identity for downstream Azure resource access
Middleware Architecture: The server uses two layers of middleware at different levels of the stack:
Starlette Middleware (ASGI level, outermost layer): Applied to the entire HTTP application before FastMCP processing. Added in _create_middleware() and registered via app.add_middleware() during serve().
- MCPSessionMiddleware (outermost):
- Extracts Mcp-Session-Id header from requests to /mcp endpoint
- Stores session ID in ASGI scope for downstream access
-
Enables session correlation across tool calls
-
AuthMiddleware (inner):
- Validates Bearer tokens on /mcp and /object-transfer/* endpoints using Entra ID
- Extracts user identity (oid/sub) and token claims
- Stores authenticated context (token, claims, user_identity)
- Bypasses /health and /.well-known/* endpoints (no auth required)
- Returns RFC 9728 WWW-Authenticate header on 401 for OAuth discovery
FastMCP Middleware (tool call level, innermost layer): Applied to MCP tool calls after HTTP auth but before Pydantic validation. Added directly to the FastMCP instance:
- AssetResolutionMiddleware (added during init):
- Resolves tagged asset references like
id to local cache paths - Runs BEFORE Pydantic validation so Path parameters receive proper values
Full execution flow: HTTP Request → MCPSessionMiddleware → AuthMiddleware → FastMCP routing → AssetResolutionMiddleware → Pydantic validation → Tool callback
Constraints: - Asset resolution happens first, so asset parameters are properly typed
Asset/Handle Injection Patterns: The server supports two different patterns for injecting assets and handles:
- Auto-Extraction (execute_code_tool):
- Handle IDs (h_xxxxxxxxxxxx) and asset tags (
id ) embedded as string literals in code are automatically detected via AST analysis. - Matched literals are replaced with synthetic variables that hold the resolved object (for handles) or a Path to the cached file (for assets).
-
Validation: References must appear as complete string literals in assignments, function arguments, return statements, or container literals (list/dict/tuple/set). Unresolvable references fail fast.
-
Middleware-Based Injection (domain tools):
- Assets embedded in natural parameter values: grid_file="
xyz " - Middleware extracts, validates, and resolves before Pydantic validation
- Use case: LLM-driven tool calls where assets are encoded in argument values
- Validation: AssetResolutionMiddleware
Initialize the code execution server.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
server_config
|
ServerConfig
|
Server configuration (environment, assets, execution policy, features) |
required |
tool_registry
|
Optional[ToolRegistry]
|
Optional ToolRegistry containing domain-specific tools |
None
|
session_manager
|
Optional[SessionManager]
|
Optional SessionManager for stateful tool support (auto-created with defaults if None) |
None
|
auth_config
|
Optional[AuthConfig]
|
Authentication configuration providing token validation, identity extraction, and credential provisioning. |
None
|
working_dir
|
Optional[Path]
|
Working directory for code execution (None = temp dir per execution) |
None
|
tool_search_backend
|
Optional[ToolSearchBackend]
|
Optional pre-configured ToolSearchBackend instance. If provided, this backend is used instead of creating one from config. Enables custom search backends (e.g. vector DB, Elasticsearch) without modifying the built-in factory. |
None
|
publishers
|
Optional[list[AssetPublisher]]
|
Optional list of :class: |
None
|
skills
|
Optional[list[Skill]]
|
Optional list of :class: |
None
|
states
|
Optional[list[State]]
|
Optional list of :class: |
None
|
Source code in src/agora_workbench/code_execution/server.py
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | |
warm()
async
¶
Pre-initialize the execution environment without serving requests.
Call this during Docker builds or process startup to avoid cold-start latency. It prepares the Python environment, provisions assets according to the ServerConfig (e.g. when auto_provision is enabled), and registers the execution kernel.
Source code in src/agora_workbench/code_execution/server.py
main(*, default_host='0.0.0.0', default_port=8000)
¶
CLI entrypoint that handles --warm, --host, and --port.
Call this from your server's if __name__ == "__main__" block to get
standard flag handling without manual sys.argv parsing::
server = MyDomainServer(...)
server.main()
Flags
--warm Pre-initialize the environment and exit (no HTTP server). --host HOST Bind address (default: default_host, or HOST env var). --port PORT Bind port (default: default_port, or PORT env var).
Source code in src/agora_workbench/code_execution/server.py
get_tool_name()
¶
public_url()
¶
Best-effort base URL for outbound references (e.g. download links).
Falls back to http://localhost:<port> when called before
:meth:run_http has stashed the bind host/port. Callers that need
the real externally-visible URL (containerized deployments behind a
proxy / Ingress) should set SERVER_PUBLIC_URL instead — that env
var takes precedence wherever this method is consulted.
Source code in src/agora_workbench/code_execution/server.py
preprocess_code(code)
¶
Preprocess code before execution.
Override to add imports, setup code, or modify the input.
validate_code(code)
¶
Validate user-provided code before execution.
This is a thin instance-method wrapper around the default implementation
in execution_defaults.validate_code, which expects self as its first
argument.
Override to adjust behavior.
Source code in src/agora_workbench/code_execution/server.py
postprocess_result(result)
¶
Postprocess execution result.
Override to filter output, add metadata, or modify the result.
get_python_executable()
async
¶
Return the path to the Python interpreter for this environment.
This will automatically build the environment if needed and build_environment=True.