Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

# Erlaubt gleichzeitige CI-Runs pro Branch (keine Auto-Cancellation).
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: false

jobs:
# --- 1) Lint: ruff auf den Source-Code -------------------------------------
lint:
name: Lint (ruff)
runs-on: ubuntu-latest
steps:
- name: Repo auschecken
uses: actions/checkout@v4

- name: Python 3.11 einrichten
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: ruff installieren
run: pip install ruff

- name: ruff auf src/ ausführen
run: ruff check src/

# --- 2) Tests: Unit + Integration via pytest -------------------------------
test:
name: Tests (pytest)
runs-on: ubuntu-latest
steps:
- name: Repo auschecken
uses: actions/checkout@v4

- name: uv einrichten
uses: astral-sh/setup-uv@v3
with:
version: latest

- name: Python 3.11 (über uv) einrichten
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Dependencies installieren (inkl. Test-Extras)
run: uv sync --all-extras

- name: pytest ausführen (unit + integration)
# PYTHONPATH leeren, um Interpreter-Hijacking durch System-Venvs zu verhindern.
run: env -u PYTHONPATH uv run pytest tests/unit tests/integration -v

# --- 3) Build: uv build + Wheel-Artefakt-Upload ---------------------------
build:
name: Build (uv build)
needs: [lint, test]
runs-on: ubuntu-latest
steps:
- name: Repo auschecken
uses: actions/checkout@v4

- name: uv einrichten
uses: astral-sh/setup-uv@v3
with:
version: latest

- name: Python 3.11 (über uv) einrichten
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Dependencies synchronisieren
run: uv sync

- name: Wheel & Sdist bauen
run: uv build

- name: Wheel installieren und Smoke-Test
# H4-Fix: Das gebaute Wheel wird tatsächlich installiert und der
# Entry-Point getestet — nicht nur gebaut und weggelegt.
run: |
uv pip install dist/*.whl --system
python -c "from mcp_server_basti.server import mcp; assert mcp.name == 'mcp-server-basti'"
mcp-server-basti --help || true

- name: Build-Artefakte hochladen
uses: actions/upload-artifact@v4
with:
name: mcp-server-basti-wheel
path: dist/
if-no-files-found: error
retention-days: 14
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ Thumbs.db
*.log
.cache/
tmp/
.pytest_cache/
.ruff_cache/

# Hermes Agent lokale Daten (Pläne, Cache — nicht fürs Repo)
.hermes/

# uv lockfile wird NICHT ignoriert (reproducible builds)

# Never commit secrets
.env
Expand Down
77 changes: 77 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,83 @@ servers) and `/agents` (shows `coder`, `perf-tuner`, `security-auditor`).
> The `github` MCP server needs `GITHUB_PERSONAL_ACCESS_TOKEN` exported in the environment where
> Claude Code runs. Set it via your shell profile or a secret manager — do **not** commit it.

## Basti's MCP Server

Zusätzlich zum externen `github`-Server bringt dieses Repo einen **lokalen MCP-Server**
namens `mcp-server-basti` mit. Er läuft über **stdio**, ist in Python/FastMCP
implementiert und wird via [`uv`](https://docs.astral.sh/uv/) gestartet — kein Docker,
kein Netzwerk-Listener, keine externen Secrets in der Default-Konfiguration.

### Tools

| Tool | Zweck |
|---|---|
| `get_system_status` | Führt `uptime` aus und gibt den Systemstatus zurück (lokal, ohne Netzwerk). |
| `echo_tool` | Smoke-Test-Tool — gibt Eingabe unverändert zurück. Nützlich zum Verifizieren, dass der Server überhaupt antwortet. |
| `get_repo_info` | Liefert Git-Branch und letzten Commit des Server-Repos. |

### Installation

Der Server liegt im Repo-Root. Es gibt zwei Install-Wege:

```bash
# 1. Global via uvx (empfohlen — keine lokale venv nötig):
uvx git+https://github.com/Toqsick/my-agent-tools.git

# 2. Lokal aus dem Repo (für Entwicklung/Debugging):
cd /home/bratan/ZCodeProject/my-agent-tools
uv run mcp-server-basti
Comment thread
Copilot marked this conversation as resolved.
```

### `.mcp.json`-Konfiguration

Der Server ist bereits in `plugins/agent-toolkit/.mcp.json` als `basti-tools`
eingetragen. Der `github`-Eintrag bleibt unverändert daneben bestehen:

```json
{
"mcpServers": {
"github": { "command": "docker", "args": [...], "env": {...} },
"basti-tools": {
"command": "uv",
"args": [
"run",
"--directory", "/home/bratan/ZCodeProject/my-agent-tools",
"mcp-server-basti"
]
}
}
}
```

Beim Plugin-Start wird der Server automatisch hochgefahren — keine weiteren
Schritte erforderlich.

### Tests ausführen

```bash
cd /home/bratan/ZCodeProject/my-agent-tools
uv sync --all-extras
uv run pytest tests/unit tests/integration -v
```

### Architektur

- **Transport:** stdio (kein HTTP, kein Port). Der Parent-Prozess (Claude Code)
startet den Server als Subprozess und spricht JSON-RPC über stdin/stdout.
- **Framework:** [FastMCP](https://github.com/jlowin/fastmcp) auf Basis von
[`mcp`](https://pypi.org/project/mcp/) — deklarative Tool-Definition via
Python-Decorators.
- **Sandboxing:** läuft mit den Rechten des aufrufenden Users. Schreibt nur in
Bereiche, in denen der User schreiben darf.
- **CI:** `.github/workflows/ci.yml` führt auf jedem Push/PR nach `main` Lint
(`ruff`), Tests (`pytest`) und Build (`uv build`) aus und lädt das Wheel
als Artefakt hoch.
- **Health-Check:** `scripts/check-mcp.sh` prüft für **jeden** in `.mcp.json`
konfigurierten Server, ob `command` im PATH ist und alle `env`-Vars gesetzt
sind, und gibt ein JSON-Array mit `{server, status, detail}` zurück
(Exit-Code 1 wenn ein Server down ist).

## Maintenance — adding a vetted tool

1. **Skill:** copy the skill folder into `plugins/agent-toolkit/skills/<name>/` (a `SKILL.md` plus any
Expand Down
69 changes: 69 additions & 0 deletions docs/mcp-server/TOOL_REFERENCE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Tool Reference — mcp-server-basti

## Tools

| Tool | Parameter | Rückgabetyp | Beschreibung | Side-Effect |
|------|-----------|-------------|--------------|-------------|
| `get_system_status` | keine | `str` (uptime-Output) | Führt `uptime` aus und gibt den stdout zurück. | read (Subprocess, keine Mutation) |
| `echo_tool` | `text: str` (required) | `str` | Gibt den übergebenen Text unverändert zurück. Health-Check-Tool. | none |
| `get_repo_info` | keine | `str` | Git-Branch und letzter Commit des Server-Repos (`DEFAULT_REPO_PATH`). | read (git-Subprocess, keine Mutation) |

## Beispiele

### get_system_status

**Input:** keine Parameter

**Output (beispielhaft, Linux):**
```
04:24:40 up 2:46, 1 user, load average: 9,64, 8,19, 6,85
```

> Format hängt vom Betriebssystem ab. Der Server gibt den rohen `uptime`-stdout zurück ohne weitere Formatierung.

**Fehlerfall:** Wenn `uptime` nicht gefunden wird oder mit Exit-Code ≠ 0 terminiert, gibt das Tool einen strukturierten Fehler zurück (`isError: true`).

### echo_tool

**Input:**
```json
{"text": "hello"}
```

**Output:**
```
hello
```

**Fehlerfall:** FastMCP validiert via Pydantic, dass `text` ein String ist. Fehlt der Parameter → `McpError` auf Client-Seite.

### get_repo_info

**Input:** keine Parameter

**Output (beispielhaft):**
```
Branch: main
Letzter Commit: 634ff36 Merge pull request #1 from Toqsick/integrate/zcode-routing
```

> Das Tool ruft `git rev-parse --abbrev-ref HEAD` und `git log -1 --oneline` für das Server-Repo (`DEFAULT_REPO_PATH` in `server.py`) auf. Es liefert **nur** Branch und Commit — kein Remote, keine Tags.

**Fehlerfall:** Wenn das Verzeichnis kein Git-Repo ist oder `git` fehlschlägt, gibt das Tool einen strukturierten Fehler zurück (`isError: true`).

## Fehlerformat

Tool-Errors nutzen `fastmcp.tools.base.ToolResult` mit `is_error=True`:

```json
{
"isError": true,
"content": [{"type": "text", "text": "Systemstatus konnte nicht ermittelt werden: ..."}]
}
```

## skill-mcp-router Integration

Der Server ist für die Integration mit dem bestehenden `skill-mcp-router` vorbereitet, aber **noch nicht aktiv verdrahtet**. Die `routing/registry/registry.json` hat ein `mcp_server`-Feld pro Skill, in das `"mcp-server-basti"` eingetragen werden kann, um Skill-Intents zu diesen Tools aufzulösen.

**Status:** Derzeit nutzt kein Skill in der Registry den Server `mcp-server-basti`. Um ihn zu aktivieren, müssten Skills mit passenden Intents angelegt und in der Registry registriert werden. Siehe `routing/registry/registry.json` für das Format.
Loading