test(tools): add unit tests for error handling functions
* Implement tests for error functions like errRequiredField, errInvalidField, and errEntityNotFound. * Ensure proper metadata is returned for various error scenarios. * Validate error handling in CRM, Files, and other tools. * Introduce tests for parsing stored file IDs and UUIDs. * Enhance coverage for helper functions related to project resolution and session management.
This commit is contained in:
132
README.md
132
README.md
@@ -34,8 +34,8 @@ A Go MCP server for capturing and retrieving thoughts, memory, and project conte
|
||||
| `archive_thought` | Soft delete |
|
||||
| `create_project` | Register a named project |
|
||||
| `list_projects` | List projects with thought counts |
|
||||
| `get_project_context` | Recent + semantic context for a project |
|
||||
| `set_active_project` | Set session project scope |
|
||||
| `get_project_context` | Recent + semantic context for a project; uses explicit `project` or the active session project |
|
||||
| `set_active_project` | Set session project scope; requires a stateful MCP session |
|
||||
| `get_active_project` | Get current session project |
|
||||
| `summarize_thoughts` | LLM prose summary over a filtered set |
|
||||
| `recall_context` | Semantic + recency context block for injection |
|
||||
@@ -54,18 +54,129 @@ A Go MCP server for capturing and retrieving thoughts, memory, and project conte
|
||||
| `add_guardrail` | Store a reusable agent guardrail (constraint or safety rule) |
|
||||
| `remove_guardrail` | Delete an agent guardrail by id |
|
||||
| `list_guardrails` | List all agent guardrails, optionally filtered by tag or severity |
|
||||
| `add_project_skill` | Link an agent skill to a project |
|
||||
| `remove_project_skill` | Unlink an agent skill from a project |
|
||||
| `list_project_skills` | List all skills linked to a project |
|
||||
| `add_project_guardrail` | Link an agent guardrail to a project |
|
||||
| `remove_project_guardrail` | Unlink an agent guardrail from a project |
|
||||
| `list_project_guardrails` | List all guardrails linked to a project |
|
||||
| `add_project_skill` | Link an agent skill to a project; pass `project` explicitly if your client does not preserve MCP sessions |
|
||||
| `remove_project_skill` | Unlink an agent skill from a project; pass `project` explicitly if your client does not preserve MCP sessions |
|
||||
| `list_project_skills` | List all skills linked to a project; pass `project` explicitly if your client does not preserve MCP sessions |
|
||||
| `add_project_guardrail` | Link an agent guardrail to a project; pass `project` explicitly if your client does not preserve MCP sessions |
|
||||
| `remove_project_guardrail` | Unlink an agent guardrail from a project; pass `project` explicitly if your client does not preserve MCP sessions |
|
||||
| `list_project_guardrails` | List all guardrails linked to a project; pass `project` explicitly if your client does not preserve MCP sessions |
|
||||
| `get_version_info` | Return the server build version information, including version, tag name, commit, and build date |
|
||||
|
||||
## MCP Error Contract
|
||||
|
||||
AMCS returns structured JSON-RPC errors for common MCP failures. Clients should branch on both `error.code` and `error.data.type` instead of parsing the human-readable message.
|
||||
|
||||
### Stable error codes
|
||||
|
||||
| Code | `data.type` | Meaning |
|
||||
|---|---|---|
|
||||
| `-32602` | `invalid_arguments` | MCP argument/schema validation failed before the tool handler ran |
|
||||
| `-32602` | `invalid_input` | Tool-level input validation failed inside the handler |
|
||||
| `-32050` | `session_required` | Tool requires a stateful MCP session |
|
||||
| `-32051` | `project_required` | No explicit `project` was provided and no active session project was available |
|
||||
| `-32052` | `project_not_found` | The referenced project does not exist |
|
||||
| `-32053` | `invalid_id` | A UUID-like identifier was malformed |
|
||||
| `-32054` | `entity_not_found` | A referenced entity such as a thought or contact does not exist |
|
||||
|
||||
### Error data shape
|
||||
|
||||
AMCS may include these fields in `error.data`:
|
||||
|
||||
- `type` — stable machine-readable error type
|
||||
- `field` — single argument name such as `name`, `project`, or `thought_id`
|
||||
- `fields` — multiple argument names for one-of or mutually-exclusive validation
|
||||
- `value` — offending value when safe to expose
|
||||
- `detail` — validation detail such as `required`, `invalid`, `one_of_required`, `mutually_exclusive`, or a schema validation message
|
||||
- `hint` — remediation guidance
|
||||
- `entity` — entity name for generic not-found errors
|
||||
|
||||
Example schema-level error:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": -32602,
|
||||
"message": "invalid tool arguments",
|
||||
"data": {
|
||||
"type": "invalid_arguments",
|
||||
"field": "name",
|
||||
"detail": "validating root: required: missing properties: [\"name\"]",
|
||||
"hint": "check the name argument"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Example tool-level error:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": -32051,
|
||||
"message": "project is required; pass project explicitly or call set_active_project in this MCP session first",
|
||||
"data": {
|
||||
"type": "project_required",
|
||||
"field": "project",
|
||||
"hint": "pass project explicitly or call set_active_project in this MCP session first"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Client example
|
||||
|
||||
Go client example handling AMCS MCP errors:
|
||||
|
||||
```go
|
||||
result, err := session.CallTool(ctx, &mcp.CallToolParams{
|
||||
Name: "get_project_context",
|
||||
Arguments: map[string]any{},
|
||||
})
|
||||
if err != nil {
|
||||
var rpcErr *jsonrpc.Error
|
||||
if errors.As(err, &rpcErr) {
|
||||
var data struct {
|
||||
Type string `json:"type"`
|
||||
Field string `json:"field"`
|
||||
Hint string `json:"hint"`
|
||||
}
|
||||
_ = json.Unmarshal(rpcErr.Data, &data)
|
||||
|
||||
switch {
|
||||
case rpcErr.Code == -32051 && data.Type == "project_required":
|
||||
// Retry with an explicit project, or call set_active_project first.
|
||||
case rpcErr.Code == -32602 && data.Type == "invalid_arguments":
|
||||
// Ask the caller to fix the malformed arguments.
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = result
|
||||
```
|
||||
|
||||
## Build Versioning
|
||||
|
||||
AMCS embeds build metadata into the binary at build time.
|
||||
|
||||
- `version` is generated from the current git tag when building from a tagged commit
|
||||
- `tag_name` is the repo tag name, for example `v1.0.1`
|
||||
- `build_date` is the UTC build timestamp in RFC3339 format
|
||||
- `commit` is the short git commit SHA
|
||||
|
||||
For untagged builds, `version` and `tag_name` fall back to `dev`.
|
||||
|
||||
Use `get_version_info` to retrieve the runtime build metadata:
|
||||
|
||||
```json
|
||||
{
|
||||
"server_name": "amcs",
|
||||
"version": "v1.0.1",
|
||||
"tag_name": "v1.0.1",
|
||||
"commit": "abc1234",
|
||||
"build_date": "2026-03-31T14:22:10Z"
|
||||
}
|
||||
```
|
||||
|
||||
## Agent Skills and Guardrails
|
||||
|
||||
Skills and guardrails are reusable agent behaviour instructions and constraints that can be attached to projects.
|
||||
|
||||
**At the start of every project session, always call `list_project_skills` and `list_project_guardrails` first.** Use the returned skills and guardrails to guide agent behaviour for that project. Only generate or create new skills/guardrails if none are returned.
|
||||
**At the start of every project session, always call `list_project_skills` and `list_project_guardrails` first.** Use the returned skills and guardrails to guide agent behaviour for that project. Only generate or create new skills/guardrails if none are returned. If your MCP client does not preserve sessions across calls, pass `project` explicitly instead of relying on `set_active_project`.
|
||||
|
||||
### Skills
|
||||
|
||||
@@ -102,6 +213,7 @@ Config is YAML-driven. Copy `configs/config.example.yaml` and set:
|
||||
- `auth.mode` — `api_keys` or `oauth_client_credentials`
|
||||
- `auth.keys` — API keys for MCP access via `x-brain-key` or `Authorization: Bearer <key>` when `auth.mode=api_keys`
|
||||
- `auth.oauth.clients` — client registry when `auth.mode=oauth_client_credentials`
|
||||
- `mcp.version` is build-generated and should not be set in config
|
||||
|
||||
**OAuth Client Credentials flow** (`auth.mode=oauth_client_credentials`):
|
||||
|
||||
@@ -230,7 +342,7 @@ Returns `{"file": {...}, "uri": "amcs://files/<id>"}`. Pass `thought_id`/`projec
|
||||
|
||||
`content_base64` and `content_uri` are mutually exclusive in both tools.
|
||||
|
||||
**Load a file** — returns metadata, base64 content, and an embedded MCP binary resource (`amcs://files/{id}`):
|
||||
**Load a file** — returns metadata, base64 content, and an embedded MCP binary resource (`amcs://files/{id}`). The `id` field accepts either the bare stored file UUID or the full `amcs://files/{id}` URI:
|
||||
|
||||
```json
|
||||
{ "id": "stored-file-uuid" }
|
||||
|
||||
Reference in New Issue
Block a user