Refactor MCP server and enhance development environment
This commit refactors the MCP server implementation, updates the Dockerfile with new development tools and dependencies, introduces a Makefile for building and running the application, and adds utility modules for sandbox management and Ollama integration. The server name has also been updated from 'echo-server' to 'PMO-Crazy-coder' in the configuration.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
reseau
|
reseau
|
||||||
|
context
|
||||||
|
|
||||||
# ---> macOS
|
# ---> macOS
|
||||||
# General
|
# General
|
||||||
|
|||||||
12
.zed/settings.json
Normal file
12
.zed/settings.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// Folder-specific settings
|
||||||
|
//
|
||||||
|
// For a full list of overridable settings, and general information on folder-specific settings,
|
||||||
|
// see the documentation: https://zed.dev/docs/configuring-zed#settings-files
|
||||||
|
{
|
||||||
|
"inlay_hints": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"colorize_brackets": true,
|
||||||
|
"project_name": "PMO Crazy Coder",
|
||||||
|
"autosave": "on_window_change",
|
||||||
|
}
|
||||||
51
Dockerfile
51
Dockerfile
@@ -1,16 +1,61 @@
|
|||||||
# Dockerfile
|
# Dockerfile
|
||||||
FROM python:3.11-slim
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
# Ajouter le dépôt Debian Testing pour les paquets plus récents
|
||||||
|
RUN echo "deb http://deb.debian.org/debian testing main" \
|
||||||
|
> /etc/apt/sources.list.d/testing.list
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Installer les outils de développement Go et Rust
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y \
|
||||||
|
clang \
|
||||||
|
llvm-dev \
|
||||||
|
libclang-dev \
|
||||||
|
pkg-config \
|
||||||
|
build-essential \
|
||||||
|
git \
|
||||||
|
make \
|
||||||
|
curl \
|
||||||
|
nodejs \
|
||||||
|
npm \
|
||||||
|
pylint \
|
||||||
|
black \
|
||||||
|
flake8 \
|
||||||
|
mypy \
|
||||||
|
isort
|
||||||
|
|
||||||
|
COPY tools tools
|
||||||
|
|
||||||
|
# Installer la dernière version de Go
|
||||||
|
RUN bash tools/install_latest_go.sh
|
||||||
|
ENV PATH=/usr/local/go/bin:$PATH
|
||||||
|
|
||||||
|
# Installer la dernière version de Rust
|
||||||
|
ENV RUSTUP_HOME=/usr/local/rustup
|
||||||
|
ENV CARGO_HOME=/usr/local/cargo
|
||||||
|
ENV PATH=/usr/local/cargo/bin:$PATH
|
||||||
|
RUN curl https://sh.rustup.rs -sSf \
|
||||||
|
| sh -s -- -y --default-toolchain stable \
|
||||||
|
&& rustup install nightly \
|
||||||
|
&& rustup component add rustfmt clippy rust-src rust-docs \
|
||||||
|
&& cargo install cargo-edit cargo-watch cargo-outdated cargo-make cargo-binstall
|
||||||
|
|
||||||
|
# Installer la dernière version de typscript
|
||||||
|
RUN npm install -g typescript tsc @types/node eslint prettier
|
||||||
|
|
||||||
|
RUN cargo binstall --strategies crate-meta-data jj-cli
|
||||||
|
|
||||||
# Installer le SDK MCP Python
|
# Installer le SDK MCP Python
|
||||||
RUN pip install --no-cache-dir fastmcp
|
RUN pip install --no-cache-dir ruff fastmcp ipython
|
||||||
|
|
||||||
# Copier le serveur
|
# Copier le serveur
|
||||||
COPY src/* .
|
COPY src .
|
||||||
|
|
||||||
# Exposer le port
|
# Exposer le port
|
||||||
EXPOSE 6666
|
EXPOSE 6666
|
||||||
|
ENV OLLAMA_ADDR="http://host.docker.internal:11434"
|
||||||
|
|
||||||
# Lancer le serveur
|
# Lancer le serveur
|
||||||
CMD ["python", "./mon_mcp.py"]
|
CMD ["python", "./PMOCrazyCoder.py"]
|
||||||
|
|||||||
33
Makefile
Normal file
33
Makefile
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
.PHONY: build run all debug
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
IMAGE_NAME = pmo_crazy_coder
|
||||||
|
TAG = latest
|
||||||
|
PORT = 7860
|
||||||
|
DOCKER_RUN_COMMON = --rm -p $(PORT):$(PORT) -v ./bac_a_sable:/sandbox
|
||||||
|
FULL_IMAGE_NAME = $(IMAGE_NAME):$(TAG)
|
||||||
|
|
||||||
|
all: run
|
||||||
|
|
||||||
|
$(SANDBOX_VOLUME):
|
||||||
|
mkdir -p $(SANDBOX_VOLUME)
|
||||||
|
|
||||||
|
stampdir:
|
||||||
|
mkdir -p stamp
|
||||||
|
|
||||||
|
stamp/build_PMOCrazyCoder: stampdir Dockerfile
|
||||||
|
@echo building the PMOCrazyCoder server
|
||||||
|
@docker build -t $(FULL_IMAGE_NAME) .
|
||||||
|
@touch $@
|
||||||
|
|
||||||
|
build: stamp/build_PMOCrazyCoder
|
||||||
|
run: build
|
||||||
|
@echo Launching the PMOCrazyCoder MCP server
|
||||||
|
@docker run $(DOCKER_RUN_COMMON) \
|
||||||
|
$(FULL_IMAGE_NAME)
|
||||||
|
|
||||||
|
debug: build
|
||||||
|
@echo Launching the PMOCrazyCoder MCP server in debug mode
|
||||||
|
@docker run $(DOCKER_RUN_COMMON) \
|
||||||
|
-it \
|
||||||
|
$(FULL_IMAGE_NAME) /bin/bash
|
||||||
49
Notes/jj_to_json.md
Normal file
49
Notes/jj_to_json.md
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
```bash
|
||||||
|
jj log | orla agent -m ollama:qwen3:0.6b \
|
||||||
|
"
|
||||||
|
Transform the following `jj log` output into JSON according to the given schema.
|
||||||
|
|
||||||
|
**Return only valid JSON, without any Markdown formatting :**
|
||||||
|
- no backticks,
|
||||||
|
- no code blocks,
|
||||||
|
- no extra text
|
||||||
|
|
||||||
|
Schema:
|
||||||
|
{
|
||||||
|
\"type\": \"array\",
|
||||||
|
\"items\": {
|
||||||
|
\"type\": \"object\",
|
||||||
|
\"properties\": {
|
||||||
|
\"hash\": {\"type\": \"string\"},
|
||||||
|
\"author\": {\"type\": \"string\"},
|
||||||
|
\"date\": {\"type\": \"string\"},
|
||||||
|
\"message\": {\"type\": \"string\"}
|
||||||
|
},
|
||||||
|
\"required\": [\"hash\", \"author\", \"date\", \"message\"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
" | grep -v '```' | jq .
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"hash": "252b5de3",
|
||||||
|
"author": "nrrwwpms",
|
||||||
|
"date": "2026-01-25 17:36:18",
|
||||||
|
"message": "(no description set)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hash": "9f9d9bc3",
|
||||||
|
"author": "stxkzlul",
|
||||||
|
"date": "2026-01-25 12:08:12",
|
||||||
|
"message": "Ajout de Dockerfile et configuration MCP"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hash": "7412b51a",
|
||||||
|
"author": "xnrxukn",
|
||||||
|
"date": "2026-01-25 07:53:42",
|
||||||
|
"message": "Initial commit"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://opencode.ai/config.json",
|
"$schema": "https://opencode.ai/config.json",
|
||||||
"mcp": {
|
"mcp": {
|
||||||
"echo-server": {
|
"PMO-Crazy-coder": {
|
||||||
"type": "remote",
|
"type": "remote",
|
||||||
"url": "http://localhost:7860/mcp"
|
"url": "http://localhost:7860/mcp"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
from fastmcp import FastMCP
|
from crazy_mcp import mcp
|
||||||
|
from sandbox.mcp import install_project_tool
|
||||||
# Création du serveur MCP
|
|
||||||
mcp = FastMCP("Serveur Echo MCP")
|
|
||||||
|
|
||||||
|
|
||||||
# Déclaration d'un outil
|
# Déclaration d'un outil
|
||||||
3
src/crazy_mcp/__init__.py
Normal file
3
src/crazy_mcp/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from fastmcp import FastMCP
|
||||||
|
|
||||||
|
mcp = FastMCP("PMO Crazy coder")
|
||||||
50
src/json_extract/__init__.py
Normal file
50
src/json_extract/__init__.py
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import json
|
||||||
|
import re
|
||||||
|
from ollama import prompt
|
||||||
|
|
||||||
|
|
||||||
|
def structure_to_json(text, schema):
|
||||||
|
"""
|
||||||
|
Convert structured text to JSON using Ollama.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
text (str): The structured text to convert
|
||||||
|
schema (dict): The JSON schema to use for conversion
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: The parsed JSON object
|
||||||
|
"""
|
||||||
|
# Format the schema as JSON string
|
||||||
|
schema_json = json.dumps(schema, indent=2)
|
||||||
|
|
||||||
|
# Create the prompt following the pattern from your bash command
|
||||||
|
full_prompt = f"""Transform the following structured text into JSON according to the given schema.
|
||||||
|
|
||||||
|
**Return only valid JSON, without any Markdown formatting :**
|
||||||
|
- no backticks,
|
||||||
|
- no code blocks,
|
||||||
|
- no extra text
|
||||||
|
|
||||||
|
Input text:
|
||||||
|
{text}
|
||||||
|
|
||||||
|
Schema:
|
||||||
|
{schema_json}"""
|
||||||
|
|
||||||
|
# Send to Ollama
|
||||||
|
response = prompt("ollama:qwen3:0.6b", full_prompt, allow_pull=True)
|
||||||
|
|
||||||
|
# Remove any markdown formatting (backticks, code blocks) that Ollama might include
|
||||||
|
# Only remove backticks at the beginning or end of the response, not those within the JSON
|
||||||
|
clean_response = response.strip()
|
||||||
|
while clean_response.startswith("`") or clean_response.startswith("```"):
|
||||||
|
clean_response = clean_response[1:].strip()
|
||||||
|
while clean_response.endswith("`") or clean_response.endswith("```"):
|
||||||
|
clean_response = clean_response[:-1].strip()
|
||||||
|
|
||||||
|
# Try to parse the response as JSON
|
||||||
|
try:
|
||||||
|
return json.loads(clean_response)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
# If parsing fails, return the raw response
|
||||||
|
return {"error": "Failed to parse JSON", "raw_response": clean_response}
|
||||||
1
src/jujutsu/__init__.py
Normal file
1
src/jujutsu/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
from .command import jj
|
||||||
87
src/jujutsu/command.py
Normal file
87
src/jujutsu/command.py
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
import json
|
||||||
|
import subprocess
|
||||||
|
from typing import List, Optional
|
||||||
|
|
||||||
|
|
||||||
|
def jj(
|
||||||
|
subcommand: str,
|
||||||
|
options: Optional[List[str]] = None,
|
||||||
|
args: Optional[List[str]] = None,
|
||||||
|
template: Optional[str] = None,
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
Lance une commande jj.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
subcommand: La sous-commande jj (ex: 'log', 'status', 'diff')
|
||||||
|
options: Liste des options (ex: ['--limit', '5'])
|
||||||
|
args: Liste des arguments additionnels
|
||||||
|
template: Template jj à utiliser (ex: 'builtin_log_compact')
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: sortie de la commande
|
||||||
|
"""
|
||||||
|
cmd = ["jj", subcommand]
|
||||||
|
|
||||||
|
# Ajoute le template spécifié
|
||||||
|
if template:
|
||||||
|
cmd.extend(["--template", template])
|
||||||
|
|
||||||
|
if options:
|
||||||
|
cmd.extend(options)
|
||||||
|
if args:
|
||||||
|
cmd.extend(args)
|
||||||
|
|
||||||
|
result = subprocess.run(cmd, capture_output=True, text=True)
|
||||||
|
|
||||||
|
if result.returncode != 0:
|
||||||
|
raise RuntimeError(
|
||||||
|
f"Commande jj échouée: {' '.join(cmd)}\nstderr: {result.stderr}"
|
||||||
|
)
|
||||||
|
|
||||||
|
return result.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def jj_log(options=None, args=None, template=None):
|
||||||
|
"""
|
||||||
|
Execute jj log command with optional arguments.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
options: List of options to pass to jj log (ex: ['--limit', '5'])
|
||||||
|
args: List of additional arguments
|
||||||
|
template: Template to use (ex: 'builtin_log_compact')
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Output of the jj log command
|
||||||
|
"""
|
||||||
|
return jj("log", options, args, template)
|
||||||
|
|
||||||
|
|
||||||
|
def jj_clone(url, destination=None, options=None):
|
||||||
|
"""
|
||||||
|
Execute jj git clone command.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
url: The repository URL to clone
|
||||||
|
destination: The destination directory (optional)
|
||||||
|
options: List of additional options for jj git clone
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Output of the jj git clone command
|
||||||
|
"""
|
||||||
|
cmd = ["jj", "git", "clone", url]
|
||||||
|
|
||||||
|
if destination:
|
||||||
|
cmd.append(destination)
|
||||||
|
|
||||||
|
if options:
|
||||||
|
cmd.extend(options)
|
||||||
|
|
||||||
|
result = subprocess.run(cmd, capture_output=True, text=True)
|
||||||
|
|
||||||
|
if result.returncode != 0:
|
||||||
|
raise RuntimeError(
|
||||||
|
f"Commande jj git clone échouée: {' '.join(cmd)}\nstderr: {result.stderr}"
|
||||||
|
)
|
||||||
|
|
||||||
|
return result.stdout
|
||||||
83
src/ollama/__init__.py
Normal file
83
src/ollama/__init__.py
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
# Get Ollama server address from environment variable, default to local address
|
||||||
|
ollama_addr = os.environ.get("OLLAMA_ADDR", "http://host.docker.internal:11434")
|
||||||
|
|
||||||
|
|
||||||
|
def prompt(model, text, allow_pull=False):
|
||||||
|
"""
|
||||||
|
Send a prompt to Ollama server and return the response.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
model (str): The model to use
|
||||||
|
text (str): The prompt text to send
|
||||||
|
allow_pull (bool): If True, automatically download the model if not available
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The response from the Ollama server
|
||||||
|
"""
|
||||||
|
# Check if model is available
|
||||||
|
if allow_pull and not is_model_available(model):
|
||||||
|
# Try to pull the model
|
||||||
|
pull_result = pull_model(model)
|
||||||
|
if not pull_result.startswith("Model downloaded successfully"):
|
||||||
|
return pull_result # Return error from pull
|
||||||
|
|
||||||
|
url = f"{ollama_addr}/api/generate"
|
||||||
|
|
||||||
|
payload = {"model": model, "prompt": text, "stream": False}
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.post(url, json=payload)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()["response"]
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
return f"Error: {str(e)}"
|
||||||
|
|
||||||
|
|
||||||
|
def pull_model(model_name, force=False):
|
||||||
|
"""
|
||||||
|
Download a model from Ollama.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
model_name (str): The name of the model to download
|
||||||
|
force (bool): If True, forces download even if model already exists
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Success message or error message
|
||||||
|
"""
|
||||||
|
url = f"{ollama_addr}/api/pull"
|
||||||
|
|
||||||
|
payload = {"name": model_name}
|
||||||
|
if force:
|
||||||
|
payload["force"] = True
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.post(url, json=payload)
|
||||||
|
response.raise_for_status()
|
||||||
|
return "Model downloaded successfully"
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
return f"Error downloading model: {str(e)}"
|
||||||
|
|
||||||
|
|
||||||
|
def is_model_available(model_name):
|
||||||
|
"""
|
||||||
|
Check if a model is available in Ollama.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
model_name (str): The name of the model to check
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if model is available, False otherwise
|
||||||
|
"""
|
||||||
|
url = f"{ollama_addr}/api/tags"
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.get(url)
|
||||||
|
response.raise_for_status()
|
||||||
|
models = response.json().get("models", [])
|
||||||
|
return any(model.get("name") == model_name for model in models)
|
||||||
|
except requests.exceptions.RequestException:
|
||||||
|
return False
|
||||||
82
src/sandbox/__init__.py
Normal file
82
src/sandbox/__init__.py
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
import os
|
||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
from jujutsu.command import jj_clone
|
||||||
|
|
||||||
|
__sandbox_root__ = "/sandbox"
|
||||||
|
|
||||||
|
# Create the sandbox root directory if it doesn't exist
|
||||||
|
os.makedirs(__sandbox_root__, exist_ok=True)
|
||||||
|
|
||||||
|
|
||||||
|
def get_sandbox_root():
|
||||||
|
"""Return the sandbox root directory path."""
|
||||||
|
return __sandbox_root__
|
||||||
|
|
||||||
|
|
||||||
|
def install_project(url, project_name=None):
|
||||||
|
"""
|
||||||
|
Clone a Git project into the sandbox root directory.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
url: The Git repository URL to clone
|
||||||
|
project_name: Optional project name (if None, derived from URL)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The name of the cloned project
|
||||||
|
"""
|
||||||
|
# If no project name is provided, derive it from the URL
|
||||||
|
if project_name is None:
|
||||||
|
# Extract project name from URL (e.g., from 'https://github.com/user/repo.git' get 'repo')
|
||||||
|
project_name = re.sub(r".*/([^/]+?)(?:\.git)?$", r"\1", url)
|
||||||
|
|
||||||
|
# Create the full path for the project
|
||||||
|
project_path = os.path.join(__sandbox_root__, project_name)
|
||||||
|
|
||||||
|
# Clone the repository
|
||||||
|
jj_clone(url, destination=project_path)
|
||||||
|
|
||||||
|
return project_name
|
||||||
|
|
||||||
|
|
||||||
|
def remove_project(project_name):
|
||||||
|
"""
|
||||||
|
Remove a project from the sandbox.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
project_name (str): The name of the project to remove
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if the project was removed successfully, False otherwise
|
||||||
|
"""
|
||||||
|
project_path = os.path.join(__sandbox_root__, project_name)
|
||||||
|
|
||||||
|
try:
|
||||||
|
if os.path.exists(project_path):
|
||||||
|
shutil.rmtree(project_path)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
except (OSError, PermissionError):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def sandboxed_project_list():
|
||||||
|
"""
|
||||||
|
List all projects available in the sandbox.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: A list of project names (strings)
|
||||||
|
"""
|
||||||
|
projects = []
|
||||||
|
try:
|
||||||
|
with os.scandir(__sandbox_root__) as entries:
|
||||||
|
for entry in entries:
|
||||||
|
if entry.is_dir():
|
||||||
|
projects.append(entry.name)
|
||||||
|
except (OSError, PermissionError):
|
||||||
|
# Return empty list if we can't access the directory
|
||||||
|
pass
|
||||||
|
|
||||||
|
return projects
|
||||||
51
src/sandbox/mcp.py
Normal file
51
src/sandbox/mcp.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
from sandbox import install_project, sandboxed_project_list, remove_project
|
||||||
|
from crazy_mcp import mcp
|
||||||
|
|
||||||
|
|
||||||
|
@mcp.tool(
|
||||||
|
description="Clone a Git repository into the sandbox. Note: Access to the cloned project is only possible through MCP tools of this server."
|
||||||
|
)
|
||||||
|
def install_project_tool(url: str, project_name: str = None) -> str:
|
||||||
|
"""
|
||||||
|
Install a Git project into the sandbox environment.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
url: The Git repository URL to clone
|
||||||
|
project_name: Optional project name (if None, derived from URL)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Confirmation message with project name
|
||||||
|
"""
|
||||||
|
project_name = install_project(url, project_name)
|
||||||
|
return f"Project '{project_name}' installed successfully in sandbox"
|
||||||
|
|
||||||
|
|
||||||
|
@mcp.tool(
|
||||||
|
description="Remove a project from the sandbox. Note: Access to the cloned project is only possible through MCP tools of this server."
|
||||||
|
)
|
||||||
|
def remove_project_tool(project_name: str) -> str:
|
||||||
|
"""
|
||||||
|
Remove a project from the sandbox environment.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
project_name (str): The name of the project to remove
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Confirmation message with project name
|
||||||
|
"""
|
||||||
|
success = remove_project(project_name)
|
||||||
|
if success:
|
||||||
|
return f"Project '{project_name}' removed successfully from sandbox"
|
||||||
|
else:
|
||||||
|
return f"Failed to remove project '{project_name}' from sandbox"
|
||||||
|
|
||||||
|
|
||||||
|
@mcp.tool(description="List all projects available in the sandbox")
|
||||||
|
def list_sandboxed_projects() -> list:
|
||||||
|
"""
|
||||||
|
Get a list of all projects available in the sandbox.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: A list of project names
|
||||||
|
"""
|
||||||
|
return sandboxed_project_list()
|
||||||
0
stamp/build_PMOCrazyCoder
Normal file
0
stamp/build_PMOCrazyCoder
Normal file
33
tools/install_latest_go.sh
Normal file
33
tools/install_latest_go.sh
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
URL="https://go.dev/dl/"
|
||||||
|
|
||||||
|
OS=$(uname -a | awk '{print $1}')
|
||||||
|
ARCH=$(uname -m)
|
||||||
|
|
||||||
|
if [[ "$ARCH" == "x86_64" ]] ; then
|
||||||
|
ARCH="amd64"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$ARCH" == "aarch64" ]] ; then
|
||||||
|
ARCH="arm64"
|
||||||
|
fi
|
||||||
|
|
||||||
|
GOFILE=$(curl "$URL" \
|
||||||
|
| grep 'class="download"' \
|
||||||
|
| grep "\.tar\.gz" \
|
||||||
|
| sed -E 's@^.*/dl/(go[1-9].+\.tar\.gz)".*$@\1@' \
|
||||||
|
| grep -i "$OS" \
|
||||||
|
| grep -i "$ARCH" \
|
||||||
|
| head -1)
|
||||||
|
|
||||||
|
GOURL=$(curl "${URL}${GOFILE}" \
|
||||||
|
| sed -E 's@^.*href="(.*\.tar\.gz)".*$@\1@')
|
||||||
|
|
||||||
|
echo "Install GO from : $GOURL" 1>&2
|
||||||
|
|
||||||
|
mkdir -p /usr/local
|
||||||
|
cd /usr/local
|
||||||
|
|
||||||
|
curl "$GOURL" \
|
||||||
|
| tar zxf -
|
||||||
Reference in New Issue
Block a user