Enhance Docker setup with new tools and configurations
Update Dockerfile to install additional tools (orla, rust-analyzer), configure user permissions, and set up bash completion. Update docker-entrypoint.sh to export new environment variables and configure MCP language servers for multiple languages (Go, Python, Rust, TypeScript) with proper workspace and LSP settings. Add new documentation file AGENTS.md with development guidelines and security rules. Add pyproject.toml for Python project configuration with dependencies and dev tools. Add src/PMOCrazyCoder.py as a new MCP server implementation with example tools.
This commit is contained in:
23
Dockerfile
23
Dockerfile
@@ -38,23 +38,36 @@ RUN curl -fsSL https://opencode.ai/install | bash && \
|
|||||||
|
|
||||||
ENV GOPATH=/usr/local/go
|
ENV GOPATH=/usr/local/go
|
||||||
ENV GOBIN=/usr/local/go/bin
|
ENV GOBIN=/usr/local/go/bin
|
||||||
RUN go install golang.org/x/tools/gopls@latest
|
RUN go install golang.org/x/tools/gopls@latest \
|
||||||
RUN go install github.com/isaacphi/mcp-language-server@latest
|
&& go install github.com/isaacphi/mcp-language-server@latest \
|
||||||
|
&& go install github.com/dorcha-inc/orla/cmd/orla@latest
|
||||||
|
|
||||||
|
RUN mkdir -p /etc/bash_completion.d \
|
||||||
|
&& orla completion bash > /etc/bash_completion.d/orla \
|
||||||
|
&& jj util completion bash > /etc/bash_completion.d/jj
|
||||||
|
|
||||||
|
RUN rustup component add rust-analyzer --toolchain nightly
|
||||||
|
|
||||||
ARG USERNAME=devuser
|
ARG USERNAME=devuser
|
||||||
ARG USER_UID=1000
|
ARG USER_UID=1000
|
||||||
ARG USER_GID=1000
|
ARG USER_GID=1000
|
||||||
RUN groupadd --gid $USER_GID $USERNAME && \
|
RUN groupadd --gid $USER_GID $USERNAME && \
|
||||||
useradd --uid $USER_UID \
|
useradd --uid $USER_UID \
|
||||||
--gid $USER_GID \
|
--gid $USER_GID \
|
||||||
-m $USERNAME \
|
-m $USERNAME \
|
||||||
--shell /bin/bash
|
--shell /bin/bash && \
|
||||||
|
echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/$USERNAME && \
|
||||||
|
chmod 440 /etc/sudoers.d/$USERNAME
|
||||||
|
|
||||||
COPY docker-entrypoint.sh /usr/local/bin/entrypoint.sh
|
COPY docker-entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||||
RUN chmod +x /usr/local/bin/entrypoint.sh
|
RUN chmod +x /usr/local/bin/entrypoint.sh
|
||||||
|
RUN mkdir -p /home/${USERNAME}/.config \
|
||||||
|
&& chown -R ${USERNAME}:${USERNAME} /home/${USERNAME}/.config
|
||||||
|
COPY --chown=${USERNAME}:${USERNAME} opencode /home/${USERNAME}/.config/opencode
|
||||||
|
|
||||||
USER $USERNAME
|
USER $USERNAME
|
||||||
WORKDIR /workspace
|
WORKDIR /workspace
|
||||||
|
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||||
CMD ["/bin/bash"]
|
CMD ["/bin/bash"]
|
||||||
|
|||||||
@@ -3,7 +3,10 @@
|
|||||||
|
|
||||||
export USERNAME=${USERNAME:-devuser}
|
export USERNAME=${USERNAME:-devuser}
|
||||||
|
|
||||||
|
export WORKSPACE=${WORKSPACE:-/workspace}
|
||||||
export LOCAL_LLM_API=${LOCAL_LLM_API:-http://host.docker.internal:1248/v1}
|
export LOCAL_LLM_API=${LOCAL_LLM_API:-http://host.docker.internal:1248/v1}
|
||||||
|
export LLM_MODEL=${LLM_MODEL:-'ollama:qwen/qwen3-coder-next@4bit'}
|
||||||
|
export ORLA_OLLAMA_HOST=$(sed -E 's@(https?://[^/]+).*$@\1@' <<< $LOCAL_LLM_API)
|
||||||
export MAXTOKEN=${MAXTOKEN:-4096}
|
export MAXTOKEN=${MAXTOKEN:-4096}
|
||||||
export NUM_CTX=${NUM_CTX:-32768}
|
export NUM_CTX=${NUM_CTX:-32768}
|
||||||
export REPEAT_PENALTY=${REPEAT_PENALTY:-1.3}
|
export REPEAT_PENALTY=${REPEAT_PENALTY:-1.3}
|
||||||
@@ -23,6 +26,8 @@ fi
|
|||||||
if [ -n "$LOCAL_LLM_API" ]; then
|
if [ -n "$LOCAL_LLM_API" ]; then
|
||||||
if ! grep -q "LOCAL_LLM_API" /home/${USERNAME}/.bashrc; then
|
if ! grep -q "LOCAL_LLM_API" /home/${USERNAME}/.bashrc; then
|
||||||
echo "export LOCAL_LLM_API=$LOCAL_LLM_API" >> /home/${USERNAME}/.bashrc
|
echo "export LOCAL_LLM_API=$LOCAL_LLM_API" >> /home/${USERNAME}/.bashrc
|
||||||
|
echo "export ORLA_OLLAMA_HOST=$ORLA_OLLAMA_HOST" >> /home/${USERNAME}/.bashrc
|
||||||
|
echo "export ORLA_MODEL='${LLM_MODEL}'" >> /home/${USERNAME}/.bashrc
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p /home/${USERNAME}/.config/opencode
|
mkdir -p /home/${USERNAME}/.config/opencode
|
||||||
@@ -31,6 +36,45 @@ if [ -n "$LOCAL_LLM_API" ]; then
|
|||||||
cat > $CONFIG_FILE <<EOF
|
cat > $CONFIG_FILE <<EOF
|
||||||
{
|
{
|
||||||
"\$schema": "https://opencode.ai/config.json",
|
"\$schema": "https://opencode.ai/config.json",
|
||||||
|
"mcp": {
|
||||||
|
"go-lsp-tools": {
|
||||||
|
"type": "local",
|
||||||
|
"command": ["mcp-language-server",
|
||||||
|
"--workspace", "$WORKSPACE",
|
||||||
|
"--lsp", "gopls"
|
||||||
|
],
|
||||||
|
"enabled": true,
|
||||||
|
"environment": {
|
||||||
|
"GOPATH": "$GOPATH"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"python-lsp-tools": {
|
||||||
|
"type": "local",
|
||||||
|
"command": ["mcp-language-server",
|
||||||
|
"--workspace", "$WORKSPACE",
|
||||||
|
"--lsp", "pyright-langserver",
|
||||||
|
"--", "--stdio"
|
||||||
|
],
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"rust-lsp-tools": {
|
||||||
|
"type": "local",
|
||||||
|
"command": ["mcp-language-server",
|
||||||
|
"--workspace", "$WORKSPACE",
|
||||||
|
"--lsp", "$(find /usr/local/rustup/toolchains -type f -name rust-analyzer)"
|
||||||
|
],
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"typescript-lsp-tools": {
|
||||||
|
"type": "local",
|
||||||
|
"command": ["mcp-language-server",
|
||||||
|
"--workspace", "$WORKSPACE",
|
||||||
|
"--lsp", "typescript-language-server",
|
||||||
|
"--", "--stdio"
|
||||||
|
],
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
},
|
||||||
"provider": {
|
"provider": {
|
||||||
"lmstudio": {
|
"lmstudio": {
|
||||||
"npm": "@ai-sdk/openai-compatible",
|
"npm": "@ai-sdk/openai-compatible",
|
||||||
@@ -75,44 +119,13 @@ if [ -n "$LOCAL_LLM_API" ]; then
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"model": "lmstudio/qwen/qwen3-coder-next@4bit"
|
"model": "${LLM_MODEL}"
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
chown ${USERNAME}:${USERNAME} ${CONFIG_FILE}
|
chown ${USERNAME}:${USERNAME} ${CONFIG_FILE}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# --- Install MCP Language Server ---
|
|
||||||
if command -v mcp-language-server &> /dev/null; then
|
|
||||||
mkdir -p /home/${USERNAME}/.config/opencode
|
|
||||||
MCP_CONFIG=/home/${USERNAME}/.config/opencode/mcp_servers.json
|
|
||||||
|
|
||||||
cat > $MCP_CONFIG <<EOF
|
|
||||||
{
|
|
||||||
"mcpServers": {
|
|
||||||
"language-server": {
|
|
||||||
"command": "mcp-language-server",
|
|
||||||
"args": [
|
|
||||||
"--workspace",
|
|
||||||
"/workspace",
|
|
||||||
"--lsp",
|
|
||||||
"gopls"
|
|
||||||
],
|
|
||||||
"env": {
|
|
||||||
"PATH": "/usr/local/go/bin:/usr/local/cargo/bin:/usr/local/bin:$PATH",
|
|
||||||
"GOPATH": "/home/${USERNAME}/go",
|
|
||||||
"GOCACHE": "/home/${USERNAME}/.cache/go-build",
|
|
||||||
"GOMODCACHE": "/home/${USERNAME}/go/pkg/mod"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
chown ${USERNAME}:${USERNAME} $MCP_CONFIG
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
# --- Force Bash comme shell par défaut ---
|
# --- Force Bash comme shell par défaut ---
|
||||||
if [ -z "$1" ]; then
|
if [ -z "$1" ]; then
|
||||||
exec /bin/bash
|
exec /bin/bash
|
||||||
|
|||||||
49
opencode/AGENTs.md
Normal file
49
opencode/AGENTs.md
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# AGENTS.md - Development Guidelines
|
||||||
|
|
||||||
|
## Code Style Guidelines
|
||||||
|
|
||||||
|
### General Principles
|
||||||
|
- Use relative paths only (never absolute paths)
|
||||||
|
- Operate strictly on explicitly mentioned files
|
||||||
|
- Generate minimal, single implementations
|
||||||
|
- Avoid speculation about missing files
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
- Use structured error messages
|
||||||
|
- Avoid verbose stack traces in user-facing output
|
||||||
|
|
||||||
|
## Naming Conventions
|
||||||
|
- Variables/functions: `snake_case`
|
||||||
|
- Types/interfaces: `PascalCase`
|
||||||
|
- Constants: `UPPER_SNAKE_CASE`
|
||||||
|
|
||||||
|
## CRITICAL Security Rules
|
||||||
|
|
||||||
|
### File Operations
|
||||||
|
- **NEVER** delete files without explicit human authorization
|
||||||
|
- **NEVER** modify files outside the scope of the requested task
|
||||||
|
- Always use relative paths (never absolute paths)
|
||||||
|
|
||||||
|
### Version Control with `jj`
|
||||||
|
- Projects are managed with `jj` (Jujutsu), NOT Git
|
||||||
|
- **Before starting modifications to respond to a user prompt**, run `jj new` to create a commit
|
||||||
|
- This creates a baseline to revert all changes from that prompt if needed
|
||||||
|
- Do NOT run `jj new` for every individual file change—only once at the start of a prompt response
|
||||||
|
|
||||||
|
## File Generation Rules
|
||||||
|
- Output only requested files
|
||||||
|
- Do not modify unrelated files
|
||||||
|
- Valid JSON without comments when requested
|
||||||
|
- Assume no knowledge of other files unless provided
|
||||||
|
|
||||||
|
## MCP Tools
|
||||||
|
- Located in `/opt/dev-tools/`
|
||||||
|
- Use SQLite for graph storage (`.ai_index/graph.db`)
|
||||||
|
- Embeddings stored in `.ai_index/embeddings/`
|
||||||
|
- AST data in `.ai_index/ast/`
|
||||||
|
|
||||||
|
## LM Studio Integration
|
||||||
|
- Local LLM API: `http://host.docker.internal:1248`
|
||||||
|
- Model: `qwen/qwen3-coder-next@4bit`
|
||||||
|
- Context window: 32768 tokens
|
||||||
|
- Max output: 65536 tokens
|
||||||
33
pyproject.toml
Normal file
33
pyproject.toml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
[project]
|
||||||
|
name = "pmocrazykoder"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "A crazy MCP server"
|
||||||
|
requires-python = ">=3.10"
|
||||||
|
dependencies = [
|
||||||
|
"crazy-mcp>=0.1.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.optional-dependencies]
|
||||||
|
dev = [
|
||||||
|
"ruff",
|
||||||
|
"black",
|
||||||
|
"mypy",
|
||||||
|
"isort",
|
||||||
|
]
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["hatchling"]
|
||||||
|
build-backend = "hatchling.build"
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
target-version = "py310"
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
select = ["E", "F", "I", "N", "W"]
|
||||||
|
ignore = []
|
||||||
|
|
||||||
|
[tool.black]
|
||||||
|
target-version = ["py310"]
|
||||||
|
|
||||||
|
[tool.mypy]
|
||||||
|
python_version = "3.10"
|
||||||
37
src/PMOCrazyCoder.py
Normal file
37
src/PMOCrazyCoder.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
from crazy_mcp import Context, mcp
|
||||||
|
from crazy_mcp.tools import *
|
||||||
|
|
||||||
|
|
||||||
|
# Déclaration d'un outil
|
||||||
|
@mcp.tool(description="Renvoie le texte reçu")
|
||||||
|
def echo_texte(texte: str) -> str:
|
||||||
|
return f"Écho du serveur : {texte} mec"
|
||||||
|
|
||||||
|
|
||||||
|
# Déclaration d'un second outil pour démonstration
|
||||||
|
@mcp.tool(description="Renvoie le texte en majuscules")
|
||||||
|
def shout_texte(texte: str) -> str:
|
||||||
|
return texte.upper()
|
||||||
|
|
||||||
|
|
||||||
|
# Déclaration d'un outil pour additionner deux nombres
|
||||||
|
@mcp.tool(description="Additionne deux nombres")
|
||||||
|
def additionner(a: float, b: float) -> float:
|
||||||
|
return a + b
|
||||||
|
|
||||||
|
|
||||||
|
@mcp.tool
|
||||||
|
async def increment(ctx: Context) -> tuple[int, str]:
|
||||||
|
count = ctx.get_state("count") or 0
|
||||||
|
ctx.set_state("count", count + 1)
|
||||||
|
return count + 1, ctx.session_id
|
||||||
|
|
||||||
|
|
||||||
|
# Lancement du serveur MCP
|
||||||
|
if __name__ == "__main__":
|
||||||
|
mcp.run(
|
||||||
|
transport="http", # Transport réseau HTTP
|
||||||
|
host="0.0.0.0", # Adresse d’écoute
|
||||||
|
port=7860, # Port TCP
|
||||||
|
path="/mcp", # Chemin MCP (par défaut /mcp)
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user