ee-mcp-public
This server provides read-only access to EternalEngine's public API, letting you query PostFrame and PayGate data with 43 GET-only tools and no write capabilities.
PostFrame (email/contacts/audiences): List/get audiences, contacts, emails, templates, domains, providers, suppressions, webhooks, API keys, billing subscription, usage quota, settings, onboarding status, analytics overview and time series.
PayGate (transactions/Connect): List/get transactions, disputes, customers by email, payment stats, month-to-date volume, merchant settings/routing rules/providers, API keys, checkout sessions, coupons, products, subscriptions, payouts, Connect account/balance, invoice PDFs, and webhook events.
Health/status: Check service health via
getStatus(public, no auth required).Safe and bounded: Every request is a GET with your own API key; no local file access, shell execution, or non-EE hosts; rate-limited and timeout-bounded.
Click 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., "@ee-mcp-public Show me my recent PayGate transactions"
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.
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) |
|
|
PayGate (transactions, disputes, customers, payouts) |
|
|
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.jsOnce 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.jsCursor
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 |
| Yes | — | Your PostFrame ( |
| No |
| Override for testing against a non-production instance. |
| No |
| 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:
Validates its input against a Zod schema derived from the spec's parameters.
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.Sends exactly one
GETrequest withAuthorization: Bearer <your key>, bounded byAbortSignal.timeout.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 typecheckTo 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 toolsgetAnalyticsOverviewB
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
Scored across 43 tools
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.
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.
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.
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
Related MCP Connectors
Read-only access to your SKRIME account: servers, domains, DNS, webspace and more via API key.
Search and read published GoVisit destination and local business data through 22 read-only tools.
Read-only access to your Consequential eCommerce marketing analytics and attribution data.
Read-only access to PRRO.cloud fiscal cash registers, shifts, tasks, billing and webhooks.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables querying Kiwify sales, subscriptions, products, and affiliates via the official API. Read-only access for viewing data.MIT
- AlicenseBqualityBmaintenanceEnables 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.13MIT
- AlicenseNot gradedqualityCmaintenanceEnables read-only access to BuzzerBeater's public API through MCP tools for retrieving team, player, match, market, national team, and other game data.MIT
- AlicenseBqualityBmaintenanceEnables 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.22Apache 2.0