Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@mpuhacz
Copy link
Contributor

@mpuhacz mpuhacz commented Oct 3, 2025

Description

The MCP stdio_client supports an errlog parameter to redirect subprocess stderr to a specific file handle, but StdioTransport didn't expose this capability. This PR provides that missing parameter across all STDIO transport variants.

The errlog parameter is now available on StdioTransport, PythonStdioTransport, NodeStdioTransport, and FastMCPStdioTransport.

Contributors Checklist

  • My change closes Expose errlog to Stdio Transport #1990
  • I have followed the repository's development workflow
  • I have tested my changes manually and by adding relevant tests
  • I have performed all required documentation updates

Review Checklist

  • I have self-reviewed my changes
  • My Pull Request is ready for review

@strawgate
Copy link
Collaborator

one of the problems i had when i tried to do this in the past is that if you pass anything apart from a file path you get deadlocks, so you cant actually pass lots of things that would normally be just fine to pass into something that takes a TextIO

@mpuhacz
Copy link
Contributor Author

mpuhacz commented Oct 3, 2025

@strawgate are you able to replicate the issues you had previously using this PR?

@strawgate
Copy link
Collaborator

I had tried this exact same thing back during this #978 (comment)

I don't think it's a huge deal but I think we should document it so that it's clear that this only supports a file path

@strawgate
Copy link
Collaborator

Also probably worth noting that the moment you do this you will no longer see server errors in the console

@mpuhacz
Copy link
Contributor Author

mpuhacz commented Oct 3, 2025

@strawgate I noticed you were using subprocess.PIPE, which is ~65KB, and i believe this might have been causing the deadlock when handling larger err logs.

@strawgate
Copy link
Collaborator

strawgate commented Oct 3, 2025

@strawgate I noticed you were using subprocess.PIPE, which is ~65KB, and i believe this might have been causing the deadlock when handling larger err logs.

The one in that link works just fine,

I had attempted to use the textio parameter but couldn't get it not to deadlock with non file destinations

Something like modelcontextprotocol/python-sdk#645

@mpuhacz
Copy link
Contributor Author

mpuhacz commented Oct 3, 2025

@strawgate docstring updated - let me know your thoughts.

Also, it would be great if you could share the code which would allow replicating the issue.

@strawgate
Copy link
Collaborator

@strawgate docstring updated - let me know your thoughts.

Also, it would be great if you could share the code which would allow replicating the issue.

I can try -- if we don't add a caveat here then we need a test for something other than a file destination anyway as we're now exposing this as part of our API

@strawgate strawgate requested a review from Copilot October 5, 2025 02:13
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds the errlog parameter to all STDIO transport classes to allow redirecting subprocess stderr to a specific file handle, addressing issue #1990. The parameter was already supported by the underlying MCP stdio_client but wasn't exposed through the transport layer.

  • Added errlog: TextIO | None parameter to all STDIO transport constructors
  • Updated the internal connection task to pass the errlog parameter to the underlying stdio_client
  • Added comprehensive tests to verify errlog functionality works correctly

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/fastmcp/client/transports.py Added errlog parameter to StdioTransport, PythonStdioTransport, and NodeStdioTransport classes with proper documentation and parameter passing
tests/client/test_stdio.py Added test class TestErrlog with fixtures and test methods to verify errlog parameter acceptance and stderr capture functionality

Comment on lines 315 to 318
# Need to wait a bit for stderr to flush
await asyncio.sleep(0.1)

content = errlog_file.read_text()
Copy link

Copilot AI Oct 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a fixed sleep for synchronization is unreliable and can cause flaky tests. Consider using a more deterministic approach like polling the file size or using proper synchronization mechanisms.

Suggested change
# Need to wait a bit for stderr to flush
await asyncio.sleep(0.1)
content = errlog_file.read_text()
# Poll for the expected content to appear in the errlog file
expected = "Test error message"
timeout = 1.0 # seconds
interval = 0.01 # seconds
elapsed = 0.0
while elapsed < timeout:
content = errlog_file.read_text()
if expected in content:
break
await asyncio.sleep(interval)
elapsed += interval
else:
content = errlog_file.read_text()

Copilot uses AI. Check for mistakes.
@mpuhacz mpuhacz requested a review from strawgate October 7, 2025 07:07
@strawgate
Copy link
Collaborator

Were you able to get anything other than a file working with textio? I would love love love to find a way to forward MCP logs to the logger

@mpuhacz
Copy link
Contributor Author

mpuhacz commented Oct 7, 2025

@strawgate Unfortunately no, I've only tried it with files so far. Forwarding MCP logs to the logger would be awesome though - I agree that would be really useful.

Maybe we could explore logger integration in a follow-up PR? Could model it after the python-sdk approach (https://github.com/modelcontextprotocol/python-sdk/blob/main/src/mcp/client/stdio/__init__.py#L138-L167).

For this PR, any changes you'd like before merging?

@strawgate
Copy link
Collaborator

The problem I have in general is that we're exposing textio in our API while we think that it doesn't actually work for the things you might expect it to work for.

E.x. In our API maybe we should just expose a log file argument

@mpuhacz
Copy link
Contributor Author

mpuhacz commented Oct 7, 2025

@strawgate just to confirm - are you suggesting renaming errlog to something like output_stderror_file for clarity around what’s being exposed? I'm okay with this, let me know if I should update it.

@strawgate
Copy link
Collaborator

Or just log_file?

@mpuhacz
Copy link
Contributor Author

mpuhacz commented Oct 7, 2025

@strawgate updated -- let me know your thoughts!

@mpuhacz
Copy link
Contributor Author

mpuhacz commented Oct 8, 2025

@strawgate just a gentle bump - do you think the current PR version can be released as is?

@strawgate
Copy link
Collaborator

My thought on log_file was that we would take a Path and make a TextIO for it. If in the future we want to expose a logger or something similar, we can add a parameter for that.

Does that make sense to you? Happy to discuss.

If that's good with you, I'm good with getting this in for 2.13

@mpuhacz
Copy link
Contributor Author

mpuhacz commented Oct 9, 2025

@strawgate sure, that makes sense - I updated the implementation accordingly, with the minor adjustment to keep it Path | TextIO | None. The Path will be automatically opened in append mode and properly closed, while TextIO is used directly for users who need custom file handling. Let me know your thoughts!

@strawgate
Copy link
Collaborator

Can you give an example of what custom file handling we're supporting with this?

The custom file handling is what I'm nervous about as the issues we are going to get are deadlocks when using textio which go away if we only support a file path

@mpuhacz
Copy link
Contributor Author

mpuhacz commented Oct 9, 2025

@strawgate One example could be using SpooledTemporaryFile where data is spooled in memory.

log_file=tempfile.SpooledTemporaryFile(
    mode="w+", max_size=1024 * 1024, encoding="utf-8"
)

Anything which follow similar protocol to SpooledTemporaryFile can be essentially used there.

@mpuhacz
Copy link
Contributor Author

mpuhacz commented Oct 10, 2025

@strawgate gentle bump 😊 - let me know your thoughts!

@strawgate strawgate requested a review from jlowin October 10, 2025 18:12
@jlowin
Copy link
Owner

jlowin commented Oct 11, 2025

Thanks @mpuhacz and @strawgate !

@jlowin jlowin merged commit 05a73e1 into jlowin:main Oct 11, 2025
5 checks passed
@jlowin jlowin added enhancement Improvement to existing functionality. For issues and smaller PR improvements. client Related to the FastMCP client SDK or client-side functionality. labels Oct 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

client Related to the FastMCP client SDK or client-side functionality. enhancement Improvement to existing functionality. For issues and smaller PR improvements.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose errlog to Stdio Transport

3 participants