Skip to main content
Glama
cexplayer01

dfwmetro-mcp

by cexplayer01
README.md
# dfwmetro-mcp

A local [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server for
**[dfwmetro.net](https://dfwmetro.net)** — the Dallas–Fort Worth directory of
genuinely online-bookable service businesses.

Give your AI agent three tools:

| Tool | What it does |
| --- | --- |
| `find_listings` | Search the directory. Every listing is labeled with its verification status; verified businesses rank first with full machine-readable booking data. |
| `find_verified_listings` | Strict search: VERIFIED businesses only — license, registration, and insurance checked by the dfwmetro verification desk. |
| `submit_listing` | Submit a DFW business to the directory. It **must** be genuinely online-bookable (a real date/time scheduling flow — not a quote form, not phone-only). Accepted submissions start as `NOT_YET_VERIFIED` and pass human review. |

## Why this exists

dfwmetro.net hosts the same tools as a stateless HTTP MCP endpoint at
`https://dfwmetro.net/mcp`. Many MCP clients, though, launch a **local process
over stdio**. This server bridges the two: it speaks stdio to your client and
forwards every call to the public endpoint, so tool definitions and validation
rules are always the live ones. No API key, no database, no secrets — it only
ever talks to dfwmetro.net's public machine API.

Requires **Node.js 18+**. Zero dependencies.

## Quick start

```bash
node server.mjs
```

It reads JSON-RPC on stdin and writes responses on stdout — your MCP client
launches it; you don't run it by hand.

### Claude Desktop

Add to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "dfwmetro": {
      "command": "node",
      "args": ["/path/to/dfwmetro-mcp/server.mjs"]
    }
  }
}
```

### Any other MCP client

Point the client at `node /path/to/dfwmetro-mcp/server.mjs` as a stdio server.

### Prefer the hosted endpoint?

If your client supports remote/HTTP MCP servers, skip this package entirely
and connect straight to:

```
https://dfwmetro.net/mcp
```

Other machine surfaces on dfwmetro.net: `GET /api/bridge/discover` for
discovery JSON, `/llms.txt` for the agent guide, and
`/.well-known/dfwmetro-agent.json` for the agent registry entry.

## Configuration

| Env var | Default | Meaning |
| --- | --- | --- |
| `DFWMETRO_MCP_URL` | `https://dfwmetro.net/mcp` | Override the remote endpoint (testing only). |

## The listing rule

The directory lists only businesses a customer can actually book online:
a real scheduling flow with date/time selection. Quote forms, contact forms,
phone-only businesses, lead aggregators, and login-gated booking do not
qualify and will not survive verification. If you're an agent submitting on
behalf of a business, find its real street address first (website footer,
contact page, or its JSON-LD LocalBusiness block) — it drives the map pin.

## License

MIT — see [LICENSE](LICENSE). The directory data itself is served by
dfwmetro.net under the terms in its `/llms.txt`.

TDQS

A3.9/5.0

Scored across 3 tools

Disambiguation3/5

submit_listing is clearly distinct from the two search tools, but find_verified_listings is fully subsumed by find_listings (the description itself says it's kept only for backward compatibility and recommends find_listings with verified_only:true). The descriptions do explicitly call out the relationship, which mitigates but does not eliminate misselection risk between the two finders.

Naming Consistency5/5

All three tools follow a clean verb_noun snake_case pattern: submit_listing, find_verified_listings, find_listings. The find_ prefix is applied predictably and no conventions are mixed.

Tool Count3/5

Three tools is thin for a directory service, and effectively only two distinct capabilities exist since find_verified_listings duplicates a mode of find_listings. The scope is narrow enough that it is defensible, but it sits at the borderline of under-provisioned.

Completeness3/5

Submit plus search covers the core loop, but there is no way to retrieve a single listing by id, no explicit status-check for a submission the caller just made, and no update/correct path despite submissions starting as NOT_YET_VERIFIED. Agents can partially work around this by filtering find_listings, but there are notable dead ends.

Maintenance

ActivityMaintained
ResponsivenessNo issues