ModernLoop Internal API

MCP

Connect MCP clients to the ModernLoop broker over Streamable HTTP or local stdio.

MCP

ModernLoop exposes the broker's OpenAPI operations as MCP tools. The production service uses stateless Streamable HTTP.

Before you connect

You need:

  • An MCP client that supports Streamable HTTP.

  • The broker API key in MLOOP_INTERNAL_MCP_API_KEY.

  • The canonical endpoint:

    https://api.modernloop.dev/mcp/v1

The key is shared with the REST API. Keep it in your client's secret or environment-variable configuration. Do not commit it to a client configuration file.

The older https://api.modernloop.dev/mcp path is a compatibility alias for the same handler. For the rest of the broker documentation, see the ModernLoop API docs.

Connection setup

Configure an HTTP MCP client with these values:

SettingValue
Server URLhttps://api.modernloop.dev/mcp/v1
TransportStreamable HTTP
AuthorizationBearer $MLOOP_INTERNAL_MCP_API_KEY
Acceptapplication/json, text/event-stream
Content-Typeapplication/json for JSON-RPC requests

The endpoint accepts GET, POST, and DELETE at the application route. MCP protocol messages use POST; clients should manage the transport details after connecting.

Codex

In Codex, export the broker key before starting Codex:

export MLOOP_INTERNAL_MCP_API_KEY='your-broker-key'

Add this server entry to ~/.codex/config.toml:

[mcp_servers.modernloop]
url = "https://api.modernloop.dev/mcp/v1?toolsets=linear,github"
bearer_token_env_var = "MLOOP_INTERNAL_MCP_API_KEY"
default_tools_approval_mode = "writes"

default_tools_approval_mode = "writes" controls Codex's client-side approval prompt. It does not expose write tools on the server. The URL above remains read-only; add &write=true only when the agent intentionally needs the server to advertise write tools. Restart Codex after changing config.toml, then run /mcp to verify the connection and available tools. See the Codex MCP documentation for Codex-specific configuration details.

Initialize

This request uses protocol version 2025-03-26, the version exercised by the repository's MCP integration tests:

curl -N \
  -H "Authorization: Bearer $MLOOP_INTERNAL_MCP_API_KEY" \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  https://api.modernloop.dev/mcp/v1 \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"my-client","version":"1.0.0"}}}'

Successful initialization returns HTTP 200 with an SSE response. The server is stateless and does not return an mcp-session-id. After initialization, the client can request tools/list and call tools with tools/call.

Endpoint options

Append query parameters to either /mcp/v1 or the compatibility /mcp path. The options combine with &:

OptionAccepted valuesEffect
toolsetsOmitted or allExposes all current toolsets. This gives the client more tools and consumes more context.
toolsetsComma-separated names, such as linear,githubExposes only the selected toolsets. Select only the services the agent needs.
writeOmitted or falseRead-only mode. Operations marked x-write: true are hidden.
writeBare write or write=trueIncludes operations marked x-write: true.

Recommended starting point:

https://api.modernloop.dev/mcp/v1?toolsets=linear,github

To enable writes for those toolsets, combine the options with an ampersand:

https://api.modernloop.dev/mcp/v1?toolsets=linear,github&write=true

Omitting toolsets or using toolsets=all exposes all current toolsets. That may be convenient for exploration, but it increases the tool list and the context an MCP client must manage. Prefer an explicit, narrow selection for production agents.

Invalid or repeated parameters return HTTP 400 with JSON-RPC error code -32602. Examples include an unknown toolset, an empty toolset name, toolsets=all,linear, write=1, write=TRUE, or repeated parameters such as write=true&write=false. Names within one comma-separated toolsets value are trimmed and de-duplicated; repeating the query parameter itself is invalid.

Available toolsets

The current operation counts come from the committed OpenAPI document. Counts include both read and write operations; the default connection exposes only the read subset.

ToolsetOperationsWhat it covers
cursor27Cursor agents, agent runs, team administration, analytics, and code tracking.
datadog14Logs, spans, RUM events, applications, and log indexes.
db1Broker database SQL queries.
firecrawl3Web scraping, search, and site mapping.
github21Repository pull requests, issues, reviews, branches, search, REST, and GraphQL.
gong24Calls, transcripts, users, activity, settings, Engage, and tasks.
google-calendar8Calendars, events, and free/busy lookup.
launchdarkly16Feature flags, environments, projects, targeting, and native API access.
linear1Linear's provider-native GraphQL endpoint.
meta1Broker health information.
notion35Search, pages, blocks, databases, data sources, comments, users, and file uploads.
posthog3Project metadata and logs queries.
pylon42Accounts, issues, contacts, users, teams, tags, custom fields, and messages.
render48Render environments, services, deploys, jobs, logs, metrics, projects, and maintenance.
sendgrid22Mail, templates, contacts, suppressions, statistics, validation, and account data.
sentry7Projects, issues, issue events, and Sentry API requests.
slack11Channels, history, threads, users, message search, messages, and reactions.

The list is derived from OpenAPI tags, so new operations or services can change the available toolsets and counts.

Tool behavior

Names and arguments

Each tool name is the OpenAPI operationId, unchanged. Examples include:

  • github_getPullRequest
  • github_listPullRequests
  • linear_graphql
  • slack_searchMessages

Path and query parameters become top-level tool arguments. A JSON request body is passed under body. For example, this tools/call request invokes github_getPullRequest:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "github_getPullRequest",
    "arguments": {
      "owner": "ModernLoop",
      "repo": "mloop-internal",
      "number": 1
    }
  }
}

The corresponding broker request is:

GET https://api.modernloop.dev/rest/v1/github/repos/ModernLoop/mloop-internal/pulls/1

For a body-bearing operation, pass the JSON payload under body. Path values are URL-encoded and provided query values use the serialization rules from the OpenAPI document.

Read and write behavior

Operations marked x-write: true are excluded unless write is enabled. The MCP tool annotations also identify reads with readOnlyHint: true and writes with destructiveHint: true.

Tool calls return one text content item containing pretty-printed JSON. A non-2xx broker response is returned as MCP content with isError: true, preserving the broker's error envelope.

Compact examples

GoalExample
Connect with only read tools for Linear and GitHubhttps://api.modernloop.dev/mcp/v1?toolsets=linear,github
Connect with Linear and GitHub writes enabledhttps://api.modernloop.dev/mcp/v1?toolsets=linear,github&write=true
List every read toolPOST https://api.modernloop.dev/mcp/v1 with a tools/list JSON-RPC request
List every tool, including writesPOST https://api.modernloop.dev/mcp/v1?toolsets=all&write=true with tools/list
Inspect the REST contractGET https://api.modernloop.dev/rest/v1/openapi.json
Open the human documentationhttps://api.modernloop.dev/docs

Local stdio

Use the generated stdio server for editor integrations that do not support Streamable HTTP:

pnpm --filter @v2/mcp build

V2_API_BASE_URL=https://api.modernloop.dev \
MLOOP_INTERNAL_MCP_API_KEY="$MLOOP_INTERNAL_MCP_API_KEY" \
pnpm --filter @v2/mcp exec v2-mcp --toolsets linear

Add --write only when the local server should expose write tools. Use --remote-spec to load the OpenAPI document from https://api.modernloop.dev/rest/v1/openapi.json at startup. The CLI defaults to the local broker at http://localhost:10001 when V2_API_BASE_URL is not set.

Validate the connection

Use this sequence when testing a new client:

  1. Send initialize and confirm HTTP 200 and an SSE response.
  2. Call tools/list and confirm the selected toolset is present.
  3. Confirm a read tool is listed without write.
  4. Add write=true only when needed and confirm the expected write tool appears.
  5. Call a read tool with the argument shape shown above.

The repository tests cover authentication, initialization, stateless behavior, tool filtering, write gating, invalid query parameters, tool derivation, URL construction, request bodies, and error mapping.

Troubleshooting

  • 401 Unauthorized: check the Authorization: Bearer <key> header, including the Bearer prefix, and verify that the key matches MLOOP_INTERNAL_MCP_API_KEY.
  • 500 SERVER_MISCONFIGURED: the broker process does not have MLOOP_INTERNAL_MCP_API_KEY configured.
  • 400 -32602 for endpoint options: check for unknown or empty toolset names, repeated query parameters, all combined with another toolset, or invalid write values. Use & between toolsets and write.
  • A write tool is missing: writes are hidden unless the URL includes write=true or bare write. Also check that the relevant toolset is selected.
  • A tool call returns isError: true: inspect the text content for the broker error envelope. The broker also applies a 30-second request timeout and returns REQUEST_TIMEOUT with HTTP 504.
  • The client sees too many tools: narrow toolsets to the services required for the task.

On this page