# MCP tools

> The full list of MMW tools, their annotations, transport and auth, plus a raw HTTP call example.

On this page you will learn:

1. which tools your assistant sees once MMW is connected, and how they differ;
2. how the server works: endpoint, transport, authentication;
3. how to call a tool directly over HTTP, without an assistant, for scripts or diagnostics.

The running example: the team keeps the agreement "staging is deployed with the systemd unit `app-staging`" in MMW and checks it with a `search` call from the terminal.

## All tools

| Tool | Provided by | Purpose | Annotations |
| --- | --- | --- | --- |
| [`remember`](/reference/remember/) | server | Save a fact, decision or note | writes, non-destructive |
| [`search`](/reference/search/) | server | Find records with their source and status | read-only, idempotent |
| [`forget`](/reference/forget/) | server | Soft-delete a record or every record from a source | destructive |
| [`validate_memory`](/reference/validate-memory/) | server | Check freshness of all records from one source | read-only, idempotent |
| [`gateway_call`](/reference/gateway-call/) | server | Call a tool of a connected integration | writes, open world |
| `github_readonly.*` and others | server, the project's integrations | Tools of integrations enabled for the key's project | read-only, idempotent, open world |
| [`mmw_sync_status`](/reference/mmw-sync-status/) | local agent mmw-agent | Session history sync status | read-only, idempotent |

Annotations are MCP hints (`readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`) that the server sends to the client. Clients use them to decide whether to ask for confirmation before a call. Exact values:

| Tool | Title | readOnly | destructive | idempotent | openWorld |
| --- | --- | --- | --- | --- | --- |
| `remember` | Save memory | no | no | no | no |
| `search` | Search memories | yes | no | yes | no |
| `forget` | Delete memory | no | yes | no | no |
| `validate_memory` | Check memory freshness | yes | no | yes | no |
| `gateway_call` | Call a connected integration | no | no | no | yes |
| `github_readonly.*` | GitHub (read-only): … | yes | no | yes | yes |
| `mmw_sync_status` | — | yes | — | yes | — |

Integration tools appear in the list only when the integration is enabled in your account for the project the key belongs to. With the GitHub integration connected, for example, you get `github_readonly.get_file_contents`, `github_readonly.pull_request_read` and `github_readonly.get_me`.

For ChatGPT connections (beta) the server exposes only the memory tools: `gateway_call` and integration tools are neither listed nor executed, and the internal fields `tenant_id`, `project_id` and `api_version` are stripped from responses.

## Server

| Setting | Value |
| --- | --- |
| Endpoint | `https://mcp.mmwhub.tech/mcp` |
| Transport | Streamable HTTP |
| Sessions | none (stateless): every request stands on its own, no reconnect needed after a pause or a server restart |
| Response format | JSON (`application/json`) |
| Authentication | `Authorization: Bearer mmw_…` header (API key from your account) or OAuth for claude.ai and ChatGPT |
| API version in responses | the `api_version` field, currently `1.0` |

A key is bound to a project: every call works with that project's memory. More on keys and OAuth in [API keys and OAuth](/account/api-keys-and-oauth/).

## How it fits together

```text
  Assistant (Claude Code, Cursor, Codex…)
        │ stdio
        ▼
  mmw-agent (local, optional) ── answers mmw_sync_status itself
        │ HTTPS, Bearer mmw_…
        ▼
  https://mcp.mmwhub.tech/mcp ── remember / search / forget / validate_memory
        │                        gateway_call and integration tools
        ▼
  memory of the key's project (+ visibility rules inside an organization)
```

The local agent forwards every call to the server unchanged: the client sees exactly the tool list the server returned, plus `mmw_sync_status`. Clients without the agent (claude.ai, ChatGPT, direct HTTP) talk to the server directly and do not see `mmw_sync_status`.

## Calling a tool over HTTP

The server keeps no sessions, so `initialize` is not required before a call: a single JSON-RPC POST is enough. The `Accept` header must list both types: `application/json, text/event-stream`.

```bash title="Search for the staging agreement"
curl -s https://mcp.mmwhub.tech/mcp \
  -H "Authorization: Bearer $MMW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "search",
      "arguments": { "query": "staging systemd", "limit": 3 }
    }
  }'
```

Response (shortened):

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      { "type": "text", "text": "{\"id\": \"4d428a41-e7b0-4f81-a886-f40c6f6c766c\", ...}" }
    ],
    "structuredContent": {
      "result": [
        {
          "id": "4d428a41-e7b0-4f81-a886-f40c6f6c766c",
          "workspace": "default",
          "scope": "shared",
          "content": "staging is deployed with the systemd unit app-staging",
          "fact_key": "deploy-staging",
          "status": "unverified",
          "score": 2
        }
      ]
    },
    "isError": false
  }
}
```

To list the tools, send the same request with `"method": "tools/list"` and empty `params`.

Keep the key in an environment variable (`$MMW_API_KEY`) rather than in the command itself: commands end up in your shell history.

## What errors look like

A tool error comes back as a normal response with `"isError": true` and the reason in `content`. For the memory tools the text reads like `Error executing tool remember: content must not be empty`. Authentication errors happen earlier, at the HTTP level, with status `401`. All texts and what to do about them are on the [Errors](/reference/errors/) page.

## Next steps
