Skip to main content
Glama
ivantacca

anytype-mcp-remote-gateway

by ivantacca

anytype-mcp-remote-gateway

An HTTP gateway that exposes the official Anytype MCP server — which only speaks stdio, so it only works with local clients like Claude Desktop — as a remote Streamable HTTP endpoint, so it can be used as a custom connector from Claude mobile/web.

This is not a reimplementation of the Anytype MCP server. It runs the official @anyproto/anytype-mcp package unmodified and bridges it to HTTP.

What this is / isn't (current status)

This repo implements Phases 0-4 of the project plan: local setup, proof of concept, a working stdio→HTTP bridge with bearer-token auth, public exposure via Tailscale Funnel (no open inbound port, automatic TLS), per-IP rate limiting, and a Docker/docker-compose deployment. Phase 5 (Claude connector registration) is automated/verified as far as this codebase can take it — see "Registering as a connector in Claude" below and npm run verify:remote — but actually adding the connector is a manual step only you can do inside your own Claude account. See ROADMAP.md for what's still ahead (token rotation, monitoring).

Related MCP server: Levitate

Architecture

Claude (mobile/web)
  │  HTTPS (Tailscale-issued TLS cert) + Authorization: Bearer <GATEWAY_AUTH_TOKEN>
  ▼
https://<device>.<tailnet>.ts.net  (Tailscale Funnel — public internet, no VPN/tailnet
  │                                 membership required on Claude's side, see below)
  ▼
gateway.ts (public Express app, this repo)
  │  trust proxy, request logging, per-IP rate limiting, bearer-token auth, reverse proxy
  │  http://127.0.0.1:<MCP_INTERNAL_PORT>
  ▼
mcp-proxy (spawned child process, loopback only, no auth of its own)
  │  spawns and bridges stdio ⇄ Streamable HTTP (/mcp) + legacy SSE (/sse)
  ▼
npx @anyproto/anytype-mcp (stdio, spawned by mcp-proxy)
  │  OPENAPI_MCP_HEADERS (Authorization + Anytype-Version)
  │  ANYTYPE_API_BASE_URL=http://127.0.0.1:31012 (or http://anytype-headless:31012 in Docker)
  ▼
anytype-cli headless (`anytype serve`), bot account

Tailscale has two related features — Serve (reachable only by devices on your own tailnet, i.e. requires the VPN) and Funnel (punches a Serve config through to the public internet at a plain HTTPS URL, no Tailscale client needed on the caller's side). This project uses Funnel: only the host running the gateway needs to be on Tailscale — Claude itself just calls a normal HTTPS URL, protected by GATEWAY_AUTH_TOKEN exactly as it would be behind any other reverse proxy.

Two HTTP servers are involved on purpose:

  • The public one (gateway.ts) is the only thing meant to ever be reachable from outside the host. It owns the bearer-token check and structured logging.

  • The internal one (spawned mcp-proxy) is bound to 127.0.0.1 only and has no auth of its own — it trusts anything that can reach it, which by design is only the gateway process on the same host. Never bind MCP_INTERNAL_PORT to a public interface.

Implementation note: why mcp-proxy is spawned as a CLI, not wired as a library

The original plan considered importing mcp-proxy's startHTTPServer/proxyServer helpers directly and hand-wiring an MCP SDK Client/Server pair around the spawned anytype-mcp process. During implementation this turned out to be unsafe: mcp-proxy@6.7.1 depends on the newer split @modelcontextprotocol/client/@modelcontextprotocol/server@^2.0.0 packages, while @anyproto/anytype-mcp@1.2.10 depends on the older unified @modelcontextprotocol/sdk@1.30.0. Mixing SDK instances from two different package families is fragile. Instead, src/mcpProxyServer.ts spawns mcp-proxy's own CLI binary (node_modules/mcp-proxy/dist/bin/mcp-proxy.mjs), which internally spawns npx -y @anyproto/anytype-mcp and bridges it using its own internally-consistent SDK pairing.

Prerequisites

  • Node.js ≥ 20 (tested with v23.10.0)

  • anytype-cli (installed via its official install script)

  • An Anytype bot account (separate from any personal/Desktop Anytype account — see below)

Setup: Anytype backend (anytype-cli headless)

This gateway talks to a headless Anytype instance via a dedicated bot account, not to Anytype Desktop and not to any personal account. See "Data isolation" below for why this matters.

# 1. Install anytype-cli (no sudo required, installs to ~/.local/bin)
/usr/bin/env bash -c "$(curl -fsSL https://raw.githubusercontent.com/anyproto/anytype-cli/HEAD/install.sh)"
export PATH="$HOME/.local/bin:$PATH"   # add to your shell rc if not already present

# 2. Start the headless server (foreground; keep this running in its own terminal/tmux pane)
anytype serve   # binds 127.0.0.1:31010-31012

# 3. In a second terminal: create a bot account (one-time)
anytype auth create anytype-mcp-gateway-bot
# ⚠ save the printed account key somewhere safe — it's also saved to your OS keychain

# 4. Generate an API key for this gateway to use
anytype auth apikey create "mcp-gateway"
# copy the printed key into .env as ANYTYPE_API_KEY (next section)

Verify the API is reachable and see what's in the bot account's space (should be new/empty):

node -e "
require('dotenv/config');
const http = require('http');
http.get({
  host: '127.0.0.1', port: 31012, path: '/v1/spaces',
  headers: { Authorization: 'Bearer ' + process.env.ANYTYPE_API_KEY, 'Anytype-Version': process.env.ANYTYPE_API_VERSION },
}, res => { let d=''; res.on('data', c => d+=c); res.on('end', () => console.log(res.statusCode, d)); });
"

Expect 200 and a single space with no name — the bot account's own auto-created default space.

Setup: the gateway

npm install
cp .env.example .env
# edit .env: generate GATEWAY_AUTH_TOKEN with `openssl rand -hex 32`,
# fill in ANYTYPE_API_KEY from the step above.
npm run dev

You should see, in order: internal mcp-proxy listening on 127.0.0.1:8788, then gateway listening on 127.0.0.1:8787 (or whatever GATEWAY_PORT/GATEWAY_HOST you set).

Testing locally with MCP Inspector

curl -i http://localhost:8787/healthz    # 200, no token needed
curl -i http://localhost:8787/mcp        # 401, no token supplied

npm run inspect

In the Inspector UI: connect to http://localhost:8787/mcp with transport Streamable HTTP, and add header Authorization: Bearer <your GATEWAY_AUTH_TOKEN>. Confirm tools/list returns the Anytype tool set and a read-only call (e.g. listing spaces) succeeds.

Public exposure (Tailscale Funnel) — bare metal

Prerequisites, one-time, in the Tailscale admin console:

  1. Enable HTTPS certificates for your tailnet (DNS → HTTPS Certificates → Enable).

  2. Make sure this node is allowed to run Funnel — either it's covered by the default ACL, or add a nodeAttrs grant for it under Access Controls (see Tailscale's Funnel docs).

  3. Install and authenticate Tailscale on the host running the gateway: tailscale up.

Then, with the gateway already running (npm run dev / npm start):

tailscale funnel --bg 8787

Verify from any device not on your tailnet (e.g. your phone on cellular data):

curl -i https://<device>.<tailnet>.ts.net/healthz    # 200, no token, no VPN needed

tailscale funnel status shows the current mapping; tailscale funnel --https=443 off tears it down. The gateway's own GATEWAY_AUTH_TOKEN check is what protects everything past /healthz — Funnel only gets you a public HTTPS URL, it does not add auth of its own.

Docker deployment

An alternative to the bare-metal setup above: docker-compose.yml runs four services — netns (a trivial, inert container that exists only to own a stable network namespace, see the comment at the top of the compose file for why it's not just tailscale), tailscale (the Funnel sidecar, the only public ingress — see deploy/tailscale/README.md for how the ingress wiring works), anytype-headless (the official anyproto/anytype-cli image), and mcp-gateway (built from Dockerfile). All four share netns's network namespace and talk to each other over 127.0.0.1, same as the bare-metal setup — no bridge-network container-DNS lookups involved (this is deliberate, not incidental — see the compose file's comment).

docker-compose.yml uses ${TS_AUTHKEY}/${TS_HOSTNAME} substitution, which Compose only reads from a file literally named .env by default — pass --env-file .env.docker explicitly on every docker compose invocation below (or alias dc='docker compose --env-file .env.docker'), otherwise those variables resolve empty.

cp .env.docker.example .env.docker
# edit .env.docker: GATEWAY_AUTH_TOKEN, TS_AUTHKEY (Tailscale admin console → Settings → Keys) —
# same HTTPS-certs/Funnel prerequisites as the bare-metal section above apply to this node too.

docker compose --env-file .env.docker up -d anytype-headless
# one-time: create the bot account and an API key for this gateway (see "Data isolation" below
# for why this is a separate bot account, not your personal Anytype account). Note: anytype-cli's
# REST API (port 31012) only starts listening once a bot account is logged in -- so this step
# isn't just bookkeeping, mcp-gateway genuinely can't reach it before this runs.
docker compose exec anytype-headless anytype auth create anytype-mcp-gateway-bot
docker compose exec anytype-headless anytype auth apikey create "mcp-gateway"
# copy the printed key into .env.docker as ANYTYPE_API_KEY

docker compose --env-file .env.docker up -d --build
docker compose logs -f mcp-gateway   # confirm "gateway listening"
curl -i https://<device>.<tailnet>.ts.net/healthz

No port is published to the host — tailscale is the only ingress, reaching the rest of the stack over the namespace they all share.

This whole flow (bot account creation, API key generation, gateway startup, an authenticated initialize call reaching the real Anytype API through the containerized gateway) was verified end-to-end against a disposable test bot account while writing this — including deliberately restarting the tailscale container mid-run to confirm it doesn't strand the other services.

Bare-metal supervision (no Docker)

For an always-on non-Docker host (Mac mini, Raspberry Pi, VPS), the gateway itself has no built-in restart-on-crash logic (Phases 0-2 intentionally fail loud and exit — see src/mcpProxyServer.ts), so it needs a process supervisor. A sample systemd unit is at deploy/systemd/anytype-mcp-gateway.service.example — copy it to /etc/systemd/system/, edit the User/WorkingDirectory paths, then systemctl enable --now anytype-mcp-gateway. It only supervises the gateway process; anytype serve needs its own supervision (anytype service install && anytype service start, see anytype-cli).

Registering as a connector in Claude

Once the gateway is reachable at its public Funnel URL (see above), point Claude at it as a custom connector. Before touching Claude's UI, run the pre-flight check:

npm run verify:remote -- https://<device>.<tailnet>.ts.net

This exercises the exact path Claude will use — HTTPS, Funnel, rate limiting, the full OAuth shim (discovery → dynamic client registration → consent → PKCE token exchange → a real MCP call authenticated with the OAuth-issued token, not the static one), the MCP initialize/tools/list handshake, a read call (list spaces), and a full create-then-delete round trip on a clearly-tagged test object ([gateway-verify] <timestamp>) in the bot's own space — and prints a pass/fail line per step. Fix anything it reports before wiring the connector into Claude; a broken gateway is much easier to debug from this script's output than from Claude's connector UI.

Claude web (claude.ai): Settings → Connectors → Add custom connector. Enter:

  • Name: anything (e.g. Anytype Gateway)

  • URL: https://<device>.<tailnet>.ts.net/mcp

Leave the "Advanced settings" OAuth Client ID/Secret fields empty and click Add. On most accounts this is currently the only auth option claude.ai's custom-connector dialog exposes — there's a separate, beta-gated "Request headers" section for a static Authorization: Bearer <token> header, but it's not rolled out to every account yet. That's exactly why this gateway also speaks OAuth (see src/oauth.ts): when Claude tries to connect with just the URL, it discovers the gateway's own /authorize and /token endpoints automatically and walks you through a one-time consent page, hosted by the gateway itself, asking for GATEWAY_AUTH_TOKEN — that's the actual credential check; OAuth here is just the transport claude.ai understands, not a second, separate secret to manage. Claude then holds an OAuth access/refresh token pair and silently refreshes it going forward, no repeat prompts.

If your account does have the "Request headers" beta, you can use that instead: header name authorization, value Bearer <GATEWAY_AUTH_TOKEN> — functionally equivalent, skips the consent-page step. Either path is accepted by the gateway; src/auth.ts's bearerAuth checks the static token first, then falls back to validating an OAuth-issued token.

claude.ai's exact field labels/beta availability can change over time — if what you see in the UI doesn't match this description, follow what's actually on screen.

Claude mobile: connectors are tied to your claude.ai account, so a connector added on web should also be usable from the mobile app — but whether mobile currently lets you add a custom connector directly (vs. only use ones added on web) is worth checking directly in the app, since this is exactly the kind of detail that changes between app versions. Don't take this README's word for it — verify in-app.

First real test, once connected: ask Claude to list your Anytype spaces, then to create a small test note. This exercises the same read/write path verify:remote already proved automatically, but through Claude itself end-to-end.

Scope note: the bot account currently only has access to its own empty space (see "Data isolation" above) — Claude won't be able to see or touch your real Anytype notes until you deliberately invite the bot into a real space. That's intentionally a separate, manual step, not something this gateway or its tooling does on its own.

Recommended follow-up — lock down the redirect host: by default /register accepts any redirect_uri host (see "Security notes"). After connecting once, check the gateway logs for a line like oauth: registered dynamic client ... hosts: [...] — that's the real host Claude just registered. Set OAUTH_ALLOWED_REDIRECT_HOSTS to that value in .env/.env.docker and restart; you'll see one more consent prompt afterward (expected — the restart clears the previous registration), and from then on /register rejects anything else outright.

Environment variables

Variable

Purpose

GATEWAY_PORT

Port the public Express app listens on (default 8787)

GATEWAY_HOST

Host/interface the public app binds to (default 127.0.0.1 — loopback is all Tailscale Funnel needs, bare metal or via the docker-compose sidecar's shared netns)

GATEWAY_AUTH_TOKEN

Bearer token required on every request except /healthz. Generate with openssl rand -hex 32.

RATE_LIMIT_WINDOW_MS

Rate-limit window in milliseconds, per IP (default 300000, 5 min)

RATE_LIMIT_MAX

Max requests per IP per window before a 429 (default 300)

MCP_INTERNAL_PORT

Port the internal mcp-proxy process listens on, loopback-only (default 8788)

ANYTYPE_API_BASE_URL

Local Anytype API base URL — http://127.0.0.1:31012 in both bare metal and Docker (all four docker-compose services share one network namespace, see "Docker deployment")

ANYTYPE_API_KEY

API key for the bot account, from anytype auth apikey create

ANYTYPE_API_VERSION

Anytype-Version header value expected by the installed @anyproto/anytype-mcp

ANYTYPE_TEST_SPACE_ID

Not read by the gateway — only by verify-remote.mjs, to pin its write+cleanup test to the bot's disposable sandbox space. See "Data isolation".

LOG_LEVEL

pino log level (default info)

OAUTH_REFRESH_TOKEN_TTL_HOURS

How long an OAuth refresh token stays usable (default 168 = 7 days). Always on — see "Security notes".

GATEWAY_RESTART_INTERVAL_HOURS

Optional scheduled self-restart, 0 disables (default). See "Security notes" — only enable with a verified process supervisor in place.

OAUTH_ALLOWED_REDIRECT_HOSTS

Comma-separated hostnames /register may accept, e.g. claude.ai,claude.com. Unset (default) accepts any host. See "Security notes".

Docker-only, set in .env.docker (see .env.docker.example):

Variable

Purpose

TS_AUTHKEY

Tailscale pre-auth key for the tailscale sidecar service (admin console → Settings → Keys)

TS_HOSTNAME

This node's name on the tailnet, and thus part of its public Funnel URL (default anytype-mcp-gateway)

Data isolation (why this doesn't touch your real Anytype notes by default)

anytype-cli's auth create command creates a brand-new bot account, with its own identity, entirely separate from any personal Anytype Desktop account and its cloud-synced data. A fresh bot account starts with a single empty space (0 objects) and has no access to any other space unless explicitly invited as a collaborator — which nothing in this project does automatically. This was verified empirically against a real bot account during setup (GET /v1/spaces → one space, GET /v1/spaces/{id}/objects → 0 objects).

anytype-cli has no concept of "log in as your personal account"auth create/auth login only create/authenticate bot identities; there's no command that imports a personal recovery phrase. This is unlike the official local MCP server, which runs on top of an already-logged-in Anytype Desktop app and so uses your real identity directly — that model doesn't translate to a headless, remotely-reachable deployment. The only supported way to have this gateway operate on your real notes is to explicitly invite the bot account into a real space, the same way you'd invite any other collaborator:

  1. In Anytype Desktop, open the real space → Settings → Members → Invite, and generate an invite link (Writer role recommended — no reason to grant the bot Owner).

  2. docker compose --env-file .env.docker exec anytype-headless anytype space join "<invite-link>" (bare metal: drop the docker compose ... exec anytype-headless prefix).

The bot account keeps its own auto-created sandbox space either way — joining a real space just adds a second one. Once the bot is a member of more than one space, scripts/verify-remote.mjs's destructive write+cleanup test will no longer guess which space is safe to write test objects into — it requires ANYTYPE_TEST_SPACE_ID (see the environment variables table) pinned to the sandbox space's id, and otherwise skips that check rather than risk running it against a real space. Capture that id with anytype space list right after auth create, before doing any of the above.

Security notes

  • GATEWAY_AUTH_TOKEN and ANYTYPE_API_KEY are read from .env/.env.docker (both gitignored) and are never logged — see the redaction list in src/logger.ts.

  • The internal mcp-proxy server has no authentication of its own; its only protection is that it's bound to 127.0.0.1. Don't change MCP_INTERNAL_PORT's bind address.

  • No compression/buffering middleware sits in front of /mcp or /sse — it would break streaming responses.

  • GATEWAY_HOST defaults to 127.0.0.1: nothing should ever need it on a public interface — Tailscale Funnel (bare metal) or the sidecar's shared network namespace (Docker) both reach the gateway over loopback. GATEWAY_AUTH_TOKEN is the only thing standing between the internet and this gateway once Funnel is on, so treat it like a credential (rotate it if it ever leaks, don't paste it into logs/issues).

  • Per-IP rate limiting (RATE_LIMIT_WINDOW_MS/RATE_LIMIT_MAX, default 300 req/5 min) runs before the bearer-token check, so it also throttles brute-force attempts against the token itself; throttled requests are logged at warn with the client IP.

  • Before relying on this for real, ongoing use: re-check Anytype's terms of service / acceptable-use policy for always-on programmatic API access — not something this repo can verify on your behalf.

  • The OAuth shim (src/oauth.ts) is single-user by design, not a general-purpose authorization server. There's exactly one credential behind it — GATEWAY_AUTH_TOKEN, required once as the consent-page secret — and no user database or per-client scoping. Registered clients, issued authorization codes, and access/refresh tokens all live in memory and are lost on restart; Claude just silently redoes the flow (and prompts you for the token again) the next time it needs to. Anyone who can reach the /authorize consent page still can't get in without the token, so the security boundary is unchanged from the plain-bearer-token design — OAuth here is a transport Claude's UI understands, not an additional party being granted access. /authorize and /token sit behind the same per-IP rate limiter as everything else, throttling brute-force attempts against the consent form the same way it already throttled the bearer-token check.

  • POST /register (dynamic client registration) is unauthenticated by spec — RFC 7591 requires it to be callable before a client has any credentials — but registering a client grants no access. It only stores a client_id and a list of redirect_uris; getting anywhere past that still requires GATEWAY_AUTH_TOKEN at the /authorize step. Two distinct things an unauthenticated caller can do here, both mitigated:

    • Memory growth: registering many clients costs the gateway a little memory each time. Capped (MAX_REGISTERED_CLIENTS, 100) and TTL'd (CLIENT_TTL_MS, 30 days) in src/oauth.ts — hitting either just makes Claude transparently re-register, no user-visible prompt.

    • Consent-hijacking via an attacker-chosen redirect_uri: nothing about RFC 7591 requires redirect_uris to point anywhere legitimate. Without a check, someone who can reach this gateway (the Funnel URL isn't public, but isn't a secret either) could register a client with their own server as the redirect_uri, then send you a crafted /authorize link. The consent page is real (correct domain, valid TLS), so if you didn't notice the destination and typed GATEWAY_AUTH_TOKEN anyway, the resulting authorization code — and the access token it becomes — would go to them, not Claude. Two mitigations, both in src/oauth.ts: the consent page always shows the exact redirect_uri (and client_id) before asking for the token, so there's a chance to notice something's wrong; and OAUTH_ALLOWED_REDIRECT_HOSTS (unset/permissive by default — see .env.example for how to determine and set it) makes /register reject any host that isn't explicitly allowed, closing the door before a malicious client can even be registered. Worth noting: the blast radius of a successful hijack is whatever spaces the bot account is a member of at the time — its own isolated sandbox space only by default, but real Anytype data too once you've invited it into a real space (see "Data isolation"). That's a reason to take OAUTH_ALLOWED_REDIRECT_HOSTS more seriously after doing so, not a reason not to invite it.

  • OAuth session lifetime is bounded two ways, deliberately redundant (defense in depth):

    1. Always on: OAUTH_REFRESH_TOKEN_TTL_HOURS (default 168 = 7 days) caps how long a refresh token is honored at all — rotating GATEWAY_AUTH_TOKEN does not revoke an already-issued refresh token (it's an independent secret with no link back to the master token's current value), so this TTL is what actually bounds a leaked token's exposure window by default, with zero configuration required.

    2. Optional, off by default: GATEWAY_RESTART_INTERVAL_HOURS — the gateway exits cleanly on a timer and relies on the process supervisor (Restart=always in the systemd unit, restart: unless-stopped already in docker-compose.yml) to bring it back up, wiping all OAuth state at once (not just expired tokens — also clears the client registry above). This is a coarser, additional layer on top of (1), not a replacement for it: it costs a brief availability gap on every restart, and only works if a supervisor is actually restarting the process — with none configured, turning this on quietly converts a security feature into an outage that never recovers. Verify that before enabling it. Trade-off either way: Claude has to redo the consent step (re-enter GATEWAY_AUTH_TOKEN) whenever a session ends, whether by TTL or by restart.

Current limitations / what's not done yet

See ROADMAP.md: the connector still needs to be added inside your own Claude account (see "Registering as a connector in Claude" above — this repo can verify and document the path but can't click the button for you), the bot account hasn't been invited into a real Anytype space, and there's no token rotation procedure or uptime monitoring/alerting yet.

Troubleshooting

  • anytype-cli not runninganytype-mcp fails fast with Can't connect to API. Please ensure Anytype is running and reachable. Start anytype serve first and confirm curl/Node request to 127.0.0.1:31012/v1/spaces returns 200 before starting the gateway.

  • Wrong Anytype-Version header — check the installed @anyproto/anytype-mcp version's expected value; a mismatch can cause API calls to fail even though the connection succeeds.

  • npx cache issues (bare metal)npx -y @anyproto/anytype-mcp fetches from the npm registry on first run; if it hangs, check network access or pre-warm the npx cache with a manual npx -y @anyproto/anytype-mcp run (Ctrl-C once it prints "running on stdio"). The Docker image avoids this entirely by installing @anyproto/anytype-mcp globally at build time (see Dockerfile).

  • docker compose exec anytype-headless anytype auth create ... hangs or fails — confirm the anytype-headless container is healthy first (docker compose ps); it needs a few seconds after docker compose up -d to start listening.

  • Funnel URL doesn't resolve / connection refused — confirm HTTPS certs and the Funnel node attribute are enabled for this node in the Tailscale admin console (see "Public exposure" above); tailscale funnel status (bare metal) or docker compose exec tailscale tailscale funnel status (Docker) shows the current mapping.

F
license - not found
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    -
    quality
    D
    maintenance
    Exposes local OpenCode instances as remote MCP servers for Claude and ChatGPT, enabling terminal access, session management, and interactive human-in-the-loop workflows. It simplifies deployment for local machines using Cloudflare Tunnels to provide secure public connectivity and OAuth support.
  • A
    license
    -
    quality
    A
    maintenance
    Lifts local stdio MCP servers into remote Streamable HTTP endpoints for cloud-hosted AI clients, with bearer-token auth and tool policy filtering.
    4
    MIT

View all related MCP servers

Related MCP Connectors

  • Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer

  • Multi-tenant Telegram gateway for AI agents — HTTP+stdio, 8 tools, MTProto User API

  • MCP server bridging holepunchto/keet-identity-key to the Hive agentic identity network

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ivantacca/anytype-mcp-remote-gateway'

If you have feedback or need assistance with the MCP directory API, please join our Discord server