MaClawSrv is the REST service entrypoint for exposing Maclaw agent capability to external programs.
-
Core business logic lives in
corelib/agentservice. -
Shared agent execution is reused from
corelib/agentthrough the service adapter layer. -
MaClawSrvfocuses on HTTP routing, authentication, JSON mapping, and control-plane orchestration. -
Data isolation is
tenant -> user. -
Each user has one shared data root, so config, memory, skill state, MCP state, and long-term history are reused across that user's instances.
-
Multiple logical instances can run at the same time under one user.
-
MaClawSrvis a pure agent service. It does not expose coding-session orchestration or local programming workspace management APIs. -
Host-local bash is security-sensitive and disabled by default.
-
SSH capability is exposed only when direct SSH is enabled or SSH host labels are configured for the user.
-
When
MACLAW_DATA_ROOTis unset, the default root is~/.maclaw_srv.
- On Windows,
maclawsrv.execan run either as a normal command-line process or as an NT service. - When launched by the Windows Service Control Manager, service stop/shutdown controls trigger the same graceful HTTP shutdown path as Ctrl+C in a console.
- Example registration:
sc.exe create MaClawSrv binPath= "C:\MaClaw\maclawsrv.exe" start= auto
sc.exe start MaClawSrv
sc.exe stop MaClawSrv-
MACLAW_ADMIN_SECRETis required and must be explicitly configured. -
MACLAW_TOKEN_SECRETis required and must be explicitly configured. -
Default listen address is
127.0.0.1:18080; wildcard addresses such as:18080require TLS orMACLAW_ALLOW_INSECURE_HTTP=true. -
Optional TLS is supported with
MACLAW_TLS_CERT_FILEandMACLAW_TLS_KEY_FILE. -
Credential secrets are stored as salted
scryptdigests. -
API keys are persisted as
hash + prefix, not plaintext. -
Runtime config files containing user secrets are written with owner-only permissions.
-
Local bash requires
MACLAW_ENABLE_LOCAL_BASH=trueand should remain disabled in multi-tenant deployments unless an external OS/container sandbox exists. -
GET /healthonly returns service status and does not expose filesystem paths. -
GET /readyzverifies the configured data root exists, is a directory, and is writable before returningready. -
GET /api/v1/admin/system/readinessreturns admin-only detailed readiness checks, including writable state-path diagnostics.
MACLAW_DATA_ROOT/
state/
store.json
tenants/
tenant_xxx/
users/
user_xxx/
data/
config.json
config/
app_config.json
instances/
inst_xxx/
bootstrap.json
workspace/
System:
-
GET /health -
GET /livez -
GET /readyz -
GET /version -
GET /openapi.json -
GET /api/v1/openapi.json
Admin:
-
GET /api/v1/admin/system/readiness -
GET /api/v1/admin/overview -
GET /api/v1/admin/dashboard -
GET /api/v1/admin/alerts -
GET /api/v1/admin/audit-events -
GET /api/v1/admin/exportwithtenant_id,user_id, and include flags for backup/export flows -
POST /api/v1/admin/importfor restore/import flows with optionaloverwrite=trueordry_run=true, returningconflicts,warnings, andplanin precheck mode -
GET /api/v1/admin/tenantswithstatusandnamefilters -
POST /api/v1/admin/tenants -
GET /api/v1/admin/tenants/{tenantId} -
GET /api/v1/admin/tenants/{tenantId}/summary -
PATCH /api/v1/admin/tenants/{tenantId} -
DELETE /api/v1/admin/tenants/{tenantId} -
GET /api/v1/admin/userswith cross-tenanttenant_id,status,name, andemailfilters -
GET /api/v1/admin/tenants/{tenantId}/userswithstatus,name, andemailfilters -
POST /api/v1/admin/tenants/{tenantId}/users -
GET /api/v1/admin/tenants/{tenantId}/users/{userId} -
PATCH /api/v1/admin/tenants/{tenantId}/users/{userId} -
DELETE /api/v1/admin/tenants/{tenantId}/users/{userId} -
GET /api/v1/admin/tenants/{tenantId}/users/{userId}/credentials -
POST /api/v1/admin/tenants/{tenantId}/users/{userId}/credentials -
GET /api/v1/admin/tenants/{tenantId}/users/{userId}/credentials/{credentialId} -
PATCH /api/v1/admin/tenants/{tenantId}/users/{userId}/credentials/{credentialId} -
POST /api/v1/admin/tenants/{tenantId}/users/{userId}/credentials/{credentialId}/rotate-secret -
POST /api/v1/admin/tenants/{tenantId}/users/{userId}/credentials/{credentialId}/rotate-key -
DELETE /api/v1/admin/tenants/{tenantId}/users/{userId}/credentials/{credentialId}
Auth and user config:
-
POST /api/v1/auth/token -
GET /api/v1/me -
GET /api/v1/config/schema -
GET /api/v1/config -
PUT /api/v1/config -
POST /api/v1/config/validate -
POST /api/v1/config/test -
GET /api/v1/usage/summary
MCP:
-
GET /api/v1/mcp/servers -
POST /api/v1/mcp/servers -
GET /api/v1/mcp/servers/{serverId} -
PATCH /api/v1/mcp/servers/{serverId} -
DELETE /api/v1/mcp/servers/{serverId} -
POST /api/v1/mcp/servers/{serverId}/start -
POST /api/v1/mcp/servers/{serverId}/stop -
POST /api/v1/mcp/servers/{serverId}/health-check -
GET /api/v1/mcp/servers/{serverId}/tools
Skills:
-
GET /api/v1/skills -
POST /api/v1/skills/search -
POST /api/v1/skills/install -
POST /api/v1/skills/import -
GET /api/v1/jobswith optionalkind,status,limit, andbeforefilters -
DELETE /api/v1/jobswithkind,status,before, orall=truefor bulk terminal-job cleanup -
GET /api/v1/jobs/{jobId} -
POST /api/v1/jobs/{jobId}/cancel -
DELETE /api/v1/jobs/{jobId} -
GET /api/v1/skill-uploads/{submissionId} -
GET /api/v1/skill-market/account -
GET /api/v1/skills/{skillName} -
DELETE /api/v1/skills/{skillName} -
GET /api/v1/skills/{skillName}/export -
POST /api/v1/skills/{skillName}/validate -
POST /api/v1/skills/{skillName}/improve -
POST /api/v1/skills/{skillName}/upload
Runtime:
-
GET /api/v1/instances -
POST /api/v1/instances -
GET /api/v1/instances/{instanceId} -
PATCH /api/v1/instances/{instanceId} -
DELETE /api/v1/instances/{instanceId} -
GET /api/v1/instances/{instanceId}/capabilities -
POST /api/v1/instances/{instanceId}/stop -
POST /api/v1/instances/{instanceId}/resume -
POST /api/v1/instances/{instanceId}/refresh-readiness -
GET /api/v1/instances/{instanceId}/summary -
GET /api/v1/instances/{instanceId}/bootstrap -
POST /api/v1/instances/{instanceId}/messages -
GET /api/v1/instances/{instanceId}/sessions -
POST /api/v1/instances/{instanceId}/sessions -
GET /api/v1/instances/{instanceId}/sessions/{sessionId} -
PATCH /api/v1/instances/{instanceId}/sessions/{sessionId} -
DELETE /api/v1/instances/{instanceId}/sessions/{sessionId} -
POST /api/v1/instances/{instanceId}/sessions/{sessionId}/archive -
POST /api/v1/instances/{instanceId}/sessions/{sessionId}/restore -
GET /api/v1/instances/{instanceId}/sessions/{sessionId}/messages -
POST /api/v1/instances/{instanceId}/sessions/{sessionId}/messages -
GET /api/v1/instances/{instanceId}/runs -
GET /api/v1/instances/{instanceId}/runs/{runId} -
GET /api/v1/instances/{instanceId}/runs/{runId}/events -
POST /api/v1/instances/{instanceId}/runs/{runId}/cancel
-
Resource reads use
GET. -
Resource creation uses
POST. -
Mutable resource updates use
PATCHorPUT. -
Resource deletion uses
DELETE. -
State-changing actions that are not plain CRUD use explicit action routes such as
/stop,/resume,/archive,/restore,/health-check, and/refresh-readiness. -
Admin APIs use
X-MaClaw-Admin-Secret. -
User APIs use
Authorization: Bearer <token>. -
Machine-readable source of truth is
openapi.go, exposed at/openapi.json.
Cursor pagination is currently supported by these list endpoints:
-
GET /api/v1/admin/tenantswithstatusandnamefilters -
GET /api/v1/admin/userswith cross-tenanttenant_id,status,name, andemailfilters -
GET /api/v1/admin/tenants/{tenantId}/userswithstatus,name, andemailfilters -
GET /api/v1/admin/tenants/{tenantId}/users/{userId}/credentials -
GET /api/v1/admin/audit-events -
GET /api/v1/admin/exportwithtenant_id,user_id, and include flags for backup/export flows -
POST /api/v1/admin/importfor restore/import flows with optionaloverwrite=trueordry_run=true, returningconflicts,warnings, andplanin precheck mode -
GET /api/v1/mcp/servers -
GET /api/v1/skills -
GET /api/v1/instances -
GET /api/v1/instances/{instanceId}/sessions -
GET /api/v1/instances/{instanceId}/sessions/{sessionId}/messages -
GET /api/v1/instances/{instanceId}/runs
Query parameters:
-
limit: positive integer, default100, max500 -
before: cursor value -
session list:
include_archivedmust betrueorfalse -
message list:
roleacceptsuser,assistant, orsystem -
run list:
statusacceptsrunning,succeeded,failed, orcancelled -
run list:
response_sourcecurrently acceptsask_user -
run list:
waiting_for_usermust betrueorfalse
Notes:
-
Most list endpoints use RFC3339 or RFC3339Nano timestamps as the cursor.
-
GET /api/v1/skillsuses case-insensitive skill name ordering and returns the next name innext_before. -
Responses keep
itemsand addlimit,has_more, and optionalnext_before.
-
POST /api/v1/skills/install?async=truereturns202 Acceptedand a user-scoped job resource. -
POST /api/v1/skills/import?async=truereturns202 Acceptedand a user-scoped job resource. -
POST /api/v1/skills/{skillName}/upload?async=truereturns202 Acceptedand a user-scoped job resource. -
POST /api/v1/mcp/servers?async=truereturns202 Acceptedand a user-scoped job resource. -
PATCH /api/v1/mcp/servers/{serverId}?async=truereturns202 Acceptedand a user-scoped job resource. -
POST /api/v1/mcp/servers/{serverId}/start?async=truereturns202 Acceptedand a user-scoped job resource. -
POST /api/v1/mcp/servers/{serverId}/stop?async=truereturns202 Acceptedand a user-scoped job resource. -
POST /api/v1/mcp/servers/{serverId}/health-check?async=truereturns202 Acceptedand a user-scoped job resource. -
Poll with
GET /api/v1/jobs/{jobId}untilstatusbecomessucceeded,failed, orcanceled. -
Use
GET /api/v1/jobsto list recent jobs,DELETE /api/v1/jobs?status=succeeded&before=<timestamp>orDELETE /api/v1/jobs?all=trueto bulk-remove finished jobs,POST /api/v1/jobs/{jobId}/cancelto request cancellation, andDELETE /api/v1/jobs/{jobId}to remove a single finished job. -
Async job payloads are isolated by tenant/user and return the same result shape as the synchronous API when finished.
Already in place:
-
Multi-tenant admin control plane for tenants, users, and credentials
-
Token issuance and bearer authentication, with immediate old-token invalidation after credential secret rotation or revoke
-
Shared per-user config lifecycle with schema, validate, test, and update APIs
-
Runtime lifecycle for instances, sessions, messages, runs, and run SSE events
-
Skill lifecycle coverage for search, install, import, export, validate, improve, upload, delete, and async job polling for heavy skill operations
-
MCP lifecycle coverage for create, update, delete, start, stop, health-check, and tool listing
-
Usage, audit, overview, dashboard, tenant summary, alerts, metrics, and admin export/import endpoints
The service is broadly usable, but it is not yet a fully complete control plane. Current gaps include:
-
Credential lifecycle has secret rotation and status control, but still lacks full API key reissue/expiry policy flows
-
Admin list filtering is now available for tenants and users, but deeper fuzzy search is still thin
-
Service export/import now has persisted snapshot create/list/get/restore/delete/prune APIs; scheduled snapshot policies and stronger restore policies are still future work
-
No service-level webhook/event subscription model beyond run SSE
-
Metrics are available at
/metrics, including service totals, unready-instance gauges, token auth failure and rate-limit counters, waiting/failed run gauges, run succeeded/failed event counters, and async job status gauges, but richer deployment dashboards and alert integrations are still thin -
No stronger analytics surfaces such as hot tenants, over-quota tenants, inactive users, or MCP/skill usage trends
-
English detailed guide:
API_MANUAL.md -
Chinese detailed guide:
API_MANUAL.zh-CN.md -
English quickstart:
QUICKSTART.md -
Chinese quickstart:
QUICKSTART.zh-CN.md -
Gap analysis:
GAP_ANALYSIS.md -
Chinese gap analysis:
GAP_ANALYSIS.zh-CN.md
- Tenant and user destructive deletes now require
?confirm=trueon the delete request. - Recommended admin flow: call
delete-checkorretire-planfirst, confirm the impact and blockers, then issue the final delete with explicit confirmation. - A request without
confirm=truereturns400and does not remove the tenant or user.
- Delete protection can be configured on both tenants and users through the normal create and update admin payloads.
- Protected resources appear as
delete_protected=truein delete-check responses, and the blockers list includeskind=delete_protected. - Even with
?confirm=true, protected tenants or users still return409until the protection flag is cleared.
- Server-generated credential issuance is supported.
POST /api/v1/admin/tenants/{tenantId}/users/{userId}/credentialsmay omitapi_keyandapi_secret; missing values are generated by the service.- The generated
api_secretis returned only in the create response. Later get/list/export responses remain sanitized unless using internal export withinclude_secrets=true.
- Credential expiry alerts are included in
GET /api/v1/admin/alerts. - Use
kind=credential_expiringorkind=credential_expiredto filter only credential lifecycle alerts. credential_expiry_window_dayscontrols how far aheadcredential_expiringlooks. The default is 7 days and the maximum is 365.
- Credential rotation can also generate new values server-side.
POST .../credentials/{credentialId}/rotate-secretmay omitapi_secret; the generated secret is returned only in that response.POST .../credentials/{credentialId}/rotate-keymay omitapi_key; the generated key is returned only in that response.
- Admin overview includes credential status and expiry-risk counters.
GET /api/v1/admin/overviewand the dashboard overview includecredentials,active_credentials,suspended_credentials,revoked_credentials,expired_credentials, andexpiring_credentials.expiring_credentialsuses the same 7-day default lookahead as credential expiry alerts.
GET /api/v1/admin/tenants/{tenantId}/summarynow includes credential lifecycle counters at both tenant level and eachuser_summaries[]item.- Fields include
credentials,active_credentials,suspended_credentials,revoked_credentials,expired_credentials, andexpiring_credentials. expiring_credentialsuses the same 7-day default lookahead as credential expiry alerts.
/metricsexposes credential lifecycle gauges for Prometheus.- Metrics include
maclaw_credentials_total,maclaw_credentials_by_status{status="active|suspended|revoked"},maclaw_credentials_expired_total, andmaclaw_credentials_expiring_total.
GET /api/v1/usage/summaryalso includes the current user's credential lifecycle counters.- This exposes only aggregate counts and never returns credential secrets, key hashes, or plaintext API keys.
POST /api/v1/admin/tenants/{tenantId}/users/{userId}/credentialsaccepts optionalexpires_atin the create body.- This lets admin callers issue generated credentials with an expiry policy in a single request, avoiding a create-then-patch window.
GET /api/v1/admin/tenants/{tenantId}/users/{userId}/credentialssupports lifecycle filters for admin consoles and automation.- Query parameters:
status=active|suspended|revoked,expired=true|false, andexpiring=true|false. expiring=trueuses the same default 7-day lookahead window used by summary counters and metrics.
GET /api/v1/admin/audit-eventssupportsresource_idandactor_typefilters in addition to tenant, user, action, and resource type filters.- This is useful for tracing one credential, run, user, tenant, or other resource through create/update/rotate/revoke operations.
GET /api/v1/admin/audit-eventssupportssinceanduntilRFC3339/RFC3339Nano filters on eventcreated_at.beforeremains the pagination cursor; usesince/untilfor logical time windows andbeforefor walking result pages.
POST /api/v1/admin/snapshotspersists a service, tenant, or user export underMACLAW_DATA_ROOT/snapshots.GET /api/v1/admin/snapshotslists persisted snapshots with tenant/user/scope/name/time-window filters and normal pagination.POST /api/v1/admin/snapshots/{snapshotId}/restorereuses the import pipeline and supportsdry_runplusoverwrite.POST /api/v1/admin/snapshots/prunesupportsolder_than,keep_latest, anddry_runfor manual retention cleanup.GET /api/v1/admin/overviewincludessnapshotsandsnapshot_bytes;/metricsexposesmaclaw_snapshots_totalandmaclaw_snapshot_bytes_total.