-
Notifications
You must be signed in to change notification settings - Fork 1
Installation
pp-mcp is a single Python process. It can run directly with python, or inside Docker. Files are always mounted/opened read-only — pp-mcp never writes to your .portfolio file.
- Python 3.11+ (matches the vendored protobuf-generated parser code)
- Dependencies from
requirements.txt:mcp,uvicorn,httpx,pydantic-settings,python-dotenv,protobuf>=6.31.1,<7,pycryptodome==3.20.0 - One (or more) Portfolio Performance
.portfoliofile(s), optionally AES-encrypted (password-protected)
pip install -r requirements.txt
export PP_FILE_PATH=/path/to/file.portfolio
# optional: export PP_PASSWORD=... ; export MCP_TRANSPORT=streamable-http
python -m src.main # from the repo root!Run it as a module (python -m src.main) from the repository root. Running python src/main.py directly fails with ModuleNotFoundError: No module named 'src', because the package needs to be importable as src.
By default the server listens on http://localhost:8080 using the streamable-http transport.
Set MCP_TRANSPORT=stdio and the server skips the HTTP layer entirely — no port, no bearer token, nothing to keep running in the background. Instead, the MCP client (e.g. Claude Desktop) launches pp-mcp itself as a subprocess for each session and talks MCP over stdin/stdout. This is the simplest option if you don't want an always-on process. See Configuring AI Tools for client-side config examples.
Two Compose files cover the two typical deployment shapes:
| File | Scenario |
|---|---|
docker-compose.dev.yml |
Simple local setup: a single .portfolio file, no auth required, no external Docker networks. |
docker-compose.yml |
Production/multi-source (e.g. Synology NAS): a directory of .portfolio files + portfolios.json, MCP_AUTH_TOKEN required, port bound only to 127.0.0.1, external networks for a shared reverse proxy (e.g. nginx-proxy-manager) and other backend containers. |
cp .env.example .env # adjust for the compose file you're using
docker-compose -f docker-compose.dev.yml up -d --build # local, single-source
# or
docker-compose up -d --build # production, multi-sourceThe container always exposes port 8080 internally; MCP_SERVER_PORT controls the host-side port mapping. Both compose files explicitly set MCP_SERVER_HOST=0.0.0.0 inside the container — required so the port mapping (and, in the production file, the nginx network) can actually reach the process. This does not weaken the app's own default (127.0.0.1, see below); it's the standard "bind to all interfaces inside an isolated container" pattern.
Files are mounted :ro (read-only) into the container in both variants.
Single-source (default): one instance serves exactly one file, configured via PP_FILE_PATH (+ optional PP_PASSWORD). All tools accept source as an optional parameter, but it can be omitted — there's nothing to disambiguate.
Multi-source: set PP_PORTFOLIOS_CONFIG to the path of a JSON file listing multiple sources (this takes precedence over PP_FILE_PATH/PP_PASSWORD, which are then ignored). Each entry needs an id, label, path, and optional password:
[
{"id": "example1", "label": "Example1", "path": "/data/portfolios/Example1.portfolio", "password": null},
{"id": "example2", "label": "Example2", "path": "/data/portfolios/Example2.portfolio", "password": null}
]See portfolios.json.example in the repo. With multiple sources configured, tools require the source parameter (the id from this config) to know which file to use; list_data_sources returns the configured id + label pairs (never paths or passwords) so a client can look them up. Each source keeps its own independent mtime-based cache.
- Call the
pingtool — it should return"pong". - A TCP healthcheck on port 8080 is enough to confirm the process is up (both Compose files already define one via
healthcheck:).
| Variable | Default | Meaning |
|---|---|---|
PP_FILE_PATH |
– | Path to the .portfolio file (single-source fallback; /data/portfolio.portfolio inside the container). Ignored if PP_PORTFOLIOS_CONFIG is set. |
PP_PASSWORD |
empty | Password for an encrypted file (single-source). |
PP_PORTFOLIOS_CONFIG |
empty | Path to the multi-source JSON config. Takes precedence over PP_FILE_PATH/PP_PASSWORD. |
MCP_TRANSPORT |
streamable-http |
streamable-http, sse, or stdio (no resident HTTP server). |
MCP_SERVER_HOST |
127.0.0.1 |
Interface HTTP transports bind to (unused for stdio). Least-exposure default for local/non-Docker runs; both Compose files override it to 0.0.0.0 since the container needs it to be reachable via the port mapping. For non-Docker use, only raise this to 0.0.0.0 if you actually need LAN reachability — and set MCP_AUTH_TOKEN if you do. |
MCP_SERVER_PORT |
8080 |
Listening port for HTTP transports (unused for stdio). |
MCP_AUTH_TOKEN |
empty | Optional bearer token; empty = no auth. Required as soon as the server is reachable outside a trusted local network. |
MCP_REQUIRE_AUTH |
false |
For HTTP transports, the server refuses to start if this is true and MCP_AUTH_TOKEN is empty. Set true in production (already set in docker-compose.yml); ignored for stdio. |
For an always-on local setup without Docker, pp-mcp can be wrapped in an OS-level service manager (e.g. launchd on macOS with KeepAlive=true). This is an environment-specific detail rather than part of core installation — see the repo's switch-portfolio.sh for an example of restarting such a service after switching the active .portfolio file.