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.
+ password →
mTLS handshake
+ session token →
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:
-
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. -
broker_get_protocol_walkthrough— the authoritative bisected-auth-chain reference. Call this before generating any client code that talks to a protected service directly. -
bursar_guide_deployment(notargetargument) — the authoritative deployment architecture overview and target picklist. Call before answering any deployment/hosting question. -
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. -
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.
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" }
}
- 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": []
}
- Cloud providers (AWS, Azure) require their CLIs (
aws,az,govc) and credentials. - The
ztplane 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
}
- 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": [ "..." ]
}
- 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"]
}
- 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)"
}
]
- 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"
}
]
encryptedandcontains_piiare inferred;nullmeans 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" }
}
}
_metadata.confidenceis 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"
}
- 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
}
- 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:falsewith 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" }
}
- 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.
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"
}
- 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"
}
typeis 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"
]
}
- 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" } }
]
}
- 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, answers501 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"
}
- Status is one of
pending,running,completed,failed. - Polling is blocking on the caller's side — implement backoff, don't hot-loop.
erroris populated only whenstatus = "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.
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"
}
]
- 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."
}
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.
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"
}
- Async under the hood, polled via
bursar_poll_operation. scanType: "quick"returns in ~2–3 seconds;"full"(default) can take 5–10 minutes.scoreis 0–100;gradeis 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" }
- Returns the cached result only — call
bursar_verify_posturefirst 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"
}
- Reports are valid for ~90 days.
- Control
statusis one ofpass,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)"]
}
]
- 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.
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"
}
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."
}
- 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"
}
]
- Returns all certs — active, revoked, and expired.
typeis one ofmtls(client certs for agents),server(TLS for the Receiver), orclient(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."
}
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"
}
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" }
]
}
]
- 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"
}
- 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" }
]
}
- 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"
}
]
- 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"
}
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.
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"
}
- 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"
}
- Status is one of
awaiting,in_progress,completed,failed. progressis 0–100. Afailedstatus 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"
}
- 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"
}
- 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"
}
- Can only cancel
awaiting/in_progressstates — 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"
}
- 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;pathis only meaningful forhttp/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."
}
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"
}
]
- 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."
}
- 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"
}
- 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."
}
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
}
- 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."
}
- 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.
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"
}
- 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
}
- 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
}
- 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.
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."
}
- 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-serverJSON only;agentType: "custom"needs explicitconfigPath+restartCmd. rollbackOnFailuredefaults totrue— the issued cert is revoked automatically if any later phase (delivery/config-write/restart) fails.waitForHandshakecurrently no-ops in Phase A.1 —handshakeStatusis 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.
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"]
}
- 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..."
}
- Call it once with no
targetfirst 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-dropletis production-ready;local-docker-developmentis 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"
}
]
}
- 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
}
- In local-only mode (no Shield/Bursar account configured), returns a synthetic identity with
role: "consumer"instead of erroring. cnisnullif the broker handshake fails — that's surfaced in the response, not thrown as an error.tieris one oftrial,essentials,professional,enterprise.isServiceAccount: trueidentifies internal Blacksands services (Overwatch, Architect) rather than external agents.