PMCP - Progressive MCP: Minimal context bloat with on-demand tool discovery
Project description
PMCP - Progressive MCP
Progressive disclosure for MCP - Minimal context bloat with on-demand tool discovery and dynamic server provisioning.
The Problem
When Claude Code connects directly to multiple MCP servers (GitHub, Jira, DB, etc.), it loads all tool schemas into context. This causes:
- Context bloat: Dozens of tool definitions consume tokens before you even ask a question
- Static configuration: Requires Claude Code restart to see new servers
- No progressive disclosure: Full schemas shown even when not needed
Anthropic has highlighted context bloat as a key challenge with MCP tooling.
The Solution
PMCP acts as a single MCP server that Claude Code connects to. Instead of exposing all downstream tools, it provides:
- 19 stable meta-tools (not the 50+ underlying tools)
- Lazy by default: downstream servers are available on demand and only eager-start when listed in
autoStart - Dynamically provisions new servers on-demand from a manifest of 90+
- Progressive disclosure: Compact capability cards first, detailed schemas only on request
- Policy enforcement: Output size caps and optional secret redaction
Quick Start
Installation
# With uv (recommended)
uv pip install pmcp
# Or run directly without installing
uvx pmcp
# With pip
pip install pmcp
Capability matching is built-in — no API key needed.
gateway.request_capabilityuses a three-tier pure-Python router: explicit name match → category match → search guidance.
Configure with pmcp setup
PMCP includes a wizard-style helper that can render ready-to-use MCP client config for Claude and OpenCode.
The generated config only connects your client to the PMCP gateway. Downstream MCP
servers stay lazy until first use unless you add them to autoStart in your
.mcp.json.
Use pmcp setup to print the generated config:
pmcp setup --client claude --mode stdio # Claude local stdio
pmcp setup --client claude --mode http # Claude shared-service HTTP
pmcp setup --client opencode --mode stdio # OpenCode local stdio
pmcp setup --client opencode --mode http # OpenCode shared-service HTTP
Write directly into your client config with --write:
pmcp setup --client claude --mode http --write
Without --write, pmcp setup prints the config so you can paste it into:
- Claude:
~/.mcp.json - OpenCode:
~/.config/opencode/opencode.json
Use shared-service HTTP mode when running one PMCP service for multiple sessions or clients. Use single-process stdio mode for local testing.
Shared Service Mode (Manual)
If you prefer manual config, point each client to the shared HTTP endpoint:
{
"mcpServers": {
"pmcp": {
"type": "http",
"url": "http://127.0.0.1:3344/mcp"
}
}
}
Why this mode: PMCP uses a singleton lock (~/.pmcp/gateway.lock), so multiple local launches can conflict. One shared service avoids lock collisions and keeps tool state consistent.
Shared gateway state:
- All clients connected to one PMCP HTTP gateway share downstream server connections, pending requests, provisioned tools, and live lifecycle state.
gateway.refresh(force=true),gateway.disconnect_server(force=true), andgateway.restart_server(force=true)can cancel or interrupt downstream work started by another client using the same gateway.gateway.healthand livepmcp status --verboseshow startup policy observations for downstream servers without exposing secret values.--rate-limit/PMCP_RATE_LIMITapplies per observed source IP on/mcp; localhost clients and reverse-proxied clients can share one bucket unless the proxy preserves distinct client IPs.
Quick verification:
systemctl --user is-active pmcp
curl -sS http://127.0.0.1:3344/mcp
Security
HTTP transport is unauthenticated by default. For any non-localhost exposure, require a bearer token:
# Start with auth token
pmcp --transport http --auth-token mysecrettoken
# Or via environment variable
PMCP_AUTH_TOKEN=mysecrettoken pmcp --transport http
Clients must then include Authorization: Bearer mysecrettoken on /mcp requests.
/health and /metrics remain unauthenticated by design; protect them with
firewall rules, IP allowlists, or reverse-proxy policy before any non-localhost
exposure.
Assumptions and trust model:
- PMCP binds to
127.0.0.1by default — not safe to expose publicly without--auth-token. - Config files (
.mcp.json) are trusted inputs — treat them like code; do not load untrusted configs. - Secrets in
.envfiles are passed to child MCP server processes; protect the.envfile with filesystem permissions.
Production background service (Linux systemd):
# ~/.config/systemd/user/pmcp.service
[Unit]
Description=PMCP MCP Gateway
[Service]
ExecStart=/usr/local/bin/pmcp --transport http --auth-token %i
Restart=on-failure
[Install]
WantedBy=default.target
systemctl --user enable --now pmcp
Or with nohup:
nohup pmcp --transport http --auth-token "$PMCP_AUTH_TOKEN" >> ~/.pmcp/logs/gateway.log 2>&1 &
TLS / Reverse Proxy
PMCP's HTTP transport is plaintext. For any exposure beyond localhost, terminate TLS at a
reverse proxy and forward to 127.0.0.1:3344. Keep --host 127.0.0.1 (the default) so PMCP
only listens on the loopback interface.
Nginx (/etc/nginx/sites-available/pmcp):
server {
listen 443 ssl;
server_name pmcp.example.com;
ssl_certificate /etc/letsencrypt/live/pmcp.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/pmcp.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3344;
proxy_set_header Authorization $http_authorization;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
Caddy (Caddyfile):
pmcp.example.com {
reverse_proxy 127.0.0.1:3344
}
Caddy handles TLS automatically via Let's Encrypt.
Other MCP Clients
PMCP works with any MCP-compatible client. Below are configuration examples for popular clients.
Codex CLI
Create ~/.codex/mcp.json (verify path in Codex documentation):
{
"mcpServers": {
"gateway": {
"command": "pmcp",
"args": []
}
}
}
Gemini CLI
Create the appropriate config file (verify path in Gemini CLI documentation):
{
"mcpServers": {
"gateway": {
"command": "pmcp",
"args": []
}
}
}
Note: Configuration paths and formats vary by client. Verify the exact location and format in each client's official documentation.
Your First Interaction
You: "Take a screenshot of google.com"
Claude uses: gateway.invoke {
tool_id: "playwright::browser_navigate",
arguments: { url: "https://google.com" }
}
// Then: gateway.invoke { tool_id: "playwright::browser_screenshot" }
Returns: Screenshot of google.com
Architecture
┌─────────────────────────────────────────────────────────────┐
│ Claude Code │
│ Only connects to PMCP (single server in config) │
└────────────────────────────┬────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ PMCP │
│ • 19 meta-tools (catalog, invoke, provision, etc.) │
│ • Progressive disclosure (compact cards → full schemas) │
│ • Policy enforcement (allow/deny lists) │
└────────────────────────────┬────────────────────────────────┘
│
┌────────────────────┼────────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Explicit │ │ Manifest │ │ Custom Servers │
│ autoStart │ │ (90+ servers │ │ (your own MCP │
│ servers │ │ on-demand) │ │ servers) │
└───────────────┘ └─────────────────┘ └─────────────────┘
Key principle: Users configure ONLY pmcp in Claude Code.
The gateway discovers and manages all other servers.
Why Single-Gateway?
- No context bloat - Claude sees 19 tools, not 50+
- No restarts - Provision new servers without restarting Claude Code
- Consistent interface - All tools accessed via
gateway.invoke - Policy control - Centralized allow/deny rules
Gateway Tools
The gateway exposes 19 meta-tools organized into four categories:
Core Tools
| Tool | Purpose |
|---|---|
gateway.catalog_search |
Search available tools, returns compact capability cards |
gateway.describe |
Get detailed schema for a specific tool |
gateway.invoke |
Call a downstream tool with argument validation |
gateway.refresh |
Reload backend configs and reconnect; refuses while requests are pending unless force=true |
gateway.health |
Get gateway and server health status |
Lifecycle Tools
| Tool | Purpose |
|---|---|
gateway.connect_server |
Connect or start a known configured, manifest/provisioned, or registered discovered server |
gateway.disconnect_server |
Runtime-stop a server without editing .mcp.json or changing autoStart |
gateway.restart_server |
Runtime-stop then reconnect a server without changing persistent config |
Capability Discovery Tools
| Tool | Purpose |
|---|---|
gateway.request_capability |
Natural language capability matching with CLI preference |
gateway.sync_environment |
Detect platform and available CLIs |
gateway.provision |
Install and start MCP servers on-demand |
gateway.update_server |
Update an MCP server package and reconnect it |
gateway.auth_connect |
Store credentials for a server and retry provisioning |
gateway.submit_feedback |
Preview/submit technical PMCP feedback issues to GitHub |
gateway.provision_status |
Check installation progress |
gateway.search_registry |
Search the public MCP Registry for external servers |
gateway.register_discovered_server |
Register a registry result for provisioning |
Monitoring Tools
| Tool | Purpose |
|---|---|
gateway.list_pending |
List pending tool invocations with health status |
gateway.cancel |
Cancel a pending tool invocation |
gateway.refresh is intentionally conservative in shared-service mode. If a
downstream request is in flight, refresh returns ok=false without disconnecting
or reconnecting servers. Use gateway.list_pending to inspect active requests,
then retry with force=true only when cancelling that work is acceptable.
gateway.disconnect_server and gateway.restart_server follow the same
shared-service disruption policy for the target server: they refuse while that
server has pending requests unless force=true. With force=true, only pending
requests for the named server are cancelled. These controls are runtime-only;
they free local resources and update live gateway state, but they do not edit
.mcp.json, remove server definitions, or change autoStart. In HTTP shared
service mode, stopping or restarting a downstream server can affect other
clients using the same PMCP gateway.
Subordinate MCP Updates
gateway.update_serveris the phase-1 update path for subordinate MCPs.pmcp update <server>andpmcp update --allcall the same gateway update workflow.gateway.describe,gateway.invoke, andgateway.provisionmay returnupdate_warningwhen a newer package version is detected.- Background stale-version indexing is active — warnings are zero-latency via hourly pre-population.
Feedback Telemetry
- PMCP can emit failure feedback hints and generate GitHub issue payload previews for agents.
- Telemetry is technical-only and warns before submission; payloads include PMCP/tool context.
- Disable permanently with
pmcp guidance --telemetry off.
Progressive Disclosure Workflow
PMCP follows a progressive disclosure pattern - start with natural language, get recommendations, drill down as needed.
Step 1: Request a Capability
You: "I need to look up library documentation"
gateway.request_capability({ query: "library documentation" })
Returns:
{
"status": "candidates",
"candidates": [{
"name": "context7",
"candidate_type": "server",
"relevance_score": 0.95,
"is_running": true,
"reasoning": "Context7 provides up-to-date documentation for any package"
}],
"recommendation": "Use context7 - already running"
}
Step 2: Search Available Tools
gateway.catalog_search({ query: "documentation" })
Step 3: Get Tool Details
gateway.describe({ tool_id: "context7::get-library-docs" })
Step 4: Invoke the Tool
gateway.invoke({
tool_id: "context7::get-library-docs",
arguments: { libraryId: "/npm/react/19.0.0" }
})
Offline Tool Discovery
When using gateway.catalog_search, you can discover tools from servers that haven't started yet:
// Search all tools including offline/lazy servers
gateway.catalog_search({
"query": "browser",
"include_offline": true
})
This uses pre-cached tool descriptions from .mcp-gateway/descriptions.yaml. To refresh the cache:
pmcp refresh
Note: Cached tools show metadata only. Full schemas are available after the server starts (use gateway.describe to trigger lazy start).
Dynamic Server Provisioning
PMCP can install and start MCP servers on-demand from a curated manifest of 90+ servers.
Example: Adding GitHub Support
You: "I need to manage GitHub issues"
gateway.request_capability({ query: "github issues" })
Returns (if not already configured):
{
"status": "candidates",
"candidates": [{
"name": "github",
"candidate_type": "server",
"is_running": false,
"requires_api_key": true,
"env_var": "GITHUB_PERSONAL_ACCESS_TOKEN",
"env_instructions": "Create at https://github.com/settings/tokens with repo scope"
}]
}
Provisioning
# 1. Set API key (if required)
export GITHUB_PERSONAL_ACCESS_TOKEN=ghp_...
# 2. Provision via gateway
gateway.provision({ server_name: "github" })
Optional Eager Startup
Packaged manifest servers do not start automatically. They are lazy by default: PMCP can discover or provision them from the manifest, then connect on first use.
To eagerly start a server every time PMCP starts, list it in top-level
autoStart:
{
"autoStart": ["playwright", "context7"],
"mcpServers": {}
}
Common opt-in choices:
| Server | Description | API Key |
|---|---|---|
playwright |
Browser automation - navigation, screenshots, DOM inspection | Not required |
context7 |
Library documentation lookup - up-to-date docs for any package | Optional (for higher rate limits) |
Startup policy decisions are visible through gateway.health and live
pmcp status --verbose. Health rows keep the existing name, status,
tool_count, and error fields, and may also include:
| Field | Meaning |
|---|---|
startup_policy |
eager, lazy, skipped, or unknown |
startup_source |
Resolver source such as project, user, manifest, configured, or auto_start |
startup_skip_reason |
Machine-readable skip reason such as policy_denied, missing_auth, or unknown_auto_start |
startup_env_var |
Required environment variable name for missing-auth skips |
Servers stopped with gateway.disconnect_server remain visible in health as
offline or lazy when PMCP still knows their configuration, and startup policy
observation fields are preserved.
Example missing-auth health row:
{
"name": "github",
"status": "offline",
"tool_count": 0,
"startup_policy": "skipped",
"startup_source": "manifest",
"startup_skip_reason": "missing_auth",
"startup_env_var": "GITHUB_PERSONAL_ACCESS_TOKEN"
}
Available Servers
The manifest includes 90+ servers that can be provisioned on-demand:
No API Key Required
| Server | Description |
|---|---|
filesystem |
File operations - read, write, search |
memory |
Persistent knowledge graph |
fetch |
HTTP requests with robots.txt compliance |
sequential-thinking |
Problem solving through thought sequences |
git |
Git operations via MCP |
sqlite |
SQLite database operations |
time |
Timezone operations |
puppeteer |
Headless Chrome automation |
Requires API Key
| Server | Description | Environment Variable |
|---|---|---|
github |
GitHub API - issues, PRs, repos | GITHUB_PERSONAL_ACCESS_TOKEN |
gitlab |
GitLab API - projects, MRs | GITLAB_PERSONAL_ACCESS_TOKEN |
slack |
Slack messaging | SLACK_BOT_TOKEN |
notion |
Notion workspace | NOTION_TOKEN |
linear |
Linear issue tracking | LINEAR_API_KEY |
postgres |
PostgreSQL database | POSTGRES_URL |
brave-search |
Web search | BRAVE_API_KEY |
google-drive |
Google Drive files | GDRIVE_CREDENTIALS |
sentry |
Error tracking | SENTRY_AUTH_TOKEN |
stripe |
Payments and billing | STRIPE_SECRET_KEY |
github-actions |
CI/CD workflows | GITHUB_PERSONAL_ACCESS_TOKEN |
datadog |
Monitoring and observability | DATADOG_API_KEY |
cloudflare |
Edge network and Workers | CLOUDFLARE_API_TOKEN |
figma |
Design files and components | FIGMA_ACCESS_TOKEN |
jira |
Issue tracking | JIRA_API_TOKEN |
airtable |
Spreadsheet database | AIRTABLE_TOKEN |
hubspot |
CRM and marketing | HUBSPOT_ACCESS_TOKEN |
twilio |
SMS and voice | TWILIO_ACCOUNT_SID |
...and 80+ more |
Use gateway.catalog_search to explore |
— |
See .env.example for all supported environment variables.
Code Execution Guidance
PMCP includes built-in guidance to encourage models to use code execution patterns, reducing context bloat and improving workflow efficiency.
Guidance Layers
L0 (MCP Instructions): Brief philosophy in server instructions (~30 tokens)
- "Write code to orchestrate tools - use loops, filters, conditionals"
L1 (Code Hints): Ultra-terse hints in search results (~8-12 tokens/card)
- Single-word hints: "loop", "filter", "try/catch", "poll"
L2 (Code Snippets): Minimal examples in describe output (~40-80 tokens, opt-in)
- 3-4 line code examples showing practical usage
L3 (Methodology Resource): Full guide (lazy-loaded, 0 tokens)
- Accessible via
pmcp://guidance/code-executionresource
Guidance Configuration
Create ~/.claude/gateway-guidance.yaml:
guidance:
level: "minimal" # Options: "off", "minimal", "standard"
layers:
mcp_instructions: true # L0 philosophy
code_hints: true # L1 hints
code_snippets: false # L2 examples (default: off)
methodology_resource: true # L3 guide
Levels:
minimal(default): L0 + L1 (~200 tokens overhead)standard: L0 + L1 + L2 (~320 tokens overhead)off: No guidance
View Guidance Status
pmcp guidance # Show configuration
pmcp guidance --show-budget # Show token estimates
Token Budget
- Minimal mode: ~200 tokens typical workflow (L0 + search)
- Standard mode: ~320 tokens (L0 + search + 1 describe)
- 80% reduction vs loading all tool schemas upfront!
Configuration
Config Discovery
PMCP discovers MCP servers from:
- Project config:
.mcp.jsonin project root (highest priority) - User config:
~/.mcp.jsonor~/.claude/.mcp.json - Custom config: Via
--configflag orPMCP_CONFIGenv var
Adding Custom Servers
For MCP servers not in the manifest, add them to ~/.mcp.json:
{
"autoStart": ["my-custom-server"],
"mcpServers": {
"my-custom-server": {
"command": "node",
"args": ["./my-server.js"],
"env": {
"API_KEY": "..."
}
}
}
}
PMCP supports both local command-based and remote URL-based downstream entries from discovered config files. Entries in mcpServers make downstream servers available lazily/on demand; they do not by themselves mean the server should be eagerly started.
The top-level autoStart list controls explicit eager startup. Names can refer to
servers defined in mcpServers or packaged manifest entries such as playwright
and context7. Omit a server from autoStart to keep it lazy.
The legacy top-level disableAutoStart list remains supported for deployments
that temporarily enable PMCP_LEGACY_MANIFEST_AUTOSTART=1, but packaged PMCP
defaults no longer require it.
Lazy Excalidraw example:
{
"mcpServers": {
"excalidraw": {
"type": "http",
"url": "https://mcp.excalidraw.com/mcp"
}
}
}
Eager Excalidraw example:
{
"autoStart": ["excalidraw"],
"mcpServers": {
"excalidraw": {
"type": "http",
"url": "https://mcp.excalidraw.com/mcp"
}
}
}
Remote Downstream Servers
You can also configure downstream MCP servers over HTTP/SSE directly in .mcp.json using type: "sse" or type: "http" (or type: "remote" for generic remote transport):
{
"mcpServers": {
"acme-sse": {
"type": "sse",
"url": "https://mcp.acme.dev/sse",
"headers": {
"Authorization": "Bearer ${ACME_MCP_TOKEN}",
"X-Tenant": "${ACME_TENANT_ID}"
}
},
"acme-http": {
"type": "http",
"url": "https://mcp.acme.dev/mcp",
"headers": {
"Authorization": "Bearer ${ACME_MCP_TOKEN}"
}
}
}
}
urlshould be the full remote endpoint for that server.headersvalues support${ENV_VAR}interpolation (Issue #40).- Resolve those environment variables from your shell environment or
~/.config/pmcp/pmcp.env.
Important: Don't add pmcp itself to this file. PMCP is configured
in your MCP client config, not in the downstream server list.
Credential Scope Management (pmcp secrets)
PMCP stores secrets in environment files by scope:
userscope:~/.config/pmcp/pmcp.envprojectscope:<project_root>/.env.pmcp
You can manage both scopes with pmcp secrets:
# Store a secret in user scope (shared by all projects)
pmcp secrets set API_TOKEN your-token --scope user
# Store a secret in project scope
pmcp secrets set API_TOKEN your-token --scope project --project /path/to/project
# Copy all user-scoped secrets into project scope
pmcp secrets sync --from-scope user --to-scope project --overwrite
# Copy project-scoped secrets into user scope
pmcp secrets sync --from-scope project --to-scope user --overwrite
Use scope-appropriate values such as API_TOKEN and keep the values in the generated .env files; PMCP and downstream MCP servers read from these files according to your active mode.
For service users, ~/.config/pmcp/pmcp.env is ideal for shared tokens used by all sessions.
Policy File
Create a policy file to control access and limits:
~/.claude/gateway-policy.yaml:
servers:
allowlist: [] # Empty = allow all
denylist:
- dangerous-server
tools:
denylist:
- "*::delete_*"
- "*::drop_*"
limits:
max_tools_per_server: 100
max_output_bytes: 50000
max_output_tokens: 4000
redaction:
patterns:
- "(api[_-]?key)[\\s]*[:=][\\s]*[\"']?([^\\s\"']+)"
- "(password|secret)[\\s]*[:=][\\s]*[\"']?([^\\s\"']+)"
CLI Commands
# Start the gateway server (default)
pmcp
# Check server status
pmcp status
pmcp status --json # JSON output
pmcp status --verbose # Include startup policy details when available
pmcp status --server playwright # Filter by server
# View logs
pmcp logs
pmcp logs --follow # Live tail
pmcp logs --tail 100 # Last 100 lines
# Refresh server connections
pmcp refresh
pmcp refresh --server github # Refresh specific server
pmcp refresh --force # Force reconnect all
# Initialize config (interactive)
pmcp init
# Render client setup snippets
pmcp setup
pmcp setup --client claude --mode stdio
pmcp setup --client opencode --mode http --write
# Run diagnostics for lock/mode/http checks
pmcp doctor
pmcp doctor --project /path/to/project
# Manage project/user secrets
pmcp secrets set API_TOKEN my-token --scope user
pmcp secrets sync --from-scope user --to-scope project --overwrite
pmcp doctor (Recommended before/after upgrades)
Use pmcp doctor to diagnose common PMCP startup and connectivity issues. It checks:
lock: detects singleton lock state and stale lock collisions at~/.pmcp/gateway.lockmode: detects local command-mode MCP config conflicts when a shared PMCP system service is runninghttp: probes the unauthenticated/healthendpoint derived fromPMCP_GATEWAY_URLorhttp://127.0.0.1:3344/mcpremote: detects unresolved remote downstream header environment referencesinstall: detects conflictinguv toolandpip --userinstalls
Example:
pmcp doctor
If any checks fail, follow the command in the output and rerun pmcp doctor.
Singleton Lock
By default, PMCP uses a global lock at ~/.pmcp/gateway.lock to ensure only one gateway runs per user. This prevents multiple gateway instances from spawning duplicate downstream servers.
Override the lock directory:
# CLI flag
pmcp --lock-dir /custom/path
# Environment variable
export PMCP_LOCK_DIR=/custom/path
pmcp
Per-project lock (not recommended):
pmcp --lock-dir ./.mcp-gateway
Deprecations
mcp-gatewaycommand naming is deprecated in documentation and examples.- Use
pmcpfor all CLI commands going forward. - Migration examples:
mcp-gateway refresh --force->pmcp refresh --forcemcp-gateway status --json->pmcp status --json
Docker
# Using Docker
docker run -it --rm \
-v ~/.mcp.json:/home/appuser/.mcp.json:ro \
-v ~/.env:/app/.env:ro \
ghcr.io/viperjuice/pmcp:latest
# Using Docker Compose
docker-compose up -d
Development
# Clone the repo
git clone https://github.com/ViperJuice/pmcp
cd pmcp
# Install with uv (recommended)
uv sync --all-extras
# Run tests
uv run pytest
# Run with debug logging
uv run pmcp --debug
Running Tests
# Run all tests
uv run pytest
# Run with coverage
uv run pytest --cov=pmcp
# Run specific test file
uv run pytest tests/test_policy.py -v
Project Structure
pmcp/
├── src/pmcp/
│ ├── __init__.py
│ ├── __main__.py # python -m pmcp entry
│ ├── cli.py # CLI commands (status, logs, init, refresh)
│ ├── server.py # MCP server implementation
│ ├── config/
│ │ └── loader.py # Config discovery (.mcp.json)
│ ├── client/
│ │ └── manager.py # Downstream server connections
│ ├── policy/
│ │ └── policy.py # Allow/deny lists
│ ├── tools/
│ │ └── handlers.py # Gateway tool implementations
│ ├── manifest/
│ │ ├── manifest.yaml # Server manifest (90+ servers)
│ │ ├── loader.py # Manifest loading
│ │ ├── installer.py # Server provisioning
│ │ └── environment.py # Platform/CLI detection
│ └── baml_client/ # BAML-generated client (used for structured parsing; no outbound LLM calls since v1.8.0)
├── tests/ # 310+ tests
├── Dockerfile
├── docker-compose.yml
├── .env.example
├── pyproject.toml
└── README.md
Troubleshooting
Server Won't Connect
pmcp status
pmcp logs --level debug
pmcp refresh --force
Missing API Key
# Check which key is needed
pmcp status --server github
# Set the key
export GITHUB_PERSONAL_ACCESS_TOKEN=ghp_...
Tool Invocation Fails
gateway.catalog_search({ query: "tool-name" })
gateway.describe({ tool_id: "server::tool-name" })
gateway.list_pending()
If gateway.refresh reports pending requests, inspect them with
gateway.list_pending() or retry refresh with force=true to cancel them before
reloading server configuration.
If gateway.disconnect_server or gateway.restart_server reports pending
requests, inspect gateway.list_pending(server="<name>") or retry with
force=true to cancel only that server's pending work.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pmcp-1.10.0.tar.gz.
File metadata
- Download URL: pmcp-1.10.0.tar.gz
- Upload date:
- Size: 453.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
93240747199ce392fcb1ced3d975a30001d961ab0065c0681d202d2d50697a6b
|
|
| MD5 |
cec969d8cc962eaacf24d436e2007a9b
|
|
| BLAKE2b-256 |
91e2a50ec6cff1ef5e05477147d64fbad4cf5d0fc8bde5425373b9ac55141c6b
|
Provenance
The following attestation bundles were made for pmcp-1.10.0.tar.gz:
Publisher:
release.yml on ViperJuice/pmcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pmcp-1.10.0.tar.gz -
Subject digest:
93240747199ce392fcb1ced3d975a30001d961ab0065c0681d202d2d50697a6b - Sigstore transparency entry: 1354716510
- Sigstore integration time:
-
Permalink:
ViperJuice/pmcp@d398bf9a01d69be22e6e8816ccf2af41aff534a7 -
Branch / Tag:
refs/tags/v1.10.0 - Owner: https://github.com/ViperJuice
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d398bf9a01d69be22e6e8816ccf2af41aff534a7 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pmcp-1.10.0-py3-none-any.whl.
File metadata
- Download URL: pmcp-1.10.0-py3-none-any.whl
- Upload date:
- Size: 171.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f93bdda06df38da110c56562ccd567e39c62822f67b1ac03dfb55f32e5b7f5c0
|
|
| MD5 |
c19a5a60644b9abae94f9aa5fce7c634
|
|
| BLAKE2b-256 |
04b07071fea84d91b48937652e62d0031809b2de78a3d6999a1073edefa100ee
|
Provenance
The following attestation bundles were made for pmcp-1.10.0-py3-none-any.whl:
Publisher:
release.yml on ViperJuice/pmcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pmcp-1.10.0-py3-none-any.whl -
Subject digest:
f93bdda06df38da110c56562ccd567e39c62822f67b1ac03dfb55f32e5b7f5c0 - Sigstore transparency entry: 1354716605
- Sigstore integration time:
-
Permalink:
ViperJuice/pmcp@d398bf9a01d69be22e6e8816ccf2af41aff534a7 -
Branch / Tag:
refs/tags/v1.10.0 - Owner: https://github.com/ViperJuice
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d398bf9a01d69be22e6e8816ccf2af41aff534a7 -
Trigger Event:
push
-
Statement type: