Skip to main content

Roadmap

Planned features and architectural improvements for MCP Gateway.

Env Hash Process Pooling (Planned)

Process pooling based on env hash, not workspace/project names. Two requests with identical resolved environment variables share the same server process.

Core Concept

process_key = hash(server_name + resolved_env)
ScenarioResult
Same env hashShare process
Different env hashDifferent process
Workspace/project nameIrrelevant at runtime

Example

Workspace A: /work/client-a → {SUPABASE_URL: prod, TOKEN: xxx}
Workspace B: /work/client-b → {SUPABASE_URL: prod, TOKEN: xxx}
→ Same hash, share process

Workspace C: /work/staging → {SUPABASE_URL: staging, TOKEN: yyy}
→ Different hash, different process

Config Resolution

  1. Request with cwd
  2. Load .env from cwd (walk up if needed)
  3. Check MCP_PROFILE env var
  4. Load profile config if set
  5. Merge env (highest priority first):
    • cwd .env
    • Profile env: block
    • ~/.mcp-gateway/.env
    • System env
  6. Hash resolved env for process key

Forced Isolation

For servers needing per-cwd isolation:

servers:
filesystem:
scope: isolated

Key becomes: hash(server_name + resolved_env + cwd)


Capability Filtering (Planned)

Currently, capabilities are tags on profiles. A future enhancement will add strict include/exclude filtering on profiles:

profiles:
# Whitelist mode - only these servers accessible
restricted:
capabilities:
include: [supabase, docs]

# Blacklist mode - all except these
developer:
capabilities:
exclude: [production-db]

# No restrictions (current behavior)
admin:
# No capabilities block = access to all

Filtering Logic

if profile.capabilities.include:
# Whitelist - only listed servers
allowed = server_name in include

elif profile.capabilities.exclude:
# Blacklist - all except listed
allowed = server_name not in exclude

else:
# No restrictions
allowed = true

Use Cases

ProfileConfigurationEffect
contractorinclude: [docs, github]Can only access docs and github servers
developerexclude: [production-db]Access to everything except production database
admin(no capabilities block)Full access

Client Mode (Planned)

A separate mcpg-client package for connecting to a remote gateway over the network. For team/enterprise scenarios where a central gateway is shared.

Architecture

┌─────────────────┐       ┌─────────────────┐       ┌─────────────────┐
│ Claude Code │ ───── │ mcpg-client │ ───── │ mcpg (remote) │
│ │ local │ localhost:8989 │ mTLS │ gateway.co:8989│
└─────────────────┘ └─────────────────┘ └─────────────────┘
Local HTTP proxy Central gateway
with auth certs with MCP servers

When to Use

ScenarioWhat to run
Local dev (solo)mcpg start - full gateway locally
Team/networkmcpg-client locally → connects to shared remote gateway

Client Responsibilities

  1. Run local HTTP server (same MCP interface as gateway)
  2. Authenticate to remote gateway with certs/API keys
  3. Fetch server list/config from remote
  4. Proxy MCP requests through to remote
  5. Pass project env context from local .env

Local Configuration

Project directory structure:

/work/my-project/
├── .env # Project env vars (passed to gateway)
├── .mcpg/
│ ├── config.yaml # Gateway URL, auth method
│ ├── client.crt # Client cert (mTLS)
│ └── client.key
└── src/

Example .mcpg/config.yaml:

gateway:
url: https://gateway.company.com:8989
auth:
type: mtls
cert: ./client.crt
key: ./client.key

# Or with bearer token
gateway:
url: https://gateway.company.com:8989
auth:
type: bearer
token: ${GATEWAY_TOKEN}

Claude Code Configuration

{
"mcpServers": {
"gateway": {
"command": "npx",
"args": ["-y", "mcpg-client"]
}
}
}

Auto-Detection

The client auto-detects the working directory when spawned:

  1. Gets cwd from process
  2. Walks up directories looking for .mcpg/config.yaml
  3. Loads .env from project root
  4. Passes env context to remote gateway

Process Pooling

The remote gateway handles process pooling using env hash:

  • Two clients with same resolved env share processes on the gateway
  • Different env = different processes
  • scope: isolated on a server forces per-cwd isolation

Security

  • mTLS preferred for production
  • Client certs issued per-developer or per-project
  • Gateway validates client cert before accepting requests
  • Project env vars are trusted (client-side)

Workspace-Based Profile Resolution (Planned)

Workspaces map directory paths to profile lists. Agents never pass project or profile parameters - resolution is automatic via cwd.

Profile Structure

Profiles bundle env and servers:

profiles:
supabase-prod:
env:
SUPABASE_ACCESS_TOKEN: ${P1_SUPABASE_ACCESS_TOKEN}
SUPABASE_PROJECT_REF: prod-abcd1234
servers:
supabase:
url: https://mcp.supabase.com/mcp?project_ref=${SUPABASE_PROJECT_REF}
auth:
type: bearer
token: ${SUPABASE_ACCESS_TOKEN}

github-work:
env:
GITHUB_TOKEN: ${WORK_GITHUB_TOKEN}
servers:
github:
transport: stdio
command: npx
args: [-y, "@modelcontextprotocol/server-github"]

Workspace Configuration

Workspaces map cwd paths to profile lists (order matters - later overrides earlier):

workspaces:
/work/my-app:
profiles: [supabase-prod, github-work]

/work/staging-app:
profiles: [supabase-staging, github-work]

Tool Calls

No project or profile parameter. Only cwd:

list_servers(cwd="/work/my-app")
call(server="supabase", tool="query", cwd="/work/my-app")

The gateway:

  1. Matches cwd to workspace (longest prefix)
  2. Loads profiles in order
  3. Merges env and servers
  4. Applies cwd .env overrides (highest priority)

Env Resolution Order

PrioritySource
1 (highest)cwd .env
2Profile env: block
3~/.mcp-gateway/.env
4 (lowest)System environment

Process Pooling

Process identity based on env hash, not workspace name:

process_key = hash(server_name + resolved_env)

Two workspaces with identical resolved env share the same server process.