SimRelay MCP Server
OfficialClick on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@SimRelay MCP Serverlist all my SIMs"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
SimRelay MCP Server
An MCP server that lets AI agents work with SimRelay SIMs: list them, lock and release them, read message history, and stream incoming SMS in real time over WebSocket.
Built for Claude Desktop, Claude Code, Cursor, and any other MCP-compatible client.
Tools
Tool | What it does |
| Open a browser to sign in to SimRelay (run on first use) |
| Forget saved tokens |
| List every SIM the user can access (id, phone number, status, country, provider, lock state, …) |
| Acquire an exclusive lock on a SIM by |
| Release a lock — idempotent |
| Paginated SMS history for a SIM ( |
| Open a WebSocket subscription; new SMS are pushed to the MCP client as |
| Stop the WebSocket subscription |
See docs/tools.md for full input/output schemas and examples, and docs/realtime.md for how the real-time stream works.
Related MCP server: Retell AI MCP Server
Install
As a Claude Desktop extension (recommended)
Install the bundled .mcpb extension. The first time you ask the assistant to do anything with SimRelay, it will call simrelay_login, which opens your browser. Sign in once; tokens persist to ~/.config/simrelay-mcp/tokens.json (chmod 0600) and refresh automatically.
As an npm package (Claude Code / Cursor / generic MCP)
npm install -g simrelay-mcp-serverClaude Code:
claude mcp add simrelay -- simrelay-mcpGeneric MCP client: configure an stdio server with command simrelay-mcp. From inside any conversation, ask the assistant to "log in to SimRelay" — or run simrelay-mcp login in a terminal beforehand.
Configuration (advanced)
End users don't need to set anything — the OAuth client ID is baked into the build. The following env vars are available for development and self-hosted deployments:
Env var | Default | Notes |
| built-in | Override the bundled OAuth client (dev/staging only). |
|
| Point at staging or a self-hosted instance. |
|
| Space-separated scopes. |
|
| Override token storage path. |
See docs/configuration.md for the full reference.
Real-time messages
After calling subscribe_to_messages, each new SMS is delivered to the MCP client as an info-level logging notification with the structured payload:
{
"event": "sms.received",
"sim_id": 42,
"from": "+491701234567",
"text": "Your verification code is 123456",
"received_at": "2026-05-12T10:00:00Z",
"raw": { /* full SimRelay event payload */ }
}In Claude Desktop these surface inline in the conversation. Agents can react to them within the same session — e.g. extract an OTP and submit it. Details: docs/realtime.md.
CLI
simrelay-mcp Start the MCP server on stdio (default)
simrelay-mcp login Sign in with SimRelay via OAuth (opens browser)
simrelay-mcp logout Forget saved tokens
simrelay-mcp help Show helpSecurity
Credentials never travel through tool arguments. OAuth happens out-of-band in your browser; tokens stay on disk.
Token file is created with
0600permissions on POSIX (~/.config/simrelay-mcp/tokens.jsonby default).All requests use
Authorization: Bearer <access_token>. Tokens are refreshed automatically before expiry.
Development
git clone https://github.com/simrelay/mcp.git
cd mcp
npm install
npm run build
npm test # node:test suite
npm run dev # tsx watch entry pointSee CONTRIBUTING.md for how to develop against a personal SimRelay OAuth client without any secrets.
Troubleshooting
Not authenticated. Run \simrelay-mcp login` first.` — your token file is missing or empty. Runsimrelay-mcp login.Token refresh failed: 401— your refresh token expired or was revoked. Runsimrelay-mcp logout && simrelay-mcp login.SIMRELAY_OAUTH_CLIENT_ID is not set— export the env var before starting the server / running login.Browser does not open during login — the URL is printed to stderr. Copy it into a browser manually.
WebSocket disconnects repeatedly — the server auto-reconnects with exponential backoff (5s → 60s). If it never reaches
READY, check that the registered OAuth scopes include broadcasting permissions.
License
ISC
Available Tools
11 toolsget_recent_smsGet recent SMS from realtime bufferARead-onlyIdempotent
Return the N most-recent SMS messages captured by the WebSocket subscription in this server's lifetime (in-memory ring buffer, capacity 100). Filter by sim_id if provided. Returns an empty list if the subscription was never started or no matching SMS has arrived since startup. For historical messages persisted by SimRelay, use get_sim_messages instead.
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | Number of most-recent buffered messages to return (default 5, max 100). | |
| sim_id | No | Optional filter — only return messages for this hosted_sim_id. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint. The description adds valuable behavioral details: empty list on missing subscription, in-memory lifetime, and capacity limit. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each carrying essential information: purpose+constraints, optional filter, and usage guidance+edge case. Front-loaded and zero waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given only 2 simple parameters, no output schema, and annotations covering safety, the description fully explains function, constraints, edge cases (empty list), and alternative. No gaps for agent decision-making.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents both parameters. The description briefly mentions filtering by sim_id and returning N most-recent, but adds no structural or format details beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Return') and identifies the resource ('SMS messages from realtime buffer'), including key constraints (in-memory ring buffer, capacity 100). It clearly distinguishes from sibling tool 'get_sim_messages' by contrasting realtime vs. historical.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use (realtime buffer) and when-not-to-use (for historical messages, use get_sim_messages instead). The alternative is named directly, giving the agent clear decision criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_sim_messagesGet SIM Message HistoryARead-onlyIdempotent
Retrieve historical SMS messages for a SIM, paginated. Returns a normalized list (id, sim_id, direction, from, to, text, received_at) plus pagination metadata.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | 1-based page number (default 1) | |
| sim_id | Yes | The integer hosted_sim_id whose messages to retrieve | |
| per_page | No | Messages per page, 1–100 (default 50) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false. The description adds value by specifying pagination behavior and the exact normalized fields returned. No contradictions; the description complements annotations with concrete behavioral details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence with front-loaded action and no filler. Every element (verb, resource, pagination, return format) earns its place. Efficient and clear.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, but description compensates by detailing the return fields and pagination metadata. For a simple paginated list endpoint, this is sufficient. Could mention session requirements but not critical given sibling tools context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with descriptions for all three parameters (sim_id, page, per_page). The description does not add meaning beyond the schema; it only summarizes pagination. Baseline of 3 is appropriate since the schema carries the semantic burden.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states the verb 'Retrieve', resource 'historical SMS messages for a SIM', and includes pagination. It distinguishes from siblings like get_recent_sms (likely non-paginated) and wait_for_next_sms (waiting for new messages). The specific return fields are listed, removing ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Description implies usage for paginated historical retrieval but lacks explicit guidance on when to use this tool vs alternatives (e.g., get_recent_sms for latest messages, wait_for_next_sms for streaming). No when-not-to-use or alternative recommendations are provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_subscription_statusGet subscription statusARead-onlyIdempotent
Return the current WebSocket subscription state, the channel we're listening on, the active filter, and the most recent buffered SMS events. Useful for diagnosing why messages aren't arriving.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint. The description adds that it returns current state and most recent buffered events, which is additional behavioral context beyond annotations and is appropriate for a diagnostic tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no wasted words: the first sentence lists the returned items, the second provides usage context. It is perfectly concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no parameters and no output schema, the description is sufficient for a simple diagnostic tool. It explains what is returned and why to use it. It could be more explicit about response format, but it is adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has no parameters, and schema description coverage is 100%. With zero parameters, the baseline is 4. The description does not need to add parameter information.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns the current WebSocket subscription state, channel, active filter, and recent buffered SMS events. It uses specific verbs and resources, and distinguishes from siblings like subscribe_to_messages and unsubscribe_from_messages.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states it is useful for diagnosing why messages aren't arriving, providing clear context. It does not explicitly mention when not to use it or provide alternatives, but the purpose is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_simsList SIMsARead-onlyIdempotent
List all SIMs the authenticated user can access, grouped by team. Each SIM includes id, phone_number, status, alias (organization-pivot label), organization, type, messages_received_count, and current lock state (unlocked, or locked-by-user with expiry). The response is structured as groups: [{ team, sims: [...] }, ...] plus a top-level flat sims array for convenience.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the tool as read-only and idempotent. The description adds value by detailing the response structure (grouped objects, flat array) and specific fields (status, lock state, etc.), which aids in understanding the output beyond the minimal annotation clues.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with critical details front-loaded. Every word carries meaning: purpose, grouping, field enumeration, and response format. No redundancy or fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only list tool with no output schema, the description fully explains the response format and fields. It covers the team grouping and convenience array, leaving no gaps for an AI agent to interpret the return value.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has no parameters, so the baseline is 4. The description does not need to clarify parameters but instead explains the output structure, compensating for the lack of an output schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the tool lists all SIMs accessible by the user, grouped by team, and enumerates the specific fields returned. This verb+resource description leaves no ambiguity and distinguishes from sibling tools like lock_sim or get_sim_messages.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for retrieving all accessible SIMs but provides no explicit guidance on when to use versus alternatives like get_sim_messages or search functions. Sibling names hint at differences, but the description lacks conditional advice.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lock_simLock SIMADestructive
Acquire an exclusive lock on a SIM so other users/agents cannot send or read messages on it. Locks expire automatically after the server-configured TTL (typically a few minutes). Use the integer hosted_sim_id from list_sims.
| Name | Required | Description | Default |
|---|---|---|---|
| sim_id | Yes | The integer hosted_sim_id of the SIM to lock |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses that lock is exclusive and expires automatically, aligning with destructiveHint=true. Adds context beyond annotations (TTL, effect on other users), with no contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no filler, essential information front-loaded. Every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Does not mention return values or error cases (e.g., lock contention). While the tool is simple, the absence of output schema makes it incomplete. Lacks details on what happens on success/failure.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and already documents the parameter. Description repeats the schema info without adding new semantic detail, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states the tool acquires an exclusive lock on a SIM, preventing others from sending/reading messages. It uses a specific verb ('acquire') and resource ('lock on a SIM'), and distinguishes from sibling 'release_sim_lock'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use context (to acquire a lock) and mentions automatic TTL expiration. Also advises using the integer from list_sims. However, does not cover when not to use (e.g., if already locked).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
release_sim_lockRelease SIM LockADestructiveIdempotent
Release a previously acquired lock on a SIM. Idempotent — safe to call even if the lock has already expired or never existed.
| Name | Required | Description | Default |
|---|---|---|---|
| sim_id | Yes | The integer hosted_sim_id of the SIM whose lock to release |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide idempotentHint and destructiveHint. Description adds context that it's safe even for expired/non-existent locks, going beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no fluff, front-loaded with purpose. Every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema, but for a simple release operation description covers idempotency and safety. Parameter fully described in schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has 100% coverage with thorough description and constraints. Description does not add beyond schema, baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states verb 'Release' and resource 'lock on a SIM'. Distinguishes from sibling 'lock_sim'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says it's idempotent and safe to call even if lock expired or never existed. Provides reassurance, but doesn't explicitly state when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
simrelay_loginSign in to SimRelayAIdempotent
Sign in to SimRelay via OAuth. Opens the user's default browser to the SimRelay authorization page; after they authorize, tokens are saved locally and refreshed automatically. Returns the path where tokens were stored. Call this when the user asks to log in or when another tool fails with 'Not authenticated'.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations (readOnlyHint=false, openWorldHint=true, idempotentHint=true) are complemented by description explaining browser opening, token saving, auto-refresh. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences front-load purpose and end with usage guideline. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers main behavior (OAuth, browser, token storage, return). Lacks mention of cancel/error handling, but sufficient for a login tool with no output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters defined; schema coverage 100%. Description adds no parameter info, but none needed. Baseline score 4 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool signs in via OAuth, opens browser, saves tokens, and returns storage path. It distinguishes from logout sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use: when user asks to log in or when another tool fails with 'Not authenticated'. Does not include exclusions but guidance is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
simrelay_logoutSign out of SimRelayADestructiveIdempotent
Forget the saved SimRelay OAuth tokens. Idempotent — safe to call even when not signed in. After this, the next tool call that needs auth will require simrelay_login again.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare idempotentHint and destructiveHint. The description adds that tokens are forgotten, it's safe when not signed in, and subsequent auth-dependent calls require login, providing context beyond 'destructive' annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no wasted words. First sentence states action, second adds idempotency and consequence. Efficiently sized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no parameters or output schema, the description fully covers what the tool does, its side effects, and safety profile. Complete for a simple logout tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist (schema coverage 100%). Baseline 4 applies as description adds no param info, but none needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it forgets saved SimRelay OAuth tokens (specific verb+resource). It distinguishes from sibling tool simrelay_login by being its counterpart. The purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies use when wanting to sign out, noting idempotency and safety when not signed in. It describes the consequence (next auth call requires login), but does not explicitly say 'use this to end the session' or compare with alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
subscribe_to_messagesSubscribe to Incoming SMSAIdempotent
Open (or reuse) a WebSocket subscription that streams new SMS for the authenticated user. Each incoming SMS is pushed as an MCP notifications/message (logger=simrelay-sms, level=info, JSON-encoded payload). Also kept in an internal ring buffer of the most recent 100. Pass sim_id to filter to a single SIM. Idempotent — calling again updates the filter and returns the current subscription state.
| Name | Required | Description | Default |
|---|---|---|---|
| sim_id | No | Optional filter — only forward messages for this hosted_sim_id. Omit to receive all incoming SMS for the authenticated user. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses WebSocket subscription, push notifications with format, internal ring buffer (100), and idempotent behavior. Annotations already indicate idempotency and non-destructive, but description adds rich context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences covering purpose, mechanism, parameter, and idempotency. No redundancy, every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given one optional parameter, no output schema, and annotations covering safety, the description is complete. Explains streaming, notification format, buffer, and lifecycle without missing critical details.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Single parameter sim_id is fully described in the schema (100% coverage). Description only restates 'filter to a single SIM,' adding no new semantics beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states 'Open (or reuse) a WebSocket subscription that streams new SMS for the authenticated user.' It specifies incoming SMS, streaming, WebSocket, and distinguishes from sibling tools like get_sim_messages (batch query) and wait_for_next_sms (polling).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Description explains filtering via sim_id and idempotency, implying use for streaming. However, it does not explicitly mention when to avoid or alternatives, though sibling context helps.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
unsubscribe_from_messagesUnsubscribe from Incoming SMSAIdempotent
Stop the real-time SMS stream and close the WebSocket. Idempotent — safe to call even if no subscription is active.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide idempotentHint and destructiveHint. The description adds concrete behavior (stopping stream, closing WebSocket) and reinforces idempotency. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two efficient sentences: first states the action, second adds safety assurance. No wasted words, perfectly sized for the tool's simplicity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless tool with no output schema, the description fully covers what the agent needs to know: what it does and that it's safe to call without active subscription.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist, and schema coverage is 100%. The description does not need to add parameter information. Baseline 4 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses specific verbs 'Stop' and 'close' with clear resources 'real-time SMS stream' and 'WebSocket'. It clearly distinguishes from sibling 'subscribe_to_messages' by indicating the opposite action.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description states 'Idempotent — safe to call even if no subscription is active', providing clear guidance on when to use. However, it does not explicitly exclude scenarios or mention alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wait_for_next_smsWait for next incoming SMSARead-only
Block until the next SMS arrives (optionally filtered by sim_id) and return its payload. Use this when an agent expects a code/OTP imminently — the call returns synchronously with the message so you don't have to poll. Ensures a WebSocket subscription is open before waiting; reuses any existing one. Default timeout is 60s, max 300s. Throws after the timeout if no matching SMS arrives.
| Name | Required | Description | Default |
|---|---|---|---|
| sim_id | No | Optional filter — wait only for messages whose hosted_sim_id matches. Omit to accept any incoming SMS for the authenticated user. | |
| timeout_seconds | No | How long to wait, in seconds (default 60, max 300). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint and openWorldHint. The description adds significant behavioral details: it blocks, has a default and maximum timeout, throws after timeout, ensures a WebSocket subscription, and reuses any existing one. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single paragraph of five sentences, each serving a purpose: main action, usage context, behavior (WebSocket), timeout details, and error handling. It is front-loaded and concise with no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description explains the return ('its payload') but does not specify the format or structure of the SMS payload. It covers blocking behavior, timeout, subscription reuse, and error case. Minor gap on return format, but otherwise complete for a blocking wait tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the parameter descriptions in the schema are already clear. The tool description mentions 'optionally filtered by sim_id' and timeout defaults, but these repeat the schema. With high schema coverage, a baseline of 3 is appropriate as the description adds no new parameter meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool blocks until the next SMS arrives and returns its payload. It specifies the resource (incoming SMS) and the action (wait for), distinguishing it from siblings like get_sim_messages (retrieves history) and subscribe_to_messages (manages subscription).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says to use when an agent expects a code/OTP imminently and that it returns synchronously to avoid polling. It mentions reusing existing subscriptions. It does not explicitly state when not to use, but the context is clear and alternatives are implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
11 tool updates
v2.0.11- First observed
get_recent_sms - First observed
get_sim_messages - First observed
get_subscription_status - First observed
list_sims - First observed
lock_sim - First observed
release_sim_lock - First observed
simrelay_login - First observed
simrelay_logout - First observed
subscribe_to_messages - First observed
unsubscribe_from_messages - First observed
wait_for_next_sms
TDQS
Scored across 11 tools
Each tool has a clear, distinct purpose: authentication (login/logout), SIM listing, locking/unlocking for concurrency control, historical messages, and real-time SMS streaming with blocking and buffered retrieval. The descriptions clearly differentiate overlapping functions like get_sim_messages vs. get_recent_sms.
Tool names consistently follow a verb_noun or verb_noun_noun pattern in snake_case (e.g., list_sims, lock_sim, get_sim_messages). Authentication tools use a simrelay_ prefix, which is a reasonable exception. Overall pattern is predictable and clear.
With 11 tools covering authentication, SIM management, and SMS handling, the count is well-scoped for a relay server. Each tool contributes a necessary function without redundancy or bloat.
The tool surface covers login, listing, locking, historical messages, and real-time streaming with wait and buffering. However, there is no tool for sending SMS, which is a notable gap for a messaging relay. All other operations are well-covered.
Maintenance
Related MCP Connectors
Communication stack for AI agents: SMS, AI voice calls, phone numbers, and account events.
Give your AI a real phone: place calls, send SMS, fetch recordings and transcripts. Local or hosted.
Give AI agents secure access to RevDesk calling, SMS, phone numbers, caller IDs, and usage.
Real SIM numbers for AI agents: SMS verification, rentals, proxies, cloud browser, x402 deposits.
Related MCP Servers
FlicenseBqualityFmaintenanceEnables interaction with Telnyx's telephony, messaging, and AI assistant APIs to manage phone numbers, send messages, make calls, and create AI assistants. Includes webhook support for real-time event handling and comprehensive tools for voice, SMS, cloud storage, and embeddings.4625-- FlicenseBqualityDmaintenanceEnables interaction with Retell AI's voice and chat agent platform. Build, deploy, and manage AI phone agents, configure conversation flows, handle calls/chats, and manage phone numbers through natural language.52-
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to manage phone numbers, send/receive SMS, and place voice calls through natural language, connecting to the phone network via the AgentPhone API.7,395121MIT
- AlicenseAqualityDmaintenanceGives AI agents real phone numbers to receive SMS and extract verification codes through tool calls.629MIT