Skip to content

Conversation

@DOsinga
Copy link
Collaborator

@DOsinga DOsinga commented Jun 27, 2025

This makes it possible to have python code inside of a recipe

Douwe Osinga added 9 commits June 27, 2025 14:46
- Add InlinePython variant to ExtensionConfig
- Add support for Python dependencies in uvx execution
- Add example recipe and test for word counting
- Update documentation with inline Python examples
- Add temp_dirs field to ExtensionManager to store TempDir instances
- Store temp dir when creating inline Python extension
- Clean up temp dir when removing extension
@DOsinga
Copy link
Collaborator Author

DOsinga commented Jun 27, 2025

This should work:

version: "1.0.0"
title: "Word Counter"
description: "A recipe that counts words in text using an inline Python extension"

instructions: |
  This recipe provides a simple word counting tool. You can:
  1. Count words in a text string
  2. Get statistics about the text (unique words, average word length)
  3. Generate word clouds from the text

parameters:
  - key: text
    input_type: string
    requirement: required
    description: "The text to analyze"

extensions:
  - type: inline_python
    name: word_counter
    code: |
      from mcp.server.fastmcp import FastMCP
      import json
      from collections import Counter
      import numpy as np
      from wordcloud import WordCloud
      import matplotlib.pyplot as plt
      import base64
      from io import BytesIO
      
      mcp = FastMCP("word_counter")
      
      @mcp.tool()
      def count_words(text: str) -> str:
          """Count the number of words in a text string and generate statistics"""
          words = text.split()
          word_count = len(words)
          unique_words = len(set(words))
          avg_length = sum(len(word) for word in words) / word_count if word_count > 0 else 0
          
          # Generate word cloud
          wordcloud = WordCloud(width=800, height=400, background_color='white').generate(text)
          
          # Save word cloud to base64
          plt.figure(figsize=(10, 5))
          plt.imshow(wordcloud, interpolation='bilinear')
          plt.axis('off')
          
          # Save to bytes
          buf = BytesIO()
          plt.savefig(buf, format='png', bbox_inches='tight', pad_inches=0)
          buf.seek(0)
          img_base64 = base64.b64encode(buf.getvalue()).decode()
          plt.close()
          
          result = {
              "total_words": word_count,
              "unique_words": unique_words,
              "average_word_length": round(avg_length, 2),
              "most_common": dict(Counter(words).most_common(5)),
              "wordcloud_base64": img_base64
          }
          
          return json.dumps(result, indent=2)
          
      if __name__ == "__main__":
          mcp.run()
    timeout: 300
    description: "Count words and provide text statistics with visualization"
    dependencies:
      - "mcp"
      - "numpy"
      - "matplotlib"
      - "wordcloud"
      - "beautifulsoup4"
      - "html2text"
      - "requests"

prompt: |
  You are a helpful assistant that can analyze text using word counting tools.
  The user has provided the following text to analyze: {{ text }}
  
  Use the word_counter__count_words tool to analyze this text and provide insights about:
  - Total word count
  - Number of unique words
  - Average word length
  - Most commonly used words
  - A word cloud visualization of the text

@DOsinga DOsinga requested a review from baxen June 30, 2025 06:03
@michaelneale
Copy link
Collaborator

diabolically good - I love it. And security reasons why this is a bad idea?

@DOsinga
Copy link
Collaborator Author

DOsinga commented Jul 21, 2025

And security reasons why this is a bad idea?

I think this can actually pave the ways to make things more secure - if you have a recipe that refers to an MCP server that is unsigned (as they all are today) and then you accept the recipe, the author of the MCP server could change the implementation and do bad things. here are least you see what is actually happening. I don't think it makes recipes less save, but very save they are not to begin with

@DOsinga DOsinga requested a review from michaelneale July 22, 2025 15:04
@DOsinga DOsinga assigned michaelneale and unassigned baxen Jul 22, 2025
@DOsinga
Copy link
Collaborator Author

DOsinga commented Jul 22, 2025

assigned to you @michaelneale

@michaelneale
Copy link
Collaborator

updated this to main and had to make some other changes for new typechecks and openapi.

@DOsinga wasn't able to run that example, having trouble speaking uv to know if this means I really need a different py installed:

Warning: Failed to start extension 'word_counter': Failed to start the MCP server from configuration `InlinePython(word_counter: 1341 chars)` `Call to '' failed for 'initialize'. Error from mcp-server: Stdio process error:   × No solution found when resolving tool dependencies:
  ╰─▶ Because python was not found in the package registry and you require
      python, we can conclude that your requirements are unsatisfiable.
`
Continuing without extension 'word_counter'

ie it was trying to do python - but failing I guess once it is bootstrapping from the python-mcp side of things?

@DOsinga
Copy link
Collaborator Author

DOsinga commented Jul 24, 2025

updated this to main and had to make some other changes for new typechecks and openapi.

@DOsinga wasn't able to run that example, having trouble speaking uv to know if this means I really need a different py installed:

Warning: Failed to start extension 'word_counter': Failed to start the MCP server from configuration `InlinePython(word_counter: 1341 chars)` `Call to '' failed for 'initialize'. Error from mcp-server: Stdio process error:   × No solution found when resolving tool dependencies:
  ╰─▶ Because python was not found in the package registry and you require
      python, we can conclude that your requirements are unsatisfiable.
`
Continuing without extension 'word_counter'

ie it was trying to do python - but failing I guess once it is bootstrapping from the python-mcp side of things?

was this with Warp on or off? we should probably do better with MCP error handling here (maybe the new version will anyway)

@michaelneale
Copy link
Collaborator

@DOsinga with it on - with it off I got another error which was clearer (usually I can run uv things - didn't quite follow this error). Am ok with merging this though as I think it should work - just not sure how reliable in the face of dependencies/registries (but small risk)

* main: (25 commits)
  fix: add maintainer, homepage and categories to DEB/RPM package config (#3096)
  blog: agent to agent convo (#3677)
  Possible to disable random thinking messages (#3304)
  Two VS code tutorials (#3603)
  small blog fixes (#3549)
  docs: fix installation command for YouTube Transcript MCP in servers.json (#3595)
  Docs for using Docker Model Runner as a local LLM provider.  (#3509)
  Docs: VS Code Extension move to tutorials (#3601)
  Fix working directory when session has no messages (#3513)
  goose docs MCP server (#3665)
  Remove confusing status output when testing sharing url connection and it shows 404 (#3659)
  chore: use typed notifications from rmcp (#3653)
  feat: convert GetPromptResult from mcp_core to rmcp version (#3650)
  feat: Replace usage of mcp_core Tools/ToolAnnotations in openapi schema (#3649)
  fix: ensure execution task result is shown (#3629)
  docs: Quick spotlight fix (#3633)
  alexhancock/rmcp-tools-annotations (#3617)
  fix: clean up subagent (#3565)
  Adds the `WaitingForUserInput` state (#3620)
  docs: update extensions library (#3612)
  ...
@michaelneale michaelneale merged commit b18213c into main Jul 28, 2025
8 of 9 checks passed
@michaelneale michaelneale deleted the add-inline-python-extension branch July 28, 2025 00:48
michaelneale added a commit that referenced this pull request Jul 28, 2025
* main: (27 commits)
  Add inline python extension (#3107)
  fix: add maintainer, homepage and categories to DEB/RPM package config (#3096)
  blog: agent to agent convo (#3677)
  Possible to disable random thinking messages (#3304)
  Two VS code tutorials (#3603)
  small blog fixes (#3549)
  docs: fix installation command for YouTube Transcript MCP in servers.json (#3595)
  Docs for using Docker Model Runner as a local LLM provider.  (#3509)
  Docs: VS Code Extension move to tutorials (#3601)
  Fix working directory when session has no messages (#3513)
  goose docs MCP server (#3665)
  Remove confusing status output when testing sharing url connection and it shows 404 (#3659)
  chore: use typed notifications from rmcp (#3653)
  feat: convert GetPromptResult from mcp_core to rmcp version (#3650)
  feat: Replace usage of mcp_core Tools/ToolAnnotations in openapi schema (#3649)
  fix: ensure execution task result is shown (#3629)
  docs: Quick spotlight fix (#3633)
  alexhancock/rmcp-tools-annotations (#3617)
  fix: clean up subagent (#3565)
  Adds the `WaitingForUserInput` state (#3620)
  ...
michaelneale added a commit that referenced this pull request Jul 28, 2025
* main: (69 commits)
  Add inline python extension (#3107)
  fix: add maintainer, homepage and categories to DEB/RPM package config (#3096)
  blog: agent to agent convo (#3677)
  Possible to disable random thinking messages (#3304)
  Two VS code tutorials (#3603)
  small blog fixes (#3549)
  docs: fix installation command for YouTube Transcript MCP in servers.json (#3595)
  Docs for using Docker Model Runner as a local LLM provider.  (#3509)
  Docs: VS Code Extension move to tutorials (#3601)
  Fix working directory when session has no messages (#3513)
  goose docs MCP server (#3665)
  Remove confusing status output when testing sharing url connection and it shows 404 (#3659)
  chore: use typed notifications from rmcp (#3653)
  feat: convert GetPromptResult from mcp_core to rmcp version (#3650)
  feat: Replace usage of mcp_core Tools/ToolAnnotations in openapi schema (#3649)
  fix: ensure execution task result is shown (#3629)
  docs: Quick spotlight fix (#3633)
  alexhancock/rmcp-tools-annotations (#3617)
  fix: clean up subagent (#3565)
  Adds the `WaitingForUserInput` state (#3620)
  ...
katzdave added a commit that referenced this pull request Jul 28, 2025
…cn/compact2-task-tracking

* 'dkatz/goose-compact2' of github.com:block/goose: (22 commits)
  rm stray files
  unused
  fmt
  fix threshold
  autocompact splice last message
  fmt
  Fix conversations before they hit the LLM (#3660)
  cli: add detailed instruction for WSL users (#3496)
  feat: recipe runs will now prompt for missing extension secrets (#3668)
  fix: pricing integration tests -> trying more runs for cache and retries (#3546)
  Add inline python extension (#3107)
  fix: add maintainer, homepage and categories to DEB/RPM package config (#3096)
  blog: agent to agent convo (#3677)
  Possible to disable random thinking messages (#3304)
  Two VS code tutorials (#3603)
  small blog fixes (#3549)
  docs: fix installation command for YouTube Transcript MCP in servers.json (#3595)
  Docs for using Docker Model Runner as a local LLM provider.  (#3509)
  Docs: VS Code Extension move to tutorials (#3601)
  Fix working directory when session has no messages (#3513)
  ...
michaelneale added a commit that referenced this pull request Jul 29, 2025
* dkatz/goose-compact2: (22 commits)
  rm stray files
  unused
  fmt
  fix threshold
  autocompact splice last message
  fmt
  Fix conversations before they hit the LLM (#3660)
  cli: add detailed instruction for WSL users (#3496)
  feat: recipe runs will now prompt for missing extension secrets (#3668)
  fix: pricing integration tests -> trying more runs for cache and retries (#3546)
  Add inline python extension (#3107)
  fix: add maintainer, homepage and categories to DEB/RPM package config (#3096)
  blog: agent to agent convo (#3677)
  Possible to disable random thinking messages (#3304)
  Two VS code tutorials (#3603)
  small blog fixes (#3549)
  docs: fix installation command for YouTube Transcript MCP in servers.json (#3595)
  Docs for using Docker Model Runner as a local LLM provider.  (#3509)
  Docs: VS Code Extension move to tutorials (#3601)
  Fix working directory when session has no messages (#3513)
  ...
atarantino pushed a commit to atarantino/goose that referenced this pull request Aug 5, 2025
Co-authored-by: Douwe Osinga <[email protected]>
Co-authored-by: Michael Neale <[email protected]>
Signed-off-by: Adam Tarantino <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants