On this page you will learn:
- which tools your assistant sees once MMW is connected, and how they differ;
- how the server works: endpoint, transport, authentication;
- 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
Section titled “All tools”| Tool | Provided by | Purpose | Annotations |
|---|---|---|---|
remember | server | Save a fact, decision or note | writes, non-destructive |
search | server | Find records with their source and status | read-only, idempotent |
forget | server | Soft-delete a record or every record from a source | destructive |
validate_memory | server | Check freshness of all records from one source | read-only, idempotent |
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 | 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.
Server
Section titled “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.
How it fits together
Section titled “How it fits together” 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
Section titled “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.
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):
{ "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.
What errors look like
Section titled “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 page.