Skip to main content
Glama
mcp-server-base

mcp-server-base

by ahmedalbanna

MCP Server Base v3.0 — Skalierung & Enterprise (2026)

CI Node 20+ MCP SDK 1.12.1 TypeScript 5.7 License MIT Coverage 88% Version 3.0.0 Smithery

Modern Model Context Protocol-Server mit dem neuesten Stack:

  • MCP SDK 1.12+ — McpServer High-Level-API + StreamableHTTPServerTransport (neu) & StdioServerTransport

  • TypeScript 5.7 ESM + NodeNext-Modul

  • Zod-Validierung → automatisches JSON-Schema + Umgebungsvalidierung (src/config.ts:1)

  • Express 4 + helmet + CORS-Allowlist + Rate-Limit + Health/Ready + Admin-UI

  • Dualer Transport: STDIO (Claude Desktop) und Streamable HTTP (remote, 2025-03-Spezifikation, zustandslos + zustandsbehaftete Fortsetzbarkeit über RedisEventStore)

  • Strukturierte Tool-/Ressourcen-/Prompt-Module + RAG-Hybrid (BM25+Vector), Web (gecacht), GitHub-Integrationen

  • Plugin-SDK (src/plugin/index.ts:1) + Integrationen (slack/notion/linear), Registry (smithery.yaml, mcpName), Prompt-Playground unter /admin

  • v3.0 Enterprise: Multi-Tenant (X-Tenant-Id, namensbasierte Stores), SSO OIDC, Control-Plane-CRUD, Cluster-Modus, Prometheus/Grafana-Stack

  • OTEL-Tracing/Metriken (src/utils/otel.ts:1), Tasks (experimentell + create_task), k6-Lasttests

  • tsx-Watch, vitest (178 Tests, 88% Abdeckung), Graceful Shutdown, docker-compose (redis, postgres, qdrant, otel-collector, prometheus, grafana)


🚀 Schnellstart

npm install
npm run build

# STDIO (for Claude Desktop, Cursor, opencode, etc.)
npm start

# HTTP (Streamable HTTP - latest)
npm run start:http
# → http://localhost:3000/mcp
# → health http://localhost:3000/health

Entwicklung

npm run dev          # stdio watch
npm run dev:http     # http watch (Streamable HTTP at http://localhost:3000/mcp)
npm test             # unit + e2e (InMemory + HTTP)
npm run test:coverage # coverage 80% thresholds
npm run lint         # eslint 9 flat config
npm run format:check # prettier
npm run typecheck    # tsc --noEmit
npm run build

CI

.github/workflows/ci.yml läuft bei push/PR auf main mit Node-20+22-Matrix: lint, format:check, typecheck, test:coverage, build, docker build.


Related MCP server: TokenHub MCP

🔌 Transporte

Transport

Verwendung

Befehl

STDIO

Lokale Clients (Claude Desktop)

node dist/index.js

Streamable HTTP

Remote / Docker / Cloud

node dist/index.js --http

Streamable HTTP ist der neue Standard und ersetzt SSE (veraltet seit März 2025).


🧰 Werkzeuge (40)

Werkzeug

Beschreibung

Eingabe

echo

Echo-Nachricht

message, uppercase?

calculator

add/sub/mul/div

operation, a, b

get_time

Aktuelle Zeit

timezone?

fetch_url

URL abrufen

url, maxLength?

list_files

Dateien unter ALLOWED_ROOT auflisten

path?, recursive?

read_file

Datei lesen (1-MB-Limit)

path

write_file

Datei schreiben + Ressourcenänderung

path, content

search_files

Text in Dateien suchen

query, path?, maxResults?

memory_set

KV im Speicher setzen

key, value

memory_get

KV abrufen

key

memory_delete

KV löschen

key

memory_list

KVs auflisten

—

memory_clear

Alle löschen

—

database_query

SQL über alasql (users, notes)

sql

database_tables

Tabellenzeilen zählen

—

shell_execute

Shell (Allowlist, standardmäßig deaktiviert)

command, timeout?

collect_user_info

Elicitation-Demo (Kontakt/Präferenzen)

infoType?

generate_with_sampling

Sampling-Demo (LLM)

prompt, maxTokens?

rag_ingest

Text aufnehmen (gechunkt, eingebettet)

text, id?, metadata?, chunk?

rag_search

Hybride Suche (Vektor+BM25)

query, topK?, threshold?, mode?

rag_list

Dokumente auflisten

—

rag_clear

Vektor-Store leeren

—

brave_search

Brave-API (Mock ohne Schlüssel)

query, count?

tavily_search

Tavily-API (Mock ohne Schlüssel)

query, maxResults?, includeAnswer?

web_fetch

Gecachter Web-Abruf

url, useCache?, maxLength?

github_search_repos

GitHub-Repository-Suche

query, perPage?

github_get_repo

GitHub-Repository abrufen

repo

github_get_issue

GitHub-Issue abrufen

repo, issueNumber

create_task

Hintergrundaufgabe erstellen

duration?, payload?

get_task

Aufgabenstatus abrufen

taskId

get_task_result

Aufgabenergebnis abrufen

taskId

slack_list_channels

Slack-Kanäle (Plugin)

—

slack_post_message

Slack-Nachricht senden (Plugin)

channel, text

slack_search

Slack-Suche (Plugin)

query, count?

notion_search

Notion-Suche (Plugin)

query, page_size?

notion_get_page

Notion-Seite (Plugin)

page_id

notion_create_page

Notion-Seite erstellen (Plugin)

title, content?

linear_list_issues

Linear-Issues (Plugin)

team?, limit?

linear_create_issue

Linear-Issue erstellen (Plugin)

title, description?, team?

linear_get_issue

Linear-Issue abrufen (Plugin)

id

📦 Ressourcen (6)

  • config://server-info — Server-Metadaten (JSON, enthält jetzt features)

  • greeting://{name} — dynamische Begrüßungsvorlage

  • file:///{+path} — sandboxed Datei (ALLOWED_ROOT), Liste + Vervollständigung, file:///notes.txt

  • memory://{key} — Memory-KV, Liste + Vervollständigung

  • db://{table}/{id} — Demo-DB-Zeile (users/notes), Liste + Vervollständigung

  • docs://{id} — RAG-Chunk (über rag_ingest aufgenommen), Liste + Vervollständigung

💬 Prompts (4)

  • code-review — Argumente: language, code

  • explain-concept — Argumente: concept, level

  • summarize — Argumente: text, length (short/medium/long), style (bullets/paragraph/tldr)

  • research — Argumente: topic, depth (overview/deep), audience (beginner/expert/executive)


⚙️ Client-Konfiguration

Claude Desktop (claude_desktop_config.json)

{
  "mcpServers": {
    "mcp-server-base": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-server/dist/index.js"]
    }
  }
}

HTTP-Client

import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
import { Client } from '@modelcontextprotocol/sdk/client/index.js';

const client = new Client({ name: 'my-client', version: '1.0.0' });
await client.connect(new StreamableHTTPClientTransport(new URL('http://localhost:3000/mcp')));
const tools = await client.listTools();

Inspector

npm run inspect
# or
npx @modelcontextprotocol/inspector node dist/index.js
npx @modelcontextprotocol/inspector http://localhost:3000/mcp

🐳 Docker

# Single container
docker build -t mcp-server-base .
docker run -p 3000:3000 --env TRANSPORT=http mcp-server-base

# Full stack (app + redis + postgres + qdrant) — see docker-compose.yml
docker compose up -d
docker compose logs -f app
# → http://localhost:3000/health, http://localhost:3000/mcp
# → redis :6379, postgres :5432, qdrant :6333

RAG-Demo (ingest → search → docs://)

# via MCP tools (Inspector or Client)
# 1. ingest
rag_ingest { "text": "MCP is Model Context Protocol...", "id": "mcp-intro" }
# 2. search
rag_search { "query": "what is MCP?", "topK": 3 }
# 3. read resource
# docs://mcp-intro  → returns ingested text

📁 Struktur

src/
├── index.ts              # entry: stdio + http (helmet/cors/rateLimit/auth/RBAC/OTEL/metrics)
├── server.ts             # createMcpServer() factory (v2.1.0, instructions)
├── config.ts             # zod env (AUTH, CORS, rateLimit, RAG, cache, integrations, OTEL, admin, tasks)
├── types.ts              # Zod schemas
├── middleware/auth.ts    # AUTH_MODE none|apiKey|bearer
├── middleware/rateLimit.ts
├── middleware/requestId.ts
├── middleware/rbac.ts    # RBAC reader/writer/admin + mcpRbacMiddleware (v2.1)
├── observability/otel-real.ts # OTEL NodeSDK init (v2.1)
├── observability/slo.ts  # checkSlo() for /health/ready (v2.1)
├── utils/logger.ts       # stderr, JSON/text, redaction, child(requestId)
├── utils/eventStore.ts   # InMemoryEventStore
├── utils/redisEventStore.ts # RedisEventStore (scale)
├── utils/cache.ts        # MemoryCache (TTL) + defaultCache
├── utils/queue.ts        # SimpleQueue
├── utils/metrics.ts      # prom-client Registry (v2.1)
├── utils/persistence.ts  # save/load backup (v2.1)
├── utils/otel.ts         # stub OTEL spans/metrics
├── tools/                # 40 tools: echo, fs, memory, db, shell, rag (hybrid), web, github, elicitation, sampling, tasks
│   ├── filesystem.tool.ts, memory.tool.ts, database.tool.ts, shell.tool.ts
│   ├── rag.tool.ts, web.tool.ts, github.tool.ts, elicitation.tool.ts, sampling.tool.ts, tasks.tool.ts
├── plugin/index.ts       # Plugin SDK: definePlugin/registerPlugin (v2.2)
├── integrations/         # slack/notion/linear plugins (v2.2)
├── middleware/tenant.ts  # Multi-tenant X-Tenant-Id + scoped stores (v3.0)
├── routes/controlplane.ts# Tenants CRUD + key rotation (v3.0)
├── utils/cluster.ts      # Cluster mode horizontal scale (v3.0)
├── resources/            # 6 resources: config, greeting, file, memory, db, docs
├── routes/admin.ts       # Admin UI + metrics/spans/stores (v2.0) + /metrics Prometheus (v2.1)
└── prompts/              # 4 prompts: code-review, explain-concept, summarize, research

Neues Tool hinzufügen: src/tools/my.tool.ts erstellen → registerMyTool(server) exportieren → zu src/tools/index.ts hinzufügen.


🔐 Sicherheit (Phase 2)

  • Helmet-Header (x-dns-prefetch-control, x-frame-options, x-content-type-options usw.) über helmet@7 (src/index.ts:1)

  • CORS-Allowlist (CORS_ORIGIN=* oder Komma-Liste) mit cors-Credentials-Handling (src/config.ts:60)

  • Auth AUTH_MODE=none|apiKey|bearer unter src/middleware/auth.ts:1 — 401 ohne gültigen X-API-Key oder Authorization: Bearer (health/ready & OPTIONS ausgenommen)

  • Rate-Limiting express-rate-limit (Standard 100/15min) auf /mcp — 429 Too Many Requests (src/middleware/rateLimit.ts:1)

  • RequestId (X-Request-Id randomUUID, Echo-Header, Child-Logger-Korrelation) (src/middleware/requestId.ts:1)

  • Zod-Umgebungsvalidierung (src/config.ts:1) — parseEnv() validiert PORT, AUTH_MODE, API_KEY kreuzfeldbezogen, bricht bei ungültiger Umgebung sofort ab

  • Strukturierter Logger JSON/Text, [REDACTED] für authorization, apiKey, token (src/utils/logger.ts:24)

  • Fortsetzbarkeit InMemoryEventStore (src/utils/eventStore.ts:1) + zustandsbehaftete Session-Map, wenn RESUMABILITY_ENABLED=true (Replay über Last-Event-ID, GET /mcp-Stream, DELETE-Schließen)

  • Docker-Härtung Nicht-Root-appuser + HEALTHCHECK (Dockerfile:1)

  • Tests: tests/unit/auth.test.ts, tests/unit/logger.test.ts, tests/unit/eventStore.test.ts, tests/e2e/security.test.ts (helmet/auth/rateLimit/resumability) — 67 Tests → 130 gesamt mit Phase 5, 90,89% Abdeckung

🔗 Integrationen (Phase 4)

  • Cache MemoryCache TTL (src/utils/cache.ts:1) — defaultCache für Web/GitHub, SimpleQueue (src/utils/queue.ts:1)

  • RAG lokaler Vektor (Hash-Embedding 128-dim, Kosinus, Chunk 500/50) unter src/tools/rag.tool.ts:1 — rag_ingest (gechunkt + sendResourceListChanged), rag_search (topK, threshold), rag_list, rag_clear + docs://{id}-Ressource

  • Web src/tools/web.tool.ts:1 — brave_search (Mock ohne BRAVE_API_KEY), tavily_search (Mock), web_fetch (gecacht über defaultCache, CACHE_TTL_MS)

  • GitHub src/tools/github.tool.ts:1 — github_search_repos, github_get_repo, github_get_issue (gecacht, GITHUB_TOKEN für Rate-Limit)

  • Stack docker-compose.yml:1 (App + redis:7 + postgres:16 + qdrant:v1.12.4) mit Healthchecks

  • Demo rag_ingest → rag_search → docs:// E2E verifiziert in tests/integrations.test.ts:1 (21 Tests)

🏢 Skalierung & Enterprise (Phase 5 — v3.0) — NEU

  • Multi-Tenant src/middleware/tenant.ts:1 — X-Tenant-Id-Header (oder ?tenant=), tenantMiddleware weist 400 zurück, wenn TENANT_REQUIRED=true und fehlt, mandantenspezifischer Speicher getTenantMemory(tid) (isolierte Stores), namespaced Cache-Schlüssel tenant:{id}:key, Registry createTenant/deleteTenant

  • SSO OIDC src/middleware/auth.ts:1 — AUTH_MODE=oidc: strukturelle Bearer-JWT-Validierung (3 Teile, exp, iss vs. OIDC_ISSUER, aud vs. OIDC_AUDIENCE), Claims an req.oidcClaims angehängt; in Produktion wird die JWKS-Signaturprüfung eingesetzt

  • Control Plane src/routes/controlplane.ts:1 — CRUD /admin/tenants (POST/GET/PATCH/DELETE + 409 Duplikat/400 ungültige ID), POST /admin/tenants/:id/rotate-key, GET /admin/tenants/:id/store Isolationsprüfung; durch Admin-Token geschützt

  • Laufzeitskalierung src/utils/cluster.ts:1 — initCluster() forkt CLUSTER_WORKERS (Standard CPU-1), automatischer Neustart bei Worker-Exit, CLUSTER_MODE=true; zustandslos + RedisEventStore für echte horizontale Skalierung

  • Monitoring-Stack docker-compose.override.yml:1 — Prometheus (prometheus.yml scraped app:3000/metrics) auf :9090 + Grafana auf :3001

  • Tests tests/v3_0.test.ts:1 (15 Tests: Tenant-Extraktion/Isolation/erforderlich-400, OIDC-Token-Validierung + Issuer/Audience + HTTP 401/200, Control-Plane-Lebenszyklus 201/409/400/404/rotate-key/store-Inspektion/deaktiviert-404, Cluster-No-op, Compose-Dienste) — insgesamt 178

🔌 Ökosystem & DX (Phase 5 — v2.2)

  • Plugin-SDK src/plugin/index.ts:1 — definePlugin({name, version, register}), registerPlugin(server, plugin) (duplikattolerant), getRegisteredPlugins(), automatische sendToolListChanged-Benachrichtigungen

  • Integrationen src/integrations/ — slackPlugin (list/post/search), notionPlugin (search/get/create), linearPlugin (list/create/get) — alle ohne Tokens gemockt (SLACK_TOKEN, NOTION_TOKEN); automatisch registriert in src/server.ts:1

  • Registry smithery.yaml:1 — Smithery-Konfiguration + MCP-Registry-Name io.github.ahmedalbanna/mcp-server-base, package.json:1 mcpName/files-Felder

  • Hybrid-RAG src/tools/rag.tool.ts:1 — rag_search-Modi vector|bm25|hybrid (Standard hybrid, Alpha 0.5), BM25 (k1=1.5, b=0.75) normalisiert + Kosinus-Re-Ranking; Evaluierungsset tests/eval/rag-eval.json (20 Q/A) mit p@5 ≥0.8 verifiziert in tests/v2_2.test.ts:1

  • Prompt-Playground src/routes/admin.ts:1 — POST /admin/prompts/:name/preview rendert Prompts serverseitig; Playground-UI im /admin-Dashboard

  • Tests tests/v2_2.test.ts:1 (16 Tests: Plugin-SDK define/register/dup/Tools aufrufbar, Registry-Dateien, Hybrid-Modi, Eval p@5, Playground-Vorschau/UI/Anzahl) — insgesamt 163

📈 Skalierung & Betriebsfähigkeit (Phase 5 — v2.0)

  • Versioniertes MCP v2.0.0 (package.json:1, config.MCP_SERVER_VERSION) mit Anweisungen pro Minor (src/server.ts:1)

  • OTEL Tracing/Metriken (src/utils/otel.ts:1) — createSpan/withSpan, incrementCounter/recordHistogram, getMetrics/getSpans, JSON-Export-Stub für OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_ENABLED-Flag

  • RedisEventStore (src/utils/redisEventStore.ts:1) — EventStore-Implementierung mit storeEvent/replayEventsAfter, In-Memory-Fallback, eventStoreFactory.create() für horizontale Skalierung (EVENT_STORE_TYPE=memory|redis, REDIS_URL)

  • Admin-UI (src/routes/admin.ts:1) — GET /admin (HTML-Dashboard), /admin/tools|resources|prompts|metrics|spans|stores|health (JSON), geschützt über ADMIN_TOKEN (X-Admin-Token), ADMIN_ENABLED-Flag

  • Aufgaben (src/tools/tasks.tool.ts:1) — experimentelles delay_task (falls SDK-Aufgaben verfügbar) + Fallback create_task/get_task/get_task_result (In-Memory, Polling), SimpleQueue/MemoryCache-Infrastruktur

  • Bench k6/load.js:1 — http_req_duration p(95)<100ms, stages 10→50 VUs, checks >99%, npm run bench / bench:local

  • Compose docker-compose.yml:1 enthält bereits redis/postgres/qdrant für Skalierung

  • Tests: tests/scale.test.ts:1 (OTEL-Spans/Metriken, RedisEventStore-Replay, Cache-TTL, Queue, Admin-HTML/Metriken/Token/bereit, Aufgaben erstellen/pollen, Version, k6-Skript) — 130 insgesamt (jetzt 147 mit v2.1)

  • Deploy bereit für Fly.io/Cloud Run (zustandslos + RedisEventStore), GHCR über release.yml, npm 2.0.0

🔒 Härtung & Beobachtbarkeit (Phase 5 — v2.1) — NEU

  • OTEL Real src/observability/otel-real.ts:1 — initOtel() dynamischer Import von @opentelemetry/sdk-node + OTLPTraceExporter (Konsolen-Fallback), OTEL_ENABLED + OTEL_EXPORTER_OTLP_ENDPOINT, sauberes shutdown bei SIGTERM

  • SLOs src/observability/slo.ts:1 — checkSlo() (Speicher/RAG/Cache/Uptime, latencyMs), GET /health → {status, checks, uptime, version, otel, eventStore} + GET /ready → 503 wenn nicht ok, GET /metrics → Prometheus text/plain über prom-client (mcp_http_requests_total, mcp_http_request_duration_ms, mcp_sessions_active)

  • RBAC src/middleware/rbac.ts:1 — reader < writer < admin (X-Role-Header, JWT-Stub), TOOL_ROLES-Map (31 Tools), mcpRbacMiddleware prüft tools/call-Body → 403 wenn reader versucht write_file/shell_execute, GET /admin → admin erforderlich

  • Backup src/utils/persistence.ts:1 — saveBackup()/loadBackup()/scheduleSave() (500ms Debounce) nach ALLOWED_ROOT/.backup.json (dynamisches getBackupFile()), protokolliert Redis-Sync-Stub wenn REDIS_URL gesetzt, loadBackup() beim Start in src/index.ts:1

  • Metriken src/utils/metrics.ts:1 — prom-client Registry + collectDefaultMetrics, httpRequestsTotal/httpRequestDuration/mcpToolCallsTotal/mcpSessionsActive, GET /metrics-Handler

  • Tests tests/v2_1.test.ts:1 (13 Tests: SLO-Prüfungen, RBAC hasRole/X-Role 403/200, SLO health/metrics 200 + Prometheus-Text, OTEL-Span, Backup speichern/laden + scheduleSave über memory_set, initOtel deaktiviert/aktiviert) + tests/unit/rbac.test.ts:1 (4 Tests) — insgesamt 147

  • Logger stderr-sicher, protokolliert niemals Geheimnisse (Redaktion)

  • Zod → JSON-Schema über SDK (src/types.ts:1, src/tools/*.tool.ts)

  • Timeout bei Fetch (10s) + strukturierte Fehler

  • Sauberes Herunterfahren (SIGINT/SIGTERM)

  • Health (GET /health) & Ready (GET /ready) getrennt von MCP

  • Zustandslos standardmäßig (sessionIdGenerator: undefined), zustandsbehaftet wenn RESUMABILITY_ENABLED=true (src/index.ts:22)

  • Typsicher, striktes TS + ESLint flat + Prettier + husky + lint-staged

  • Abdeckung 85% Zeilen / 70% Zweige erzwungen (vitest.config.ts:1), 178 Tests: Unit + e2e HTTP/Sicherheit/Fähigkeiten/Integrationen/Skalierung/v2.1/v2.2/v3.0

📚 Dokumentation

Vollständige Dokumentation in docs/:

  • Architektur — Diagramm, Modulübersicht, Anfragelebenszyklus

  • Konfiguration — jede Umgebungsvariable + Validierungsregeln

  • API-Referenz — Tools/Ressourcen/Prompts/Endpunkte

  • Sicherheit — Authentifizierung, RBAC, OIDC, Mandantenfähigkeit, Härtungs-Checkliste

  • Plugins — Plugin-SDK-Anleitung + Registry-Verteilung

  • Bereitstellung — Docker, Cluster-/Multi-Replica-Skalierung, Monitoring, k6

  • Testen — Suite-Übersicht, Muster, CI

🤝 Mitwirken

Siehe CONTRIBUTING.md — nvm use, npm test, Tool/Ressource/Prompt hinzufügen, sicherstellen, dass lint/typecheck/test bestehen. Siehe CODE_OF_CONDUCT.md.


📚 MCP-Dokumentation

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    C
    maintenance
    A production-packaged Model Context Protocol server for coding agents that routes large file, git, web, database, and other tasks through token-budgeted tools and workflows.
    6
    2 npm
    1
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    A production-ready Model Context Protocol suite over Streamable HTTP providing a sandboxed file server with tools, resources, prompts, and both manual and AI-driven clients.
    MIT
  • A
    license
    B
    quality
    C
    maintenance
    Enables running a Model Context Protocol server with a validated echo tool over stdio or Streamable HTTP, including strict schemas, tests, and hardened container deployment.
    1
    1
    MIT