@cyanheads/mailchimp-mcp-server
v0.3.9
Published
Draft, test, and send Mailchimp campaigns straight from your MCP client — with audience management, subscriber CRUD, and post-send analytics behind safe-by-default send gates. STDIO or Streamable HTTP.
Downloads
746
Maintainers
Readme
Overview
Mailchimp campaign management over the Mailchimp Marketing API v3. Draft, test, and send email campaigns, manage audiences and subscribers, and review post-send analytics from any MCP client. Runs as a stdio process or a local Streamable HTTP server.
Tools
| Tool | Description |
|:---|:---|
| mailchimp_account | Account profile, plan, data center, and the Chimp Chatter activity feed. |
| mailchimp_audiences | Manage audiences (lists) — read, create/update, per-audience analytics, signup-form config. No delete. |
| mailchimp_audience_overview | One-call audience health digest: info, stats, growth history, top email clients, merge-field schema. |
| mailchimp_subscribers | Subscriber CRUD + tags/notes/activity. archive is the strongest delete available. |
| mailchimp_upsert_subscriber | Add or update a subscriber idempotently with status, merge fields, tags, and an optional note. |
| mailchimp_find_subscriber | Locate a subscriber by email in one audience or across the account. |
| mailchimp_import_subscribers | Batch add/update subscribers (capped at 500/call). Status defaults to pending. |
| mailchimp_segments | CRUD for audience segments (saved, static, fuzzy) plus member listing and batch add/remove. |
| mailchimp_merge_fields | Read + create/update custom subscriber attributes. No delete. |
| mailchimp_campaigns | Campaign record management: list/get/create/update, replicate, content, checklist, RSS/resend controls. |
| mailchimp_send_campaign | Compose and send (or schedule/test) a campaign in one call. |
| mailchimp_replicate_campaign | Duplicate a campaign with optional overrides, then draft/test/send/schedule. |
| mailchimp_reports | Campaign reports — generic slicer across ten dimensions. |
| mailchimp_campaign_report | Post-send analytics digest — headline metrics plus top-N slices in one response. |
| mailchimp_templates | Mailchimp-hosted templates: reads work on free; writes require a paid plan. |
| mailchimp_files | File Manager (Content Studio) — upload, list, fetch, rename, delete files on Mailchimp's CDN. |
| mailchimp_search | Global search across members or campaigns. |
| mailchimp_assets (conditional — set MAILCHIMP_ASSETS_DIR) | Local-assets surface — inspect and pre-warm uploads for @assets/<path> references in campaign HTML. |
| mailchimp_local_templates (conditional — set MAILCHIMP_TEMPLATES_DIR) | Author and render local .eta templates — the write path for templates on free-tier Mailchimp. |
| mailchimp_playbook | Structured procedural playbook merged with live account state. Advice-only. |
Resources
| Resource | Description |
|:---|:---|
| mailchimp://account | Account info snapshot — profile, plan, data center, total subscribers. |
| mailchimp://audiences/{audienceId} | Audience snapshot — name, contact, stats, double opt-in status. |
| mailchimp://campaigns/{campaignId} | Campaign snapshot — status, settings, recipients summary. |
| mailchimp://campaigns/{campaignId}/report | Post-send campaign report headline metrics. |
All resource data is also reachable via tools. Large collections (audiences, campaigns) are not exposed as resources — use the list operation on the corresponding tool instead.
Prompts
| Prompt | Description |
|:---|:---|
| newsletter_from_source | Compose a monthly editorial newsletter from a URL or brief, chaining into mailchimp_playbook and the draft → test → send flow. |
Design reference: docs/email-design-playbook.md.
Capability reference
mailchimp_account tool
operation: inforeturns profile, plan, data center, and total subscribers;operation: activity-feedreturns the Chimp Chatter event streamactivity-feedpages viacount(max 100, default 20) andoffset; each item carries type, timestamp, and a human-readable description- An empty activity feed returns a plain-language
noteexplaining likely causes instead of a bare empty array
mailchimp_audiences tool
list/get/create/updatemanage audience records;createrequiresname,contact(company/address1/city/state/zip/country),permissionReminder, andcampaignDefaults(fromName/fromEmail/language)- Analytics reads:
list-activity,list-growth,list-clients,list-abuse-reports,list-locations get-signup-forms/customize-signup-formsmanage hosted/embedded signup-form header, content sections, and CSS- No delete — on the free plan's 1-audience cap this is destructive; delete via the Mailchimp UI
countcaps at 1000 per page
mailchimp_audience_overview tool
- One call merges audience info,
growthMonthsof growth history (1–36, default 12), top email clients, and the full merge-field schema notes[]distinguishes "no data yet" (new audience, no sends) from a genuine empty-engagement signal
mailchimp_subscribers tool
- CRUD except permanent delete:
list/get/update, plusarchive(removes from the active audience, preserves the record so the email can resubscribe) set-tagsis declarative — the provided set becomes the full active tag list; anything not included is removed unless named inpreserveTags- Mailchimp stores static-segment membership as a tag, so an unguarded
set-tagscan silently drop segment membership list-notes/add-note/update-note/delete-notemanage CRM-style notes;list-activity/list-events/list-goalsare engagement reads- No GDPR permanent-delete — do that in the Mailchimp UI
mailchimp_upsert_subscriber tool
- Idempotent add-or-update by email — creates via PUT, updates via PATCH, skipping merge-field revalidation on updates that don't touch merge fields
- Declarative tag sync computes the add/remove delta from a desired set;
preserveTagsprotects named tags (including static-segment names) from removal status: 'pending'triggers Mailchimp's double opt-in email;'subscribed'requires documented consentupdateExistingStatus: falseappliesstatusonly to newly-created subscribers, leaving existing ones untouched
mailchimp_find_subscriber tool
- Searches one audience (
audienceId) or every audience on the account by email, returning separateexactMatches/fuzzyMatchesarrays - Each match is enriched with merge fields and engagement stats;
includeTags: true(default) adds the full active tag list at one extra call per match
mailchimp_import_subscribers tool
- Batch add/update, capped at 500 rows per call — chunk larger imports client-side
statusdefaults topending(double opt-in) to prevent accidental mass-sends; a per-rowstatusoverrides the top-level defaultupdateExisting: false(default) skips rows that already exist instead of overwriting them- Returns per-row succeeded/failed with Mailchimp error codes and messages
mailchimp_segments tool
- CRUD for saved, static, and fuzzy segments; free tier supports static and basic saved segments — advanced dynamic conditions require Premium
list-memberspages current segment membershipbatch-update-membersadds/removes many subscribers from a static segment in one call — not reversible in one shotdeleteis exposed here (unlike audiences/merge-fields), since removing a segment doesn't destroy subscriber data
mailchimp_merge_fields tool
list/get/create/updatefor custom subscriber attributes (merge tags such asFNAME, limited to 10 characters)- No delete — removing a merge field drops that data column across every subscriber; do it in the Mailchimp UI
optionscarries type-specific config:choicesfor dropdown/radio,date_formatfor date/birthday,phone_formatfor phone
mailchimp_campaigns tool
list/get/create/update/replicatefor campaign records;get-content/set-contentmanage the HTML/plaintext payloadget-checklistruns Mailchimp's send-readiness checklist without sending;cancel-sendaborts an in-flight sendcreate-resendbuilds a resend-to-non-openers draft;pause-rss/resume-rsscontrol RSS-driven campaigns- No
send/send-test/schedule/delete— usemailchimp_send_campaignormailchimp_replicate_campaignfor dispatch (checklist-validated, gated onconfirmSend: true); delete would destroy report history on a sent campaign set-contentacceptshtml,plainText,templateId+templateSections, an archive payload, a fetchurl, orlocalTemplate(mutually exclusive withhtml/templateId)
mailchimp_send_campaign tool
- Chains create → set-content → checklist → optional test → send/schedule in one call
modedefaults todraft;send/schedulerequireconfirmSend: trueplus a re-entrant confirmation round before any campaign mutation- Blocking checklist errors throw
pre_send_checklist_failedbefore dispatch;cleanupOnError: true(default) deletes the orphaned draft on any mid-flow failure scheduleTimemust be at least 15 minutes in the future;testEmailscaps at 50 recipients
mailchimp_replicate_campaign tool
- Duplicates an existing campaign, then optionally overrides subject/previewText/fromName/replyTo/title/audience/segment/content before draft/test/send/schedule
- Same
confirmSend: trueplus re-entrant confirmation andcleanupOnErrorsemantics asmailchimp_send_campaign overridesApplied[]in the output lists which overrides actually took effect
mailchimp_reports tool
list/getare report-index reads;slicepulls one dimension viadimension(abuse-reports, advice, click-details, open-details, domain-performance, eepurl, email-activity, locations, sent-to, unsubscribed)click-detailsdrills into one URL withlinkId;open-detailsdrills into one member withsubscriberHashget/slicethrowcampaign_not_sentwhen the campaign has no send yet- For a full digest in one call, prefer
mailchimp_campaign_report
mailchimp_campaign_report tool
- One call parallelizes headline delivery/engagement metrics with top-N clicked links, top locations, and recent unsubscribes (
includeTopN, 1–100, default 10) - Throws
campaign_not_sentif the campaign hasn't been dispatched yet - Includes industry benchmarks when Mailchimp reports them for the account's declared vertical
mailchimp_templates tool
list/get/get-default-contentare reads that work on free forbase/usertemplate types;create/update/deleteare paid-tier writes regardless of typegallery(drag-and-drop) is read-gated to paid plans too- Per-section edits aren't supported here — Mailchimp's PATCH only accepts
name/html/folderId; per-section overrides at send time go throughmailchimp_campaigns(set-content) ormailchimp_send_campaign'stemplateSections - Prefer
mailchimp_local_templatesfor authoring — it works on every plan tier
mailchimp_files tool
upload/list/get/update/deletemanage Mailchimp File Manager (Content Studio); works on every plan tier including free- Size caps: 1 MB per image, 10 MB per other file;
fileDatais base64 with nodata:prefix - Upload response's
fullSizeUrlis the public CDN URL to embed in campaign HTML updatewithfolderId: 0moves a file to root; folder CRUD isn't exposed — use the Mailchimp UI or upload to root- WebP/AVIF aren't in Mailchimp's allowed-extension list — convert to PNG/JPG first
mailchimp_search tool
scope: membersmatches across all audiences (or one viaaudienceId);scope: campaignsmatches subject/title/preview/archive text- Member results split into
exactandfuzzyarrays with separate upstream totals - Capped at
includeTopNresults (1–100, default 10); usemailchimp_find_subscriberfor full subscriber detail and tags
mailchimp_assets tool
- Conditional — registered only when
MAILCHIMP_ASSETS_DIRis set list/info/sync/clear-cacheinspect and pre-warm the local-assets pipeline; most workflows never call this directly@assets/<path>references in campaign HTML auto-upload viamailchimp_send_campaign,mailchimp_replicate_campaign, ormailchimp_campaigns set-content— hash → upload cache misses → cachesha256 → fileId/URLat<assetsDir>/.mailchimp-cache.json→ rewrite to the CDN URL- Path traversal (
.., absolute paths) is rejected; deleting the cache file forces re-upload on next reference - Node-only
mailchimp_local_templates tool
- Conditional — registered only when
MAILCHIMP_TEMPLATES_DIRis set list/get/render-preview/seed-from-mailchimpmanage.etatemplate files (Eta v4 — partials, conditionals, loops) with optional YAML frontmatter (subject,previewText,vars) or a legacy<name>.meta.yamlsidecar- Canonical write path for templates on free-tier Mailchimp accounts, where the upstream
/templatesAPI is read-only - When a template declares
vars, every declared name must be present inrender-preview'svarsinput or the render fails — undeclared lookups fall back to an empty string seed-from-mailchimpbootstraps a local template from an existing Mailchimpbase/usertemplate by ID- Reference from any campaign tool via
content.localTemplate+content.localTemplateVars; mutually exclusive withhtml/templateId
mailchimp_playbook tool
topicselects a procedural playbook:send,post-send-review,deliverability,list-hygiene,onboarding,subscriber-triage,design-campaign- Returns markdown
instructionstailored to live account/audience state, aliveStatesnapshot, andnextToolSuggestionswith pre-filled arguments - Advice-only — makes no writes; the agent executes the suggested follow-up tool calls
design-campaignincludes the editorial-design reference (palette, typography, layout, graphics via CDN) tailored by audience size and engagement
mailchimp://account resource
- Account snapshot as
application/json— profile, plan, data center, total subscribers,fetchedAttimestamp - No parameters; equivalent to
mailchimp_accountoperation: info
mailchimp://audiences/{audienceId} resource
- Audience snapshot — name, contact, stats, campaign defaults, double opt-in status
audienceIdcomes frommailchimp_audiencesoperation: list
mailchimp://campaigns/{campaignId} resource
- Campaign snapshot — status, settings, recipients summary, tracking, report summary
campaignIdcomes frommailchimp_campaignsoperation: list
mailchimp://campaigns/{campaignId}/report resource
- Post-send headline metrics — bounces, opens, clicks, industry stats
- Throws a validation error if the campaign hasn't been sent yet
newsletter_from_source prompt
- Arguments:
source(URL or free-form brief, required),audienceId(optional — feeds live engagement state intodesign-campaign),seasonalContext(optional) - Chains into
mailchimp_playbook(topic: design-campaign) for audience-aware design guidance, then walks draft → test → send viamailchimp_send_campaign - Returns a single user-role message carrying the full workflow instructions
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
Mailchimp-specific:
- Auto-derives the API base URL and data center from the
-dcsuffix on the API key - Safe-by-default send workflows — re-entrant confirmation before dispatch, pending-status imports, no permanent deletes from the agent surface
- Upstream requests share a configurable concurrency limit and 429 cooldown (
MAILCHIMP_CONCURRENCY_LIMIT) - Local-first authoring for assets and templates — bypasses the free tier's read-only Templates API and File Manager UI friction
- Declarative tag sync computes add/remove deltas instead of requiring callers to track state
Agent-friendly output:
- Provenance and freshness — plain-language
notes/notefields explain empty results (e.g. "no growth history yet" vs. zero engagement) - Graceful partial failure —
mailchimp_import_subscribersandmailchimp_segmentsbatch operations return per-row succeeded/failed with Mailchimp error codes instead of failing the whole request - Discriminated output contracts —
operation/dimensionfields on multi-operation tools tell the caller which optional fields are populated - Typed error contracts with required recovery hints — every declared error reason carries a
recoverystring describing the caller's next move
Getting started
Add the following to your MCP client configuration file. See docs/api-key.md for how to generate a Mailchimp API key.
{
"mcpServers": {
"mailchimp-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/mailchimp-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"MAILCHIMP_API_KEY": "your-key-with-dc-suffix-e.g.-us22"
}
}
}
}Or with npx (no Bun required):
{
"mcpServers": {
"mailchimp-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/mailchimp-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"MAILCHIMP_API_KEY": "your-key-with-dc-suffix-e.g.-us22"
}
}
}
}Or with Docker:
{
"mcpServers": {
"mailchimp-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"-e", "MAILCHIMP_API_KEY=your-key-with-dc-suffix-e.g.-us22",
"ghcr.io/cyanheads/mailchimp-mcp-server:latest"
]
}
}
}For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 MAILCHIMP_API_KEY=... bun run start:http
# Server listens at http://localhost:3010/mcpPrerequisites
- Bun v1.4.0 or higher (or Node.js v24+).
- A Mailchimp Marketing API key — the key's
-dcsuffix (e.g.-us22) identifies your data center and is parsed at startup.
Installation
- Clone the repository:
git clone https://github.com/cyanheads/mailchimp-mcp-server.git- Navigate into the directory:
cd mailchimp-mcp-server- Install dependencies:
bun install- Configure environment:
cp .env.example .env
# edit .env and set MAILCHIMP_API_KEYConfiguration
| Variable | Description | Default |
|:---------|:------------|:--------|
| MAILCHIMP_API_KEY | Required. Mailchimp Marketing API key including -dc suffix (e.g. abc…-us22). | — |
| MAILCHIMP_BASE_URL | Override API base URL (for mock servers or tests). | https://{dc}.api.mailchimp.com/3.0 |
| MAILCHIMP_TIMEOUT_MS | Per-request timeout in milliseconds. | 60000 |
| MAILCHIMP_MAX_RETRIES | Max retry attempts for transient upstream failures (0-10). | 3 |
| MAILCHIMP_CONCURRENCY_LIMIT | Max in-flight upstream requests across all tools in this process (1-10). | 4 |
| MAILCHIMP_ASSETS_DIR | Absolute path to a local assets directory. Enables mailchimp_assets and auto-upload of @assets/<path> references in campaign HTML. Node-only. | unset |
| MAILCHIMP_TEMPLATES_DIR | Absolute path to a local templates directory. Enables mailchimp_local_templates and content.localTemplate on campaign tools. Node-only. | unset |
| MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
| MCP_SESSION_MODE | auto, stateful, or stateless; auto resolves to stateful. HTTP requires stateful for campaign confirmation and rejects a stateless override. Stdio is unaffected. | stateful |
| MCP_HTTP_HOST | HTTP server hostname. | 127.0.0.1 |
| MCP_HTTP_PORT | HTTP server port. | 3010 |
| MCP_HTTP_ENDPOINT_PATH | MCP endpoint path. | /mcp |
| MCP_AUTH_MODE | Auth mode: none, jwt, or oauth. | none |
| MCP_LOG_LEVEL | Log level (RFC 5424). | info |
| LOGS_DIR | Directory for log files (Node.js only). | <project-root>/logs |
| OTEL_ENABLED | Enable OpenTelemetry. | false |
See .env.example for the full list of optional overrides.
Local assets (optional)
Set MAILCHIMP_ASSETS_DIR to enable a local-image workflow on top of Mailchimp's File Manager. Drop image files into the directory, reference them in HTML as @assets/<relative-path>, and the server uploads + rewrites at send time.
export MAILCHIMP_ASSETS_DIR=/Users/me/Pictures/email-assetsThen in a campaign:
<img src="@assets/hero.png" alt="Hero">
<a href="@assets/whitepaper.pdf">Download</a>When mailchimp_send_campaign (or mailchimp_campaigns set-content / mailchimp_replicate_campaign contentOverride) sees these references, it:
- Hashes each referenced file (SHA-256).
- Uploads cache misses to Mailchimp File Manager via the
mailchimp_filestool surface. - Caches
sha256 → file_id + URLat<assetsDir>/.mailchimp-cache.json(atomic writes; safe to delete to force re-upload). - Rewrites every
@assets/<path>to the public CDN URL before passing content upstream.
The mailchimp_assets tool exposes list, info, sync (pre-warm), and clear-cache for direct inspection — most workflows don't need it.
Caveats:
- Mailchimp caps images at 1 MB and other files at 10 MB. Oversize files fail before upload with an actionable error.
- Allowed extensions: see the
mailchimp_filestool description. WebP and AVIF are NOT in the allowlist — convert to PNG/JPG. - Path traversal is rejected (
../and absolute paths throwForbidden). - The
mailchimp_assetstool is Node-only.
Local templates (optional)
Set MAILCHIMP_TEMPLATES_DIR to enable a local-template authoring workflow on top of Eta (v4 — fast, ESM-native, supports partials/conditionals/loops). This is the canonical write path for templates on free-tier Mailchimp accounts, where the upstream /templates API is read-only.
export MAILCHIMP_TEMPLATES_DIR=/Users/me/email-templatesemail-templates/
welcome.eta # body + optional YAML frontmatter
newsletter.eta
partials/
header.eta
footer.etaTemplate (welcome.eta) — YAML frontmatter on top, Eta body below:
---
subject: "Welcome to {{brand}}"
previewText: "Onboarding starts here"
vars:
- firstName
- brand
---
<%~ include('partials/header', it) %>
<h1>Hello <%= it.firstName %></h1>
<p>Welcome to <%= it.brand %>.</p>
<img src="@assets/hero.png" alt="Hero">Frontmatter and its fields are optional. When vars: is present, every listed variable must be supplied; undeclared variable lookups render as an empty string.
Sidecar fallback (legacy): prior to v0.3.1, meta lived in a separate
<name>.meta.yamlfile next to the body. That form still works for backward compatibility — if a.etahas no frontmatter, the loader falls back to reading the sidecar. Frontmatter takes precedence when both exist.
Reference from any campaign tool:
{
"audienceId": "abc123",
"subject": "Welcome to Acme",
"fromName": "Casey",
"replyTo": "[email protected]",
"content": {
"localTemplate": "welcome",
"localTemplateVars": { "firstName": "Sam", "brand": "Acme" }
},
"mode": "draft"
}The render pipeline:
- Eta renders
welcome.etawithit = { firstName: 'Sam', brand: 'Acme' }. - If L1 is configured,
@assets/hero.pngis uploaded to Mailchimp File Manager and rewritten to a CDN URL. - Final HTML is set on the campaign via Mailchimp's
set-content.
The mailchimp_local_templates tool exposes list, get, render-preview (returns HTML without sending), and seed-from-mailchimp (reads a Mailchimp base/user template by ID and writes it to disk as a starting point — useful on free where you can read but not write upstream).
Example templates in this repo
The templates/ directory holds working examples — point MAILCHIMP_TEMPLATES_DIR at it directly to try them, or copy them into your own dir as a starting point:
| Template | What it shows |
|:---------|:--------------|
| welcome.eta | Minimal body — frontmatter declaring subject / previewText / vars, <%= it.firstName %> interpolation, <% if %> conditional CTA block |
| redden-gardens-april-2026.eta | Full inline-styled HTML newsletter. Demonstrates the recommended split: Mailchimp merge tags (*\|FNAME\|*) for per-recipient personalization on real list sends, Eta vars (volume / issue / monthYear / URLs) for list-wide constants substituted at template-render time |
Caveats:
localTemplateis mutually exclusive withhtmlandtemplateIdon the same content block.- Missing declared variables fail before rendering; extra variables are allowed.
- Path traversal is rejected.
Running the server
Local development
Watch mode (transport via
MCP_TRANSPORT_TYPE):bun run dev # stdio (default) MCP_TRANSPORT_TYPE=http bun run dev # httpBuild and run:
bun run rebuild bun run start:stdio # or bun run start:httpRun checks and tests:
bun run devcheck # Lint, format, typecheck, security bun run test # Vitest test suite bun run lint:mcp # Validate MCP definitions against spec
Docker
docker build -t mailchimp-mcp-server .
docker run --rm -e MAILCHIMP_API_KEY=your-key-us22 -p 3010:3010 mailchimp-mcp-serverThe Dockerfile defaults to HTTP transport, stateful session mode, and logs to /var/log/mailchimp-mcp-server. Stateful HTTP preserves campaign confirmation for 2025-era clients. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
| Directory | Purpose |
|:---|:---|
| src/index.ts | createApp() entry point — registers tools/resources/prompts and inits services. |
| src/config | Server-specific environment variable parsing and validation with Zod. |
| src/mcp-server/tools | Tool definitions (*.tool.ts). Eighteen always-on tools plus two conditional local-workspace tools. |
| src/mcp-server/resources | Resource definitions (*.resource.ts). Four snapshot resources. |
| src/mcp-server/prompts | Prompt definitions (*.prompt.ts). Newsletter starter prompt. |
| src/services/mailchimp | Mailchimp client wrapper — HTTP plumbing, retries, normalization, typed surface. |
| templates/ | Example .eta templates (frontmatter + Eta syntax) — point MAILCHIMP_TEMPLATES_DIR here to try them. |
| tests/ | Vitest coverage for configuration, services, tool workflows, output formatting, framework contracts, and regressions. |
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catchin tool logic - Use
ctx.logfor request-scoped logging - Register new tools and resources via the barrels in
src/mcp-server/*/definitions/index.ts - Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run testLicense
Apache-2.0 — see LICENSE for details.
