Bursar MCP — Training Guide @blacksandscyber/mcp-server-bursar · mcp-server-blacksands-shield/
55 tools · 9 categories · 14 [FREE] / 41 authenticated
See also: Bursar FAQ

Bursar MCP training guide

Bursar is the Blacksands zero-trust MCP server. It gives an AI agent (Claude Code, Claude Desktop, or any other MCP client) direct control over codebase security scanning, application onboarding, mTLS certificate management, compliance reporting, security operations, and Receiver (edge-proxy) lifecycle — 55 tools in total, grouped into 9 functional categories. This guide walks a new engineer or administrator through the architecture once, then through every tool, category by category, with realistic example calls and responses.

Companion reference: the Bursar FAQ answers "why does this behave this way" and troubleshooting questions using the same terminology and category groupings as this guide.

This guide is developer-focused (tool-level inputs/outputs). For account, plan, or billing questions, see the live Bursar AI Agents knowledge base instead.

iHow the auth model works

Every authenticated Bursar tool call ultimately rides on Blacksands' bisected mTLS broker pattern. Unlike a typical single-stage mTLS setup, an agent has to complete two independent mTLS handshakes before it ever reaches a real backend service — and the backend is never directly reachable at all.

Agent Claude / MCP client, holds an mTLS cert issued for this org
① mTLS handshake
+ password →
Authorizer Validates cert against org identities. Returns service list + Receiver URL + short-lived session token
② second, independent
mTLS handshake
+ session token →
Receiver Public-IP edge proxy. Re-verifies the same cert on its own, forwards over a private network
private network →
Backend service Bursar API or protected app. Never directly reachable by the agent

Authorization is stateless and cert-only — there are no API keys and no bearer-token fallback path. The same client certificate is presented at both hops; the Receiver's independent re-verification means a compromised Authorizer alone can't grant backend access, and a stolen session token alone (without the matching cert) is useless. Before writing any client code that talks to a protected service directly, call broker_get_protocol_walkthrough — it is the authoritative description of this flow and ships copy-paste Node/Python/curl examples.

14 FREE tools — no account needed

Local codebase/environment scanning, framework/PII/endpoint/service/datastore detection, manifest generation, cosmetic topology visualization, and the four Category I guidance tools (broker_get_my_identity, broker_get_protocol_walkthrough, bursar_guide_deployment, bursar_get_protection_requirements). These run with zero configuration, most with no network calls at all.

41 authenticated tools — broker credentials required

Org/app provisioning, MCP identity and app-level certificate management, compliance and posture verification, security operations (lockdown, policies, DNS, sessions), Receiver lifecycle and monitoring, and remote agent installation. These need an mTLS cert + auth password + org id, issued by a human admin (Overwatch/SysAdmin) or redeemed from a one-time bootstrap token.

Roles matter too: a cert issued with role: "consumer" only ever sees the 14 FREE tools (plus broker access to whatever services it's been granted) — it cannot provision, revoke, or manage anything. role: "master" sees the full tool surface, subject to the gating above. Role is set at cert issuance time and cannot be self-escalated by the agent.

▶Getting started

Whether you're exploring Bursar for the first time or writing an integration, call these FREE tools first, in this order:

  1. broker_get_my_identity — confirms who you are: cert CN, RBAC role, org id, tier, and whether you're in local-only or broker mode. Safe to call even with zero configuration.
  2. broker_get_protocol_walkthrough — the authoritative bisected-auth-chain reference. Call this before generating any client code that talks to a protected service directly.
  3. bursar_guide_deployment (no target argument) — the authoritative deployment architecture overview and target picklist. Call before answering any deployment/hosting question.
  4. bursar_scan_codebase — if you're onboarding a real application, this is usually the first substantive action: a full local scan that also assembles a security manifest.
  5. bursar_get_protection_requirements — feed it the manifest (or a project path) for a plain-English checklist of what has to exist before Blacksands can protect the app.

From there, the provisioning path (Category B) is typically bursar_create_org → bursar_create_app → bursar_generate_manifest → bursar_submit_manifest → bursar_provision_app, which returns a step-by-step plan and makes no changes itself; you then run the tools it names. The Receiver setup path (Category F) is receiver_initialize → (installer redeems the token on the target host) → receiver_init_status (poll) → receiver_activate → receiver_onboard_service per proxied service.

ACodebase & Environment Scanning (10 tools)

This is where most engineers start: ten tools that inspect a local project (and, optionally, its local infrastructure) without needing a Blacksands account. Nine of the ten are fully FREE and read-only — they walk source code, detect frameworks, flag candidate PII, and assemble the findings into a schema-validated Security Manifest that later feeds Category B provisioning. The tenth, bursar_publish_environment, is the one paid/master-gated exception — it runs the same environment scan but publishes the result to your Blacksands account for cloud visualization and 30-day history retention.

🖼 Screenshot placeholder: sysadmin-dashboard-v3 — viewing a completed bursar_scan_codebase result (severity breakdown, detected framework, PII findings) inside the Overwatch/SysAdmin UI. data-slot="codebase-scan-results"

bursar_scan_codebase free

Full composite codebase security scan in one call — framework, endpoints, PII, external services, data stores, and a generated manifest.

Example call

{
  "projectPath": "/Users/dev/my-app"
}

Example response

{
  "bySeverity": { "CRITICAL": 0, "HIGH": 2, "MEDIUM": 5 },
  "highestSeverity": "HIGH",
  "framework": { "name": "Express", "language": "JavaScript" },
  "endpoints": [ "..." ],
  "piiFields": [ "..." ],
  "externalServices": [ "..." ],
  "dataStores": [ "..." ],
  "manifest": { "...": "SecurityManifest" }
}
Gotchas
  • No Blacksands account needed; runs fully local.
  • Appends an anonymized-scan footer linking to a Glass preview or Posture Home if authenticated.
  • Heavy I/O — a full tree walk plus pattern matching can take 10–30s on large codebases.

bursar_scan_environment free

Scan local infrastructure (macOS containers, Docker, AWS, Azure, VMware) and return normalized topology JSON (schemaVersion 1.0).

Example call

{
  "provider": "docker",
  "planes": ["infra", "zt"],
  "appId": "app-xyz"
}

Example response

{
  "schemaVersion": "1.0",
  "metadata": {
    "host": "host.local",
    "timestamp": "2026-07-24T00:00:00Z",
    "trust": { "authoritative": true }
  },
  "planes": {
    "infra": { "nodes": [], "edges": [] },
    "zt": { "nodes": [], "edges": [] }
  },
  "zones": { "purdue-level": [] },
  "extraNotes": []
}
Gotchas
  • Cloud providers (AWS, Azure) require their CLIs (aws, az, govc) and credentials.
  • The zt plane is empty (metadata.trust.authoritative=false) whenever the Shield/Bursar API is unreachable.
  • Read-only — no mutation of the inspected environment.
  • Container inspection uses the Apple Container CLI on macOS; requires it to be installed.

bursar_detect_framework free

Identify application framework, runtime, and package manager from project files.

Example call

{ "projectPath": "/Users/dev/my-app" }

Example response

{
  "name": "Express",
  "language": "JavaScript",
  "version": "4.18.0",
  "runtime": "Node.js",
  "runtimeVersion": "18.12.0",
  "packageManager": "npm",
  "dockerImage": null
}
Gotchas
  • Detects from package.json, pyproject.toml, Gemfile, pom.xml, build.gradle, go.mod, etc.
  • No network calls — purely filesystem-based.

bursar_scan_endpoints free

Extract HTTP/API routes from source code with method, auth classification, and severity.

Example call

{ "projectPath": "/Users/dev/my-app" }

Example response

{
  "bySeverity": { "CRITICAL": 0, "HIGH": 1, "MEDIUM": 3 },
  "highestSeverity": "MEDIUM",
  "endpoints": [
    {
      "method": "GET",
      "path": "/api/users",
      "auth_method": "jwt",
      "auth_confidence": "high",
      "file": "src/routes/users.js",
      "line": 42,
      "severity": "LOW"
    },
    {
      "method": "POST",
      "path": "/public",
      "auth_method": "unknown",
      "severity": "MEDIUM",
      "severity_rationale": "Unauthenticated endpoint detected"
    }
  ],
  "summary": {
    "total": 24,
    "byMethod": { "GET": 12, "POST": 8, "PUT": 4 },
    "byAuth": { "jwt": 18, "unknown": 6 },
    "unauthenticated_or_unknown": 6
  },
  "routes_with_no_detectable_authentication": [ "..." ]
}
Gotchas
  • Auth detection is heuristic — looks for middleware, decorators, jwt.verify, etc. Low-confidence routes are flagged "unknown", not assumed safe or unsafe.
  • Finds routes declared in code, not from runtime introspection — a route gated by infra-level auth (e.g. an API gateway) may still show as unknown.

bursar_flag_pii_candidates free

Scan source code for candidate PII fields (SSN, credit card, health data, DOB, etc.) for human review.

Example call

{ "projectPath": "/Users/dev/my-app" }

Example response

{
  "bySeverity": { "CRITICAL": 1, "HIGH": 3, "MEDIUM": 2 },
  "highestSeverity": "CRITICAL",
  "fields": [
    {
      "type": "credit_card",
      "sensitivity": "critical",
      "field": "cardNumber",
      "file": "src/payment.js",
      "line": 87,
      "confidence": "high",
      "severity": "CRITICAL",
      "remediation": "Tokenize card numbers or use a payment processor API; never store raw PAN data."
    }
  ],
  "summary": {
    "total": 6,
    "byConfidence": { "high": 3, "medium": 2, "low": 1 },
    "types": ["credit_card", "ssn", "health_record"]
  },
  "sensitivityLevel": "high",
  "complianceHints": ["HIPAA", "PCI-DSS", "GDPR"]
}
Gotchas
  • Confidence is per-finding: high = structural match, medium = bare identifier, low = comment/prose.
  • Findings are candidates for human review, not confirmed PII — don't auto-remediate off this alone.
  • Comment/prose-only matches are filtered out to reduce false positives.

bursar_detect_external_services free

Detect third-party service integrations (Stripe, OpenAI, AWS, Firebase, Twilio, etc.).

Example call

{ "projectPath": "/Users/dev/my-app" }

Example response

[
  {
    "name": "Stripe",
    "domain": "api.stripe.com",
    "port": 443,
    "protocol": "https",
    "purpose": "Payment processing",
    "detectedFrom": "package.json (stripe dep)"
  },
  {
    "name": "OpenAI",
    "domain": "api.openai.com",
    "port": 443,
    "protocol": "https",
    "purpose": "LLM API",
    "detectedFrom": "src/services/ai.js (import)"
  }
]
Gotchas
  • Detects from package dependencies, imports, and hardcoded URLs.
  • No validation that the service is actually invoked at runtime — a listed but unused dependency still shows up.

bursar_detect_data_stores free

Detect database connections (PostgreSQL, MongoDB, Redis, ORMs).

Example call

{ "projectPath": "/Users/dev/my-app" }

Example response

[
  {
    "type": "PostgreSQL",
    "host": "localhost",
    "port": 5432,
    "encrypted": false,
    "contains_pii": null,
    "detectedFrom": "package.json (pg dep) + .env"
  },
  {
    "type": "Redis",
    "host": "redis.internal",
    "port": 6379,
    "encrypted": null,
    "contains_pii": null,
    "detectedFrom": "docker-compose.yml"
  }
]
Gotchas
  • encrypted and contains_pii are inferred; null means unknown, not "no".
  • Detects from env vars, connection strings, and Docker config.

bursar_generate_manifest free

Assemble detection results into a Security Manifest JSON — the artifact Category B provisioning consumes.

Example call

{ "projectPath": "/Users/dev/my-app" }

Example response

{
  "application": {
    "name": "myapp",
    "version": "1.0.0",
    "framework": "Express",
    "runtime": "Node.js"
  },
  "endpoints": [ { "type": "api", "protocol": "https", "port": 8080, "path": "/api/users", "auth_method": "jwt" } ],
  "external_services": [ "..." ],
  "data_stores": [ "..." ],
  "compliance": {
    "frameworks": ["HIPAA", "PCI-DSS"],
    "data_residency": "US",
    "audit_required": true
  },
  "security_preferences": {
    "session_ttl": 3600,
    "mfa_required": true,
    "ip_binding": false,
    "auto_rotate_certs": true
  },
  "_metadata": {
    "generated_by": "mcp-scan",
    "confidence": 0.87,
    "pii_summary": { "total_fields": 6, "sensitivity_level": "high" }
  }
}
Gotchas
  • _metadata.confidence is an aggregate score across all sub-scans, not per-field.
  • The manifest is schema-validated downstream — bursar_submit_manifest rejects anonymization failures on submission.

bursar_report_activity free

Emit a cosmetic activity record to the local Container Manager visualization launcher (http://127.0.0.1:4178).

Example call

{
  "op": "scan",
  "provider": "docker",
  "target": { "type": "container", "id": "c-123", "name": "web-api" },
  "status": "ok",
  "message": "Codebase scan complete: HIGH severity"
}

Example response

{
  "recorded": true,
  "destination": "http://127.0.0.1:4178",
  "fallback": "~/.blacksands/container-manager/activity.jsonl"
}
Gotchas
  • Purely presentational — cannot change topology, trust, certs, sessions, or any Blacksands state.
  • Delivery is best-effort: POST to the launcher, else a journal file, else a graceful no-op.
  • Secrets are redacted (creds, tokens, connection strings); message is length-capped (~300 chars).
  • Never throws.

bursar_show_topology free

Open (or compose a link to) the local Container Manager topology visualization.

Example call

{ "provider": "docker", "focus": "container-xyz" }

Example response

{
  "vizUrl": "http://127.0.0.1:4178/?provider=docker&focus=container-xyz",
  "launched": true,
  "opened": true,
  "note": null
}
Gotchas
  • Probes the launcher on http://127.0.0.1:4178; spawns it detached if it isn't running and the directory is available.
  • On macOS, opens a browser tab automatically.
  • For remote/sandboxed agents, returns launched:false, opened:false with a note to open the URL on your workstation.
  • Never throws.

bursar_publish_environment authenticated

Scan the local environment (same pipeline as bursar_scan_environment) and publish the resulting topology to your Blacksands account for cloud/enterprise viz and 30-day / 200-snapshot history retention.

Requires: master role · paid tier (essentials/professional/enterprise)

Example call

{
  "provider": "aws",
  "environmentKey": "prod-us-east",
  "label": "Production — US East"
}

Example response

{
  "schemaVersion": "1.0",
  "metadata": { "...": "same as bursar_scan_environment" },
  "operation": { "status": "published" }
}
Gotchas
  • Requires master MCP role.
  • Requires an account on a paid tier — community/trial orgs get an upgrade-path error instead of a scan.
  • Posts topology to the Shield/Bursar API via the Receiver.

BApp & Org Provisioning (7 tools)

Once a manifest exists (from Category A), this category walks it from a raw org/app registration through to a live security stack: certificates, DNS, policies, and endpoints. All seven tools require broker authentication. The typical order is bursar_create_org → bursar_create_app → bursar_submit_manifest → bursar_provision_app, with bursar_list_orgs / bursar_list_apps used to check for existing orgs/apps first (org names must be unique). bursar_provision_app returns a provisioning plan; it doesn't provision anything itself.

🖼 Screenshot placeholder: sysadmin-dashboard-v3 — creating an org via bursar_create_org data-slot="org-creation-flow"

bursar_create_org authenticated

Create a new organization in Blacksands.

Example call

{ "name": "Acme Corp", "plan": "trial" }

Example response

{
  "id": "org-abc123",
  "name": "Acme Corp",
  "plan": "trial",
  "createdAt": "2026-07-24T00:00:00Z",
  "updatedAt": "2026-07-24T00:00:00Z"
}
Gotchas
  • Org name must be unique — no duplicates.
  • Trial plan has hard limits: 1 receiver, 3 apps max, 30-day limit.

bursar_list_orgs authenticated

List all organizations (paginated).

Example call

{ "page": 1, "pageSize": 50 }

Example response

{
  "data": [
    { "id": "org-xyz", "name": "Acme Corp", "plan": "trial" }
  ],
  "total": 142,
  "page": 1,
  "pageSize": 50
}

bursar_create_app authenticated

Register a new application with an organization.

Example call

{
  "orgId": "org-abc",
  "name": "My API",
  "type": "api",
  "framework": "Express",
  "runtime": "Node.js",
  "environment": "production"
}

Example response

{
  "id": "app-xyz",
  "orgId": "org-abc",
  "name": "My API",
  "type": "api",
  "status": "active",
  "createdAt": "2026-07-24T00:00:00Z"
}
Gotchas
  • type is required by the Shield/Bursar API; defaults to "web" for least-privilege.
  • App starts in "active" status — it can be provisioned immediately.

bursar_list_apps authenticated

List applications for an organization.

Example call

{ "orgId": "org-abc" }

Example response

{
  "data": [ { "id": "app-1", "name": "My API", "status": "active" } ],
  "total": 5,
  "page": 1,
  "pageSize": 50
}

bursar_submit_manifest authenticated

Submit a security manifest (from bursar_generate_manifest) to the Shield/Bursar API for validation and provisioning.

Example call

{
  "orgId": "org-abc",
  "manifest": { "application": { "name": "my-app" }, "...": "..." }
}

Example response

{
  "id": "manifest-xyz",
  "status": "validated",
  "appName": "my-app",
  "validationErrors": [],
  "validationWarnings": [
    "PII detected in endpoints; ensure encryption in transit"
  ]
}
Gotchas
  • Schema-validated — validation errors block submission entirely.
  • PII findings trigger compliance warnings (non-blocking).
  • Must pass anonymization checks before the Shield/Bursar API accepts it.

bursar_provision_app authenticated

Build a step-by-step provisioning plan from a submitted manifest. It makes no changes: provisioning from a manifest isn't automated yet. Each step names a tool that does make the change, with arguments prefilled from the manifest and the inputs you still need to supply.

Example call

{ "manifestId": "manifest-xyz" }

Example response

{
  "manifestId": "manifest-xyz",
  "appId": "app-123",
  "application": "orders",
  "automated": false,
  "note": "Nothing was provisioned. ...",
  "steps": [
    { "step": 1, "tool": "receiver_list",
      "needsFromYou": ["Which Receiver to use"] },
    { "step": 2, "tool": "receiver_onboard_service",
      "args": { "name": "orders", "port": 3000, "protocol": "https" },
      "needsFromYou": ["receiverUID from the previous step",
                       "Backend host the Receiver should reach"] },
    { "step": 3, "tool": "bursar_update_dns_rules", "optional": true,
      "args": { "appId": "app-123", "rules": [
        { "domain": "api.stripe.com", "action": "allow" } ] } },
    { "step": 4, "tool": "bursar_verify_posture",
      "args": { "appId": "app-123" } }
  ]
}
Gotchas
  • Nothing is provisioned by this tool, and there is no operation to poll. Run the steps it returns, in order.
  • A security manifest describes what the app is, not where it runs, so the plan asks you for the backend host and which Receiver to use.
  • The underlying API, POST /v1/manifests/:id/provision, answers 501 Not Implemented.

bursar_poll_operation authenticated

Check the status of an async Shield/Bursar API operation.

Example call

{ "operationId": "op-xyz" }

Example response

{
  "id": "op-xyz",
  "type": "provision",
  "status": "completed",
  "result": { "provisioned": 12, "errors": 0 },
  "error": null,
  "createdAt": "2026-07-24T10:00:00Z",
  "completedAt": "2026-07-24T10:15:30Z"
}
Gotchas
  • Status is one of pending, running, completed, failed.
  • Polling is blocking on the caller's side — implement backoff, don't hot-loop.
  • error is populated only when status = "failed".

CmTLS Certificate Management — MCP identities (2 tools)

Two tools, both scoped to the agent's own MCP client identity — the cert an agent uses to talk to Bursar at all — not the app-level certificates covered in Category E. Issuing a new MCP cert is still a human action through Overwatch/SysAdmin (or the Category H composite tool); these two only let an already-authenticated agent inspect or revoke what already exists for its org.

🖼 Screenshot placeholder: sysadmin-dashboard-v3 — the MCP client certificate list view (fingerprint, issued/expiry dates, status) as surfaced by bursar_list_mcp_certs. data-slot="mcp-cert-list"

bursar_list_mcp_certs authenticated

List all active mTLS client certificates issued for this organization's MCP instances.

Example call

{}

Example response

[
  {
    "clientName": "claude-desktop-userx2",
    "cn": "claude-desktop-userx2",
    "fingerprint": "sha256:abc123...",
    "issuedAt": "2026-07-20T00:00:00Z",
    "expiresAt": "2026-10-20T00:00:00Z",
    "status": "active",
    "role": "master"
  }
]
Gotchas
  • Lists only active certs for the calling org.
  • Cert issuance is performed by a human administrator through Overwatch/SysAdmin (this tool is read-only).

bursar_revoke_mcp_cert authenticated

Revoke an mTLS client certificate by client name.

Example call

{ "clientName": "claude-desktop-userx2" }

Example response

{
  "clientName": "claude-desktop-userx2",
  "status": "revoked",
  "revokedAt": "2026-07-24T00:00:00Z",
  "note": "Certificate was revoked successfully. Any MCP client using this cert will be denied access."
}
Destructive action Immediate and irreversible. Existing sessions are not forcibly terminated — they expire naturally. Idempotent: revoking an already-revoked cert returns the same result rather than erroring. To issue a replacement cert, use Overwatch or SysAdmin.

DVerification & Compliance (4 tools)

Once an app is provisioned, these four tools answer "how secure is it, really, and against which framework." bursar_verify_posture runs a fresh scored scan; bursar_get_posture reads the cached result of the most recent one without re-scanning. bursar_compliance_report and bursar_compliance_controls do the same pairing for a named framework (SOC2, HIPAA, PCI-DSS, ISO27001) — one generates a scored report against an app, the other lists the framework's control catalog on its own.

🖼 Screenshot placeholder: sysadmin-dashboard-v3 — an app's posture score/grade view plus a generated SOC2/HIPAA compliance report, from bursar_verify_posture and bursar_compliance_report. data-slot="posture-compliance-dashboard"

bursar_verify_posture authenticated

Run a security posture verification scan on an application.

Example call

{ "appId": "app-abc", "scanType": "quick" }

Example response

{
  "id": "verify-xyz",
  "appId": "app-abc",
  "score": 72,
  "grade": "B",
  "status": "NEEDS_ATTENTION",
  "dimensions": {
    "authentication": 85, "encryption": 62,
    "network_isolation": 78, "compliance": 65
  },
  "checks": [
    {
      "name": "All endpoints require authentication",
      "passed": false,
      "severity": "critical",
      "details": "3 unauthenticated endpoints detected"
    }
  ],
  "recommendations": [
    "Add authentication to GET /public endpoint",
    "Enable TLS for all data in transit"
  ],
  "scannedAt": "2026-07-24T00:00:00Z"
}
Gotchas
  • Async under the hood, polled via bursar_poll_operation.
  • scanType: "quick" returns in ~2–3 seconds; "full" (default) can take 5–10 minutes.
  • score is 0–100; grade is A–F.
  • Unreachable downstream services (Receiver/backend) are skipped rather than failing the whole scan.

bursar_get_posture authenticated

Get the latest security posture score, grade, and recommendations for an application (cached — does not trigger a new scan).

Example call

{ "appId": "app-abc" }

Example response

{ "...": "same shape as bursar_verify_posture, from the most recent scan" }
Gotchas
  • Returns the cached result only — call bursar_verify_posture first if you need fresh data.
  • If no prior scan exists, returns null/error.
  • Appends a Posture Home portal link in the response footer.

bursar_compliance_report authenticated

Generate a compliance report (SOC2, HIPAA, PCI-DSS, ISO27001) for an application.

Example call

{ "appId": "app-abc", "framework": "SOC2" }

Example response

{
  "id": "report-xyz",
  "appId": "app-abc",
  "framework": "SOC2",
  "score": 68,
  "summary": "Application meets 34 of 50 SOC2 controls.",
  "controls": [
    {
      "id": "CC6.1", "name": "Logical access controls",
      "status": "pass", "evidence": "mTLS enforced on all endpoints"
    },
    {
      "id": "CC7.2", "name": "Encryption of sensitive data",
      "status": "partial",
      "evidence": "Data in transit encrypted; at-rest encryption needs work"
    }
  ],
  "generatedAt": "2026-07-24T00:00:00Z",
  "expiresAt": "2026-10-24T00:00:00Z"
}
Gotchas
  • Reports are valid for ~90 days.
  • Control status is one of pass, fail, partial, not_applicable.
  • Appends a portal deep link for richer rendering.

bursar_compliance_controls authenticated

List all compliance controls for a given framework.

Example call

{ "framework": "ISO27001" }

Example response

[
  {
    "id": "CC6.1",
    "name": "Logical Access Controls",
    "description": "Entities restrict system access to authorized personnel and processes...",
    "criteria": ["CC6.1a", "CC6.1b", "CC6.1c"],
    "mappings": ["ISO27001:A.9.1", "HIPAA:164.312(a)(2)(i)"]
  }
]
Gotchas
  • Used to understand what controls an app needs to implement before requesting a scored report.
  • Control definitions are static and framework-specific.

ESecurity Operations & Cert Management (10 tools)

The day-two operations category: app-level certificates (distinct from the MCP-identity certs in Category C), network/DNS/access policies, sessions, and the two emergency-response tools — bursar_emergency_lockdown and bursar_lift_lockdown. Several tools here are immediate and irreversible; read the destructive-action callouts before calling them against a production app.

🖼 Screenshot placeholder: sysadmin-dashboard-v3 — the confirmation dialog for bursar_emergency_lockdown, and the resulting policy/session list view for a locked app. data-slot="emergency-lockdown-confirm"

bursar_emergency_lockdown authenticated

Emergency lockdown: immediately revoke all certificates and sessions for an application.

Example call

{
  "appId": "app-xyz",
  "reason": "Suspected credential breach"
}

Example response

{
  "appId": "app-xyz",
  "status": "locked",
  "certsRevoked": 5,
  "sessionsRevoked": 12,
  "lockedAt": "2026-07-24T00:00:00Z",
  "reason": "Suspected credential breach"
}
Destructive action Immediate — all active sessions are forcibly terminated and every cert on the app is revoked. Idempotent (locking twice is a no-op). reason is logged for the compliance audit trail. Reserve for genuine security incidents.

bursar_lift_lockdown authenticated

Lift an emergency lockdown on an application.

Example call

{ "appId": "app-xyz" }

Example response

{
  "appId": "app-xyz",
  "status": "active",
  "unlockedAt": "2026-07-24T00:00:00Z",
  "note": "App is now active. New certs and sessions can be established. All previous certs remain revoked."
}
Gotchas
  • Unlocking does not restore revoked certs/sessions — they stay revoked permanently.
  • Requires re-issued certificates (bursar_rotate_cert) to get a working cert bundle again.

bursar_list_certs authenticated

List all certificates for an application.

Example call

{ "appId": "app-xyz" }

Example response

[
  {
    "id": "cert-abc", "appId": "app-xyz", "type": "mtls",
    "fingerprint": "sha256:deadbeef...",
    "issuedAt": "2026-07-10T00:00:00Z",
    "expiresAt": "2026-10-10T00:00:00Z",
    "status": "active"
  },
  {
    "id": "cert-def", "appId": "app-xyz", "type": "server",
    "fingerprint": "sha256:cafebabe...",
    "status": "expired"
  }
]
Gotchas
  • Returns all certs — active, revoked, and expired.
  • type is one of mtls (client certs for agents), server (TLS for the Receiver), or client (deprecated).

bursar_rotate_cert authenticated

Rotate a specific certificate — issue a new one, revoke the old one.

Example call

{ "appId": "app-xyz", "certId": "cert-abc" }

Example response

{
  "oldCertId": "cert-abc",
  "newCertId": "cert-xyz",
  "newCert": "-----BEGIN CERTIFICATE-----...",
  "newKey": "-----BEGIN PRIVATE KEY-----...",
  "rotatedAt": "2026-07-24T00:00:00Z",
  "note": "Old cert revoked. New cert is active. Update your app/agent immediately."
}
Destructive action Synchronous — the old cert is revoked the instant the new one is issued, with no grace period. Anything still using the old cert loses connectivity immediately. Use bursar_revoke_cert on your own schedule instead if you need a grace period.

bursar_revoke_cert authenticated

Revoke a specific certificate.

Example call

{
  "appId": "app-xyz",
  "certId": "cert-abc",
  "reason": "Scheduled rotation"
}

Example response

{
  "certId": "cert-abc",
  "appId": "app-xyz",
  "status": "revoked",
  "revokedAt": "2026-07-24T00:00:00Z",
  "reason": "Scheduled rotation"
}
Destructive action Immediate, no grace period — unlike rotation, this does not issue a replacement cert. Apps using the revoked cert lose access right away.

bursar_list_policies authenticated

List security policies for an application.

Example call

{ "appId": "app-xyz" }

Example response

[
  {
    "id": "policy-abc", "appId": "app-xyz",
    "name": "Block China", "type": "network", "enabled": true,
    "rules": [
      { "action": "deny", "target": "10.0.0.0/8" },
      { "action": "deny", "target": "CN" }
    ]
  }
]
Gotchas
  • Policies are enforced at the Receiver layer, before a request reaches the backend.
  • Types: network (IP/CIDR), dns (domain), access (RBAC), compliance (data-handling).

bursar_create_policy authenticated

Create a security policy (network, DNS, access, or compliance) for an application.

Example call

{
  "appId": "app-abc",
  "name": "Prod access only",
  "type": "access",
  "rules": [
    { "action": "allow", "target": "prod-*", "conditions": { "role": "admin" } }
  ]
}

Example response

{
  "id": "policy-xyz", "appId": "app-abc",
  "name": "Prod access only", "type": "access", "enabled": true,
  "rules": [
    { "action": "allow", "target": "prod-*", "conditions": { "role": "admin" } }
  ],
  "createdAt": "2026-07-24T00:00:00Z"
}
Gotchas
  • Rules are evaluated left-to-right — the first matching rule wins, so order your array carefully.
  • The "log" action records the decision without blocking the request.

bursar_update_dns_rules authenticated

Add or remove application-level DNS allow/block rules (egress) — not Receiver DNS (ingress), which is auto-managed.

Example call

{
  "appId": "app-xyz",
  "rules": [
    { "domain": "api.stripe.com", "action": "allow" },
    { "domain": "*.internal.acme.com", "action": "block", "reason": "no internal egress" }
  ]
}

Example response

{
  "appId": "app-xyz",
  "rulesAdded": 2,
  "rulesRemoved": 0,
  "activeRules": [
    { "id": "dns-1", "domain": "api.stripe.com", "action": "allow" },
    { "id": "dns-2", "domain": "*.internal.acme.com", "action": "block" }
  ]
}
Gotchas
  • Applies to outbound DNS lookups the app makes (egress filtering) — not the public hostname clients use to reach the app.
  • Receiver DNS (ingress) is auto-managed by Blacksands; see receiver_get_dns (read-only).
  • Rules are evaluated in order — first match wins.

bursar_list_sessions authenticated

List active sessions for an application.

Example call

{ "appId": "app-xyz" }

Example response

[
  {
    "id": "sess-abc", "appId": "app-xyz", "userId": "user-123",
    "status": "active",
    "createdAt": "2026-07-24T10:00:00Z",
    "expiresAt": "2026-07-24T13:00:00Z",
    "lastActivity": "2026-07-24T12:55:00Z"
  }
]
Gotchas
  • Sessions are mTLS-based (cert + password + optional device binding).
  • Expiration is TTL-based — there are no refresh tokens.

bursar_revoke_session authenticated

Revoke a specific session.

Example call

{ "appId": "app-xyz", "sessionId": "sess-abc" }

Example response

{
  "sessionId": "sess-abc",
  "appId": "app-xyz",
  "status": "revoked",
  "revokedAt": "2026-07-24T00:00:00Z"
}
Destructive action Immediate — the session's bearer token becomes invalid right away, with no grace period.

FReceiver Lifecycle & Service Onboarding (13 tools)

The biggest category, and the one that actually stands up the public-facing edge proxy. A Receiver is a Linux host (EC2, VPS, DigitalOcean droplet — see bursar_guide_deployment) running the Blacksands Receiver container. The lifecycle is: receiver_initialize (creates the record, emails a one-time setup token) → a human runs the Docker bootstrap command on the target host → receiver_init_status (poll) → receiver_activate. Once active, receiver_onboard_service registers each backend service to be proxied, and the bursar_service_* tools manage each service's protection state day to day (pause, resume, disable, status-check) without touching the Receiver itself.

🖼 Screenshot placeholder: sysadmin-dashboard-v3 / OVERWATCH "Add Receiver" wizard — from receiver_initialize through receiver_activate, plus onboarding a service via receiver_onboard_service. data-slot="receiver-onboarding-wizard"

receiver_initialize authenticated

Start Receiver initialization: creates the Receiver record and emails installation credentials to the installer.

Example call

{
  "installerEmail": "admin@example.com",
  "organizationId": "org-abc",
  "notes": "Prod East zone"
}

Example response

{
  "receiverUID": "recv-xyz123",
  "status": "awaiting",
  "organizationId": "org-abc",
  "setupTokenSentTo": "admin@example.com",
  "setupTokenExpiresIn": "2 hours",
  "installerNotes": "Prod East zone",
  "createdAt": "2026-07-24T00:00:00Z"
}
Gotchas
  • The Receiver requires a Linux server with Docker (EC2, VPS, DigitalOcean, etc.).
  • The setup email carries a one-time bootstrap token, valid ~2 hours.
  • A human must be present to run docker run ... <token> on the target host.

receiver_init_status authenticated

Check the initialization status of a Receiver.

Example call

{ "receiverUID": "recv-xyz" }

Example response

{
  "receiverUID": "recv-xyz",
  "status": "in_progress",
  "progress": 60,
  "message": "Installing Blacksands Receiver container...",
  "nextStep": "Waiting for health check",
  "estimatedTimeRemaining": "2 minutes"
}
Gotchas
  • Status is one of awaiting, in_progress, completed, failed.
  • progress is 0–100. A failed status includes error details.

receiver_activate authenticated

Activate a Receiver after initialization completes.

Example call

{ "receiverUID": "recv-xyz" }

Example response

{
  "receiverUID": "recv-xyz",
  "status": "active",
  "activatedAt": "2026-07-24T00:00:00Z",
  "dnsName": "recv-xyz.shields.blacksandscyber.online",
  "healthCheck": "ok"
}
Gotchas
  • Only possible after initialization reaches status: "completed".
  • Idempotent — activating an already-active Receiver is a no-op.

receiver_resend_email authenticated

Resend installation credentials email for a pending Receiver initialization.

Example call

{ "receiverUID": "recv-xyz" }

Example response

{
  "receiverUID": "recv-xyz",
  "emailSentTo": "admin@example.com",
  "setupTokenExpiresIn": "2 hours",
  "note": "Setup token re-sent successfully"
}
Gotchas
  • Only works while initialization is still "awaiting".

receiver_cancel_init authenticated

Cancel a pending Receiver initialization.

Example call

{ "receiverUID": "recv-xyz" }

Example response

{
  "receiverUID": "recv-xyz",
  "status": "cancelled",
  "cancelledAt": "2026-07-24T00:00:00Z"
}
Gotchas
  • Can only cancel awaiting/in_progress states — cannot cancel a completed/active Receiver.

receiver_onboard_service authenticated

Add a service to be proxied by the Receiver. Supply networking inputs only; Blacksands handles proxy wiring, certificates, and firewall internally.

Example call

{
  "receiverUID": "recv-xyz",
  "name": "web-api",
  "host": "localhost",
  "port": 8080,
  "protocol": "https",
  "path": "/api/v1"
}

Example response

{
  "receiverUID": "recv-xyz",
  "serviceName": "web-api",
  "status": "onboarded",
  "upstreamAddress": "localhost:8080",
  "publicUrl": "https://web-api.recv-xyz.shields.blacksandscyber.online/",
  "certificateProvisioned": true,
  "onboardedAt": "2026-07-24T00:00:00Z"
}
Gotchas
  • The Receiver auto-assigns a unique public URL and provisions a certificate — you don't specify either.
  • DNS updates can take 5–10 seconds to propagate.
  • protocol: "ssh" / "rdp" are forwarded directly, not HTTP-wrapped; path is only meaningful for http/https.

receiver_remove_service authenticated

Remove a proxied service from a Receiver.

Example call

{ "receiverUID": "recv-xyz", "serviceName": "web-api" }

Example response

{
  "receiverUID": "recv-xyz",
  "serviceName": "web-api",
  "status": "removed",
  "removedAt": "2026-07-24T00:00:00Z",
  "note": "Service was removed. Certificate is being revoked."
}
Destructive action Removal is immediate; there's no "undo" short of re-onboarding via receiver_onboard_service. The service's certificate is revoked asynchronously (10–30 seconds).

receiver_list_services authenticated

List all services currently proxied by a Receiver.

Example call

{ "receiverUID": "recv-xyz" }

Example response

[
  {
    "name": "web-api", "host": "localhost", "port": 8080,
    "protocol": "https", "status": "active",
    "publicUrl": "https://web-api.recv-xyz.shields.blacksandscyber.online/",
    "health": "ok", "lastHealthCheck": "2026-07-24T12:59:00Z"
  }
]
Gotchas
  • Only listed services are proxied — anything not onboarded is not reachable through the Receiver at all.

bursar_service_pause authenticated

Pause a proxied service: temporarily stop accepting new connections while keeping its registration.

Example call

{ "receiverUID": "recv-xyz", "serviceName": "web-api" }

Example response

{
  "receiverUID": "recv-xyz",
  "serviceName": "web-api",
  "status": "paused",
  "pausedAt": "2026-07-24T00:00:00Z",
  "note": "Service is paused. Existing connections are allowed; new connections are denied."
}
Gotchas
  • Reversible via bursar_service_resume.
  • Existing connections stay open — only new ones are blocked. Good for maintenance windows.

bursar_service_resume authenticated

Resume a paused service, returning it to active so it accepts connections again.

Example call

{ "receiverUID": "recv-xyz", "serviceName": "web-api" }

Example response

{
  "receiverUID": "recv-xyz",
  "serviceName": "web-api",
  "status": "active",
  "resumedAt": "2026-07-24T00:00:00Z"
}
Gotchas
  • Idempotent — resuming an already-active service is a no-op.

bursar_service_disable authenticated

Disable a proxied service: take it offline in a state that requires an explicit re-enable — stronger than pause.

Example call

{ "receiverUID": "recv-xyz", "serviceName": "web-api" }

Example response

{
  "receiverUID": "recv-xyz",
  "serviceName": "web-api",
  "status": "disabled",
  "disabledAt": "2026-07-24T00:00:00Z",
  "note": "Service is disabled. New connections are denied. Existing connections are terminated."
}
Destructive-ish action Unlike pause, existing connections are severed immediately, not just blocked for new ones. Requires an explicit re-enable to recover.

bursar_service_status authenticated

Get the current protection state (active / paused / disabled) and health of a proxied service.

Example call

{ "receiverUID": "recv-xyz", "serviceName": "web-api" }

Example response

{
  "receiverUID": "recv-xyz",
  "serviceName": "web-api",
  "status": "active",
  "health": "ok",
  "upstreamReachability": "reachable",
  "uptime": 99.95,
  "lastHealthCheck": "2026-07-24T12:59:30Z",
  "activeConnections": 42
}
Gotchas
  • Health is checked every 10–30 seconds.
  • An unreachable upstream is not treated as an error — the Receiver logs it and keeps accepting connections rather than auto-pausing the service.

receiver_get_dns authenticated

View the DNS name(s) automatically assigned to a Receiver by Blacksands. Read-only.

Example call

{ "receiverUID": "recv-xyz" }

Example response

{
  "receiverUID": "recv-xyz",
  "dnsName": "recv-xyz.shields.blacksandscyber.online",
  "wildcardDomain": "*.recv-xyz.shields.blacksandscyber.online",
  "publicIP": "203.0.113.42",
  "note": "DNS records are auto-provisioned by Blacksands. To change them, the Receiver must be re-registered."
}
Gotchas
  • Read-only from the agent's perspective — DNS is provisioned at Receiver registration and cannot be edited directly.
  • The wildcard domain is what enables per-service subdomains (e.g. web-api.recv-xyz.shields...).

GReceiver Monitoring (3 tools)

Fleet-wide observability once one or more Receivers are live: per-Receiver health metrics, a filterable list across an org, and aggregate deployment statistics. These are read-only and cheap to call — good candidates for a periodic status check or dashboard refresh.

🖼 Screenshot placeholder: sysadmin-dashboard-v3 — the Receiver fleet health/monitoring view (uptime, CPU/memory/disk, services proxied) from receiver_health and receiver_list. data-slot="receiver-health-monitoring"

receiver_health authenticated

Get the health status of a specific Receiver.

Example call

{ "receiverUID": "recv-xyz" }

Example response

{
  "receiverUID": "recv-xyz",
  "status": "healthy",
  "uptime": 99.98,
  "cpuUsage": 12.5,
  "memoryUsage": 45.2,
  "diskUsage": 23.1,
  "lastHealthCheck": "2026-07-24T12:59:00Z",
  "systemLogs": "No errors in the last 24 hours"
}
Gotchas
  • Metrics update every 10–30 seconds.
  • CPU/memory/disk usage is a percentage (0–100).

receiver_list authenticated

List all Receivers with optional status and organization filters.

Example call

{ "organizationId": "org-abc", "status": "active" }

Example response

{
  "data": [
    {
      "receiverUID": "recv-xyz",
      "organizationId": "org-abc",
      "status": "active",
      "dnsName": "recv-xyz.shields.blacksandscyber.online",
      "publicIP": "203.0.113.42",
      "healthStatus": "ok",
      "servicesProxied": 5,
      "createdAt": "2026-07-20T00:00:00Z",
      "lastActivity": "2026-07-24T12:59:00Z"
    }
  ],
  "total": 12, "page": 1, "pageSize": 50
}
Gotchas
  • Paginated (default 50 per page).

receiver_statistics authenticated

Get Receiver initialization and deployment statistics.

Example call

{}

Example response

{
  "total": 42,
  "byStatus": {
    "awaiting": 2, "in_progress": 1,
    "completed": 35, "failed": 4
  },
  "avgInitTime": 1245000,
  "totalServicesProxied": 127,
  "uptime7day": 99.97,
  "healthCheckFailures24h": 0
}
Gotchas
  • Aggregate across all Receivers in the org.
  • Time values (avgInitTime) are in milliseconds.

HComposite Remote Agent Installation (1 tool)

A single composite tool that provisions a brand-new Bursar agent identity — cert issuance, credential delivery, remote config write, and (eventually) handshake confirmation — in one call. Think of it as the automated version of what a human admin currently does through Overwatch/ SysAdmin when onboarding a new MCP client. As of the current phase (Phase A.1), only the bootstrap-token delivery transport is fully implemented; SSH and AWS SSM are defined in the schema but not yet functional.

🖼 Screenshot placeholder: sysadmin-dashboard-v3 — the remote agent install flow driven by bursar_install_agent_remotely (bootstrap-token delivery path), showing the issued setup token and target config write confirmation. data-slot="remote-agent-install-flow"

bursar_install_agent_remotely authenticated

Provision and install a new Blacksands Bursar AI-agent identity on a remote host.

Example call

{
  "clientName": "claude-agent-prod",
  "orgId": "org-abc",
  "agentType": "mcp-server",
  "role": "master",
  "transport": {
    "type": "bootstrap-token",
    "ttlSeconds": 900,
    "oneShot": true,
    "deliverVia": "return"
  },
  "serviceId": "shield-api",
  "dryRun": false,
  "rollbackOnFailure": true
}

Example response

{
  "clientName": "claude-agent-prod",
  "orgId": "org-abc",
  "operationId": "install-xyz",
  "status": "completed",
  "setupToken": "bss_...",
  "credentialBundle": {
    "clientCert": "-----BEGIN CERTIFICATE-----...",
    "clientKey": "-----BEGIN PRIVATE KEY-----...",
    "caCert": "-----BEGIN CERTIFICATE-----..."
  },
  "configWrote": {
    "path": "/home/user/.config/claude/mcp-config.json",
    "updatedAgent": "mcp-server"
  },
  "handshakeStatus": "pending",
  "note": "Agent identity provisioned. Target must redeem the setup token within 15 minutes."
}
Gotchas
  • Phase A.1: only transport.type: "bootstrap-token" is fully implemented; "ssh" and "aws-ssm" throw "not-implemented".
  • Setup token is valid ~15 minutes and one-shot (consumed on first redemption).
  • Config merge supports claude-desktop + mcp-server JSON only; agentType: "custom" needs explicit configPath + restartCmd.
  • rollbackOnFailure defaults to true — the issued cert is revoked automatically if any later phase (delivery/config-write/restart) fails.
  • waitForHandshake currently no-ops in Phase A.1 — handshakeStatus is always "pending"; don't block on it flipping.
  • Guide the human operator to run the bootstrap command on the target (e.g. docker run ... --env SHIELD_SETUP_TOKEN=...).

ILocal Guidance & Learning (4 tools)

All four tools in this category are FREE and exist specifically to keep an LLM from improvising wrong answers about Blacksands' architecture. Two are "authoritative reference" tools meant to be called before generating code or advice (bursar_guide_deployment, broker_get_protocol_walkthrough); the other two are introspection helpers (broker_get_my_identity, bursar_get_protection_requirements). This is the category covered in Getting started above — start here on any new integration.

🖼 Screenshot placeholder: sysadmin-dashboard-v3 — a panel showing the calling agent's identity (CN, role, org, tier) as returned by broker_get_my_identity, alongside the protocol-walkthrough reference surfaced by broker_get_protocol_walkthrough. data-slot="broker-identity-panel"

bursar_get_protection_requirements free

Given a security manifest or project path, explain in plain English what is needed to protect the app with Blacksands — including infrastructure setup.

Example call

{ "projectPath": "/Users/dev/my-app" }

Example response

{
  "summary": "What you need before protecting this app with Blacksands Bursar",
  "requirements": [
    {
      "status": "required_before_receiver",
      "item": "Deployed backend server with Blacksands Receiver alongside",
      "description": "Your app has 8 API endpoints...",
      "helpLink": "https://onboard.beta.blacksandscyber.online/pricing"
    },
    {
      "status": "required_for_shield_tools",
      "item": "Blacksands Bursar account",
      "description": "Create a free account at https://onboard.beta.blacksandscyber.online/pricing...",
      "helpLink": "https://onboard.beta.blacksandscyber.online/pricing"
    }
  ],
  "nextStep": "Deploy your app first, then create a Blacksands account.",
  "localToolsAvailable": ["bursar_scan_codebase", "bursar_detect_framework"]
}
Gotchas
  • No account needed — returns a checklist, not a live provisioning action.
  • If PII is detected in the scan, the checklist recommends a compliance framework review.

bursar_guide_deployment free

Authoritative deployment guide. Call before answering any deployment/hosting question. Returns architecture overview + copy-paste deployment steps.

Example call (overview — no target)

{}

Example response (overview)

{
  "kind": "architecture-overview",
  "blacksandsArchitecture": {
    "receiverIsPublicIpEdgeProxy": "The Receiver is a public-IP edge proxy...",
    "inbound": "Requires inbound TCP 443 for mTLS",
    "outbound": "Receiver consumes Kafka messages from Manager (no HTTP to Authorizer)"
  },
  "falseModelsToReject": [
    "NOT like Cloudflare Tunnel (outbound agent)",
    "NOT like Tailscale Funnel (mesh VPN)",
    "NOT like ngrok (HTTP tunneling)"
  ],
  "pickATarget": [
    { "target": "digitalocean-droplet", "recommended": "Best for production. ~$6/mo, ~20 min setup." },
    { "target": "local-docker-development", "recommended": "Development only — laptops lack public IP" }
  ]
}

Example call (specific target)

{
  "target": "digitalocean-droplet",
  "appImage": "myapp:latest",
  "appPort": 8080,
  "appName": "my-app",
  "receiverSetupToken": "bss_..."
}

Example response (specific target)

{
  "kind": "guide",
  "target": "digitalocean-droplet",
  "estimatedCost": "$6/month",
  "estimatedTimeMinutes": 20,
  "walkthroughMarkdown": "# Step 1: Create a DigitalOcean Droplet\n...",
  "dockerCompose": "version: '3.8'\nservices:\n  app: ...\n  receiver: ...",
  "verificationSteps": [
    "SSH into the Droplet and run: curl https://localhost:8443",
    "Check receiver_list to see your Receiver in the console"
  ],
  "honestTamperingNote": "A determined attacker with Droplet access can still intercept traffic..."
}
Gotchas
  • Call it once with no target first to get the architecture overview and reject the wrong mental models before generating any instructions.
  • Blacksands is not Cloudflare Tunnel, Tailscale, or ngrok — it's an inbound public-IP edge proxy, not an outbound tunneling agent.
  • The Receiver needs inbound TCP 443, not an outbound connection.
  • Control plane is Kafka (Manager → Receiver for policy/DNS/cert-rotation), not HTTP polling.
  • digitalocean-droplet is production-ready; local-docker-development is dev-only — laptops can't host a Receiver (no public IP).

broker_get_protocol_walkthrough free

Authoritative broker auth protocol. Call before writing any code to access a Blacksands-protected service.

Example call

{ "language": "node" }

Example response

{
  "kind": "protocol-walkthrough",
  "summary": "Make TWO mTLS handshakes in sequence: Authorizer (discovers services + session token), then Receiver (verifies cert again + proxies to backend).",
  "bisectedFlow": [
    { "step": 1, "actor": "agent", "action": "POST to Authorizer with cert + password + serviceId" },
    { "step": 2, "actor": "authorizer", "action": "Verify cert + password, return service URL + session token" },
    { "step": 3, "actor": "agent", "action": "POST/GET to Receiver URL + session token + re-present cert" },
    { "step": 4, "actor": "receiver", "action": "Verify cert + token AGAIN, proxy request to backend" }
  ],
  "falseModelsToReject": [
    "DO NOT present cert to the backend service directly (it's unreachable)",
    "DO NOT assume single-stage mTLS like Cloudflare Access",
    "DO NOT skip Receiver cert re-verification (step 4)",
    "DO NOT use API keys or Bearer tokens instead of mTLS"
  ],
  "codeExamples": [
    { "language": "node", "filename": "blacksands-api-client.js", "code": "const agent = new https.Agent({ cert, key, ca }); ..." }
  ],
  "commonPitfalls": [
    {
      "symptom": "\"Certificate verification failed\" calling the Receiver",
      "cause": "CA cert missing or expired",
      "fix": "Load caCert PEM; refresh from ~/.blacksands/mcp-certs/blacksands-ca.crt"
    },
    {
      "symptom": "\"Unauthorized\"/\"Invalid token\" from the Receiver",
      "cause": "Session token expired or cert mismatch",
      "fix": "Re-authenticate with the Authorizer; reuse the same cert for both hops"
    }
  ]
}
Gotchas
  • Must be called before generating client code — the auth chain (two independent mTLS handshakes) is unusual and will be guessed wrong from generic training-data assumptions.
  • The backend service is never directly reachable.
  • The cert is presented at both the Authorizer and the Receiver — not just once.
  • The session token is ephemeral; there are no refresh tokens.

broker_get_my_identity free

Introspect the calling MCP cert's identity and RBAC role.

Example call

{}

Example response

{
  "cn": "claude-agent-prod",
  "role": "master",
  "orgId": "org-abc",
  "clientName": "claude-agent-prod",
  "tier": "professional",
  "isServiceAccount": false,
  "protocol_hint": "To make requests through your assigned services, call broker_get_protocol_walkthrough first...",
  "warning": null
}
Gotchas
  • In local-only mode (no Shield/Bursar account configured), returns a synthetic identity with role: "consumer" instead of erroring.
  • cn is null if the broker handshake fails — that's surfaced in the response, not thrown as an error.
  • tier is one of trial, essentials, professional, enterprise.
  • isServiceAccount: true identifies internal Blacksands services (Overwatch, Architect) rather than external agents.