Skip to content

Conversation

@Kigstn
Copy link
Contributor

@Kigstn Kigstn commented Oct 25, 2025

This PR adds support for the server to output files.
This is done via Embedded Ressources

image

This allows this server to do cool stuff like generate matplotlib graphs :)

@Kigstn
Copy link
Contributor Author

Kigstn commented Oct 27, 2025

The pyright action is failing - but tbh I did not touch most of the code. Can happily fix the issues, but wanted to ask before :)

@DouweM
Copy link

DouweM commented Oct 27, 2025

@Kigstn Thanks Daniel! Can you pull the verbose changes that cause the linter errors into a separate PR, so we can just focus on output files here?

@DouweM DouweM mentioned this pull request Oct 27, 2025
@DouweM DouweM self-assigned this Oct 27, 2025
@DouweM
Copy link

DouweM commented Oct 27, 2025

Note that we'll want to think about how this interacts with #9

@Kigstn
Copy link
Contributor Author

Kigstn commented Oct 28, 2025

@DouweM of course, done!
One thing I am not 100% happy with is the mounting of folder into pyodide. This may led to problems when multiple calls are made at the same time - however changing this would have been quite complex due to how pyodide is passed currently. Will happily do it if wanted tho :)

Gernally - Happy to adapt things, just give me some feedback :)
Thanks!


I made a 2nd tiny PR for the verbose changes

@agahkarakuzu
Copy link

This would be an excellent addition, thank you so much for working on this feature!

@Kigstn I tried to install this locally (pip install -e .), as I was eager to see file output working (output_files). Yet I get the following error:

    raise RuntimeError(f'`deno run ...` returned a non-zero exit code {p.returncode}: {"".join(stdout)}')
RuntimeError: `deno run ...` returned a non-zero exit code 1: Initialize @types/[email protected] [email protected] [email protected] [email protected] @modelcontextprotocol/[email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected]: Module not found "file:///private/var/folders/qc/6xvjmcj12gj80tn60__2648c0000gn/T/tmpb1b5xz2c/mcp-run-python/src/prepareEnvCode.ts".at file:///private/var/folders/qc/6xvjmcj12gj80tn60__2648c0000gn/T/tmpb1b5xz2c/mcp-run-python/src/runCode.ts:3:35

Am I missing something?

@DouweM
Copy link

DouweM commented Oct 30, 2025

One thing I am not 100% happy with is the mounting of folder into pyodide. This may led to problems when multiple calls are made at the same time - however changing this would have been quite complex due to how pyodide is passed currently. Will happily do it if wanted tho :)

@Kigstn Yeah we'll need to support parallel runs. Could we use a virtual FS that's only mounted into a specific run, instead of a real directory on disk?

I also think this should be an opt-in feature, so we don't change people's existing usage of the mcp server if they just want text output, no files.

@Kigstn
Copy link
Contributor Author

Kigstn commented Nov 3, 2025

This would be an excellent addition, thank you so much for working on this feature!

@Kigstn I tried to install this locally (pip install -e .), as I was eager to see file output working (output_files). Yet I get the following error:

    raise RuntimeError(f'`deno run ...` returned a non-zero exit code {p.returncode}: {"".join(stdout)}')
RuntimeError: `deno run ...` returned a non-zero exit code 1: Initialize @types/[email protected] [email protected] [email protected] [email protected] @modelcontextprotocol/[email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected]: Module not found "file:///private/var/folders/qc/6xvjmcj12gj80tn60__2648c0000gn/T/tmpb1b5xz2c/mcp-run-python/src/prepareEnvCode.ts".at file:///private/var/folders/qc/6xvjmcj12gj80tn60__2648c0000gn/T/tmpb1b5xz2c/mcp-run-python/src/runCode.ts:3:35

Am I missing something?

Yes, you need to run make build first to install some extra things @agahkarakuzu :)

@agahkarakuzu
Copy link

I totally missed that, thank you @Kigstn!

@Kigstn
Copy link
Contributor Author

Kigstn commented Nov 3, 2025

One thing I am not 100% happy with is the mounting of folder into pyodide. This may led to problems when multiple calls are made at the same time - however changing this would have been quite complex due to how pyodide is passed currently. Will happily do it if wanted tho :)

@Kigstn Yeah we'll need to support parallel runs. Could we use a virtual FS that's only mounted into a specific run, instead of a real directory on disk?

I will investigate this. From a quick look a virtual FS will not solve the problem, as you simple can't re-mount the same directory. I am going to look at either:

  • spawning multiple instances of pyodide
  • using semaphores to limit code execution to one
  • using web workers to put code execution into threads

Any preferences @DouweM ? :)

@Kigstn
Copy link
Contributor Author

Kigstn commented Nov 3, 2025

And for opt-in, that makes sense & is very reasonable :)

@DouweM
Copy link

DouweM commented Nov 4, 2025

@Kigstn Ah the issue is that we're using the same Pyodide instance, right. Then in this scenario I think multiple instances makes sense.

@Kigstn
Copy link
Contributor Author

Kigstn commented Nov 7, 2025

Alright @DouweM - I think it's now ready.

As you can see, getting this to run was a bit more complicated & required more changes. So have fun with the review 😅


So what changed:

  • Changed pyodide to be seperate instances. 10 by default, this can be configured via CLI
    • There also is a timeout when waiting for an instance. Can also be configured via CLI
  • Added timeout functionality to the code run function. TBH this should have been a different PR, but I was chaning the same references so many times I just added it :D
    Now the code is only allowed to run for 60s, then it gets interrupted. Honestly a very important feature that was missing, and also configurable via CLI. Default again 60s
  • Added tests for parallelism. Pyodide needs 1-2s for a worker to be ready, but this only effects the first batch of code in my testing. Seems to work well - feel free to suggest any tests that are missing :)
  • Made the file upload feature opt-in, again CLI :)

@Kigstn
Copy link
Contributor Author

Kigstn commented Nov 8, 2025

Also have a question regarding the failing test: it's a performance test I added to check that worker creation (which takes 2-3s) is not repeated constantly. So I fire 500 super simple code snippets against it and test the time. Locally that takes 15s to run, on CI 25ish. The problem however is that due to the CI worker running the test for all python versions, this is super slow & inconsistent.

Personally, I would move these tests out of Ci and maybe into their own Ci instance where it is only run once. Otherwise the benchmarking will always be inconsistent...

Or these tests can be removed / only exist locally

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants