Sign inSign up

simonferquel/pi-agent-mcp-gateway-kit:latest

Manifest digest

sha256:929c802b67123774c08bcf93c0957d2476f50364474343d1e08f0450907fe30e

Last pushed

26 days by simonferquel

Type

Sandbox Kit

Manifest digest

sha256:929c802b67123774c08bcf93c0957d2476f50364474343d1e08f0450907fe30e

yaml
schemaVersion: "2"
kind: sandbox
name: pi-agent-mcp
displayName: Pi (MCP Gateway)
description: 'Minimal terminal coding agent with extensible tools, skills, and TUI -- a personal-preferences kit derived from docker/sbx-kits-contrib''s `pi`: bakes in pi-mcp-adapter (pi has no MCP client of its own) and self-registers the sandbox''s hosted MCP gateway (when one is reserved) into pi-mcp-adapter''s own ~/.pi/agent/mcp.json, so pi discovers gateway-provided tools automatically with no manual setup step.'
sandbox:
    image: docker.io/simonferquel/pi-agent-mcp-base:latest
    entrypoint:
        - pi
agentInstructions:
    filename: AGENTS.md
permissions:
    network:
        allow:
            - api.anthropic.com
            - registry.npmjs.org
            - platform.claude.com:443
credentials:
    - service: anthropic
      apiKey:
        name: ANTHROPIC_API_KEY
        proxyManaged: true
        inject:
            - domain: api.anthropic.com
              header: x-api-key
              format: '%s'
      oauth:
        tokenEndpoint:
            host: platform.claude.com
            path: /v1/oauth/token
        resourceHosts:
            - api.anthropic.com
        sentinels:
            accessToken: sk-ant-oat01-proxy-managed
            refreshToken: sk-ant-ort01-proxy-managed
        credentialFile:
            path: ~/.pi/agent/auth.json
            structure:
                anthropic:
                    access: '{{.AccessToken}}'
                    expires: '{{.ExpiresAt}}'
                    refresh: '{{.RefreshToken}}'
                    type: oauth
setup:
    install:
        - command: if [ -n "${HTTP_PROXY:-}" ]; then npm config set proxy="$HTTP_PROXY" https-proxy="${HTTPS_PROXY:-$HTTP_PROXY}"; fi
          user: "1000"
          description: Point npm at the sandbox proxy in ~/.npmrc so pi's runtime npm use (`pi install npm:...`, `pi update`, startup package fetches) works in exec contexts that do not inherit the proxy environment variables
    startup:
        - command:
            - sh
            - -c
            - |
              set -e
              [ -n "${MCP_GATEWAY_URL:-}" ] || exit 0
              MCP_GATEWAY_URL="$MCP_GATEWAY_URL" MCP_SENTINEL_TOKEN_NAME="${MCP_SENTINEL_TOKEN_NAME:-mcp-gateway}" node <<'NODEEOF'
              'use strict';
              const fs = require('fs');
              const os = require('os');
              const path = require('path');

              const gatewayUrl = process.env.MCP_GATEWAY_URL;
              const tokenName = process.env.MCP_SENTINEL_TOKEN_NAME;
              const configPath = path.join(os.homedir(), '.pi', 'agent', 'mcp.json');

              let config = {};
              try {
                if (fs.existsSync(configPath)) {
                  const raw = fs.readFileSync(configPath, 'utf8');
                  const parsed = raw.trim() ? JSON.parse(raw) : {};
                  if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
                    config = parsed;
                  }
                }
              } catch (err) {
                // Fail safe: an unreadable/corrupt file is left untouched rather
                // than clobbered; the next sandbox start retries naturally.
                process.stderr.write('pi-agent-mcp-kit: mcp.json unreadable, skipping gateway registration: ' + err.message + '\n');
                process.exit(0);
              }

              if (typeof config.mcpServers !== 'object' || config.mcpServers === null || Array.isArray(config.mcpServers)) {
                config.mcpServers = {};
              }

              config.mcpServers['mcp-gateway'] = {
                url: gatewayUrl,
                headers: { Authorization: 'Bearer ' + tokenName },
                lifecycle: 'eager',
              };

              fs.mkdirSync(path.dirname(configPath), { recursive: true });
              const tmpPath = configPath + '.tmp';
              fs.writeFileSync(tmpPath, JSON.stringify(config, null, 2) + '\n');
              fs.renameSync(tmpPath, configPath);
              NODEEOF
          user: "1000"
          description: Register the sandbox's hosted MCP gateway (when reserved) as a remote MCP server in pi-mcp-adapter's ~/.pi/agent/mcp.json; no-op when no gateway is reserved