Container Mcp — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Container Mcp (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
A secure, container-based implementation of the Model Context Protocol (MCP) for executing tools on behalf of large language models.
Container-MCP provides a sandboxed environment for safely executing code, running commands, accessing files, and performing web operations requested by large language models. It implements the MCP protocol to expose these capabilities as tools that can be discovered and called by AI systems in a secure manner.
The architecture uses a domain-specific manager pattern with multi-layered security to ensure tools execute in isolated environments with appropriate restrictions, protecting the host system from potentially harmful operations.
BashManager: Secure command executionPythonManager: Sandboxed Python code executionFileManager: Safe file operationsWebManager: Secure web browsing and scrapingKnowledgeBaseManager: Structured document storage with semantic searchListManager: Organized list and collection managementMarketManager: Stock and cryptocurrency data via Yahoo FinanceRssManager: RSS and Atom feed fetching#### system_run_command Executes bash commands in a secure sandbox environment.
command (string, required): The bash command to executeworking_dir (string, optional): Working directory (ignored in sandbox)stdout (string): Command standard outputstderr (string): Command standard errorexit_code (integer): Command exit codesuccess (boolean): Whether command completed successfully{
"stdout": "file1.txt\nfile2.txt\n",
"stderr": "",
"exit_code": 0,
"success": true
}#### system_run_python Executes Python code in a secure sandbox environment.
code (string, required): Python code to executeworking_dir (string, optional): Working directory (ignored in sandbox)output (string): Print output from the codeerror (string): Error output from the coderesult (any): Optional return value (available if code sets _ variable)success (boolean): Whether code executed successfully{
"output": "Hello, world!\n",
"error": "",
"result": 42,
"success": true
}#### system_env_var Gets environment variable values.
var_name (string, optional): Specific variable to retrievevariables (object): Dictionary of environment variablesrequested_var (string): Value of the requested variable (if var_name provided){
"variables": {
"MCP_PORT": "8000",
"SANDBOX_ROOT": "/app/sandbox"
},
"requested_var": "8000"
}#### health_check Gets server health status and system information.
status (string): Server health statustimestamp (string): Current ISO timestampserver (object): Server details (name, host, port, platform, python_version)system (object): System metrics (cpu_percent, memory_percent, disk_percent)managers (object): Status of each manager (enabled/disabled){
"status": "healthy",
"timestamp": "2024-01-15T10:30:00.000Z",
"server": {
"name": "Container-MCP",
"host": "127.0.0.1",
"port": 9001,
"platform": "linux",
"python_version": "3.12.0"
},
"system": {
"cpu_percent": 12.5,
"memory_percent": 45.2,
"disk_percent": 67.8
},
"managers": {
"bash": "enabled",
"python": "enabled",
"file": "enabled",
"web": "enabled",
"kb": "enabled",
"list": "enabled",
"market": "enabled",
"rss": "enabled"
}
}#### fs_read Reads file contents safely.
path (string, required): Path to the file (relative to sandbox root)encoding (string, optional): File encoding (default: "utf-8")content (string): File contentsize (integer): File size in bytesmodified (float): Last modified timestampsuccess (boolean): Whether the read was successful{
"content": "This is the content of the file.",
"size": 31,
"modified": 1673452800.0,
"success": true
}#### fs_write Writes content to a file safely.
path (string, required): Path to the file (relative to sandbox root)content (string, required): Content to writeencoding (string, optional): File encoding (default: "utf-8")success (boolean): Whether the write was successfulpath (string): Path to the written file{
"success": true,
"path": "data/myfile.txt"
}#### fs_list Lists contents of a directory safely.
path (string, optional): Path to the directory (default: "/")pattern (string, optional): Glob pattern to filter filesrecursive (boolean, optional): Whether to list recursively (default: true)entries (array): List of directory entries with metadatapath (string): The listed directory pathsuccess (boolean): Whether the listing was successful{
"entries": [
{
"name": "file1.txt",
"path": "file1.txt",
"is_directory": false,
"size": 1024,
"modified": 1673452800.0
},
{
"name": "data",
"path": "data",
"is_directory": true,
"size": null,
"modified": 1673452500.0
}
],
"path": "/",
"success": true
}#### fs_delete Deletes a file safely.
path (string, required): Path of the file to deletesuccess (boolean): Whether the deletion was successfulpath (string): Path to the deleted file{
"success": true,
"path": "temp/old_file.txt"
}#### fs_move Moves or renames a file safely.
source_path (string, required): Source file pathdestination_path (string, required): Destination file pathsuccess (boolean): Whether the move was successfulsource_path (string): Original file pathdestination_path (string): New file path{
"success": true,
"source_path": "data/old_name.txt",
"destination_path": "data/new_name.txt"
}#### fs_apply_diff Applies a unified diff patch to a file in the sandbox filesystem.
path (string, required): Path to the file to patch (relative to sandbox root)diff (string, required): Unified diff content to applysuccess (boolean): Whether the patch was applied successfullypath (string): Path to the patched filelines_applied (integer): Number of lines changednew_size (integer): New file size in byteserror (string): Error message if patch failed{
"success": true,
"path": "src/main.py",
"lines_applied": 5,
"new_size": 1248,
"error": null
}#### web_search Uses a search engine to find information on the web.
query (string, required): The query to search forresults (array): List of search resultsquery (string): The original query{
"results": [
{
"title": "Search Result Title",
"url": "https://example.com/page1",
"snippet": "Text snippet from the search result..."
}
],
"query": "example search query"
}#### web_scrape Scrapes a specific URL and returns the content.
url (string, required): The URL to scrapeselector (string, optional): CSS selector to target specific contentoutput_format (string, optional): Use "markdown" to return Markdown (preserves links). Default is plain text.content (string): Scraped contenturl (string): The URL that was scrapedtitle (string): Page titlesuccess (boolean): Whether the scrape was successfulerror (string): Error message if scrape failed{
"content": "This is the content of the web page...",
"url": "https://example.com/page",
"title": "Example Page",
"success": true,
"error": null
}Markdown output example:
{
"content": "This is a [link](https://example.com) in Markdown...",
"url": "https://example.com/page",
"title": "Example Page",
"success": true,
"error": null
}#### web_browse Interactively browses a website using Playwright.
Note: web_browse requires Playwright browser binaries. Outside the container, install them with python -m playwright install chromium (or playwright install).
url (string, required): Starting URL for browsing sessioncontent (string): Page HTML contenturl (string): The final URL after any redirectstitle (string): Page titlesuccess (boolean): Whether the browsing was successfulerror (string): Error message if browsing failed{
"content": "<!DOCTYPE html><html>...</html>",
"url": "https://example.com/after_redirect",
"title": "Example Page",
"success": true,
"error": null
}The knowledge base system provides structured document storage with semantic search capabilities, RDF-style relationships, and metadata management. Documents are organized in a hierarchical namespace structure and support preferences (arbitrary RDF triples) and references (links between documents).
#### Document URI Format
Knowledge base documents use a structured URI format: kb://namespace/collection[/subcollection]*/name
Examples:
kb://projects/docs/api-referencekb://research/papers/machine-learning/transformerskb://personal/notes/meeting-2024-01-15#### kb_create_document Creates a new document in the knowledge base with optional metadata and content.
uri (string, required): Document URI in format "kb://namespace/collection[/subcollection]*/name"metadata (object, optional): Document metadata (default: {})content (string, optional): Document content (allows single-step create and write)content parameter, or use a two-step process by creating first and then adding content with kb_write_content.{
"namespace": "projects",
"collection": "docs",
"name": "api-reference",
"type": "document",
"subtype": "text",
"created_at": "2024-01-15T10:30:00.000Z",
"updated_at": "2024-01-15T10:30:00.000Z",
"content_type": "text/plain",
"chunked": false,
"fragments": {},
"preferences": [],
"references": [],
"referenced_by": [],
"indices": [],
"metadata": {"author": "John Doe", "version": "1.0"}
}#### kb_write_content Writes content to an existing document in the knowledge base.
uri (string, required): Document URIcontent (string, required): Document contentforce (boolean, optional): Whether to overwrite existing content (default: false)kb_create_document.{
"namespace": "projects",
"collection": "docs",
"name": "api-reference",
"type": "document",
"subtype": "text",
"created_at": "2024-01-15T10:30:00.000Z",
"updated_at": "2024-01-15T10:35:00.000Z",
"content_type": "text/plain",
"chunked": false,
"fragments": {},
"preferences": [],
"references": [],
"referenced_by": [],
"indices": [],
"metadata": {"author": "John Doe", "version": "1.0"}
}#### kb_read Reads document data from the knowledge base. When called without a uri, lists all documents (replacing the need for a separate list operation).
uri (string, optional): Document URI. If omitted, lists all documents.recursive (boolean, optional): Whether to list recursively (default: true)include_content (boolean, optional): Whether to include document content (default: false)include_index (boolean, optional): Whether to include document metadata (default: false)uri is omitted, returns a list of document URIsuri is a partial path (namespace or collection), returns multiple documentsuri is a full document path, returns a single documentReading a single document:
{
"status": "success",
"uri": "kb://projects/docs/api-reference",
"content": "This is the API reference content...",
"index": {
"namespace": "projects",
"collection": "docs",
"name": "api-reference",
"created_at": "2024-01-15T10:30:00Z",
"metadata": {"author": "John Doe"}
}
}Listing all documents (no uri):
{
"mode": "list",
"documents": [
"kb://projects/docs/api-reference",
"kb://projects/docs/user-guide",
"kb://research/papers/transformers"
],
"count": 3
}#### kb_update_triples Manages RDF triples (preferences, references, and metadata) for documents. This tool also handles metadata updates via triple_type="metadata", replacing the need for a separate metadata update operation.
action (string, required): Action to perform ("add" or "remove")triple_type (string, required): Type of triple ("preference", "reference", or "metadata")uri (string, required): Source document URIpredicate (string, required): Predicate of the tripleobject (string, optional): Object of the triple (for preferences and metadata)ref_uri (string, optional): Referenced document URI (for references only)Adding a preference (arbitrary RDF triple):
{
"status": "updated",
"preference_count": 3,
"action": "add",
"triple_type": "preference"
}Adding a reference (link to another document):
{
"status": "success",
"message": "Reference added",
"added": true,
"action": "add",
"triple_type": "reference"
}Updating metadata:
{
"status": "updated",
"action": "add",
"triple_type": "metadata"
}Removing a reference:
{
"status": "updated",
"reference_count": 2,
"action": "remove",
"triple_type": "reference"
}#### kb_search Searches the knowledge base using text queries and/or graph expansion.
query (string, optional): Text query for semantic search and rerankingseed_uris (array, optional): Starting full URIs (kb://namespace/collection/name) for graph expansionroot_uri (string, optional): Partial URI (kb://namespace or kb://namespace/collection) to scope searchexpand_hops (integer, optional): Number of relationship hops to expand (default: 0)filter_uris (array, optional): URIs to exclude from resultsrelation_predicates (array, optional): Predicates to follow during graph traversal (default: ["references"])top_k_sparse (integer, optional): Number of sparse search results to retrieve (default: 50)top_k_rerank (integer, optional): Number of final results after reranking (default: 10)include_content (boolean, optional): Whether to include document content (default: false)include_index (boolean, optional): Whether to include document metadata (default: false)use_reranker (boolean, optional): Whether to use semantic reranking (default: true){
"results": [
{
"urn": "kb://projects/docs/api-reference",
"sparse_score": 1.95,
"content": "API reference content...",
"index": {
"namespace": "projects",
"collection": "docs",
"name": "api-reference",
"type": "document",
"subtype": "text",
"created_at": "2025-07-02T23:13:17.362283Z",
"updated_at": "2025-07-02T23:18:23.396660Z",
"content_type": "text/plain",
"chunked": false,
"fragments": {},
"preferences": [],
"references": [
[
"references",
"kb://project/docs/api-dto"
]
],
"referenced_by": [],
"indices": [],
"metadata": {
"purpose": "testing_collection_organization",
"created_for": "kb_exercise",
"type": "test_document",
"created_date": "2025-07-02",
"topic": "search_performance",
"related_to": "rebuild_test"
}
},
"rerank_score": 0.84,
}
],
"count": 1
}#### kb_manage Manages knowledge base operations like moving documents and rebuilding search indices.
action (string, required): Management action to perform"move_document": Move a document"delete": Archive a document"rebuild_search_index": Rebuild search indicesoptions (object, required): Action-specific options"move_document": {"uri": "...", "new_uri": "..."}"delete": {"uri": "..."}"rebuild_search_index": {"rebuild_all": true} (optional)Moving a document:
{
"action": "move_document",
"status": "success",
"old_path": "projects/docs/old-name",
"new_path": "projects/docs/new-name",
"result": {
"namespace": "projects",
"collection": "docs",
"name": "new-name",
"type": "document",
"subtype": "text",
"created_at": "2024-01-15T10:30:00.000Z",
"updated_at": "2024-01-15T10:50:00.000Z",
"content_type": "text/plain",
"chunked": false,
"fragments": {},
"preferences": [],
"references": [],
"referenced_by": [],
"indices": [],
"metadata": {}
}
}Archiving a document:
{
"action": "delete",
"status": "success",
"path": "projects/docs/obsolete",
"result": {
"status": "archived",
"message": "Document archived: kb://projects/docs/obsolete",
"original_path": "projects/docs/obsolete",
"archive_path": "archive/projects/docs/obsolete",
"archive_urn": "kb://archive/projects/docs/obsolete"
}
}The list system provides org-mode based list management for tasks, notes, shopping, and general collections. Lists support various item statuses and can be tagged for organization.
#### Item Statuses
Items in lists can have the following statuses: TODO, DONE, WAITING, CANCELLED, NEXT, SOMEDAY
#### List Types
Lists can be one of: todo, shopping, notes, checklist, project, reading, ideas
#### list_create Creates a new organized list for tasks, notes, shopping, or any collection.
name (string, required): Internal name for the list (used for filename)title (string, optional): Display title for the listlist_type (string, optional): Type of list (default: "todo")description (string, optional): Optional descriptiontags (array, optional): Tags for organizationproperties (object, optional): Custom user-defined propertiessuccess (boolean): Whether creation succeededname (string): List namemetadata (object): Title, type, created timestamp, propertiespath (string): File path{
"success": true,
"name": "grocery-list",
"metadata": {
"title": "Weekly Groceries",
"type": "shopping",
"created": "2024-01-15T10:30:00.000Z",
"properties": {}
},
"path": "/app/lists/grocery-list.org"
}#### list_get Retrieves and browses lists with flexible filtering options.
name (string, optional): Name of specific list to retrieve. If omitted, lists all available lists.include_items (boolean, optional): Whether to include items in response (default: true)summary_only (boolean, optional): Return only summary statistics without items (default: false)status_filter (string, optional): Filter items by status (TODO, DONE, WAITING, CANCELLED, NEXT, SOMEDAY)tag_filter (array, optional): Filter items by tags (items must have ALL specified tags)name is omitted: lists (array of summaries), countname is provided: name, metadata, items, statisticsListing all lists:
{
"success": true,
"lists": [
{"name": "grocery-list", "title": "Weekly Groceries", "type": "shopping"},
{"name": "project-tasks", "title": "Q1 Tasks", "type": "todo"}
],
"count": 2
}Getting a specific list:
{
"success": true,
"name": "project-tasks",
"metadata": {"title": "Q1 Tasks", "type": "todo"},
"items": [
{
"text": "Complete API integration",
"status": "TODO",
"index": 0,
"tags": ["backend"],
"created": "2024-01-15T10:30:00.000Z",
"completed": null,
"properties": {}
}
],
"statistics": {
"total_items": 5,
"status_counts": {"TODO": 3, "DONE": 2},
"completion_percentage": 40.0
}
}#### list_modify Modifies list items by adding, updating, or removing them.
list_name (string, required): Name of the listaction (string, required): Operation to perform ("add", "update", or "remove")item_text (string, optional): Text of item (required for "add", optional for "update")item_index (integer, optional): Index of item (required for "update" and "remove")status (string, optional): Item status (TODO, DONE, WAITING, CANCELLED, NEXT, SOMEDAY)tags (array, optional): Tags for the itemproperties (object, optional): Custom propertiessuccess (boolean): Whether the operation succeededaction (string): The action performeditem (object): The affected item detailsAdding an item:
{
"success": true,
"action": "add",
"item": {
"text": "Buy milk",
"status": "TODO",
"index": 3,
"tags": ["dairy"]
},
"total_items": 4
}Updating an item:
{
"success": true,
"action": "update",
"item_index": 0,
"item": {"text": "Buy milk", "status": "DONE"},
"old_item": {"text": "Buy milk", "status": "TODO"}
}Removing an item:
{
"success": true,
"action": "remove",
"removed_item": {"text": "Buy milk", "status": "DONE", "index": 0},
"remaining_items": 3
}#### list_update Updates list properties and metadata. Properties use merge semantics — only provided keys are updated, existing keys are preserved.
name (string, required): Name of the listtitle (string, optional): New titlelist_type (string, optional): New list typedescription (string, optional): New descriptiontags (array, optional): New tags (replaces existing)author (string, optional): New authorproperties (object, optional): Custom properties (merged with existing)success (boolean): Whether the update succeededname (string): List namemetadata (object): Updated metadata{
"success": true,
"name": "project-tasks",
"metadata": {
"title": "Q1 Tasks - Updated",
"type": "project",
"tags": ["work", "q1"],
"description": "Updated project task list"
}
}#### list_delete Permanently deletes an entire list and all its items. The list file will be archived for safety but the list will no longer be accessible through normal operations.
name (string, required): Name of the list to deletesuccess (boolean): Whether the deletion succeededname (string): Deleted list nameitems_count (integer): Number of items that were in the listarchived_to (string): Archive file path{
"success": true,
"name": "old-grocery-list",
"items_count": 12,
"archived_to": "/app/lists/.archive/old-grocery-list.org"
}#### list_search Searches for items across multiple lists by text or tags.
query (string, required): Search query stringlist_names (array, optional): Specific lists to search in (searches all if omitted)search_in (array, optional): Where to search: "text", "tags", or both (default: ["text"])case_sensitive (boolean, optional): Whether search is case-sensitive (default: false)matches (array): List of matching items with list contexttotal_matches (integer): Total number of matcheslists_searched (integer): Number of lists searchedsearch_options (object): Applied search parameters{
"success": true,
"query": "milk",
"matches": [
{
"list_name": "grocery-list",
"list_title": "Weekly Groceries",
"item_index": 2,
"item_text": "Buy milk",
"item_status": "TODO",
"item_tags": ["dairy"],
"match_type": "text"
}
],
"total_matches": 1,
"lists_searched": 3,
"search_options": {
"search_in": ["text"],
"case_sensitive": false
}
}The market system provides financial data queries using Yahoo Finance for stocks and cryptocurrencies.
#### market_query Queries stock or cryptocurrency prices with fundamentals, news, and trend analysis.
symbol (string, required): Stock/crypto symbol (e.g., "AAPL", "BTC-USD", "TSLA")period (string, optional): Historical period for trend metrics (default: "1y")interval (string, optional): Historical data interval (default: "1d")news_count (integer, optional): Number of recent news items to return (default: 5)symbol (string): Queried symbolname (string): Company/asset nameprice (float): Current pricechange (float): Price changechange_percent (float): Percentage changevolume (integer): Trading volumemarket_cap (integer): Market capitalizationcurrency (string): Currency codetimestamp (string): ISO format timestampfundamentals (object): Earnings, PE ratios, dividends, marginsnews (array): Recent news itemstrend (object): Moving averages, RSI, volatility, historical returnssuccess (boolean): Whether the query succeedederror (string): Error message if query failed{
"symbol": "AAPL",
"name": "Apple Inc.",
"price": 185.92,
"change": 2.35,
"change_percent": 1.28,
"volume": 54321000,
"market_cap": 2890000000000,
"currency": "USD",
"timestamp": "2024-01-15T16:00:00Z",
"fundamentals": {
"trailing_pe": 29.5,
"forward_pe": 27.8,
"dividend_yield": 0.0054,
"profit_margin": 0.256,
"earnings_quarterly_growth": 0.13
},
"news": [
{
"title": "Apple Reports Strong Q4 Earnings",
"link": "https://example.com/article",
"publisher": "Reuters",
"published": "2024-01-15T12:00:00Z",
"type": "STORY"
}
],
"trend": {
"as_of": "2024-01-15T16:00:00Z",
"close": 185.92,
"return_1w": 0.023,
"return_1m": 0.045,
"return_3m": 0.12,
"ma20": 183.50,
"ma50": 180.25,
"ma200": 175.80,
"rsi14": 58.3,
"volatility_20d": 0.18,
"range_52w_low": 164.08,
"range_52w_high": 199.62,
"data_points": 252
},
"success": true,
"error": null
}The RSS system fetches and parses RSS and Atom feeds.
#### rss_fetch Fetches and parses an RSS or Atom feed, returning structured items.
url (string, required): RSS feed URLlimit (integer, optional): Maximum number of items to return (default: 10)feed_title (string): Title of the feedfeed_link (string): Link to the feed's websiteitems (array): Feed items, each with:title (string): Item titlelink (string): Item URLpublished (string): Publication datesummary (string): Item summary/descriptionitem_count (integer): Number of items returnedsuccess (boolean): Whether the fetch succeedederror (string): Error message if fetch failed{
"feed_title": "Hacker News",
"feed_link": "https://news.ycombinator.com",
"items": [
{
"title": "Show HN: A new open-source project",
"link": "https://example.com/project",
"published": "2024-01-15T14:30:00Z",
"summary": "An innovative approach to solving..."
}
],
"item_count": 10,
"success": true,
"error": null
}Container-MCP provides isolated execution environments for different types of operations, each with its own security measures and resource constraints.
The main Container-MCP service runs inside a container (using Podman or Docker) providing the first layer of isolation:
The Bash execution environment is configured with multiple isolation layers:
BASH_ALLOWED_COMMANDSExample allowed commands:
ls, cat, grep, find, echo, pwd, mkdir, touchThe Python execution environment is designed for secure code execution:
The file system environment controls access to files within the sandbox:
The web environment provides controlled access to external resources:
The knowledge base environment provides structured document storage and semantic search:
The list environment provides organized collection management:
The market environment provides controlled access to financial data:
The RSS environment provides feed fetching capabilities:
The project follows a modular architecture:
container-mcp/
├── cmcp/ # Main application code
│ ├── managers/ # Domain-specific managers
│ │ ├── bash_manager.py # Secure bash execution
│ │ ├── file_manager.py # Secure file operations
│ │ ├── knowledge_base_manager.py # Knowledge base operations
│ │ ├── list_manager.py # List/collection operations
│ │ ├── market_manager.py # Market data operations
│ │ ├── python_manager.py # Secure python execution
│ │ ├── rss_manager.py # RSS feed operations
│ │ └── web_manager.py # Secure web operations
│ ├── kb/ # Knowledge base components
│ │ ├── document_store.py # Document storage and retrieval
│ │ ├── models.py # Data models and schemas
│ │ ├── path.py # Path parsing and validation
│ │ └── search.py # Search indices and ranking
│ ├── tools/ # MCP tool implementations
│ │ ├── file.py # File operation tools
│ │ ├── kb.py # Knowledge base tools
│ │ ├── list.py # List operation tools
│ │ ├── market.py # Market data tools
│ │ ├── rss.py # RSS feed tools
│ │ ├── system.py # System operation tools
│ │ └── web.py # Web operation tools
│ ├── utils/ # Utility functions
│ │ ├── diff.py # Diff/patch utilities
│ │ ├── io.py # I/O helpers
│ │ └── logging.py # Logging utilities
│ ├── __init__.py
│ ├── config.py # Configuration system
│ └── main.py # MCP server setup
├── apparmor/ # AppArmor profiles
│ ├── mcp-bash # Bash execution profile
│ └── mcp-python # Python execution profile
├── bin/ # Build/run scripts
│ ├── 00-all-in-one.sh # Complete setup script
│ ├── 01-init.sh # Project initialization
│ ├── 02-build-container.sh # Container build script
│ ├── 03-setup-environment.sh # Environment setup
│ ├── 04-run-container.sh # Container run script
│ ├── 05-check-container.sh # Container health check
│ ├── 06-run-tests.sh # Test execution
│ ├── 07-attach-container.sh # Container shell access
│ ├── 08-testnetwork.sh # Network testing
│ ├── 09-view-logs.sh # Log viewing
│ ├── zy-shutdown.sh # Container shutdown
│ └── zz-teardown.sh # Complete teardown
├── tests/ # Test suites
│ ├── integration/ # Integration tests
│ ├── unit/ # Unit tests
│ └── conftest.py # Test configuration
├── volume/ # Persistent storage
│ ├── config/ # Configuration files
│ ├── data/ # Data directory
│ ├── kb/ # Knowledge base storage
│ │ ├── search/ # Search indices
│ │ │ ├── sparse_idx/ # Sparse search index
│ │ │ └── graph_idx/ # Graph search index
│ │ ├── archive/ # Archived documents
│ ├── logs/ # Log files
│ ├── sandbox/ # Sandboxed execution space
│ │ ├── bash/ # Bash sandbox
│ │ ├── browser/ # Web browser sandbox
│ │ ├── files/ # File operation sandbox
│ │ └── python/ # Python sandbox
│ └── temp/ # Temporary storage
├── Containerfile # Container definition
├── podman-compose.yml # Container orchestration
├── pyproject.toml # Python project configuration
├── uv.lock # Dependency lock file
├── pytest.ini # Test configuration
└── README.md # Project documentationEach manager follows consistent design patterns:
.from_env() class method for environment-based initializationContainer-MCP implements multiple layers of security:
apt install firejail or dnf install firejail)apt install apparmor apparmor-utils or dnf install apparmor apparmor-utils)The quickest way to get started is to use the all-in-one script:
git clone https://github.com/54rt1n/container-mcp.git
cd container-mcp
chmod +x bin/00-all-in-one.sh
./bin/00-all-in-one.shYou can also perform the installation steps individually:
./bin/01-init.sh ./bin/02-build-container.sh ./bin/03-setup-environment.sh ./bin/04-run-container.sh ./bin/05-run-tests.shOnce the container is running, you can connect to it using any MCP client implementation. The server will be available at http://localhost:8000 or the port specified in your configuration.
Important: When configuring your MCP client, you must set the endpoint URL to http://127.0.0.1:<port>/sse (where <port> is 8000 by default or the port you've configured). The /sse path is required for proper server-sent events communication.
from mcp.client.sse import sse_client
from mcp import ClientSession
import asyncio
async def main():
# Connect to the Container-MCP server
# Note the /sse endpoint suffix required for SSE communication
sse_url = "http://127.0.0.1:8000/sse" # Or your configured port
# Connect to the SSE endpoint
async with sse_client(sse_url) as (read, write):
async with ClientSession(read, write) as session:
# Initialize the connection
await session.initialize()
# Discover available tools
result = await session.list_tools()
print(f"Available tools: {[tool.name for tool in result.tools]}")
# Execute a Python script
python_result = await session.execute_tool(
"system_run_python",
{"code": "print('Hello, world!')\nresult = 42\n_ = result"}
)
print(f"Python result: {python_result}")
# Execute a bash command
bash_result = await session.execute_tool(
"system_run_command",
{"command": "ls -la"}
)
print(f"Command output: {bash_result['stdout']}")
if __name__ == "__main__":
asyncio.run(main())Container-MCP can be configured through environment variables, which can be set in volume/config/custom.env:
# MCP Server Configuration
MCP_HOST=127.0.0.1
MCP_PORT=9001
DEBUG=true
LOG_LEVEL=INFO# Bash Manager Configuration
BASH_ALLOWED_COMMANDS=ls,cat,grep,find,echo,pwd,mkdir,touch
BASH_TIMEOUT_DEFAULT=30
BASH_TIMEOUT_MAX=120# Python Manager Configuration
PYTHON_MEMORY_LIMIT=256
PYTHON_TIMEOUT_DEFAULT=30
PYTHON_TIMEOUT_MAX=120# File Manager Configuration
FILE_MAX_SIZE_MB=10
FILE_ALLOWED_EXTENSIONS=txt,md,csv,json,py# Web Manager Configuration
WEB_TIMEOUT_DEFAULT=30
WEB_ALLOWED_DOMAINS=*# Knowledge Base Manager Configuration
CMCP_KB_STORAGE_PATH=/app/kb
KB_TIMEOUT_DEFAULT=30
KB_TIMEOUT_MAX=120
# Search Configuration
CMCP_KB_SEARCH_ENABLED=true
CMCP_KB_SPARSE_INDEX_PATH=/app/kb/search/sparse_idx
CMCP_KB_GRAPH_INDEX_PATH=/app/kb/search/graph_idx
CMCP_KB_RERANKER_MODEL=mixedbread-ai/mxbai-rerank-base-v1
CMCP_KB_SEARCH_RELATION_PREDICATES=references
CMCP_KB_SEARCH_GRAPH_NEIGHBOR_LIMIT=1000
# Tool Enable/Disable
TOOLS_ENABLE_KB=true# List Manager Configuration
CMCP_LIST_STORAGE_PATH=/app/lists
TOOLS_ENABLE_LIST=true# Market Manager Configuration
MARKET_TIMEOUT_DEFAULT=30
MARKET_TIMEOUT_MAX=60
TOOLS_ENABLE_MARKET=true# RSS Manager Configuration
RSS_TIMEOUT_DEFAULT=15
RSS_TIMEOUT_MAX=30
RSS_USER_AGENT=container-mcp/1.0
TOOLS_ENABLE_RSS=true python3.12 -m venv .venv
source .venv/bin/activate pip install -r requirements-dev.txt pip install -e .# Run all tests
pytest
# Run only unit tests
pytest tests/unit
# Run only integration tests
pytest tests/integration
# Run with coverage report
pytest --cov=cmcp --cov-report=term --cov-report=htmlTo run the MCP server in development mode:
python -m cmcp.main --test-modeThis project is licensed under the Apache License 2.0.
Martin Bukowski
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.