Skip to content

Commit 606f4e8

Browse files
committed
readme updates
1 parent 58708c0 commit 606f4e8

File tree

2 files changed

+106
-1
lines changed

2 files changed

+106
-1
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "temporalio"
3-
version = "1.17.0"
3+
version = "1.18.0"
44
description = "Temporal.io Python SDK"
55
authors = [{ name = "Temporal Technologies Inc", email = "[email protected]" }]
66
requires-python = ">=3.9"

temporalio/contrib/openai_agents/README.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,111 @@ Of course, code running in the workflow can invoke a Temporal activity at any ti
351351
Tools that run in the workflow can also update OpenAI Agents context, which is read-only for tools run as Temporal activities.
352352

353353

354+
## MCP Support
355+
356+
This integration provides support for Model Context Protocol (MCP) servers through two wrapper approaches designed to handle different implications of failures.
357+
358+
While Temporal provides durable execution for your workflows, this durability does not extend to MCP servers, which operate independently of the workflow and must provide their own durability. The integration handles this by offering stateless and stateful wrappers that you can choose based on your MCP server's design.
359+
360+
### Stateless vs Stateful MCP Servers
361+
362+
You need to understand your MCP server's behavior to choose the correct wrapper:
363+
364+
**Stateless MCP servers** treat each operation independently. For example, a weather server with a `get_weather(location)` tool is stateless because each call is self-contained and includes all necessary information. These servers can be safely restarted or reconnected to without changing their behavior.
365+
366+
**Stateful MCP servers** maintain session state between calls. For example, a weather server that requires calling `set_location(location)` followed by `get_weather()` is stateful because it remembers the configured location and uses it for subsequent calls. If the session or the server is restarted, state crucial for operation is lost. Temporal identifies such failures and raises an `ApplicationError` to signal the need for application-level failure handling.
367+
368+
### Usage Example (Stateless MCP)
369+
370+
The code below gives an example of using a stateless MCP server.
371+
372+
#### Worker Configuration
373+
374+
```python
375+
import asyncio
376+
from datetime import timedelta
377+
from agents.mcp import MCPServerStdio
378+
from temporalio.client import Client
379+
from temporalio.contrib.openai_agents import (
380+
ModelActivityParameters,
381+
OpenAIAgentsPlugin,
382+
StatelessMCPServerProvider,
383+
)
384+
from temporalio.worker import Worker
385+
386+
async def main():
387+
# Create the MCP server provider
388+
filesystem_server = StatelessMCPServerProvider(
389+
lambda: MCPServerStdio(
390+
name="FileSystemServer",
391+
params={
392+
"command": "npx",
393+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/files"],
394+
},
395+
)
396+
)
397+
398+
# Register the MCP server with the OpenAI Agents plugin
399+
client = await Client.connect(
400+
"localhost:7233",
401+
plugins=[
402+
OpenAIAgentsPlugin(
403+
model_params=ModelActivityParameters(
404+
start_to_close_timeout=timedelta(seconds=60)
405+
),
406+
mcp_servers=[filesystem_server],
407+
),
408+
],
409+
)
410+
411+
worker = Worker(
412+
client,
413+
task_queue="my-task-queue",
414+
workflows=[FileSystemWorkflow],
415+
)
416+
await worker.run()
417+
418+
if __name__ == "__main__":
419+
asyncio.run(main())
420+
```
421+
422+
#### Workflow Implementation
423+
424+
```python
425+
from temporalio import workflow
426+
from temporalio.contrib import openai_agents
427+
from agents import Agent, Runner
428+
429+
@workflow.defn
430+
class FileSystemWorkflow:
431+
@workflow.run
432+
async def run(self, query: str) -> str:
433+
# Reference the MCP server by name (matches name in worker configuration)
434+
server = openai_agents.workflow.stateless_mcp_server("FileSystemServer")
435+
436+
agent = Agent(
437+
name="File Assistant",
438+
instructions="Use the filesystem tools to read files and answer questions.",
439+
mcp_servers=[server],
440+
)
441+
442+
result = await Runner.run(agent, input=query)
443+
return result.final_output
444+
```
445+
446+
The `StatelessMCPServerProvider` takes a factory function that creates new MCP server instances. The server name used in `stateless_mcp_server()` must match the name configured in the MCP server instance. In this example, the name is `FileSystemServer`.
447+
448+
### Stateful MCP Servers
449+
450+
For implementation details and examples, see the [samples repository](https://github.com/temporalio/samples-python/tree/main/openai_agents/mcp).
451+
452+
When using stateful servers, the dedicated worker maintaining the connection may fail due to network issues or server problems. When this happens, Temporal raises an `ApplicationError` and cannot automatically recover because it cannot restore the lost server state.
453+
To recover from such failures, you need to implement your own application-level retry logic.
454+
455+
### Hosted MCP Tool
456+
457+
For network-accessible MCP servers, you can also use `HostedMCPTool` from the OpenAI Agents SDK, which uses an MCP client hosted by OpenAI.
458+
354459
## Feature Support
355460

356461
This integration is presently subject to certain limitations.

0 commit comments

Comments
 (0)