Overview
mcp-agent gives you two complementary ways to expose agent behaviour:- Decorator-based tools – mark a plain Python function with
@app.toolor@app.async_toolto expose it as an MCP tool. This is the quickest way to add synchronous or long-running behaviour to your app. - Workflow classes – build stateful, structured flows by subclassing
Workflow[T]. Workflows give you fine-grained control over orchestration, retries, and Temporal integration.
examples/workflows (parallel, router, orchestrator, etc.) are built using these same primitives—they are patterns, not the Workflow base class itself.
The rest of this page walks through the decorators first (because most apps start there) and then dives into the Workflow class.
Decorator-based tools
@app.tool – synchronous tools
Use @app.tool when the work can complete within a single MCP call. The return value is sent straight back to the client—no polling required.
- Works great for quick operations or simple glue code.
- You can accept an optional
app_ctx: Contextparameter to access logging, server registry, etc. - The tool result is serialised and returned to the caller immediately.
@app.async_tool – long-running tools
Agents often need to run tasks that take longer than an MCP request allows (multi-step research, human-in-the-loop flows, durable Temporal runs). Decorate those entry points with @app.async_tool:
@app.async_tool starts a workflow in the background and returns identifiers that clients can poll via the built-in workflows-get_status tool. This pattern keeps your agent responsive even when the underlying work takes minutes or requires human decisions.
Tip: Agent servers rely heavily on these decorators—see Agent Servers for end-to-end examples.
The Workflow Class
TheWorkflow[T] base class lets you model multi-step or stateful logic while still exposing an MCP tool. Workflows are most useful when you need retries, shared state, or tight integration with the execution engine (asyncio or Temporal).
Basic workflow definition
@app.workflow and the entry point with @app.workflow_run. Whatever you return from the method becomes the MCP tool result.
Useful workflow features
- Access
self.contextfor logging, MCP connections, and configuration. - Store reusable helpers or caches on
selfinside__init__. - Raise exceptions to trigger retries (Temporal) or propagate errors to the caller.
- Combine with
@app.workflow_task/@app.workflow_signalwhen you need durable activities or signal handlers.
Workflow patterns (examples/workflows)
The repository has anexamples/workflows directory that demonstrates higher-level agent patterns: router, parallel fan-out, orchestrator, evaluator/optimizer, and more. These samples compose agents and AugmentedLLMs with helpers from mcp_agent.workflows.factory. They do not correspond one-to-one with the Workflow base class above—they are ready-made orchestration patterns you can adopt or customise.
Use the patterns when you want opinionated orchestration, and drop down to the Workflow class (or @app.async_tool) when you need bespoke control flow.
Advanced Workflow Patterns
Workflow Composition
Compose complex workflows from simpler ones:Workflow with Agents
Integrate agents into workflows:Parallel Workflow Execution
Execute multiple workflows in parallel:Stateful Workflows
Maintain state across workflow executions:Temporal Integration
Workflows seamlessly support Temporal for durable execution:MCP Server Integration
Exposing Workflows as MCP Tools
Workflows and tools are automatically exposed when creating an MCP server:Tool Discovery
MCP clients can discover available tools:Best Practices
Choose the Right Abstraction
Choose the Right Abstraction
- Use
@app.toolfor simple, stateless operations - Use
@app.async_toolfor long-running operations that need polling - Use
Workflowclass for complex, multi-step processes
Type Hints and Documentation
Type Hints and Documentation
Always provide type hints and docstrings:
Error Handling
Error Handling
Handle errors gracefully:
Resource Management
Resource Management
Use context managers for resources:
Logging and Observability
Logging and Observability
Use structured logging:
