Recipe → MCP Bridge

Turn any PraisonAI recipe into a scoped MCP server for Claude Desktop, Cursor, and Windsurf

Serve any recipe as its own MCP server, so an MCP client sees exactly one recipe’s tools, prompts, and resources — safe-mode on by default.

Diagram

📋 Recipe file
support-reply

⚙️ serve-recipe

🔌 Scoped MCP server

✅ MCP client
Claude Desktop / Cursor

Quick Start

  1. Build an agent recipe
    python
    from praisonaiagents import Agent
    
    agent = Agent(
        name="support-reply",
        instructions="Draft a friendly reply to a customer support ticket.",
    )
    agent.start("Customer says their order is late.")

    Save the recipe as support-reply so the bridge can find it by name.

  2. Serve the recipe as an MCP server
    bash
    praisonai mcp serve-recipe support-reply --transport stdio

    Only this recipe’s tools and prompts are exposed — nothing else.

  3. Point your MCP client at it
    bash
    praisonai mcp config-generate-recipe support-reply --client claude-desktop

    Paste the printed block into your Claude Desktop config and the recipe appears as a tool.


How It Works

A recipe maps to MCP primitives: agent tools become MCP tools, agent instructions become MCP prompts, and the recipe config becomes MCP resources — all behind a deny-list gate.

Diagram
AgentDeny-List GateRecipe HostMCP ClientUserAgentDeny-List GateRecipe HostMCP ClientUserCall recipe tooltools/callCheck tool nameAllowedRun recipeResultResponseAnswer
Recipe partBecomesExample
Recipe runMCP toolsupport-reply.run
Agent toolMCP tool (namespaced)support-reply.agent.tool
Recipe configMCP resourcerecipe://support-reply/config
Config schemaMCP resourcerecipe://support-reply/schema
Recipe descriptionMCP promptsupport-reply-description
Agent instructionsMCP promptsupport-reply-agent-instructions

CLI Commands

Five commands work with recipes over MCP — one to discover, four to serve. Each works as praisonai mcp <command> inside the full stack, or praisonai-mcp <command> standalone.

list-recipes

List every recipe the discovery layer can see — custom (~/.praison, ~/.config), project (./.praison), and bundled (agent_recipes). You need a recipe name before you can serve-recipe.

bash
praisonai mcp list-recipes
praisonai-mcp list-recipes
praisonai mcp list-recipes --source package
praisonai mcp list-recipes --tags video,social
praisonai mcp list-recipes --json
FlagDefaultDescription
--sourceNone (all sources)Filter by source. Only custom, project, package are accepted — the exact labels TemplateDiscovery assigns.
--tagsNoneComma-separated tag filter (--tags video,social).
--jsonoffJSON output — safe for pipes and CI.

Source labels — what each one lists:

SourceWhere discovery reads fromTypical use
custom~/.praison, ~/.config/praisonUser-installed recipes on this machine
project./.praison (current working directory)Recipes checked into a repo
packageBundled agent_recipes inside the wheelThe recipes that ship with PraisonAI

Expected output (default, non-JSON):

Available Recipes (2):

  • data-analyst (v1.0.0)
    Data analysis template using pandas tools

  • support-reply (v1.0.0)
    Draft a friendly reply to a customer support ticket

JSON output (--json):

json
{
  "recipes": [
    {
      "name": "data-analyst",
      "version": "1.0.0",
      "description": "Data analysis template using pandas tools",
      "source": "package",
      "tags": ["data", "pandas"]
    }
  ]
}

Which recipe do I serve?

Pair list-recipes with serve-recipe — discover first, then serve.

Diagram

No

Yes

Know the recipe name?

praisonai mcp list-recipes

Pick a recipe

praisonai mcp serve-recipe

✅ Claude Desktop / Cursor

serve-recipe

Turn a recipe into a scoped MCP server.

bash
praisonai mcp serve-recipe support-reply --transport stdio
praisonai-mcp serve-recipe support-reply --transport http-stream --port 8080
FlagDefaultDescription
--transportstdiostdio or http-stream
--host127.0.0.1HTTP host (http-stream only)
--port8080HTTP port (http-stream only)
--endpoint/mcpHTTP endpoint path
--api-keyNoneBearer token for HTTP auth
--safe-mode / --no-safe-modeenabledApply the deny-list gate
--expose-tools / --no-expose-toolsenabledExpose agent tools
--expose-prompts / --no-expose-promptsenabledExpose prompts
--session-ttl3600Session TTL in seconds
--log-levelwarningdebug, info, warning, or error
--jsonoffJSON output

validate-recipe

Check a recipe is safe to host before serving it.

bash
praisonai mcp validate-recipe support-reply
FlagDefaultDescription
--jsonoffJSON output

Warnings flag recipes with no tools or with shell/exec tools.

inspect-recipe

Show the tools, resources, and prompts a recipe would expose.

bash
praisonai mcp inspect-recipe support-reply --tools
FlagDefaultDescription
--toolsoffShow tools
--resourcesoffShow resources
--promptsoffShow prompts
--metadataoffShow recipe metadata
--jsonoffJSON output

With no flags, it shows everything.

config-generate-recipe

Emit a client config block that points at this recipe.

bash
praisonai mcp config-generate-recipe support-reply --client claude-desktop
FlagDefaultDescription
--clientclaude-desktopclaude-desktop, cursor, vscode, windsurf, or generic
--transportstdiostdio or http-stream
--host127.0.0.1HTTP host (http-stream only)
--port8080HTTP port (http-stream only)
--outputNoneWrite config to a file instead of stdout

Which Serve Command

Three commands serve MCP — pick the one that matches your scope.

Diagram

One recipe

Full capability registry

Config-driven tools

What do you want
to expose?

praisonai mcp serve-recipe

praisonai-mcp serve

praisonai serve mcp

CommandServesUse it for
praisonai mcp serve-recipeOne recipe, scopedShip a single recipe to a client
praisonai-mcp serveFull capability registryExpose the whole heavy host
praisonai serve mcpConfig-driven toolsLight server from shared config

Allow / Deny Lists and Safe Mode

Safe mode is on by default and filters every tool through a deny-list before it reaches a client.

Default denied tools (from DEFAULT_DENIED_TOOLS in the adapter):

Denied toolDenied toolDenied tool
shell.execshell.runshell_tool
file.writefile.deletefs.write
fs.deletenetwork.unrestricteddb.write
db.deleteexecute_commandos.system
subprocess.runevalexec

A tool is blocked when a denied name matches part of the tool name in either direction. Set an allow-list and only those tools pass; leave it empty and the deny-list applies.

python
from praisonai_mcp.mcp_server import RecipeMCPConfig

# Allow-list: only these tools pass
config = RecipeMCPConfig(
    recipe_name="support-reply",
    tool_allowlist=["search", "summarize"],
)

# Deny-list: extend the defaults
config = RecipeMCPConfig(
    recipe_name="support-reply",
    tool_denylist=["shell.exec", "file.delete", "my.custom.tool"],
)

Python API

Load a recipe and run it as an MCP server in three lines.

python
from praisonai_mcp.mcp_server import RecipeMCPAdapter

adapter = RecipeMCPAdapter("support-reply")
adapter.load()
adapter.to_mcp_server().run(transport="stdio")

RecipeMCPAdapter

MethodSignatureReturns
__init__RecipeMCPAdapter(recipe_name, config=None)adapter
loadload()None — loads recipe, builds registries
to_mcp_serverto_mcp_server()MCPServer ready to run
get_recipe_infoget_recipe_info()metadata dict
get_tool_registryget_tool_registry()tool registry
get_resource_registryget_resource_registry()resource registry
get_prompt_registryget_prompt_registry()prompt registry
__init__ paramTypeDefaultDescription
recipe_namestrrequiredRecipe to adapt
configRecipeMCPConfigNoneConfig (defaults applied if omitted)

RecipeMCPConfig

OptionTypeDefaultDescription
recipe_namestrrequiredRecipe name
expose_agent_toolsboolTrueExpose agent tools
expose_run_toolboolTrueExpose the recipe.run meta-tool
tool_namespacestr"prefixed"flat, nested, or prefixed
expose_configboolTrueExpose recipe config as a resource
expose_outputsboolTrueExpose output definitions
expose_promptsboolTrueExpose prompts
expose_agent_instructionsboolTrueExpose agent instructions as prompts
safe_modeboolTrueApply the deny-list gate
tool_allowlistList[str]NoneOnly these tools pass
tool_denylistList[str]NoneBlocked tools (defaults if None)
workspace_pathstrNoneWorkspace root for the recipe
allow_networkboolFalseAllow network access
env_allowlistList[str]NoneEnvironment variables to pass through
server_namestrNoneServer name (defaults to recipe name)
server_versionstr"1.0.0"Server version
server_descriptionstrNoneServer description
server_iconstrNoneServer icon
session_ttlint3600Session TTL in seconds
max_concurrent_runsint5Concurrent recipe runs

End-to-End Example

Go from an agent recipe to a working Claude Desktop tool in three steps.

  1. Write the recipe
    python
    from praisonaiagents import Agent
    
    agent = Agent(
        name="support-reply",
        instructions="Draft a friendly reply to a customer support ticket.",
    )
  2. Serve it
    bash
    praisonai mcp serve-recipe support-reply --transport stdio
  3. Generate the client config
    bash
    praisonai mcp config-generate-recipe support-reply --client claude-desktop

    Standalone (praisonai-mcp)

    json
    {
      "mcpServers": {
        "support-reply": {
          "command": "praisonai-mcp",
          "args": ["serve-recipe", "support-reply", "--transport", "stdio"]
        }
      }
    }

    Umbrella (praisonai)

    json
    {
      "mcpServers": {
        "support-reply": {
          "command": "praisonai",
          "args": ["mcp", "serve-recipe", "support-reply", "--transport", "stdio"]
        }
      }
    }

Paste that block into Claude Desktop’s config and the support-reply recipe appears as a tool.


Best Practices

Validate before you serve

Run praisonai mcp validate-recipe <name> to catch missing tools or shell/exec warnings before a client connects.

Inspect what you expose

praisonai mcp inspect-recipe <name> shows the exact tools, resources, and prompts a client will see.

Keep safe mode on

Safe mode blocks destructive tools like shell.exec and file.delete. Only use --no-safe-mode for recipes you fully trust.

Prefer an allow-list for production

An allow-list exposes only the tools you name, which is tighter than extending the deny-list.


Related