Muriel AI

Every published drinking water result, AI native.

Our agent or yours. Connect Muriel to Claude, ChatGPT, Cursor or any AI assistant as an MCP connector, build it into your software with the API, or pull the record for your own analysis: millions of results from dozens of states, back to the 1970s, updated as states publish.

Not a developer? Try the Muriel agent, no code needed.

Use Muriel in your AI harness

Add Muriel to the AI tools you already use.

Two steps to bring near real-time water quality results, trends, and compliance intelligence into Claude, Cursor, VS Code, ChatGPT, or any assistant that supports remote MCP servers.

The quickest way: paste it into your AI coding assistant and it sets up the Muriel connector for you. You just sign in and click Allow. Or follow the two steps below.
Preview the prompt
Set up the Muriel drinking water MCP server for me, in the AI tool you are running in.

Server details:
- Name: muriel
- URL: https://mcp.murielai.io/mcp
- Transport: remote MCP over Streamable HTTP
- Sign-in: OAuth. I will sign in with my Muriel account in a browser window and click Allow. There is no API key, so do not ask me for one or write one into any file.

1. Work out which tool you are and add the server the way it expects:
   - Claude Code: run `claude mcp add --transport http --scope user muriel https://mcp.murielai.io/mcp`, so it is available in every project. Then, inside Claude Code, run /mcp, pick muriel and choose Authenticate.
   - Cursor: add "muriel": {"url": "https://mcp.murielai.io/mcp"} under "mcpServers" in ~/.cursor/mcp.json.
   - VS Code (GitHub Copilot agent mode): add "muriel": {"type": "http", "url": "https://mcp.murielai.io/mcp"} under "servers" in .vscode/mcp.json.
   - Any other tool: follow its documentation for adding a remote (Streamable HTTP) MCP server with OAuth. If it can only run local (stdio) servers, use the command `npx -y mcp-remote https://mcp.murielai.io/mcp`.
   - If you cannot edit your own configuration (for example the Claude app or claude.ai), do not try. Tell me to open Settings, then Connectors, choose Add custom connector, name it Muriel and paste the URL.

2. When you edit a config file, merge with what is already there. Keep the existing JSON valid and do not change or remove any other MCP servers.

3. Tell me exactly what is left for me to do. Usually that is reloading or restarting the tool, then signing in to Muriel in the browser window that opens and clicking Allow.

4. Once it is connected, check it works: ask Muriel what data it has for Illinois (it should use the data_coverage tool) and show me a short summary of the answer. If the connection fails, show me the exact error and what you tried.
1

Add the connector

Add one URL to your assistant, then sign in to your Muriel account and click Allow. No API key to copy.

# Settings → Connectors → Add custom connector
Name   Muriel
URL    https://mcp.murielai.io/mcp
2

Ask in your assistant

It calls Muriel when a question needs drinking water data, and answers from what Muriel returns.

Tool call

get_notable_events({
  "pwsid": "IL0316000",
  "since": "2026-09-29"
})

Muriel returns (trimmed)

{
  "rows": [{
    "event_type":
      "result.prior_comparison",1
    "severity": "watch",
    "system_name": "CHICAGO",
    "pwsid": "IL0316000",2
    "summary": "NITRATE at ENTRY
      POINT 01 for IL0316000:
      0.31 → 0.42 mg/L (+35.5%)",3
    "federal_limit_mgl": 10.0,
    "exceeds_federal_limit": false,
    "collection_date": "2026-09-24"
  }],
  "returned": 14
}

Numbers match each field Muriel returns to where it appears in the answer. Example only: the response is the real shape, but the event and its figures are illustrative. Everything else you need is in the MCP server reference below.

Build it in

One call puts Muriel in your software.

Two steps to instant integrations of real-time water quality results, trends, and compliance intelligence. Create an API key on your account page first. For Python, pip install muriel (PyPI); for JavaScript and TypeScript, npm install @muriel-ai/sdk (npm).

1

Send a request

Ask for a water system’s results by its ID, from any application. Filter by contaminant, date and detections.

# pip install muriel
import muriel  # reads MURIEL_API_KEY from the environment

results = muriel.get_results(
    pwsid="IL0316000",
    analyte="Lead",
    limit=12,
)
2

Show the results in your software, or use them for analysis

Muriel returns structured results, ready to display.

Response (trimmed)

{
  "pwsid": "IL0316000",
  "system_name": "CHICAGO",1
  "record_count": 12,2
  "records": [{
    "result_analyte_name": "LEAD",
    "concentration_value": 2.1,
    "concentration_units": "UG/L",3
    "sample_collection_date":
      "2026-09-24",4
    "result_non_detect": false
  }, …]
}

Numbers match each field in the response to where it appears in the app. Example only: the response is the real shape of /api/v1/records/system/{pwsid}, but the figures are illustrative.

Try it Paste it into any AI coding assistant to get a working Python script for the Muriel API.
Preview the prompt
I want to connect a Python application to the Muriel drinking water quality API.

1. Read the API documentation at https://api.murielai.io/docs and the OpenAPI spec at https://api.murielai.io/openapi.json. Use only the endpoints, parameters and response fields that appear there. If something I ask for below is not in the docs, say so rather than guessing.

2. Write one Python 3 script, muriel_client.py, that:
   - reads the API key from the MURIEL_API_KEY environment variable and sends it in the X-API-Key header (never hard-code the key);
   - has a function get_system_results(pwsid, analyte=None, limit=100, detections_only=False) that calls GET /api/v1/records/system/{pwsid}, passing analyte as result_analyte_name;
   - as a working example, fetches the 12 most recent lead results for Chicago (PWSID IL0316000) and prints one line per record: sample date, analyte, concentration value and units, or "not detected";
   - handles failures with clear messages: missing key, 401 (invalid key), 404 (no records for that PWSID), 429 (rate limited), timeouts, and 5xx errors;
   - uses only the standard library and the requests package.

3. Keep it short and readable, with a comment at the top explaining how to set MURIEL_API_KEY and run the script. When you are done, tell me the exact commands to install requests and run it.

For research and analysis

The whole record, in one shape, ready for your own analysis.

Every state’s results in the same units and terms, so a comparison across states or decades starts with the question rather than the cleanup.

History back to the 1970s

Decades of results for most states, alongside the current feed, in one dataset.

Exactly the rows you need

Use since to pull only what is new, and schema to get the columns your notebook expects.

CSV when you want it

Ask the agent for any table and export it as a CSV, no code required.

Limits stated, not hidden

Muriel says where each state’s data stops, so a gap is never mistaken for a clean record.

MCP server reference

Everything about the Muriel connector, in one place.

For people adding Muriel to an assistant, and for developers building an MCP client that talks to it.

At a glance

Connector URLhttps://mcp.murielai.io/mcp
TransportStreamable HTTP (MCP specification 2025-03-26 or later). Stateless, JSON responses.
Sign-inYour Muriel account, through OAuth 2.1. The assistant registers itself; there is no key to copy.
AccessRead only: 16 tools over published sample results, events, trends and the federal rules.
CostYour Muriel credits, on the same price list as the app and the API: 1 credit per 1,000 records returned, added up across calls. A call that returns nothing is free.
Limits30 tool calls a minute and 2,000 a day per account.
DisconnectAccount page → Connected apps → Disconnect. Takes effect within a minute.

Set up

You need a Muriel account. If you don’t have one, the sign-in screen creates it with an emailed link.

Claude (claude.ai and the Claude desktop app)

  1. Open Settings → Connectors and choose Add custom connector.
  2. Name it Muriel and paste https://mcp.murielai.io/mcp as the URL.
  3. Click Connect. A Muriel page opens: sign in, then click Allow.
  4. In a chat, make sure Muriel is turned on in the tools menu, then ask a question.

On Team and Enterprise plans an owner may need to add the connector for the organization first.

Claude Code

  1. Run claude mcp add --transport http muriel https://mcp.murielai.io/mcp. Add --scope user to use it in every project.
  2. Inside Claude Code, type /mcp, choose muriel, then Authenticate. Your browser opens to sign in and allow.

Cursor

  1. Add Muriel to ~/.cursor/mcp.json (all projects) or .cursor/mcp.json (one project): {"mcpServers": {"muriel": {"url": "https://mcp.murielai.io/mcp"}}}
  2. Open Settings → MCP, find Muriel, and click to sign in.

VS Code (GitHub Copilot agent mode)

  1. Add to .vscode/mcp.json: {"servers": {"muriel": {"type": "http", "url": "https://mcp.murielai.io/mcp"}}}, or run MCP: Add Server from the command palette and choose HTTP.
  2. Start the server when prompted and sign in in the browser window that opens.

ChatGPT

Where your plan allows custom connectors (developer mode), create a connector with the URL above and OAuth authentication, then sign in when ChatGPT asks. Availability varies by plan and workspace settings.

Other assistants

Any MCP client that supports remote servers and OAuth works with the URL alone. For one that only runs local (stdio) servers, use npx -y mcp-remote https://mcp.murielai.io/mcp as the command; it handles sign-in in your browser.

Test it without an assistant

Run npx @modelcontextprotocol/inspector, choose Streamable HTTP, enter the URL and connect. You can sign in, list the tools and call each one by hand.

Sign-in and permissions

The first time your assistant uses Muriel, it opens a Muriel page. If you are signed out you sign in first (Google, an emailed link or a password), then see what the assistant is asking for and click Allow or Cancel.

It can

  • Look up published sample results, trends and notable events
  • Find water systems and check results against federal standards
  • Search the federal drinking water rules
  • Use your credits for the data it looks up (1 per 1,000 records)

It can’t

  • See your Muriel conversations or documents
  • Change your account or buy anything
  • Act as anyone but you, or work after you disconnect it

Each assistant gets its own connection, and you can disconnect any of them from Connected apps on your account page. A free trial session can’t approve a connection; sign in with a real account first.

Tools

All tools are read-only and take JSON arguments. Your assistant chooses them for you; the parameters are listed for anyone writing prompts or a client. pwsid is a water system’s federal ID (for example IL0316000); state is a two-letter code; dates are ISO (2026-09-01).

ToolUse it forParameters
Find and check coverage
find_water_systemTurning a utility name into a PWSID, with how many results it has.query*, state, limit
data_coverageWhat data exists for a state or system: row counts, analytes, date range.state, pwsid
historical_depthHow far back the archive goes, before asking a long-range question.state, pwsid
Results
get_sample_resultsIndividual results with value, unit, non-detect flag and normalized mg/L.pwsid, contaminant, state, start, end, only_detections, limit
summarize_sample_resultsPer-contaminant counts, date range and min/max/mean for a system or state.pwsid, state, contaminant, limit
rank_systems_by_sizeA state-wide question with no system named: one row per system, largest first.state, contaminant, only_exceeding, start, end, limit
deep_history_searchResults from the full archive, decades back, beyond the current window.pwsid, state, analyte, since, until, limit
What changed
get_notable_eventsRecent changes worth a look: moves from a previous result, unusually high values, sample-point changes. Severity info, watch or high.pwsid, state, since, min_severity, event_type, limit
get_record_changesResults that appeared, disappeared or were amended between updates.pwsid, state, since, kind, limit
analyte_trendWhether a contaminant is rising or falling at a system’s sampling points, or across a state.contaminant, pwsid, state, min_span_days
Compliance math
check_compliance_from_dataThe correct statistic from real results: running annual average, locational RAA, 90th percentile.pwsid*, contaminant*, start, end
check_monitoring_gapsCandidate missed samples against the monitoring schedule the state publishes.pwsid, state, analyte, only_assessable, limit
Rules and standards
lookup_standardThe federal MCL or action level, MCLG, units, averaging basis and CFR citation.contaminant or category
evaluate_resultA measured value against the federal standard, with unit conversion.contaminant*, value*, unit
resolve_analyteHow a lab’s analyte name maps to a regulated contaminant.analyte_name*
search_regulationsPassages from the federal rules: monitoring, lead and copper, DBPs, PFAS, public notice.query*, top_k

* required. The full JSON schema for each tool comes back from tools/list.

Example questions

Getting good answers

Limits

For client developers

Muriel follows the MCP authorization specification. A compliant client needs nothing but the connector URL.

MCP endpointPOST https://mcp.murielai.io/mcp — stateless; each request stands alone, responses are application/json
Protected resource metadatahttps://mcp.murielai.io/.well-known/oauth-protected-resource/mcp (RFC 9728)
Authorization serverhttps://murielai.io — metadata at /.well-known/oauth-authorization-server (RFC 8414)
RegistrationDynamic client registration, POST /oauth/register (RFC 7591). token_endpoint_auth_method: none, client_secret_post or client_secret_basic
Redirect URIsHTTPS; http://localhost or 127.0.0.1 on any port (RFC 8252); or a private-use scheme such as cursor://. Matched exactly.
GrantAuthorization code with PKCE, S256 only. The authorization response carries iss (RFC 9207).
Scopemuriel.read
ResourceSend resource=https://mcp.murielai.io/mcp (RFC 8707). Tokens work only at the MCP server.
TokensBearer access token, one hour. Refresh token, 60 days, rotated on every use; reusing a spent one revokes the connection.
RevocationPOST /oauth/revoke (RFC 7009)
CORSAllowed from any origin on the MCP endpoint and on the token, registration and metadata endpoints, for browser-based clients.

The flow: POST /mcp without a token returns 401 with WWW-Authenticate: Bearer resource_metadata="…". The client reads that metadata, finds murielai.io, registers, sends the person to /oauth/authorize, exchanges the code at /oauth/token, and retries with Authorization: Bearer. A 401 later means the token expired or the person disconnected; refresh, or start sign-in again.

Agent-to-agent (A2A)

Muriel publishes an A2A 1.0 Agent Card at /.well-known/agent-card.json and answers JSON-RPC at POST https://murielai.io/a2a. Each skill on the card is one of the tools above, with the same sign-in, limits and cost (none). Send one skill call per message as a data part, and the reply comes back at once as a message:

{"jsonrpc": "2.0", "id": 1, "method": "SendMessage",
 "params": {"message": {"messageId": "m1", "role": "ROLE_USER",
   "parts": [{"data": {"skill": "get_notable_events",
                       "arguments": {"state": "CA", "min_severity": "high"}},
              "mediaType": "application/json"}]}}}

Send the bearer token in Authorization. A2A 0.3 clients (message/send) work too. Muriel keeps no long-running tasks, and doesn’t stream or send push notifications.

Headless agents: sign up by email (auth.md)

An agent with no browser to open can register for a person by email instead. It posts the person’s address to /agent/auth. Muriel emails them a link and a short code, and the agent polls /oauth/token with the device-code grant until they sign in and click Allow. It then gets the same read-only tokens. Every request and response is in auth.md. Anonymous registration is not supported.

Troubleshooting

The sign-in page says the app “can’t connect to Muriel”.
The assistant sent a return address it didn’t register, or its registration is stale. Remove the connector and add it again.
I signed in but went back to the assistant without approving.
Start the connection again from the assistant. You’ll go straight to the Allow screen, since you’re already signed in.
It worked yesterday and now says my sign-in expired.
The connection was disconnected (perhaps from another device), or the assistant lost its refresh token. Reconnect from the assistant’s connector settings.
Claude Code shows Muriel as “needs authentication”.
Run /mcp, choose muriel, then Authenticate.
The assistant says Muriel found nothing.
Check that the state publishes the data you asked about (ask “what data does Muriel have for Ohio?”), and try the system’s PWSID instead of its name.
“Rate limit reached” or “Muriel is busy”.
Wait a minute and ask again. If you need more than the daily limit, tell us.
My company network blocks it.
The assistant needs to reach mcp.murielai.io and your browser needs murielai.io, both over HTTPS. Ask IT to allow both.

Still stuck? Write to us with the assistant you’re using and what it said.