sha256:4b564e3c6906f39614720442028fb6946950fa7192fbd4a2b4f07aa3e5311d30
Last pushed
16 days by docker
Type
Sandbox Kit
Manifest digest
sha256:4b564e3c6906f39614720442028fb6946950fa7192fbd4a2b4f07aa3e5311d30
schemaVersion: "2"
kind: sandbox
name: pi-hsp-kit
displayName: Pi (HSP Steering)
description: HSP-capable Pi kit -- the `pi` terminal coding agent (with pi-mcp-adapter's hosted MCP gateway self-registration) plus this repo's pi HSP adapter baked into the image, wired up so the session declares Harness Steering Protocol (hsp/1) support. The base image builds directly from the Docker-owned docker/sandbox-templates:shell-docker template (see pi/kit/Dockerfile), reproducing the same pi install steps docker/sbx-kits-contrib's own `pi` kit uses plus pi-mcp-adapter -- no dependency on any externally-hosted derivative image. Built to test/demo the Agentic Platform's custom-kit-only HSP capability (APT-1382).
sandbox:
image: docker.io/docker/hsp:pi-base-image-latest
entrypoint:
- pi
command:
default:
- -e
- /opt/hsp/pi/src/index.ts
interactive:
- -e
- /opt/hsp/pi/src/index.ts
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) {
process.stderr.write('pi-hsp-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