get_search

Read-only

Calls GET /api/search as the signed-in person · REST reference

Console omnibox - search organizations, users and vouchers in one call

Authenticated, but authorization is NOT a gate here - it is a filter. SearchService decides per category from the caller's own permissions (query:ListOrgsQuery AND platform staff for organizations, query:ListUsersQuery for users, platform staff for vouchers), and a caller who holds none of them gets an empty 200 rather than a 403, so the omnibox degrades quietly instead of erroring on every keystroke. Because the permission decides only WHETHER a category is searched, the category itself carries the boundary: users is org-scoped at the DAL from the caller's own forwarded token, so a caller sees only their own organizations' people unless they are platform staff. organizations is not org-scoped at the DAL, so it additionally requires platform staff. The searched array is how a client tells "no matches" from "you were not allowed to look". A query shorter than 2 characters returns an empty 200, and an unrecognised category is ignored, so every permitted category is searched - neither is an error. A category whose DAL read fails is logged and omitted from searched rather than failing the whole search. Results are ranked exact match, then prefix, then substring, capped at 10 per category.

Arguments

ArgumentTypeDescription
qquerystringSearch text. Trimmed; under 2 characters returns an empty result set. A missing or non-string value is treated as an empty query.
categoryquery"organizations" | "users" | "vouchers"Restrict to one category. A value outside this set is silently ignored and all permitted categories are searched.

Example call

A client sends this over the MCP session; Claude and other agents build it for you. The values are placeholders — the shape is real.

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_search",
    "arguments": {}
  }
}

Result

On success (HTTP 200) the tool returns one text item holding the API's JSON, pretty-printed.

Ranked results, plus the categories actually searched after permission scoping. Both arrays are empty when the caller may search nothing.

json
{
  "results": [
    {
      "id": "string",
      "metadata": {},
      "subtitle": "string",
      "title": "string",
      "type": "organizations"
    }
  ],
  "searched": [
    "organizations"
  ]
}

Fields

FieldTypeDescription
resultsarray of object
results[].idstring
results[].metadataobject
results[].subtitlestring
results[].titlestring
results[].type"organizations" | "users" | "vouchers"
searchedarray of "organizations" | "users" | "vouchers"Categories this caller was permitted to search and that answered.

When it fails

A failed call returns isError: true with the API's message as text.

403

The request reached the handler with no bearer token to forward to the DAL (authenticate answers 401 before that for a request without one).

What the model is shown

This is the tool exactly as the server lists it in tools/list. The description starts with the REST call it makes.

json
{
  "name": "get_search",
  "description": "GET /api/search — Authenticated, but authorization is NOT a gate here - it is a filter. SearchService decides per category from the caller's own permissions (query:ListOrgsQuery AND platform staff for organizations, query:ListUsersQuery for users, platform staff for vouchers), and a caller who holds none of them gets an empty 200 rather than a 403, so the omnibox degrades quietly instead of erroring on every keystroke. Because the permission decides only WHETHER a category is searched, the category itself carries the boundary: `users` is org-scoped at the DAL from the caller's own forwarded token, so a caller sees only their own organizations' people unless they are platform staff. `organizations` is not org-scoped at the DAL, so it additionally requires platform staff. The `searched` array is how a client tells \"no matches\" from \"you were not allowed to look\". A query shorter than 2 characters returns an empty 200, and an unrecognised `category` is ignored, so every permitted category is searched - neither is an error. A category whose DAL read fails is logged and omitted from `searched` rather than failing the whole search. Results are ranked exact match, then prefix, then substring, capped at 10 per category.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "q": {
        "type": "string",
        "description": "Search text. Trimmed; under 2 characters returns an empty result set. A missing or non-string value is treated as an empty query."
      },
      "category": {
        "type": "string",
        "description": "Restrict to one category. A value outside this set is silently ignored and all permitted categories are searched."
      }
    }
  },
  "annotations": {
    "readOnlyHint": true,
    "openWorldHint": false
  }
}