Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Logflare Code Mode

БесплатноНе проверен

Enables agents to interact with the Logflare API by writing JavaScript functions that run in a Vercel Sandbox, using three tools: search, execute_read, and exec

GitHubEmbed

Описание

Enables agents to interact with the Logflare API by writing JavaScript functions that run in a Vercel Sandbox, using three tools: search, execute_read, and execute_write.

README

A Model Context Protocol server that gives an agent three tools instead of dozens for driving the Logflare Management API. The agent writes a short JavaScript function that runs inside a Vercel Sandbox and calls the API through a thin api.request() client — looping, filtering, and chaining calls in one round-trip.

This applies Cloudflare's Code Mode pattern to Logflare:

  • LLMs write API-calling code more reliably than long chains of individual tool calls.
  • Intermediate data stays in the sandbox, out of the model's context.
  • The agent discovers endpoints with search (the OpenAPI spec), then calls them with execute_read/execute_write.

This is a local stdio server — one process per MCP client, communicating over stdin/stdout, the same way you'd run any locally-installed MCP server (npx, or a command/args entry in your client config). Logflare has no OAuth 2.1 authorization server, so there's no per-request bearer token to broker the way a remote streamable-HTTP server would; the API key is just an environment variable for the whole process.


Quickstart

Prerequisites: Node.js ≥ 20.12, pnpm (corepack enable provides it), a Vercel account with Sandbox access, and a Logflare API key (Logflare account → API Keys).

pnpm install
pnpm build

Copy .env.example to .env and fill in VERCEL_TOKEN/VERCEL_TEAM_ID/VERCEL_PROJECT_ID and LOGFLARE_API_KEY — the local .env is only for pnpm dev/pnpm test; a real MCP client sets these as env entries in its own config instead (see below).

Connect an MCP client — this repo ships a .mcp.json:

{
  "mcpServers": {
    "logflare-code-mode": {
      "command": "node",
      "args": ["dist/index.js"],
      "env": {
        "LOGFLARE_API_KEY": "${LOGFLARE_API_KEY}",
        "VERCEL_TOKEN": "${VERCEL_TOKEN}",
        "VERCEL_TEAM_ID": "${VERCEL_TEAM_ID}",
        "VERCEL_PROJECT_ID": "${VERCEL_PROJECT_ID}"
      }
    }
  }
}

Once published, the same thing works via npx:

{
  "mcpServers": {
    "logflare-code-mode": {
      "command": "npx",
      "args": ["-y", "logflare-mcp-code-mode", "--read-only"],
      "env": { "LOGFLARE_API_KEY": "...", "VERCEL_TOKEN": "...", "VERCEL_TEAM_ID": "...", "VERCEL_PROJECT_ID": "..." }
    }
  }
}

Run node dist/index.js --help for the full option/env-var reference.

Try it — call execute_read with an async arrow function:

async () => {
  const res = await api.request({ method: 'GET', path: '/api/sources' })
  return { status: res.status, count: res.data.length }
}

You get back e.g. { "status": 200, "count": 3 } — produced by code the agent wrote, run in a sandbox that can reach only the Logflare API.


The three tools

Each takes a single code string — an async arrow function that returns a value. console.log output comes back separately as stdout.

Tool What it does In scope Annotation
search Query the Logflare OpenAPI spec (all $refs resolved) to find endpoints and their shapes. Network-isolated. spec read-only
execute_read Call the Logflare API via api.request()GET only. api read-only
execute_write Call the Logflare API via api.request() — any method (POST/PUT/PATCH/DELETE). api destructive

The workflow is: search to find an endpoint's path and request shape, then execute_read/execute_write to call it. The client is api.request({ method, path, query?, body?, contentType?, rawBody? }), which returns { status, ok, data }.

Run with --read-only to lock the whole server instance into read-only mode: search's spec only contains GET operations (so the agent can't even discover write endpoints), and execute_write isn't registered at all — it's absent from tools/list, and calling it anyway fails as an unknown tool. This is a startup flag (a property of the process), not a per-call one.


How it works

MCP client ──stdio (newline-delimited JSON-RPC)──▶ McpServer (2 or 3 tools)
                                                          │
                          ┌───────────────────────────────┼───────────────────────────────┐
                        search                       execute_read                   execute_write
                          │                                └───────────────┬───────────────┘
                          ▼                                                ▼
                 fresh Vercel Sandbox                             fresh Vercel Sandbox
                 (networkPolicy: deny-all)                        (networkPolicy: allow logflare.app;
                 embeds `spec`                                     LOGFLARE_API_KEY injected;
                                                                    `api.request()` client)
  • TransportStdioServerTransport from the MCP SDK: reads newline-delimited JSON-RPC from stdin, writes responses to stdout. stdout is exclusively the protocol channel — all logging goes to stderr (see src/log.ts).
  • Per call — a fresh Vercel Sandbox (@vercel/sandbox), stopped in finally. No SDK is installed inside it, so there's nothing to amortize with a warm pool.
  • search sandboxnetworkPolicy: "deny-all"; the slimmed OpenAPI spec (fetched from LOGFLARE_OPENAPI_URL, default https://api.logflare.app/api/openapi) is embedded as spec for the agent's read-only code to query. In --read-only mode the spec is filtered to GET-only operations first.
  • execute_* sandboxnetworkPolicy: { allow: ["logflare.app"] } (the Management API's actual host); LOGFLARE_API_KEY is injected as an env var and sent as Authorization: Bearer <key> by api.request(). The read/write split and the credential/backend/team block are enforced by the provided api.request() client: execute_read throws on any non-GET before the fetch, and both tools refuse the paths in BLOCKED_PATH. This is a guard against accidental or confused agent behavior, not a hard sandbox capability restriction — agent code is plain Node with the global fetch in scope, so it could in principle call logflare.app directly and bypass both checks. Safety for a genuinely adversarial caller rests on the fact that they're using their own API key against an API they already have full access to, not on this guard.
  • Runner — agent code is written to a file and run with node (never eval); output returns via a result file. The code sits on its own lines in the invoke scaffold, so a trailing // comment can't swallow the closing tokens.
  • Vercel credentials — explicit VERCEL_TOKEN/VERCEL_TEAM_ID/VERCEL_PROJECT_ID are required (this process never runs on Vercel itself, so there's no ambient OIDC fallback in practice).

The source is small and layered by responsibility:

File Responsibility
src/index.ts Entry point: parses --read-only/--help, loads .env, starts the stdio transport.
src/server.ts The MCP surface: the two or three tools (depending on read-only mode), response formatting, the untrusted-data boundary.
src/sandbox.ts Sandbox plumbing: runner construction, the two sandbox shapes, the injected api.request() client, output caps, the credential/backend guard.
src/spec.ts Fetches, $ref-resolves, slims, caches, and (optionally) GET-filters the Logflare OpenAPI spec for search.
src/log.ts pino logger (stderr only) + credential redaction.

Security notes

Agent code is untrusted but runs inside a Vercel Sandbox microVM and authenticates with the caller's own Logflare key — so by design it can use that key against the Logflare API. Beyond the sandbox isolation, per-tool egress, and read/write split above:

  • Untrusted-data boundary — all execute output (result/stdout/stderr) may embed API content (log events, source metadata), so it's wrapped in a <untrusted-data-{uuid}>…</> envelope (error path too), with the model told not to follow instructions inside. Truncation happens before wrapping, so a size cap can't sever the closing tag.
  • Credential/backend/team block — paths containing access-tokens (mints/lists/reveals full API tokens), backends (backend config can embed DB passwords, service-account keys, and other connection secrets), or teams (the Team response embeds the full User object, whose api_key is the account's master Logflare API key) are refused, matched anywhere in the path (e.g. /api/sources/{id}/backends/{id}). The path is first normalized to a fixpoint (percent-decode, re-resolve dot-segments, collapse slashes, lowercase), so encoded spellings (/%61ccess-tokens, //backends, /x%2F..%2Fbackends, /TEAMS) still match; it only over-blocks. This guard covers the intended api.request() path; see the caveat above about raw fetch in the sandbox.
  • Known gap — some Source fields (slack_hook_url, webhook_notification_url) embed secrets the caller configured (their own Slack webhook, etc.) rather than Logflare-minted credentials. These are not blocked, the same way reading your own resource's other fields isn't blocked — but a prompt-injected agent could still surface them into its context via execute_read/execute_write, same as any other resource field.
  • Output caps — bounded inside the sandbox before reaching the server: runner result cap (400k chars), head -c reads (500k file / 20k per stream), final server truncate (100k result / 10k logs).
  • Token location — like Vercel Sandbox generally, there's no outbound-fetch proxy hook to keep the token out of the isolate, so LOGFLARE_API_KEY lives in the sandbox env (agent code can read it). Safety rests on isolation + egress — the key only reaches logflare.app — not token secrecy.
  • Single-tenant by design — there's no bearer-token auth gate because there's nothing to gate: this process is spawned per-caller by an MCP client, already scoped to whoever's shell/config started it, unlike the remote-HTTP shape this was originally built as (see git log — the streamable-HTTP version is preserved in history if a remote deployment is ever needed again).

Configuration

Env var / flag Default Meaning
LOGFLARE_API_KEY (env) Required. The Logflare API key used for every execute_read/execute_write call.
VERCEL_TOKEN (env) Required. Vercel API token for sandbox creation.
VERCEL_TEAM_ID (env) Required. Vercel team ID for sandbox creation.
VERCEL_PROJECT_ID (env) Required. Vercel project ID for sandbox creation.
--read-only (CLI flag) off Hide execute_write; restrict search's spec to GET operations.
LOGFLARE_SANDBOX_RUNTIME (env) node24 Vercel Sandbox runtime the sandboxes boot from
LOGFLARE_EXEC_TIMEOUT_MS (env) 120000 Per-call budget for the agent's code
LOGFLARE_OPENAPI_URL (env) https://api.logflare.app/api/openapi Override the OpenAPI spec URL the search tool loads
LOG_LEVEL (env) info trace/debug/info/warn/error/fatal/silent
LOG_FORMAT (env) json json (structured) or pretty (dev)

Observability

Structured logs via pino to stderr only — stdout is reserved for JSON-RPC. One line per tool invocation/completion (tool name, code length, duration, calledEndpoints count for execute calls) plus a startup line noting read-only mode. Use LOG_FORMAT=pretty locally. Credentials are never logged (see redactToken in src/log.ts).


Testing

pnpm test
  • test/server.test.ts — the MCP surface via an in-memory client/server pair (tool list, annotations, error shapes, readOnly: true hiding execute_write). No key.
  • test/stdio.test.ts — end-to-end over the real stdio transport: spawns the built binary as a child process and speaks newline-delimited JSON-RPC over its stdin/stdout, exactly like a real MCP client. Covers --help, --read-only over the wire, and that stdout only ever carries JSON-RPC (logs land on stderr). No key. Requires pnpm build first.
  • test/sandbox.test.ts — offline unit tests for the credential/backend/team guard (path normalization + block regex). No key, no sandbox.
  • test/spec.test.ts — offline unit tests for the read-only spec filter (GET-only operations, paths with no GET dropped entirely). No key, no network.
  • test/live.test.ts — end-to-end against real Logflare + Vercel Sandbox: spec search, execute_read GET plus non-GET rejection, trailing-comment tolerance, error/SyntaxError surfacing inside the boundary, the credential/backend/team guard (including encoded bypasses), an execute_write create+delete round-trip, egress denial, and the stdout size cap. Runs only when LOGFLARE_API_KEY and the VERCEL_* credentials are set.

from github.com/Rodriguespn/logflare-mcp-code-mode

Установка Logflare Code Mode

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/Rodriguespn/logflare-mcp-code-mode

FAQ

Logflare Code Mode MCP бесплатный?

Да, Logflare Code Mode MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для Logflare Code Mode?

Нет, Logflare Code Mode работает без API-ключей и переменных окружения.

Logflare Code Mode — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить Logflare Code Mode в Claude Desktop, Claude Code или Cursor?

Открой Logflare Code Mode на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare Logflare Code Mode with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории development