MCP server for fmsg: send and receive federated messages from any AI agent via a deployed fmsg Web API
- ✓Open-source license (MIT)
- ✓Actively maintained (<30d)
- ✓Clear description
- ✓Topics declared
- ✓Documented (README)
claude mcp add fmsg-mcp -- npx -y @markmnl/fmsg-mcp{
"mcpServers": {
"fmsg-mcp": {
"command": "npx",
"args": ["-y", "@markmnl/fmsg-mcp"],
"env": {
"FMSG_API_URL": "<fmsg_api_url>",
"FMSG_API_KEY": "<fmsg_api_key>"
}
}
}
}FMSG_API_URLFMSG_API_KEYMCP Servers overview
# fmsg-mcp
[](https://github.com/markmnl/fmsg-mcp/actions/workflows/tests.yml)
[](https://www.npmjs.com/package/@markmnl/fmsg-mcp)
[](./LICENSE)
An [MCP](https://modelcontextprotocol.io) server that gives any AI agent its own
[fmsg](https://github.com/markmnl/fmsg) address: send messages, follow threads, react, exchange
attachments and wait for replies, through a deployed
[fmsg Web API](https://github.com/markmnl/fmsg-webapi). Connect through stdio in hosts such as
Claude Code, Claude Desktop, Cursor and VS Code, or through HTTP using API-key headers or configured OAuth.
Use your choice of fmsg hosting provider, or self-host. No hosting provider or identity provider
is built in.
- **stdio** for local hosts: one address per server process, configured by two environment variables.
- **Streamable HTTP** for shared or remote deployments: one endpoint serving many users, each
authenticated by their own fmsg API key or OAuth connection.
- The fmsg Web API client is exported for reuse: `import { FmsgClient } from "@markmnl/fmsg-mcp/client"`.
## 1. Choose a connection
### OAuth: connect and sign in
Get an OAuth-enabled MCP URL from your fmsg hosting provider, add it to your AI host, and sign in.
You do not need an API key or a local installation for this connection. Your AI host must support
the authorization server's client registration method; see [OAuth onboarding](docs/oauth.md#discovery-and-client-onboarding).
Operators can enable this with [HTTP OAuth](docs/oauth.md).
### API key: use locally or over HTTP
You send as an fmsg address, authenticated by an API key (`fmsgk_…`) issued by your fmsg host:
- **Using a hosting provider?** Create an account with an fmsg hosting provider and obtain an
API URL and API key for the address your agent will use.
- **Self-hosting?** Run the stack with [fmsg-docker](https://github.com/markmnl/fmsg-docker) and issue
a key with `fmsg-webapi api-key create`.
Use the API URL and key for local installation below, or use your provider's API-key MCP endpoint
with an `Authorization: Bearer fmsgk_...` header. The endpoint must use the fmsg Web API that accepts
your key.
### MCP Registry
Find `io.github.markmnl/fmsg-mcp` in the [official MCP Registry](https://registry.modelcontextprotocol.io/?q=io.github.markmnl%2Ffmsg-mcp).
The listing offers local npm installation and configurable remote connections for OAuth or API keys.
For a remote connection, supply the MCP endpoint from your fmsg hosting provider or your own deployment;
the registry input takes its hostname and path without the `https://` prefix, such as `mcp.example.com/mcp`.
OAuth sign-in is discovered from that endpoint; the API-key option additionally asks for your key.
If your AI host cannot configure registry URL templates, add the full MCP URL directly instead.
## 2. Install
Requires Node.js 22 or later.
### Claude Code
```sh
claude mcp add fmsg --scope user \
--env FMSG_API_URL=https://api.example.com \
--env FMSG_API_KEY=fmsgk_... \
-- npx -y @markmnl/fmsg-mcp
```
Then in any session: *"Send @bob@example.com a note about the release"*, *"What's in my fmsg inbox?"*,
*"Wait for Bob's reply and answer it"*. `/fmsg:chat` and `/fmsg:reply` are available as prompts.
### Claude Desktop, Cursor, VS Code and other stdio hosts
Add a server entry with the same command; only the config file differs:
```json
{
"mcpServers": {
"fmsg": {
"command": "npx",
"args": ["-y", "@markmnl/fmsg-mcp"],
"env": { "FMSG_API_URL": "https://api.example.com", "FMSG_API_KEY": "fmsgk_..." }
}
}
}
```
(Claude Desktop: `claude_desktop_config.json`; Cursor: `.cursor/mcp.json`; VS Code: `.vscode/mcp.json`
under `"servers"` with `"type": "stdio"`.)
### Remote (Streamable HTTP) mode
Run one server for many users. Each client sends **its own** fmsg API key as a bearer token; the
server exchanges it at the fmsg host and acts as that address. `FMSG_API_KEY` must not be set.
```sh
FMSG_API_URL=https://api.example.com FMSG_MCP_ALLOWED_HOSTS=mcp.example.com \
npx -y @markmnl/fmsg-mcp --http 0.0.0.0:8765
# or
docker build -t fmsg-mcp .
docker run -e FMSG_API_URL=https://api.example.com \
-e FMSG_MCP_ALLOWED_HOSTS=mcp.example.com -p 8765:8765 fmsg-mcp
```
The MCP endpoint is `/mcp`; `/healthz` reports liveness. Use a client that supports an explicitly
configured `Authorization: Bearer fmsgk_...` header. Each caller supplies its own key; a shared
header means a shared fmsg identity. For browser sign-in without user API keys, configure
[HTTP OAuth](docs/oauth.md): the operator supplies an issuer, resource URI and exchange client.
Users add the public MCP URL in a host supporting that issuer's client registration method.
For [Claude Code over HTTP](https://code.claude.com/docs/en/mcp):
```sh
claude mcp add --transport http fmsg --scope user https://mcp.example.com/mcp \
--header "Authorization: Bearer fmsgk_..."
```
Deploy behind a TLS-terminating reverse proxy and set `FMSG_MCP_ALLOWED_HOSTS` to the public hostname
when binding to a non-loopback address; startup fails without it. Browser clients on another origin
also need `FMSG_MCP_ALLOWED_ORIGINS` containing exact origins, such as `https://app.example.com`.
For loopback binds, loopback browser origins on any port work by default, including MCP Inspector
at `http://localhost:6274`. Setting an explicit origin list replaces that loopback default.
Allowed preflights need no credentials; actual MCP requests always require authentication.
`wait_for_message` holds a request open for up to
`FMSG_MCP_WAIT_MAX_SECONDS` (230), so give the proxy an idle timeout of at least 240 s.
See the [TLS reverse-proxy example](docs/http-deployment.md) for a loopback deployment with Caddy.
## Tools
| Tool | What it does |
|---|---|
| `whoami` | The address this server acts as, the API URL and token expiry |
| `resolve_address` | Turn a short name into `@user@domain` (directory, then default domain) |
| `list_messages` | Inbox, newest first, with previews; reactions hidden; optional unread filter |
| `list_sent` | Sent messages with per-recipient delivery state |
| `get_message` | One message with headers, full text body, attachments and reactions |
| `get_thread` | The lineage from the thread root to a message, with gaps for messages you cannot see |
| `send_message` | Start a new thread; sends immediately (fmsg messages are immutable) |
| `reply` | Reply into a thread; reply-all by default, refuses terminal and no-reply parents |
| `add_recipients` | Add recipients to a sent message |
| `react` | Set or clear your emoji reaction |
| `mark_read` | Mark received messages read |
| `download_attachment` | Fetch a small attachment inline: text as text, images as image blocks, other files as base64 resources |
| `save_attachment` | Stream an attachment to the configured local folder; stdio only, enabled by `FMSG_MCP_DOWNLOAD_DIR` |
| `delivery_status` | Per-recipient delivery times and host response codes |
| `wait_for_message` | Block until the next inbound message (WebSocket push), batched per thread, with thread context |
Every tool returns readable Markdown plus `structuredContent`. Ids are decimal strings. Message
bodies are labelled as data from other parties, not instructions.
Resources `fmsg://message/{id}` and `fmsg://thread/{id}` expose the same content to hosts that
attach resources; prompts `chat` and `reply` script the wait → reply loop and a guided reply.
## Configuration
| Variable | Default | Purpose |
|---|---|---|
| `FMSG_API_URL` | — | Base URL of the fmsg Web API (required) |
| `FMSG_API_KEY` | — | `fmsgk_…` key; stdio mode only |
| `FMSG_MCP_AUTH_MODE` | `api-key` | HTTP authentication: `api-key` or `oauth`; see [OAuth settings](docs/oauth.md#operator-configuration) |
| `FMSG_ALLOW_INSECURE_HTTP` | disabled | Set to `1` only to permit cleartext API access on a trusted development/private network; loopback HTTP is allowed by default |
| `FMSG_DEFAULT_DOMAIN` | — | Lets short names resolve: `bob` → `@bob@<domain>` |
| `FMSG_DIRECTORY` | — | JSON file mapping short names to full addresses |
| `FMSG_MCP_DOWNLOAD_DIR` | — | Enable `save_attachment` in stdio; folder for new files named from message ID and filename |
| `FMSG_MCP_WAIT_MAX_SECONDS` | `230` | Cap on one `wait_for_message` call |
| `FMSG_MCP_HOST` / `FMSG_MCP_PORT` | `127.0.0.1` / `8765` | HTTP bind address (or `--http host:port`) |
| `FMSG_MCP_ALLOWED_HOSTS` | loopback names | Comma-separated `Host` header allowlist; required for non-loopback binds |
| `FMSG_MCP_ALLOWED_ORIGINS` | same origin; loopback origins on loopback binds | Comma-separated browser origins including scheme and port; an explicit list replaces the loopback default; hostname-only values are rejected |
| `FMSG_MCP_KEY_CACHE_MAX` / `FMSG_MCP_KEY_CACHE_TTL_SECONDS` | `500` / `1800` | HTTP client cache bound; TTL applies only to API-key mode |
The API key is exchanged for a short-lived access token that the server renews automatically.
API URLs must not contain credentials, query strings or fragments. Authenticated requests do not
follow redirects; configure the final API URL directly.
To save attachments directly to disk, add `FMSG_MCP_DOWNLOAD_DIR` to your stdio server's environment,
for example `/home/you/Downloads/fmsg`. The optional `save_attachment` tool streams files into that
folder without sending their bytes through model context. It accepts only a message ID and attachment
filename and creates a new file such as `123-report.pdf`. Repeat saves use `123-report-1.pdf`,
`123-report-2.pdf`, etc., leaving existing files untouched. Unusual filenames are converted to
portable names; use the returned `saved_to` path. Streaming downloads can run longer than 60 seconds
while making progress; a 60-second idle timeout deWhat people ask about fmsg-mcp
What is markmnl/fmsg-mcp?
+
markmnl/fmsg-mcp is mcp servers for the Claude AI ecosystem. MCP server for fmsg: send and receive federated messages from any AI agent via a deployed fmsg Web API It has 1 GitHub stars and its last recorded update is dated 2026-09-17.
How do I install fmsg-mcp?
+
You can install fmsg-mcp by cloning the repository (https://github.com/markmnl/fmsg-mcp) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.
Is markmnl/fmsg-mcp safe to use?
+
Our security agent has analyzed markmnl/fmsg-mcp and assigned a Trust Score of 95/100 (tier: Verified). See the full breakdown of passed checks and flags on this page.
Who maintains markmnl/fmsg-mcp?
+
markmnl/fmsg-mcp is maintained by markmnl. The last recorded GitHub activity is dated 2026-09-17, with 0 open issues.
Are there alternatives to fmsg-mcp?
+
Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.
Deploy fmsg-mcp to your cloud
Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.
Maintain this repo? Add a badge to your README
Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.
[](https://claudewave.com/repo/markmnl-fmsg-mcp)<a href="https://claudewave.com/repo/markmnl-fmsg-mcp"><img src="https://claudewave.com/api/badge/markmnl-fmsg-mcp" alt="Featured on ClaudeWave: markmnl/fmsg-mcp" width="320" height="64" /></a>More MCP Servers
Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.
User-friendly AI Interface (Supports Ollama, OpenAI API, ...)
An open-source AI agent that brings the power of Gemini directly into your terminal.
Real-time global intelligence dashboard. AI-powered news aggregation, geopolitical monitoring, and infrastructure tracking in a unified situational awareness interface
🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl! Don't be shy, join here: https://discord.gg/EMgGbDceNQ
The fastest path to AI-powered full stack observability, even for lean teams.