Skip to main content
Glama

ee-mcp-public

A read-only Model Context Protocol (MCP) server for the EternalEngine public API. It runs on your machine (or your CI, or your agent's sandbox), authenticated with your own API key. It has 43 tools, one per public GET endpoint, and no others — there is no write tool anywhere in this package, and none can be added without editing scripts/codegen.mjs or the public spec it reads from (EternalEngineOS/openapi).

The read-only guarantee

Every tool corresponds to exactly one GET operation. deriveTools() in scripts/codegen.mjs reads only paths[path].get — structurally, there is no code path anywhere in this repository that constructs a request body or issues any HTTP method other than GET (src/client.ts's getJson() hard-codes method: 'GET'). A checked-in drift test (tests/codegen.test.ts) fails the build if the generated tool list and the source spec ever disagree.

This package:

  • Cannot write, modify, or delete anything on EternalEngine, by construction.

  • Cannot bypass your own authorization — every request carries exactly the key you supply.

  • Cannot read local files, invoke a shell, or reach any host other than EE_API_BASE.

  • Cannot see or exfiltrate your MCP client's other tools, prompts, or conversation context.

Read THREAT-MODEL.md for the full trust boundary, including the honest bound on what a leaked API key can do (this package narrows the blast radius of a key used through it; it cannot narrow the blast radius of the key itself once it exists).

Related MCP server: coinmarketcap-keyless-mcp

Get your API key

Mint one from the EternalEngine developers page. Keys are per-app:

App

Key prefix

Mint from

PostFrame (email, contacts, audiences, analytics)

pf_live_* / pf_test_*

app.eternalengineos.io/postframe/developers

PayGate (transactions, disputes, customers, payouts)

pg_live_* / pg_test_*

app.eternalengineos.io/paygate/developers

Install & run

Not yet published to npm — publishing is a manual, deliberate step reserved for the EternalEngine team (see docs/growth/PUBLIC-API-AND-MCP.md in the main repository), not something this package's CI does automatically. Until it is published, run from source. These exact commands are verified against this repository:

git clone https://github.com/EternalEngineOS/ee-mcp-public.git
cd ee-mcp-public
pnpm install
pnpm build
EE_API_KEY=pf_live_your_key node dist/index.js

Once published, the same thing will be EE_API_KEY=pf_live_your_key npx ee-mcp-public.

Claude Desktop

Add to your claude_desktop_config.json (until the npm package ships, point command/args at your local clone's dist/index.js instead of npx):

{
  "mcpServers": {
    "eternalengine": {
      "command": "node",
      "args": ["/absolute/path/to/ee-mcp-public/dist/index.js"],
      "env": { "EE_API_KEY": "pf_live_your_key" }
    }
  }
}

Claude Code

claude mcp add eternalengine --env EE_API_KEY=pf_live_your_key -- node /absolute/path/to/ee-mcp-public/dist/index.js

Cursor

Add to your MCP config (~/.cursor/mcp.json or the project's .cursor/mcp.json):

{
  "mcpServers": {
    "eternalengine": {
      "command": "node",
      "args": ["/absolute/path/to/ee-mcp-public/dist/index.js"],
      "env": { "EE_API_KEY": "pf_live_your_key" }
    }
  }
}

Any other MCP client

This is a standard stdio MCP server (@modelcontextprotocol/sdk, StdioServerTransport). Point your client's config at node /absolute/path/to/ee-mcp-public/dist/index.js with EE_API_KEY set in its environment.

Configuration (env vars only — no config file, no CLI flags for secrets)

Variable

Required

Default

Purpose

EE_API_KEY

Yes

—

Your PostFrame (pf_*) or PayGate (pg_*) API key. The process exits with a clear message if unset.

EE_API_BASE

No

https://app.eternalengineos.io/api/v1

Override for testing against a non-production instance.

EE_API_TIMEOUT_MS

No

15000

Per-request timeout. Every request is bounded — there is no unbounded network wait.

What each tool does

Every tool corresponds to exactly one GET operation in the public OpenAPI spec published at EternalEngineOS/openapi, human-readable at eternalengineos.io/developers. Tool names are the spec's operationIds (e.g. listMessages, getAnalyticsOverview, getConnectBalance). This package ships 43 tools, counted directly from the generated tool list (src/generated-tools.ts, produced by scripts/codegen.mjs from spec/openapi.public.json).

Each tool call:

  1. Validates its input against a Zod schema derived from the spec's parameters.

  2. Checks a client-side rate limiter matching the tool's documented limit — a courtesy that fails fast locally instead of burning your server-side quota on a round-trip to get a 429.

  3. Sends exactly one GET request with Authorization: Bearer <your key>, bounded by AbortSignal.timeout.

  4. Returns the JSON response as MCP tool output, or a structured error (isError: true) — this process never throws an unhandled exception across the MCP boundary.

Rate limits

Each tool's description states its rate limit, sourced from the spec's x-rate-limit field. The client-side limiter in this package (src/rate-limiter.ts) enforces the same number locally; the EternalEngine gateway enforces it too and is the actual authority. A 429 from the server is returned as a tool error with the Retry-After value, never retried silently.

Development

pnpm install
pnpm codegen     # regenerate src/generated-tools.ts from spec/openapi.public.json
pnpm build       # codegen + tsc
pnpm test        # vitest — 56 tests, zero network calls (all fetches mocked)
pnpm typecheck

To pick up a spec change: update spec/openapi.public.json from EternalEngineOS/openapi, then pnpm codegen. The checked-in drift test (tests/codegen.test.ts) fails if src/generated-tools.ts and the spec ever disagree.

Security

Read THREAT-MODEL.md first. Found a way for this package to do something that document says it cannot? That is a real finding — open an issue at EternalEngineOS/.github or email info@eternalengineos.io (the one address EternalEngine publishes for every inbound purpose, including security reports — see SECURITY.md).

Support

General questions or bugs: open an issue at EternalEngineOS/.github.

License

MIT — see LICENSE.

Available Tools

43 tools
getAnalyticsOverviewB

Get delivery overview (rate limit: 100 requests per 1m) Read-only (GET /postframe/analytics/overview).

Inputs: to, from.

getAnalyticsTimeseriesB

Get time series metrics (rate limit: 100 requests per 1m) Read-only (GET /postframe/analytics/timeseries).

Inputs: to, from, interval.

getApiKeysA

List API keys (rate limit: 100 requests per 1m) Read-only (GET /postframe/api-keys).

Inputs: no named parameters.

getAudiencesA

List audiences (rate limit: 100 requests per 1m) Read-only (GET /postframe/audiences).

Inputs: no named parameters.

getAudiencesByAudienceIdBroadcastsA

List broadcasts for an audience (rate limit: 100 requests per 1m) Read-only (GET /postframe/audiences/{audienceId}/broadcasts).

Inputs: audienceId (required).

getAudiencesByIdA

Get audience details (rate limit: 100 requests per 1m) Read-only (GET /postframe/audiences/{id}).

Inputs: id (required).

getBillingSubscriptionA

Get subscription status (rate limit: 100 requests per 1m) Read-only (GET /postframe/billing/subscription).

Inputs: no named parameters.

getConnectAccountA

Get the tenant's Stripe Connect account status (rate limit: 100 requests per 1m) Read-only (GET /paygate/connect/account).

Inputs: no named parameters.

getConnectBalanceA

Get the connected account's Stripe balance (rate limit: 100 requests per 1m) Read-only (GET /paygate/connect/balance).

Inputs: no named parameters.

getContactsB

List contacts (rate limit: 100 requests per 1m) Read-only (GET /postframe/contacts).

Inputs: limit, offset, search.

getContactsByIdC

Get a contact (rate limit: 100 requests per 1m) Read-only (GET /postframe/contacts/{id}).

Inputs: id (required).

getCustomerByEmailA

Get a customer's transaction history (rate limit: 100 requests per 1m) Read-only (GET /paygate/customers/{email}).

Inputs: email (required).

getDisputeByIdA

Get a dispute by ID (rate limit: 100 requests per 1m) Read-only (GET /paygate/transactions/disputes/{id}).

Inputs: id (required).

getDomainsA

List domains (rate limit: 100 requests per 1m) Read-only (GET /postframe/domains).

Inputs: no named parameters.

getDomainsByIdA

Get domain details (rate limit: 100 requests per 1m) Read-only (GET /postframe/domains/{id}).

Inputs: id (required).

getEmailsC

List emails (rate limit: 100 requests per 1m) Read-only (GET /postframe/emails).

Inputs: to, limit, offset, status, +2 more.

getEmailsByIdA

Get email details (rate limit: 100 requests per 1m) Read-only (GET /postframe/emails/{id}).

Inputs: id (required).

getMerchantSettingsA

Get merchant settings and fraud rules (rate limit: 100 requests per 1m) Read-only (GET /paygate/settings).

Inputs: no named parameters.

getMonthToDateVolumeA

Get the tenant's month-to-date processing volume (rate limit: 100 requests per 1m) Read-only (GET /paygate/me/volume).

Inputs: no named parameters.

getPaymentStatsB

Payment stats (rate limit: 100 requests per 1m) Read-only (GET /paygate/transactions/stats).

Inputs: no named parameters.

getProvidersA

List providers (rate limit: 100 requests per 1m) Read-only (GET /postframe/providers).

Inputs: no named parameters.

getSettingsB

Get tenant settings (rate limit: 100 requests per 1m) Read-only (GET /postframe/settings).

Inputs: no named parameters.

getSettingsOnboardingA

Get onboarding status (rate limit: 100 requests per 1m) Read-only (GET /postframe/settings/onboarding).

Inputs: no named parameters.

getStatusA

Service health (public, no auth) This endpoint requires no authentication. Read-only (GET /paygate/status).

Inputs: no named parameters.

getSubscriptionInvoicePdfA

Download a branded PDF of the tenant's own platform subscription invoice (rate limit: 100 requests per 1m) Read-only (GET /paygate/me/invoices/{invoiceId}/pdf).

Inputs: invoiceId (required).

getSuppressionsC

List suppressions (rate limit: 100 requests per 1m) Read-only (GET /postframe/suppressions).

Inputs: type, limit, offset.

getTemplatesB

List templates (rate limit: 100 requests per 1m) Read-only (GET /postframe/templates).

Inputs: limit, offset.

getTemplatesByIdA

Get a template (rate limit: 100 requests per 1m) Read-only (GET /postframe/templates/{id}).

Inputs: id (required).

getTransactionByIdA

Get transaction by ID (rate limit: 100 requests per 1m) Read-only (GET /paygate/transactions/{id}).

Inputs: id (required).

getUsageQuotaA

Get usage quota (rate limit: 100 requests per 1m) Read-only (GET /postframe/usage/quota).

Inputs: no named parameters.

getWebhooksA

List webhooks (rate limit: 100 requests per 1m) Read-only (GET /postframe/webhooks).

Inputs: no named parameters.

listApiKeysA

List API keys for the tenant (rate limit: 100 requests per 1m) Read-only (GET /paygate/api-keys).

Inputs: no named parameters.

listCheckoutSessionsA

List recent Checkout sessions (rate limit: 100 requests per 1m) Read-only (GET /paygate/connect/checkout/sessions).

Inputs: limit.

listCouponsA

List Stripe coupons on the connected account (rate limit: 100 requests per 1m) Read-only (GET /paygate/connect/coupons).

Inputs: no named parameters.

listCustomersB

List customers (aggregated from transaction history) (rate limit: 100 requests per 1m) Read-only (GET /paygate/customers).

Inputs: limit, offset, search, sort_by, +1 more.

listDisputesC

List disputes (rate limit: 100 requests per 1m) Read-only (GET /paygate/transactions/disputes).

Inputs: limit, offset, status.

listPayoutsC

List Stripe Connect payouts (rate limit: 100 requests per 1m) Read-only (GET /paygate/connect/payouts).

Inputs: limit, offset.

listProductsA

List Stripe products/plans on the connected account (rate limit: 100 requests per 1m) Read-only (GET /paygate/connect/products).

Inputs: no named parameters.

listProvidersA

List configured payment providers (rate limit: 100 requests per 1m) Read-only (GET /paygate/transactions/providers).

Inputs: no named parameters.

listRoutingRulesA

List routing rules (rate limit: 100 requests per 1m) Read-only (GET /paygate/transactions/routing).

Inputs: no named parameters.

listSubscriptionsA

List Stripe subscriptions on the connected account (rate limit: 100 requests per 1m) Read-only (GET /paygate/connect/subscriptions).

Inputs: search, status.

listTransactionsB

List transactions (rate limit: 100 requests per 1m) Read-only (GET /paygate/transactions).

Inputs: type, limit, offset, search, +4 more.

listWebhookEventsA

List webhook delivery events (rate limit: 100 requests per 1m) Read-only (GET /paygate/webhooks/events).

Inputs: limit, offset, status, event_type.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.1/5.0

    Scored across 43 tools

    Disambiguation2/5

    Several tools have near-identical names and purposes, such as getApiKeys/listApiKeys, getProviders/listProviders, and getWebhooks/listWebhookEvents, which only differ by internal API module. With 43 tools, an agent can easily select the wrong variant despite reading descriptions.

    Naming Consistency3/5

    The set is consistently camelCase with get/list prefixes, but it mixes getX and listX for collection endpoints and creates duplicate-looking names across the email and payment domains. The pattern is readable but not predictable enough to be considered mostly consistent.

    Tool Count2/5

    43 tools is well above a comfortable MCP surface and many are near-duplicates (getApiKeys/listApiKeys, getProviders/listProviders). The server covers two domains, but the number feels heavy rather than tightly scoped.

    Completeness3/5

    As a read-only/public surface, it exposes a broad set of list and detail endpoints across email and payment resources. However, several resources are list-only with no detail lookup, and there are no write or management operations, so lifecycle coverage is incomplete for common workflows.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables querying Kiwify sales, subscriptions, products, and affiliates via the official API. Read-only access for viewing data.
      MIT
    • A
      license
      B
      quality
      B
      maintenance
      Enables credential-free, read-only access to selected public market-data routes via 13 typed MCP tools covering asset mapping, metadata, quotes, listings, global metrics, Fear & Greed, Altcoin Season, and CMC index data.
      13
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables read-only access to BuzzerBeater's public API through MCP tools for retrieving team, player, match, market, national team, and other game data.
      MIT
    • A
      license
      B
      quality
      B
      maintenance
      Enables read-only access to public Star Atlas-inspired game data, profile key audits, DAO treasury/proposal/revenue/Ecosystem Fund information, and signed hub updates, listings, and claims through MCP tools, without signing or writing to any chain.
      22
      Apache 2.0