MCPCloud
MCPCloud
Self-hosted MCP (Model Context Protocol) gateway. Write any Python function, register it as a skill, and it instantly becomes a tool that Claude Desktop, Claude API, Cursor, or any MCP-compatible client can call.
Website: mcpcloud.dev · Demo: demo.mcpcloud.dev · GitHub: carsor007/mcpcloud
How it works
Claude Desktop / Claude API / any MCP client
↓ MCP tool call
MCPCloud (this repo)
↓ your code runs
Jira · Slack · Salesforce · anythingEvery Python function registered as a skill becomes an MCP tool. No vendor lock-in, no proprietary agent framework — just functions.
Quickstart
Deploy to Cloud
Subscribe on AWS Marketplace for a fully managed deployment on ECS Fargate — no Docker, no ECR setup, no servers to manage. Includes a 7-day free trial.
Run locally with Docker
git clone https://github.com/carsor007/mcpcloud.git
cd mcpcloud
cp .env.example .env
docker compose upOpen http://localhost:8000/ui — the tool browser shows all registered skills.
Connect an MCP client
MCPCloud exposes a config endpoint for every agent type. Use it to generate a ready-to-paste snippet for any MCP client.
Claude Desktop
Install Claude Desktop from claude.ai/download
Get the config snippet for the skills you want:
curl http://localhost:8000/mcp/jira_ops/configOpen (or create)
~/Library/Application Support/Claude/claude_desktop_config.jsonand add the returned snippet undermcpServers:
{
"mcpServers": {
"jira_ops": {
"url": "http://localhost:8000/mcp/jira_ops",
"transport": "http"
},
"slack_ops": {
"url": "http://localhost:8000/mcp/slack_ops",
"transport": "http"
}
}
}Restart Claude Desktop. Your skills appear as tools in every conversation.
Cloud deployment: replace
http://localhost:8000with your MCPCloud URL (e.g.https://demo.mcpcloud.dev).
Cursor
Add the same JSON to .cursor/mcp.json in your project root, or globally at ~/.cursor/mcp.json. The URL and transport fields are identical.
Claude API (programmatic)
Pass the MCP server URL when initializing a client session — the endpoint follows the MCP 2025-03-26 spec over HTTP.
Adding a skill
Two ways to add a skill: drop a file into skills/ (loaded on startup, lives in your repo), or use the browser editor (saved to Redis, live immediately, no restart or redeploy).
Option A: filesystem
Drop a .py file into skills/. Any file with a register_all() function is loaded automatically on startup.
# skills/my_tools.py
from registry import SkillResult, get_registry
async def my_skill(input: dict, context: dict) -> SkillResult:
'''One-line description shown in the UI.'''
return SkillResult(success=True, output={"result": input.get("text", "")})
def register_all():
get_registry().register(
"my_tools", # agent type — groups skills in the sidebar
"my_skill", # skill name — shown under the group
my_skill,
schema={
"type": "object",
"required": ["text"],
"properties": {
"text": {"type": "string", "description": "Input text"}
}
}
)Restart the server. The skill appears in the UI and is immediately callable as an MCP tool.
Option B: browser editor
Open /ui/skills for a Monaco-based editor — no filesystem or restart required. Write an async function whose name matches the skill name:
async def my_skill(input: dict, ctx: dict) -> dict:
"""One-line description shown in the UI."""
return {"success": True, "result": input.get("text", "")}
# Optional: JSON Schema for inputs shown in the tool browser
# SCHEMA = {"type": "object", "properties": {"text": {"type": "string"}}}Saving POSTs the code to /api/skills, where it's stored in Redis (or in-memory if Redis isn't configured) and registered immediately — the skill is callable as soon as you save, with no restart. This is a separate store from the filesystem skills in skills/, so it survives redeploys of the container image but not a Redis wipe; check code in with Option A if you want it version-controlled.
Included skills
Both work out of the box — real API calls run when credentials are configured, stub data is returned otherwise.
jira_ops
Skill | Description |
| Create a Jira issue with priority, type, and description |
| Fetch status, assignee, and priority by issue key |
| Run a JQL query and return a summary list |
Configure by setting JIRA_URL, JIRA_EMAIL, JIRA_API_TOKEN in .env.
slack_ops
Skill | Description |
| Post a message to a channel with optional field grid |
| Send an urgent alert with severity badge — critical sends |
Configure by setting SLACK_WEBHOOK_URL in .env.
Audit log
Every tool call is recorded — caller, tool name, arguments, success/failure, and latency — and available at:
UI:
http://localhost:8000/ui/audit— live table, auto-refreshes every 3s, filterable by agent type/skill nameAPI:
GET /api/audit?agent_type=jira_ops&skill_name=get_ticket&limit=100
Entries are also emitted as structured JSON log lines, so they flow into CloudWatch Logs (or any log pipeline) for SIEM ingestion. Backed by Redis when REDIS_URL is set (survives restarts, shared across workers); falls back to an in-memory ring buffer otherwise.
Configuration
Variable | Required | Description |
| No | Enables multi-worker session tracking. Set automatically in Docker Compose and CloudFormation. |
| No | e.g. |
| No | Atlassian account email |
| No | |
| No | Default project key (default: |
| No | |
| No | Required only by skills that call Claude |
| No | Required only by skills that call OpenAI |
License
Apache 2.0 — see LICENSE.
Free to self-host. Managed deployment available on AWS Marketplace.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/carsor007/mcpcloud'
If you have feedback or need assistance with the MCP directory API, please join our Discord server