BMLT Meetings

io.github.bmlt-enabledPublished by GitHub account bmlt-enabledv0.3.0Updated Oct 24, 2026

Search Narcotics Anonymous meetings worldwide via the BMLT directory.

VerifiedStreamable HTTPWeb executableLocation & LifestyleWeb Search & Scraping

Overview

AI-generated overview

Read-only MCP server for searching Narcotics Anonymous meetings worldwide through the BMLT meeting directory.

What you can do
  • Search meetings by address or coordinates with radius, weekday, time, format, venue type and service body filters
  • Fetch the full record of a single meeting by its BMLT id
  • List meeting formats and service bodies so names can be mapped to IDs used in searches
  • Inspect a root server's capabilities, version, languages and default coordinates
  • List public BMLT root servers known to the aggregator and query a chosen one
When to use it
Useful when an assistant should help someone find in-person, virtual or hybrid NA meetings by place, day or time, or look up details of a specific meeting. It suits directories, helpline-style assistants and local recovery resources.
Requirements
The public instance is a remote streamable HTTP endpoint needing no account or key. Self-hosting needs PHP 8.2+ or Docker, a required BMLT_ROOT_SERVER_URL setting, and optionally a geocoder (Nominatim by default, or a Google API key) plus an allowlist of permitted root servers.
Before you install
All tools are read-only. The public deployment has no authentication, so anyone reaching the endpoint can call the tools. Address searches are geocoded by a third party (Nominatim/OSM or Google). Self-hosted setups should keep the root allowlist and avoid allowing any root URL, which the README warns enables SSRF-style queries.

Installation

In SourceWeft

  1. Open BMLT Meetings in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.

Use with an agent

Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.

Read https://sourceweft.com/mcp/io.github.bmlt-enabled%2Fbmlt-server-mcp/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.

Read the install guide the agent follows

Other MCP clients

Add this to your client's mcpServers config.

{
  "mcpServers": {
    "bmlt-meetings": {
      "type": "http",
      "url": "https://mcp.bmlt.app/mcp"
    }
  }
}

README

bmlt-server-mcp

A streamable HTTP Model Context Protocol server that exposes BMLT (Basic Meeting List Toolbox — the Narcotics Anonymous meeting directory) as a set of read-only tools that AI assistants can call directly.

BMLT hosts approximately 85% of Narcotics Anonymous meetings worldwide; the default backend is the BMLT aggregator, which federates every public BMLT root server (server list) into a single search surface — effectively the authoritative AI-accessible source for finding NA meetings.

MCP is an open protocol, so any compatible client works: Claude (Code, Desktop, web), ChatGPT (Connectors and the Responses API), Google Gemini, Cursor, Windsurf, Zed, Cline, Continue, and others.

Unlike the npm bmlt-mcp-server (stdio-only, runs as a local subprocess), this server speaks MCP over HTTP and is meant to be hosted once and consumed remotely.

Built on Laravel + PHP 8.2+ using the official laravel/mcp package.

A live deployment runs at https://mcp.bmlt.app/ (landing page) with a tools reference at https://mcp.bmlt.app/reference.


Tools

All tools are read-only and idempotent. All tools accept an optional root_server_url argument; if omitted, the configured BMLT_ROOT_SERVER_URL is used.

ToolWhat it does
search_meetingsSearch meetings by address (geocoded server-side) or lat/lng + radius, filtered by weekday, time, format, venue type (in-person / virtual / hybrid), service body, and free text. Returns a curated summary by default (data_format=full for the raw BMLT response).
get_meetingFetch a single meeting by its BMLT id_bigint.
list_formatsList meeting format codes (Open, Closed, Speaker, Beginners, language tags, …) so callers can map names → IDs for search_meetings.
list_service_bodiesList zones / regions / areas / groups so callers can map names → IDs for search_meetings.
get_server_infoCapabilities, version, languages, and default coordinates for the configured root server.
list_root_serversPublic BMLT root servers known to the aggregator. Useful when the caller wants to switch roots.

Quick start

Docker (recommended)

bash
cp .env.example .envdocker compose up --build

The MCP endpoint is then live at http://localhost:8080/mcp over the Streamable HTTP transport.

Local PHP

bash
composer installcp .env.example .envphp artisan key:generatephp artisan serve     # http://localhost:8000/mcp

Verify with the MCP Inspector

bash
php artisan mcp:inspector

Then connect to http://localhost:8000/mcp (or :8080 for Docker) and list tools.


Configuration

All configuration lives in .env (see .env.example). The interesting bits:

VariablePurpose
BMLT_ROOT_SERVER_URLRequired. Default BMLT root server, including /main_server path.
BMLT_ALLOWED_ROOTSComma-separated allowlist for the optional root_server_url tool argument. The default root is always implicitly allowed.
BMLT_ALLOW_ANY_ROOTtrue allows any URL via root_server_url — not recommended in production (enables SSRF-style queries). Off by default.
BMLT_AGGREGATOR_URLAggregator queried by list_root_servers. Defaults to the public aggregator.
GEOCODERnominatim (default), google, or null. null rejects address inputs and requires lat/lng.
NOMINATIM_USER_AGENTIdentifies your deployment to OSM — required by Nominatim's ToS. Always set this in production.
GOOGLE_GEOCODER_API_KEYRequired when GEOCODER=google.

Why an allowlist?

The optional root_server_url tool argument lets a single deployment serve any BMLT root, but accepting arbitrary URLs would let callers turn the server into an SSRF probe against your network. The default is a strict allowlist (the configured default root, plus anything you add to BMLT_ALLOWED_ROOTS). Set BMLT_ALLOW_ANY_ROOT=true only when the server is isolated from anything sensitive.


Connecting AI clients

The endpoint of a deployed instance is https://your-host.example.com/mcp. Replace it below with your own host (or use https://mcp.bmlt.app/mcp to try the public instance).

Claude Code (CLI)

bash
claude mcp add --transport http bmlt https://your-host.example.com/mcp

Claude Desktop — Custom Connector (newer builds)

Settings → Connectors → Add custom connector → paste the URL.

Claude Desktop — Config file (any version, needs Node.js)

jsonc
{  "mcpServers": {    "bmlt": {      "command": "npx",      "args": ["-y", "mcp-remote", "https://your-host.example.com/mcp"]    }  }}

ChatGPT / OpenAI Responses API

json
{  "tools": [    {      "type": "mcp",      "server_label": "bmlt",      "server_url": "https://your-host.example.com/mcp"    }  ]}

In ChatGPT itself (Pro/Business/Enterprise): Settings → Connectors → Add, using the same URL.

Cursor / Windsurf / Zed / Cline / Continue

All of these read an mcpServers block. For Cursor, edit ~/.cursor/mcp.json (or the project-local .cursor/mcp.json); other clients use a similar config file.

json
{  "mcpServers": {    "bmlt": {      "url": "https://your-host.example.com/mcp"    }  }}

For per-tool parameter documentation and BMLT-API mappings, see the live reference page. For day-to-day commands on a deployed instance (log tailing, usage summaries, cache clears, upgrades), see docs/operations.md.


Adding authentication

The default config has no auth — anyone who can reach /mcp can call the tools. To gate it:

php
// routes/ai.phpuse Laravel\Mcp\Facades\Mcp;
Mcp::oauthRoutes();                          // OAuth 2.1 (Laravel Passport)Mcp::web('/mcp', BmltServer::class)    ->middleware('auth:api');

Or add a simple bearer-token check via custom middleware. See the Laravel MCP docs for the full options.


Architecture

app/├── Mcp/│   ├── Servers/BmltServer.php           # Registers the 6 tools│   └── Tools/│       ├── SearchMeetingsTool.php│       ├── GetMeetingTool.php│       ├── ListFormatsTool.php│       ├── ListServiceBodiesTool.php│       ├── GetServerInfoTool.php│       ├── ListRootServersTool.php│       └── Concerns/ResolvesBmltClient.php├── Services/│   ├── Bmlt/│   │   ├── BmltClient.php               # Wraps client_interface/json│   │   ├── BmltClientFactory.php        # Allowlist enforcement│   │   └── BmltException.php│   └── Geocoding/│       ├── Geocoder.php                 # Interface│       ├── GeocoderManager.php          # Driver resolver│       ├── NominatimGeocoder.php        # OSM (rate-limited, cached)│       ├── GoogleGeocoder.php           # Google Geocoding API│       ├── NullGeocoder.php             # Disabled│       ├── GeocodingResult.php│       └── GeocodingException.php└── Providers/BmltServiceProvider.php
config/bmlt.php                          # All knobsroutes/ai.php                            # Mcp::web('/mcp', BmltServer::class)

The HTTP API wrapped by BmltClient is formally specified by the BMLT Semantic OpenAPI document (OpenAPI 3.1) — refer to it for every parameter, response shape, and field definition that BMLT itself supports, even if this MCP server doesn't yet expose it as a tool argument.


License

MIT

Source: README.md at commit 1eb54ce

Tools

6

search_meetings

Search Narcotics Anonymous meetings

Search Narcotics Anonymous meetings on a BMLT root server. Filter by location (address or lat/lng + radius), weekday, time of day, format, venue type (in-person / virtual / hybrid), and service body. Returns a trimmed summary by default; pass data_format='full' for the raw BMLT response.

Parameterspageaddresslanguagelatitudeweekdayslongitudepage_sizeradius_kmformat_idsdata_formatsearch_textvenue_types+6 more

get_meeting

Get a single meeting by ID

Fetch the full record for a single meeting by its BMLT id_bigint.

Parametersidrequiredroot_server_url

list_formats

List meeting formats

List available meeting formats (Open, Closed, Speaker, Beginners, language tags, etc.) so the caller can map human-friendly format names to BMLT format IDs.

Parameterslanguageformat_idskey_stringsinclude_unusedroot_server_url

list_service_bodies

List service bodies (regions / areas)

List BMLT service bodies (zones, regions, areas, groups). Useful for translating "Northern California Region" to a service body ID for use with search_meetings.

Parametersinclude_parentsroot_server_urlinclude_childrenservice_body_ids

get_server_info

Get BMLT root server info

Return capabilities, version, languages, and default coordinates for a BMLT root server.

Parametersroot_server_url

list_root_servers

List known BMLT root servers

List public BMLT root servers known to the BMLT aggregator. Use the returned root_server_url values with other tools to query a specific server.

Parametersname_contains

Version history

1
  1. v0.3.0LatestSep 16, 2026

Score

90% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 daysRequired25 pts
  • Auth declaredRequired10 pts
  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts

    Declare a license in the repository or the registry entry.