Skip to content

Conversation

@dr-shrey
Copy link

🚀 Profile-Based Docker Containerization Architecture

Collaborating with @renato-umeton - This PR replaces/supersedes #2 with a more comprehensive implementation.

🏗️ What This Implements

  • Profile-Based Architecture: Replaces separate Docker CLI with integrated workflow profiles
  • Dynamic Dockerfile Generation: Environment-aware generation (development vs production)
  • Multiple Workflow Types:
    • build-only: Generate config + Dockerfile + build image locally
    • build-and-push: Full CI/CD pipeline with registry push
    • docker-dev: Custom development workflow with parameters
  • Comprehensive Testing: Full smoke test suite validating end-to-end workflows
  • Development Mode Detection: Automatic local source installation when in MCPStack repo

🧪 Testing Completed

Profile Discovery: All Docker profiles listed and filtered correctly
Basic Config Generation: FastMCP config generation working
Development Workflow: Complete Docker workflow (3.5s execution time)
Runtime Testing: Container runs successfully with proper MCP server startup
Production Pipeline: Build and push workflow (graceful registry failure handling)
Custom Profiles: Parameter support and environment variable expansion
Error Handling: Fuzzy matching suggestions and graceful degradation
Performance: Sub-4-second complete Docker workflows

📁 Key Files Added/Modified

  • New: .dockerignore, docs/API/mcp_config_generators/docker.md, docs/docker-migration-guide.md
  • New: src/MCPStack/core/profile_manager.py, src/MCPStack/core/workflow.py
  • New: workflows/*.yaml (profile definitions)
  • Modified: src/MCPStack/cli.py (integrated profile system)
  • Comprehensive test suite: 15+ new test files

🎯 Ready For

  • Early feedback on implementation approach
  • Architecture review
  • Testing by maintainers

This enables users to build and deploy MCP pipelines as Docker containers for production environments through a unified, profile-based interface.

renato-umeton and others added 2 commits August 22, 2025 23:49
- Add Docker config generator for Claude Desktop integration
- Add Dockerfile template system with environment variable support
- Add Docker build utilities (build, push, tag, list)
- Add CLI commands: docker-dockerfile, docker-build, docker-config
- Add comprehensive test suite with 95% coverage (59 tests)
- Add integration tests for end-to-end Docker workflows
- Support volume mounts, port mappings, and custom networks
- Follow biomcp-style containerization pattern
- Add CLAUDE.md documentation for development workflow

Closes MCP-Pipeline#1

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Replace separate Docker CLI with integrated workflow profiles
- Add dynamic Dockerfile generation with environment detection
- Implement build-only, build-and-push, and custom dev profiles
- Add comprehensive Docker architecture documentation
- Include full smoke test suite validating end-to-end workflows
- Support both development (local source) and production deployments

This architectural change consolidates Docker functionality into the
main MCPStack workflow system, enabling containerized MCP deployments
through a unified profile-based interface.
Copy link
Member

@simonprovost simonprovost left a comment

Choose a reason for hiding this comment

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

Hello, @dr-shrey! Absolutely brilliant! I am happy to see this PR. Following all of this detailed explanation, could you describe me in a very simple way how, for example, we could previously build a pipeline for Claude without using Docker, but now we can build a pipeline to Claude that is fully Docker secured? (Like Before -> After). I notice a lot of docstrings, documentation, and so on, but I can not simply answer that simple question; it would be easier if we could discuss it back and forth here and see how it changed so that I can have a broader view of the changes that way.

Have you ran one pipeline in a docker-style? Do you have a quick video showing out maybe? Tests are passing 100% too?

Feel free to take those two tutorials as an example to let me know the before and after:

It is quite a big PR let's not rush with the risk of failing somewhere; Thank you so much; we will see where this goes! Meanwhile, I have included some general thoughts below.

@@ -0,0 +1,265 @@
"""Docker build utilities for MCPStack."""
Copy link
Member

Choose a reason for hiding this comment

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

Let's try to avoid such docstring above files it does not add anything

if quiet:
cmd.append("--quiet")

# Add context path as final argument
Copy link
Member

Choose a reason for hiding this comment

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

All omments within methods/functions are only and only necessary if really it is complex otherwise the docstring of the methods/functions suffice

Comment on lines 71 to 73
# Special handling for MCP-related functionality
# Include variables that might be needed for the container to function
# e.g., `_ADAPTER_ENDPOINTS`, `_PATH`, etc.
Copy link
Member

Choose a reason for hiding this comment

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

Same as previously

with open(path, "w") as f:
json.dump(data, f, indent=4)
logger.info(f"Saved pipeline config to {path}.")
logger.info(f"Saved pipeline config to {path}.")
Copy link
Member

Choose a reason for hiding this comment

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

I believe this is out of scope?

Comment on lines 853 to 860
# Use simple ASCII art that works on Windows
ascii_art = Text("""
MCPStack
========
Composable MCP pipelines.
""", style="bold blue")

Copy link
Member

Choose a reason for hiding this comment

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

I believe this is out of scope

Relies on each tool CLI's `status()` implementation to render.
"""
console.print("[bold green]💬 Checking status...[/bold green]")
console.print("[bold green]Checking status...[/bold green]")
Copy link
Member

Choose a reason for hiding this comment

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

I believe this is out of scope

Comment on lines 237 to 238
for t in stack.tools:
if t.__class__.__name__.lower() == tool_name.lower():
Copy link
Member

Choose a reason for hiding this comment

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

It is always great to avoid extreme abbreviations in modern Python for smooth reading of Python scripts by others. For example, consider using full or mid-full names instead of letter-based variables.

Look for other loops, such as line 239 in docker_builder.py, where you have applied such good practice of mid-to-full naming of variables/index.

I would here just rename t.

"build_args": kwargs.get("build_args"),
}

build_kwargs = {k: v for k, v in build_kwargs.items() if v is not None}
Copy link
Member

Choose a reason for hiding this comment

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

It is always great to avoid extreme abbreviations in modern Python for smooth reading of Python scripts by others. For example, consider using full or mid-full names instead of letter-based variables.

Look for other loops, such as line 239 in docker_builder.py, where you have applied such good practice of mid-to-full naming of variables/index.

I would here just rename k and v.

@dr-shrey
Copy link
Author

Hello, @dr-shrey! Absolutely brilliant! I am happy to see this PR. Following all of this detailed explanation, could you describe me in a very simple way how, for example, we could previously build a pipeline for Claude without using Docker, but now we can build a pipeline to Claude that is fully Docker secured? (Like Before -> After). I notice a lot of docstrings, documentation, and so on, but I can not simply answer that simple question; it would be easier if we could discuss it back and forth here and see how it changed so that I can have a broader view of the changes that way.

Have you ran one pipeline in a docker-style? Do you have a quick video showing out maybe? Tests are passing 100% too?

Feel free to take those two tutorials as an example to let me know the before and after:

It is quite a big PR let's not rush with the risk of failing somewhere; Thank you so much; we will see where this goes! Meanwhile, I have included some general thoughts below.

Thanks, Simon! Here is the description:

Dockerization Before/After Snapshot

CLI surface

  • Before: StackCLI.build accepted only the basic config flags, so there was no --profile path and Docker actions had to be scripted manually.
  • After: The CLI now instantiates ProfileManager, exposes list-profiles, and routes --profile, --build-image, --dockerfile-path, --docker-push, and --build-args into the workflow orchestrator (src/MCPStack/cli.py:68, src/MCPStack/cli.py:179, src/MCPStack/cli.py:390, src/MCPStack/cli.py:523).

Workflow orchestration

  • Before: There was no profile registry or orchestrator, so multi-stage Docker workflows (config -> Dockerfile -> image) couldn't be executed in one command.
  • After: New ProfileManager and ProfileOrchestrator declare built-in build-only / build-and-push profiles and load YAML workflows from the workflows/ directory, handling requirement checks and stage context (src/MCPStack/core/profile_manager.py:17, src/MCPStack/core/workflow.py:30, src/MCPStack/core/workflow.py:57, workflows/docker-dev.yaml:1).

Config generators & Docker tooling

  • Before: The config registry exposed only fastmcp, claude, and universal, and MCPStackCore.build couldn't forward Docker-specific parameters.
  • After: DockerMCPConfigGenerator stitches together config generation, Dockerfile emission, image builds, optional pushes, and build arguments while MCPStackCore.build forwards the extras (src/MCPStack/core/mcp_config_generator/registry.py:1, src/MCPStack/core/mcp_config_generator/mcp_config_generators/docker_mcp_config.py:17, src/MCPStack/core/docker/docker_builder.py:15, src/MCPStack/core/docker/dockerfile_generator.py:21, src/MCPStack/stack.py:181).

Developer experience

  • Before: Docker workflows lacked documentation and automated coverage.
  • After: Dedicated docs and regression tests capture the new flows and guard the CLI (docs/docker-migration-guide.md:1, docs/API/cli/stack_cli.md:1, tests/core/test_build_only_profile.py:1, tests/cli/test_profile_integration.py:36, tests/integration/test_docker_integration.py:1).

@dr-shrey
Copy link
Author

Hello, @dr-shrey! Absolutely brilliant! I am happy to see this PR. Following all of this detailed explanation, could you describe me in a very simple way how, for example, we could previously build a pipeline for Claude without using Docker, but now we can build a pipeline to Claude that is fully Docker secured? (Like Before -> After). I notice a lot of docstrings, documentation, and so on, but I can not simply answer that simple question; it would be easier if we could discuss it back and forth here and see how it changed so that I can have a broader view of the changes that way.

Have you ran one pipeline in a docker-style? Do you have a quick video showing out maybe? Tests are passing 100% too?

Feel free to take those two tutorials as an example to let me know the before and after:

It is quite a big PR let's not rush with the risk of failing somewhere; Thank you so much; we will see where this goes! Meanwhile, I have included some general thoughts below.

Thanks for sharing those links and the comments- that makes sense!
Yeah I did test extensively. See attached pytest-summary.txt (all 270 passed).
pytest-summary.txt
Let me know if you’d like any more details or additional runs. Happy to iterate!

@simonprovost
Copy link
Member

simonprovost commented Sep 29, 2025

Brills @dr-shrey thanks so much for all that! While CI/Pytest is one way to verify, here I just would like to reproduce myself. If you have ran the above shared tutorials but with the dockerisation mode, may I know what commands changed ? (before it was X now it is Y). No need videos for that I believe.

Cheers

@dr-shrey
Copy link
Author

Brills @dr-shrey thanks so much for all that! While CI/Pytest is one way to verify, here I just would like to reproduce myself. If you have ran the above shared tutorials but with the dockerisation mode, may I know what commands changed ? (before it was X now it is Y). No need videos for that I believe.

Cheers

Thanks a ton, Simon! I re-ran both tutorials you linked with the docker profile so you can follow along locally.

Before (original tutorial command): uv run mcpstack build --pipeline my_pipeline.json --config-type claude
After (dockerised, local image): uv run mcpstack build --pipeline my_pipeline.json --config-type docker --profile build-only --build-image my-pipeline:latest
After (dockerised, build + push): uv run mcpstack build --pipeline my_pipeline.json --config-type docker --profile build-and-push --build-image my-pipeline:latest --docker-push
Same swap works for the Urban Mapper tutorial—just keep the pipeline file you generated in steps 1–3 and pick whichever docker profile you need. Let me know if you’d like the sample output or image tags I used.

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