AgentStack
MCP verified MIT Self-run

LeszczynskiKarol Mcp Server

mcp-leszczynskikarol-mcp-server · by LeszczynskiKarol

Self-hosted MCP server for Claude.ai. Give Claude direct access to your AWS, SSH, local shell, GitHub, PostgreSQL and PM2 — without Claude Code. Your keys never leave your machine.

No reviews yet
0 installs
3 views
0.0% view→install

Install

$ agentstack add mcp-leszczynskikarol-mcp-server

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of LeszczynskiKarol Mcp Server? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

mcp-server

> Self-hosted MCP server for Claude.ai > > Give Claude direct access to your AWS account, SSH into your servers, run shell commands on your laptop, query your databases, and manage PM2 processes — all from a Claude chat. No Claude Code subscription needed. Your keys never leave your machine.

All 10 tools live in your Claude.ai sidebar - no Desktop install, no separate client, just a custom connector.

[](https://github.com/LeszczynskiKarol/mcp-server/actions/workflows/ci.yml) [](LICENSE) [](https://nodejs.org/) [](https://modelcontextprotocol.io/)


What is this?

A small Node.js MCP server you run on your own machine (laptop, desktop, VPS) and connect to Claude.ai (or any MCP client) as a Custom Connector. It exposes a configurable set of tools that let Claude do real work on your infrastructure:

  • Run AWS CLI commands using your local profile
  • SSH into your servers using your .pem keys
  • Execute shell commands on your local machine
  • Write files directly on your local disk (full UTF-8, no shell quoting)
  • Hit the GitHub REST API with your Personal Access Token
  • Query PostgreSQL databases on remote hosts via SSH
  • Inspect PM2 processes on remote servers
  • Iterate over very long documents (book editing) that exceed the context window

Architecture:

  Claude.ai  ──HTTPS──►  nginx + cert  ──HTTP──►  frps  ──tunnel──►  frpc + node
   (cloud)               on a VPS         :8080    (vhost)            (your PC)
                                                                          │
                                ┌───────────────┬───────────────┬─────────┼─────────┐
                                ▼               ▼               ▼         ▼         ▼
                            AWS CLI       ssh -i *.pem      cmd.exe    psql via   pm2 list
                            (local)       user@host         git/npm      SSH      (remote)

SSH keys, GitHub PAT and AWS credentials never leave your local machine. The tunnel only carries MCP requests and their results.


Why self-host this?

The MCP ecosystem mostly does two things today:

  1. MCP servers as npm packages that run via stdio and require Claude Desktop.
  2. Hosted MCP services behind someone else's auth and API limits.

This project is the third option: your own MCP server, your keys, your servers, accessible from web Claude.ai (where you already work). It's a single ~1000-line server.js file that you can read end-to-end in 20 minutes and extend in 5.

Killer features:

  • No Claude Code subscription needed — works with regular Claude.ai (web)
  • OAuth 2.1 with PKCE — proper Claude.ai integration, not a hacky workaround
  • Your keys stay yours — SSH keys, GitHub PATs, AWS creds never leave your machine
  • Self-hostable — Windows, Linux, Mac, anything that runs Node 18+
  • Configurable via JSON — add a new server or new key without touching code
  • One file to read — no framework magic, no hidden config
  • Hardened OAuth — PKCE S256, client_secret enforcement, refresh token rotation, RFC 7009 revocation, dynamic IP allowlist with auto-enroll, anti-clickjacking

Tools

| Tool | What it does | | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | | aws_cli | Run any aws using your local AWS CLI profile | | ssh_exec | SSH into any host using a key defined in hosts.json | | local_exec | Run any shell command on the local machine (cmd.exe on Windows, /bin/sh elsewhere) | | write_file | Write text content to a local file (overwrite or append). Full UTF-8, no shell quoting issues — preferred over local_exec for any non-trivial file write | | github_api | Make REST API requests to GitHub using your Personal Access Token | | postgres_query | Run psql queries via SSH (sudo -u postgres) on a host from hosts.json | | pm2_status | Show pm2 list and optional logs on a remote server | | sftp_download | Stream a file from a remote host to the local filesystem (uses the persistent SSH pool). Essential when working from Claude.ai web — the cloud sandbox has no native scp | | sftp_upload | Stream a local file to a remote host. Optional POSIX mode flag (e.g. 0755). Parent dir must exist on remote | | book_split | Split a large text file into ~3000-word chunks | | book_chunk | Read one chunk from a directory created by book_split | | book_note | Manage JSON notes for iterative work on long documents |


See it in action

Real examples from a real Claude.ai chat using this MCP server.

Server health snapshot over SSH

> "SSH into my matury server and show me: disk usage (df -h), memory usage (free -h), and uptime. Use a single command and present the output nicely."

Claude composes a single SSH command, parses the multi-section output, and renders disk, memory and uptime as a clean snapshot with key numbers highlighted.

List EC2 instances in any region

> "Using AWS CLI, list all my EC2 instances in eu-central-1 with their IDs, types, and state. Format the result as a clean table."

Claude calls aws_cli with a describe-instances --query ... filter, then parses the JSON and renders it as a markdown table with running/stopped status indicators.

Query PostgreSQL databases over SSH

> "Run a SQL query on my 'panel' PostgreSQL database to count the total users, then on database 'smartedu' count rows in the users table, and tell me how my system is doing."_

Two tools work together here: ssh_exec to enumerate databases when the first guess misses, then postgres_query against the right one.

Claude lists every database on the host, identifies the ones with a users table, and runs COUNT(*) queries in parallel.


Requirements

  • Node.js 18+ (tested on 22, 24, 25)
  • SSH .pem keys locally (for hosts you want to control)
  • AWS CLI configured locally (aws configure) — only if you use the aws_cli tool
  • A public HTTPS endpoint — only if you want to expose this to Claude.ai

Quick start

git clone https://github.com/LeszczynskiKarol/mcp-server.git
cd mcp-server
npm install
cp .env.example .env                # fill in MCP_PASS and MCP_BASE_URL
cp hosts.example.json hosts.json    # add your servers
node server.js

You should see:

Loaded N hosts and M keys from ./hosts.json
MCP server: my-mcp-server
Port: 4500
Static IP allowlist: (none)
Auto-enroll: enabled (TTL 30 days)
Trust proxy: false
MCP listening on :4500

That's it for local. To use this from Claude.ai (web), you need to expose it over HTTPS — see [Exposing publicly](#exposing-publicly-claudeai) below.


Configuration

.env (secrets — never commit)

# REQUIRED
MCP_USER=admin
MCP_PASS=
MCP_BASE_URL=https://your-domain.com

# OPTIONAL — GitHub integration
GITHUB_TOKEN=github_pat_xxxxxxxxxxxxxxxx
GITHUB_OWNER=YourGitHubUsername

# OPTIONAL — server tuning
PORT=4500
TOKEN_TTL_SECONDS=2592000      # 30 days
AUTH_CODE_TTL_SECONDS=600      # 10 minutes
CLIENT_TTL_SECONDS=7776000     # 90 days (unused-client cleanup)
EXEC_BUFFER_MB=10
EXEC_TIMEOUT_SECONDS=120       # per-command timeout
MCP_SERVER_NAME=my-mcp-server
HOSTS_CONFIG=./hosts.json
OAUTH_STATE_FILE=./oauth-state.json

# OPTIONAL — IP allowlist (security)
# Comma-separated static IPs/CIDRs that are always allowed.
# Leave empty if you only want auto-enroll via OAuth login.
MCP_ALLOWED_IPS=
# Trust X-Forwarded-For — use "loopback" when behind FRP/nginx on the same box.
# Other valid values: comma-separated list of trusted proxy IPs/CIDRs, "false"
# (default), or "true" (rejected in production — would let any client spoof XFF).
MCP_TRUST_PROXY=loopback
# Auto-enroll the requesting /24 subnet to allowlist after a successful OAuth login
MCP_AUTO_ENROLL=true
# How long an auto-enrolled subnet stays on the allowlist (default 30 days)
MCP_ENROLL_TTL_SECONDS=2592000

hosts.json (server list — never commit)

{
  "hosts": {
    "production": {
      "ip": "1.2.3.4",
      "user": "ubuntu",
      "key": "main",
      "description": "Main production server"
    },
    "staging": {
      "ip": "5.6.7.8",
      "user": "ubuntu",
      "key": "main",
      "description": "Staging environment"
    }
  },
  "keys": {
    "main": "/path/to/main.pem"
  }
}

Key paths can use:

  • Absolute paths: D:/keys/server.pem or D:\\keys\\server.pem
  • Tilde expansion: ~/keys/server.pem (resolved to $HOME / %USERPROFILE%)
  • Forward slashes work on Windows too

Exposing publicly (Claude.ai)

Claude.ai requires HTTPS. The recommended setup uses FRP (Fast Reverse Proxy) + nginx + Let's Encrypt on a small VPS.

1. DNS record

mcp.your-domain.com    A        TTL 300

2. nginx vhost on VPS

/etc/nginx/sites-available/mcp.your-domain.com:

server {
    server_name mcp.your-domain.com;
    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # SSE / long-lived MCP connections
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_buffering off;
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }
    listen 80;
}
sudo ln -s /etc/nginx/sites-available/mcp.your-domain.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d mcp.your-domain.com

3. FRP server (frps) on VPS

/etc/frp/frps.toml:

bindPort = 7000
vhostHTTPPort = 8080
auth.method = "token"
auth.token = ""

4. FRP client (frpc) on your local machine

frpc-mcp.toml:

serverAddr = ""
serverPort = 7000
auth.method = "token"
auth.token = ""

[[proxies]]
name = "mcp"
type = "http"
localPort = 4500
customDomains = ["mcp.your-domain.com"]

5. Add the connector in Claude.ai

  1. Open Settings → Connectors → Add custom connector
  2. URL: https://mcp.your-domain.com/mcp (with /mcp suffix!)
  3. OAuth Client ID/Secret: leave empty
  4. Click Connect → a login form appears → enter MCP_USER and MCP_PASS from your .env
  5. In a chat: + → Connectors → toggle this MCP on → start a new conversation (tools attach at chat start)

The first request from a new IP will trigger an OAuth re-login, which adds your /24 subnet to the allowlist for 30 days. This is intentional — see [Security](#security).


Recommended Claude.ai preferences

Even with the right tools installed, Claude will sometimes waste tokens on common failure modes: re-reading files after writing them, copying files into the sandbox "to edit them", lying that a file is on disk when only an artifact was created.

[CLAUDE_PREFERENCES.md](CLAUDEPREFERENCES.md) is a curated set of user preferences that closes those holes. Paste them into Settings -> Profile -> Personal preferences in Claude.ai. They're battle-tested against the exact failure modes that prompted writing some of the tools in this server (especially write_file).

Covers, among other things:

  • File-tool hierarchy: always write_file for new files, PowerShell for surgical edits, never base64-chunks through cmd.exe
  • "Trust the write" -- don't re-read a file just to confirm it saved
  • Sandbox isolation -- the bash sandbox has no access to your local disk; don't bridge it via public file hosts (uguu.se, transfer.sh, etc.)
  • Artifacts vs. MCP file writes -- "Created a file" tiles in the chat UI are NOT saved to your disk
  • Raw content rule -- write_file content must be raw, not JSON-escaped
  • Anti-loop limits -- stop after 3 failures on the same problem
  • Non-ASCII character handling on Windows (cmd.exe code page gotcha)

Running on Windows

The recommended autostart on Windows uses Task Scheduler + a small .bat with a restart loop. PM2 used to be the recommendation but is currently incompatible with Node 25's named-pipe handling (EPERM \\.\pipe\rpc.sock), so the project has switched to plain Task Scheduler.

One-shot install

After .env and hosts.json are in place, run as administrator:

install-task.bat

This is a small batch wrapper around install-task.ps1. The PowerShell script:

  1. Generates start-mcp-hidden.vbs (so the cmd.exe window stays hidden).
  2. Generates mcp-task.generated.xml with %USERDOMAIN%\%USERNAME% filled in — nothing hard-coded.
  3. Registers a Task Scheduler entry named MCP Server that runs at every logon with HighestAvailable privilege.

The action of the task is wscript.exe "...\start-mcp-hidden.vbs", which silently launches start-mcp.bat. That batch keeps node alive with a restart loop:

@echo off
cd /d D:\mcp-server
if not exist logs mkdir logs
:loop
node server.js >> logs\mcp.log 2>&1
echo [%date% %time%] node exited, restarting in 5s >> logs\mcp.log
timeout /t 5 /nobreak >nul
goto loop

Useful commands:

schtasks /run /tn "MCP Server"            :: start now
schtasks /query /tn "MCP Server" /v /fo LIST  :: status
schtasks /delete /tn "MCP Server" /f      :: uninstall
tasklist | findstr node.exe               :: check that node is alive
type D:\mcp-server\logs\mcp.log           :: read the log

To restart after editing server.js:

taskkill /F /IM node.exe /T

The :loop in start-mcp.bat will restart node within 5 seconds.

FRP tunnel autostart

The tunnel is separate from the MCP server. The simplest setup is a start-mcp.bat (different file in a different directory) that only launches frpc:

@echo off
cd /d C:\Users\YourUser\frp\frp_0.61.1_windows_amd64
start "FRP tunnel mcp" /min frpc.exe -c frpc-mcp.toml

Add it to Task Scheduler the same way (At logon, highest privileges), or shove it in shell:startup.

Without autostart

If you just want to run node manually for development:

cd /d D:\mcp-server
node server.js

Ctrl+C to stop.


Extending

Adding a new host

Edit hosts.json:

{
  "hosts": {
    "production": {},
    "new-server": {
      "ip": "5.6.7.8",
      "user": "ubuntu",
      "key": "main",
      "description": "New server"
    }
  }
}

The server reads hosts.json at boot, so kill node (taskkill /F /IM node.exe /T) and the restart loop will pick up the new config in 5 seconds. In Claude.ai, disconnect and reconnect the connector so it sees the new host in the host parameter dropdown.

Adding a new SSH key

{
  "keys": {
    "main": "/path/to/main.pem",
    "client-x": "~/keys/client-x.pem"
  }
}

Adding a new tool

In server.js:


…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [LeszczynskiKarol](https://github.com/LeszczynskiKarol)
- **Source:** [LeszczynskiKarol/mcp-server](https://github.com/LeszczynskiKarol/mcp-server)
- **License:** MIT
- **Homepage:** https://mcpservers.org/servers/leszczynskikarol/mcp-server

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.