Skip to main content
Glama

PersonalMCP

A local Python MCP server that gives an MCP client (VS Code, Copilot CLI) read/write access to one approved workspace: file and directory CRUD, search, git, shell commands, Python tooling, data conversion, web fetch, HTTP testing, system diagnostics and a todo list (68 tools). It uses the official MCP Python SDK over stdio and does not invoke an LLM. All tools run under one security model: workspace confinement, protected-name denylist, secret redaction, hashed audit logging, size/time limits, and an optional operator policy. Set read_only for inspection only, or allow_commands=false to disable process execution. Tool groups are documented at docs://tools (or the get_tool_docs tool) and in src/personal_mcp/toolkit/resources.

Requirements

  • Python 3.11 or newer

  • Git is optional; Git inspection is disabled when it is unavailable or the workspace is not itself a repository

  • Install from the release ZIP for an offline installation, or install the pinned project dependencies from PyPI

Related MCP server: Cloud Harness MCP

Run from a checkout

python -m pip install .
python -m personal_mcp --workspace C:\path\to\workspace serve
python -m pip install .
python -m personal_mcp --workspace "$HOME/project" serve

The server defaults to the current directory when no workspace is supplied. Configuration can be passed as JSON with --config; MCP_WORKSPACE_ROOT is the only supported environment override. See docs/configuration.md.

Administration

python -m personal_mcp --version
python -m personal_mcp validate-config
python -m personal_mcp self-test
python -m personal_mcp print-client-config
python -m personal_mcp diagnostics
python -m personal_mcp capability-manifest

See docs/installation.md, docs/security-and-guardrails.md, and docs/compatibility.md before deployment. Manual GitHub Copilot and VS Code validation is documented in tests/manual/github-copilot-vscode-validation.md.

Development

python -m unittest discover -s tests -v
python scripts/validate/validate_docs.py
python scripts/build/build_release.py

This project is not affiliated with or an extension to GitHub Copilot or Visual Studio Code. See SECURITY.md for vulnerability reporting.

Available Tools

68 tools
api_load_testA

Tiny load probe: send requests requests (max 200) with concurrency workers (max 20) and report status counts, errors and latency percentiles. Use only against systems you own.

Inputs: url (required), method, timeout, requests, +1 more. Returns: result

check_tcp_portB
Read-onlyIdempotent

Test whether a TCP connection to host:port succeeds, with connect time.

Inputs: host (required), port (required), timeout. Returns: result

cim_queryA
Read-onlyIdempotent

Query CIM/WMI classes via Get-CimInstance (Windows only), e.g. Win32_OperatingSystem, Win32_LogicalDisk, Win32_NetworkAdapterConfiguration, Win32_Service. filter is a WQL WHERE clause such as "DriveType=3". Read-only.

Inputs: class_name (required), limit, filter, namespace, +1 more. Returns: result

convert_dataA

Convert between json, yaml, toml, csv, xml and psd1 (PowerShell data files). Provide either path or text. from_format is inferred from the file extension when omitted. With output_path the result is written there; otherwise it is returned. Reading psd1 needs pwsh (restricted language mode, no code execution); XML uses @attr / #text conventions.

Inputs: to_format (required), path, text, from_format, +1 more. Returns: result

copy_pathB

Copy a file or directory inside the workspace. Never overwrites.

Inputs: source (required), destination (required). Returns: result

create_diagnostic_bundleB

Write a sanitized local diagnostic summary to the approved diagnostics directory.

Inputs: no named parameters. Returns: object

create_directoryC

Create a directory and any missing parents. Succeeds if it already exists.

Inputs: path (required). Returns: result

create_fileB

Create a file (and parent dirs) with the given content. Writes are atomic.

Inputs: path (required), content (required), overwrite. Returns: result

delete_fileA
Destructive

Delete a file or directory (recursively). Irreversible. Refuses the workspace root, trees that contain links, nested repositories or protected files, and huge trees.

Inputs: path (required). Returns: result

dns_lookupB
Read-onlyIdempotent

Resolve a hostname to its addresses using the system resolver.

Inputs: host (required). Returns: result

edit_fileA

Replace old_string with new_string in a file. Fails unless it matches exactly once (or replace_all is true). dry_run=true returns a unified diff without writing.

Inputs: path (required), new_string (required), old_string (required), dry_run, +1 more. Returns: result

edit_file_multiA
Destructive

Apply several edits atomically. Each edit is {"old_string": ..., "new_string": ..., optional "replace_all": "true"}. Edits apply in order; if any fails nothing is written.

Inputs: path (required), edits (required), dry_run. Returns: result

environment_variablesB
Read-onlyIdempotent

Environment variables of the server process. Values of secret-looking names are redacted.

Inputs: name_contains. Returns: result

format_codeB

Format Python code with ruff; check_only=True only reports.

Inputs: cwd, path, check_only. Returns: result

get_capability_helpA

Return the capability inventory or one capability's manifest entry.

Inputs: capability. Returns: object

get_file_metadataB

Return safe metadata for one file without reading its contents.

Inputs: path (required). Returns: object

get_tool_docsA
Read-onlyIdempotent

Return usage docs and examples for a toolkit group (filesystem, search, shell, git, python, web-fetch, data-conversion, api-testing, diagnostics, todo, policy) or 'index'. Call this after a tool error.

Inputs: topic. Returns: result

git_addC

Stage files.

Inputs: paths (required), repo. Returns: result

git_blameB
Read-onlyIdempotent

Show who last changed each line of a file (read-only). Optionally limit to a line range.

Inputs: path (required), repo, end_line, start_line. Returns: result

git_branch_createA

Create a new branch (and optionally switch to it). Never overwrites an existing branch.

Inputs: name (required), repo, switch, start_point. Returns: result

git_branch_listA
Read-onlyIdempotent

List branches with their last commit and upstream (read-only). all_branches includes remotes.

Inputs: repo, all_branches. Returns: result

git_commitC

Commit staged changes.

Inputs: message (required), repo. Returns: result

git_diffB
Read-onlyIdempotent

Show git diff (optionally staged and/or for one path).

Inputs: path, repo, staged. Returns: result

git_diff_statB
Read-onlyIdempotent

Summarise changes per file (read-only), compact for large diffs. base compares with a revision.

Inputs: base, repo, staged. Returns: result

git_diff_summaryA

Return bounded diff statistics without patch contents.

Inputs: no named parameters. Returns: object

git_initB

Initialise a new git repository (non-destructive; existing repos are left intact).

Inputs: repo, initial_branch. Returns: result

git_logC
Read-onlyIdempotent

Show recent commits.

Inputs: repo, max_count. Returns: result

git_pushA
Destructive

Push a branch (default: current) to a remote. Force pushes and ref deletion are not supported. tags=true pushes tags instead of a branch.

Inputs: repo, tags, branch, remote, +1 more. Returns: result

git_recent_historyB

Return a bounded list of recent commit summaries.

Inputs: limit. Returns: object

git_remote_infoA
Read-onlyIdempotent

List configured remotes and their URLs (read-only). Credentials in URLs are masked.

Inputs: repo. Returns: result

git_repository_statusB

Return bounded read-only Git status; no untracked filenames are enumerated.

Inputs: no named parameters. Returns: object

git_showB
Read-onlyIdempotent

Show a commit's message and diff (read-only). stat_only=true gives only the file summary.

Inputs: rev, path, repo, stat_only. Returns: result

git_stash_listB
Read-onlyIdempotent

List stashes (read-only).

Inputs: repo. Returns: result

git_statusC
Read-onlyIdempotent

Show short git status.

Inputs: repo. Returns: result

git_switchB

Switch to an existing branch. Git refuses if it would overwrite local changes.

Inputs: name (required), repo. Returns: result

git_tag_createB

Create a tag (annotated if message given). Never moves or replaces an existing tag.

Inputs: name (required), repo, target, message. Returns: result

globA
Read-onlyIdempotent

Find files by glob pattern (e.g. '**/*.py'), relative to path. Skips git-ignored files unless respect_gitignore=false. Use offset to page.

Inputs: pattern (required), path, offset, max_results, +1 more. Returns: result

grepA
Read-onlyIdempotent

Regex search file contents. Returns path:line: text matches. Skips git-ignored files (and .git, node_modules, .venv) unless respect_gitignore=false. Use offset to page.

Inputs: pattern (required), path, offset, file_glob, +3 more. Returns: result

http_requestA

Send an HTTP request (localhost and private addresses allowed) and report status, timing, redacted headers and a truncated body. Optional assertions: expect_status, expect_json ({"data.items[0].id": 5} path->value), expect_contains (substring of body), max_latency_ms. Result begins with PASS/FAIL when assertions are given.

Inputs: url (required), body, method, params, +9 more. Returns: result

lintB

Lint Python code with ruff (optionally auto-fix).

Inputs: cwd, fix, path. Returns: result

list_directoryC

List one workspace directory. Use cursor for the next bounded page.

Inputs: path, cursor, page_size, include_hidden. Returns: object

list_portsB
Read-onlyIdempotent

List TCP/UDP sockets with owning process. May need elevated rights to see other users' PIDs.

Inputs: protocol, listening_only. Returns: result

list_processesB
Read-onlyIdempotent

List processes (pid, name, user, cpu%, memory) sorted by 'memory' or 'cpu' or 'pid'.

Inputs: limit, sort_by, name_contains. Returns: result

list_servicesB
Read-onlyIdempotent

List services (systemd on Linux, Get-Service on Windows, launchctl on macOS). state: e.g. running / stopped (Windows) or running / failed / active (systemd).

Inputs: state, name_contains. Returns: result

markdown_to_scriptA

Extract code from a markdown file. Only fenced blocks tagged with language are kept unless extract_all_blocks is true. Prose becomes comments when include_prose is true.

Inputs: path (required), language (required), output_path, include_prose, +1 more. Returns: result

move_pathB
Destructive

Move or rename a file or directory inside the workspace. Never overwrites.

Inputs: source (required), destination (required). Returns: result

network_interfacesA
Read-onlyIdempotent

NIC configuration: addresses, netmask, MAC, MTU, speed and up/down state, plus I/O counters.

Inputs: no named parameters. Returns: result

pandoc_convertB

Convert documents with pandoc (docx, html, md, rst, pdf output needs a LaTeX engine...). Runs in --sandbox mode so the document cannot read other files or run filters.

Inputs: input_path (required), output_path (required), to_format, from_format. Returns: result

policy_infoA
Read-onlyIdempotent

Show whether an operator policy file exists and its contents (allow/deny lists, command deny patterns, web_fetch domain allow-list).

Inputs: no named parameters. Returns: result

query_dataB
Read-onlyIdempotent

Extract values from a json/yaml/toml/csv/xml/psd1 file with a path expression such as 'servers[0].name', 'users[].email' or '.port'. Returns JSON (a list of matches).

Inputs: path (required), query (required), format. Returns: result

read_event_logsA
Read-onlyIdempotent

Recent system events. Linux: journalctl (source = unit name, level = minimum severity). Windows: Get-WinEvent (source = log name, default 'System'; level = exact level). macOS: log show. level: critical|error|warning|info|verbose.

Inputs: level, source, contains, max_entries, +1 more. Returns: result

read_text_fileC

Read a bounded UTF-8 excerpt from an approved workspace file.

Inputs: path (required), end_line, start_line. Returns: object

replace_linesA

Replace lines start_line..end_line (1-based, inclusive) with new_text. Use end_line=start_line-1 to insert before start_line.

Inputs: path (required), end_line (required), new_text (required), start_line (required), +1 more. Returns: result

run_commandA
Destructive

Run a shell command and return exit code, stdout and stderr. Uses PowerShell on Windows and the default shell elsewhere. The working directory must be inside the workspace (default: the workspace root). The command itself is NOT confined: a shell can still reach any path the server's user can. Secret-named environment variables are removed and output is redacted.

Inputs: command (required), cwd, timeout. Returns: result

run_testsC

Run pytest on a path with optional extra args (e.g. '-k name -x').

Inputs: cwd, args, path. Returns: result

script_to_markdownA

Convert a script into literate markdown: column-0 comment blocks (and PowerShell <# #> blocks) become prose, everything else becomes fenced code. Heuristic and meant for documentation; markdown_to_script reverses it.

Inputs: path (required), language, output_path. Returns: result

search_workspace_textC

Search bounded text files and return sanitized line excerpts.

Inputs: query (required), path, cursor, page_size, +1 more. Returns: object

server_healthB

Return safe server health, version, configuration state, and diagnostics status.

Inputs: no named parameters. Returns: object

service_statusC
Read-onlyIdempotent

Detailed status of one service.

Inputs: name (required). Returns: result

summarize_project_structureC

Return a shallow, bounded inventory without reading file contents.

Inputs: max_files. Returns: object

system_infoA
Read-onlyIdempotent

OS, kernel, uptime, CPU, load, memory, swap and disk usage for this machine.

Inputs: no named parameters. Returns: result

todo_addA

Add a todo (status pending) to the workspace scratchpad and return the updated list.

Inputs: text (required). Returns: result

todo_listA
Read-onlyIdempotent

List the workspace todo scratchpad. Optional status filter: pending, in_progress, done.

Inputs: status. Returns: result

todo_removeA

Remove one todo from the scratchpad by id; returns the updated list.

Inputs: id (required). Returns: result

todo_updateA

Change a todo's status (pending, in_progress, done) and/or text; returns the updated list.

Inputs: id (required), text, status. Returns: result

validate_server_configurationB

Validate the loaded configuration without returning machine-specific paths.

Inputs: no named parameters. Returns: object

web_fetchA

Download a web page (after explicit user confirmation), sanitise it and save it as a local markdown file. Returns the file path only; read the file to consume it. Executable/archive/ document extensions and non-text content types are rejected; scripts, forms, iframes, event handlers and unsafe links are stripped. Private/loopback addresses are blocked.

Inputs: url (required), output_dir. Returns: result

workspace_infoA

Return an opaque workspace identifier and active safety limits.

Inputs: no named parameters. Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    C2.9/5.0

    Scored across 68 tools

    Disambiguation3/5

    Tools are grouped into clear domains, but several within-domain pairs overlap heavily: git_status vs git_repository_status, git_log vs git_recent_history, and git_diff vs git_diff_summary vs git_diff_stat. Descriptions help distinguish bounded/read-only variants, but an agent could still easily misselect among them.

    Naming Consistency3/5

    All names are snake_case, which is consistent, but the structural convention is mixed: verb_noun (list_directory, read_text_file), noun_verb (todo_list, git_status), and noun_noun (service_status, git_repository_status) all appear. The domain prefixes help readability, but there is no single predictable pattern.

    Tool Count1/5

    With 68 tools, the surface is extremely large even for a broad personal automation server, and several tools duplicate existing read-only git functionality. This is squarely in the 50+ extreme-count range and makes discovery and selection harder.

    Completeness4/5

    The server covers filesystem, search, shell, Python tooling, git, data conversion, web/API testing, diagnostics, todos, and system inspection with broad lifecycle support. The main gaps are git network/workflow operations such as clone/fetch/pull/merge and service or process control, though run_command provides a workaround.

    Maintenance

    ActivityNo data
    ResponsivenessSyncing

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      C
      maintenance
      Exposes a secure, path-confined bridge to a local workspace and git remotes, enabling MCP clients to search, read, write, reset files, and perform git operations.
      -
    • A
      license
      A
      quality
      B
      maintenance
      Enables MCP clients to safely read, write, edit, search, and optionally run commands within one or more named project workspaces, while maintaining a work journal and tracking changes.
      19
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables managed access to workspace file operations, background tasks, Skills, and upstream MCP services through a unified web console with workspace-bound keys and explicit tool permissions.
      MIT