agentleFS
ficaviolaodorata520ficaviolaodorata520/met-museum-mcp-server/skills/api-config/SKILL.md

api-config

Skill0 starsChanged 6 months agoApache-2.0View on GitHub

Reference for core and server configuration in `@cyanheads/mcp-ts-core`. Covers env var tables with defaults, priority order, server-specific Zod schema pattern, and Workers lazy-parsing requirement.

  • Reads credentials

The file

We split this skill into the rules it gives an agent

4 rules. About 0 are common, 0 are distinctive, and 4 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈0

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Import: AppConfig, config, parseConfig, resetConfig, ConfigSchema from @cyanheads/mcp-ts-core/config.

    line 16
  2. Very specific:

    Use the lazy init/accessor pattern — do not parse process.env at module top-level.

    line 213
  3. Very specific:

    Instead of a raw ZodError dump at startup.

    line 245
  4. Very specific:

    Workers: Do not parse process.env at module top-level.

    line 249

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Overview

Configuration has two layers: core config (managed by the framework, env-driven) and server config (your own Zod schema for domain-specific env vars). Never merge them.

Import: AppConfig, config, parseConfig, resetConfig, ConfigSchema from @cyanheads/mcp-ts-core/config.


Core config

Managed by @cyanheads/mcp-ts-core. Validated via Zod from environment variables. Uses a lazy proxy — parsing is deferred until the first property read.

Priority (highest to lowest):

  1. name/version overrides passed to createApp() or createWorkerHandler()
  2. Environment variables
  3. package.json fields

Identity

Env VarAppConfig fieldDefaultNotes
MCP_SERVER_NAMEmcpServerNamepackage.json nameOverrides package name
MCP_SERVER_VERSIONmcpServerVersionpackage.json versionOverrides package version
MCP_SERVER_DESCRIPTIONmcpServerDescriptionpackage.json descriptionOptional
PACKAGE_NAMEpkg.namepackage.json nameRarely needed
PACKAGE_VERSIONpkg.versionpackage.json versionRarely needed
NODE_ENVenvironmentdevelopmentAliases: dev→development, prod→production, test→testing
MCP_LOG_LEVELlogLeveldebugAliases: warn→warning, err→error, fatal/silent→emerg, trace→debug, information→info
LOGS_DIRlogsPath<project-root>/logsNode.js only; absolute or relative to project root

Transport

Env VarAppConfig fieldDefaultNotes
MCP_TRANSPORT_TYPEmcpTransportTypestdiostdio | http
MCP_HTTP_PORTmcpHttpPort3010Port for HTTP transport
MCP_HTTP_HOSTmcpHttpHost127.0.0.1Bind address
MCP_HTTP_ENDPOINT_PATHmcpHttpEndpointPath/mcpHTTP endpoint path
MCP_HTTP_MAX_BODY_BYTESmcpHttpMaxBodyBytes1048576 (1 MiB)Max inbound JSON-RPC request body; oversized requests get 413 before per-request allocation. Does not cap upstream data staged into a canvas or response sizes. 0 disables (defer to runtime/proxy).
MCP_HTTP_MAX_PORT_RETRIESmcpHttpMaxPortRetries15Retry count if port is busy
MCP_HTTP_PORT_RETRY_DELAY_MSmcpHttpPortRetryDelayMs50Delay between port retries (ms)
MCP_SESSION_MODEmcpSessionModeautostateless | stateful | auto
MCP_STATEFUL_SESSION_STALE_TIMEOUT_MSmcpStatefulSessionStaleTimeoutMs180000030 min; stale session eviction
MCP_RESPONSE_VERBOSITYmcpResponseVerbositystandardminimal | standard | full
MCP_ALLOWED_ORIGINSmcpAllowedOrigins—Comma-separated list; omit to allow all
MCP_SERVER_RESOURCE_IDENTIFIERmcpServerResourceIdentifier—RFC 8707 resource indicator URL
MCP_PUBLIC_URLmcpPublicUrl—Public-facing origin for reverse proxies (Cloudflare Tunnel, nginx, ALB) so emitted URLs carry the correct scheme
MCP_HEARTBEAT_INTERVAL_MSmcpHeartbeatIntervalMs0 (disabled)Heartbeat ping interval; 0 disables
MCP_HEARTBEAT_MISS_THRESHOLDmcpHeartbeatMissThreshold3Missed heartbeats before session is considered stale
MCP_GC_PRESSURE_INTERVAL_MSmcpGcPressureIntervalMs0 (disabled)Bun-only opt-in forced GC loop for HTTP deployments with heap growth

Auth

Env VarAppConfig fieldDefaultNotes
MCP_AUTH_MODEmcpAuthModenonenone | jwt | oauth
MCP_AUTH_SECRET_KEYmcpAuthSecretKey—Required for jwt mode; min 32 chars
MCP_AUTH_DISABLE_SCOPE_CHECKSmcpAuthDisableScopeChecksfalseWhen true, bypasses both withRequiredScopes (declared auth: [...]) and checkScopes (runtime/tenant scopes). Token validation (sig/aud/iss/exp) intact. Logs a WARNING at startup. See api-auth skill.
OAUTH_ISSUER_URLoauthIssuerUrl—Required for oauth mode
OAUTH_AUDIENCEoauthAudience—Required for oauth mode
OAUTH_JWKS_URIoauthJwksUri—Override JWKS endpoint (otherwise derived from issuer)
OAUTH_JWKS_COOLDOWN_MSoauthJwksCooldownMs3000005 min; min time between JWKS refetches
OAUTH_JWKS_TIMEOUT_MSoauthJwksTimeoutMs5000JWKS fetch timeout (ms)
DEV_MCP_AUTH_BYPASSdevMcpAuthBypassfalseSkip auth in development; blocked in production
MCP_JWT_EXPECTED_ISSUERmcpJwtExpectedIssuer—Optional issuer validation for JWT mode
MCP_JWT_EXPECTED_AUDIENCEmcpJwtExpectedAudience—Optional audience validation for JWT mode
DEV_MCP_CLIENT_IDdevMcpClientId—Dev-only: override client ID
DEV_MCP_SCOPESdevMcpScopes—Dev-only: comma-separated scope overrides

OAuth proxy (optional sub-object)

Activated when OAUTH_PROXY_AUTHORIZATION_URL or OAUTH_PROXY_TOKEN_URL is set.

Env VarAppConfig fieldNotes
OAUTH_PROXY_AUTHORIZATION_URLoauthProxy.authorizationUrlProxy authorization endpoint
OAUTH_PROXY_TOKEN_URLoauthProxy.tokenUrlProxy token endpoint
OAUTH_PROXY_REVOCATION_URLoauthProxy.revocationUrlOptional
OAUTH_PROXY_ISSUER_URLoauthProxy.issuerUrlOptional
OAUTH_PROXY_SERVICE_DOCUMENTATION_URLoauthProxy.serviceDocumentationUrlOptional
OAUTH_PROXY_DEFAULT_CLIENT_REDIRECT_URISoauthProxy.defaultClientRedirectUrisComma-separated list

Storage

Env VarAppConfig fieldDefaultNotes
STORAGE_PROVIDER_TYPEstorage.providerTypein-memoryin-memory | filesystem | supabase | cloudflare-r2 | cloudflare-kv | cloudflare-d1; aliases: mem, fs
STORAGE_FILESYSTEM_PATHstorage.filesystemPath./.storageUsed only when providerType is filesystem

Canvas (DataCanvas primitive — Tier 3, optional peer dep @duckdb/node-api)

Env VarAppConfig fieldDefaultNotes
CANVAS_PROVIDER_TYPEcanvas.providerTypenonenone | duckdb. Set to duckdb to enable core.canvas. Fails closed on Cloudflare Workers (DuckDB has no V8-isolate build).
CANVAS_DEFAULT_MEMORY_LIMIT_MBcanvas.defaultMemoryLimitMb1024Per-canvas DuckDB memory_limit PRAGMA value, in MB.
CANVAS_EXPORT_PATHcanvas.exportRootPath./.canvas-exportsSandbox root for path-targeted exports. Absolute paths and .. traversal are rejected.
CANVAS_MAX_CANVASES_PER_TENANTcanvas.maxCanvasesPerTenant100Active canvas cap per tenant; throws RateLimited when exceeded.
CANVAS_TTL_MScanvas.ttlMs86400000Sliding TTL (24 h). Every operation extends the expiry.
CANVAS_ABSOLUTE_CAP_MScanvas.absoluteCapMs604800000Absolute cap from creation (7 d). Sliding window clamps to this.
CANVAS_SWEEPER_INTERVAL_MScanvas.sweeperIntervalMs60000Background sweep interval. Set to 0 to disable.
CANVAS_DEFAULT_ROW_LIMITcanvas.defaultRowLimit10000Default cap on rows materialized into a query response.
CANVAS_SCHEMA_SNIFF_ROWScanvas.schemaSniffRows100Rows to materialize for schema inference when schema is omitted.

Platform support: Linux/macOS/Windows × x64 supported, Linux/macOS arm64 supported. Windows arm64 unsupported (DuckDB upstream). See api-canvas skill for the full DataCanvas reference.

Supabase (optional sub-object)

Activated when both SUPABASE_URL and SUPABASE_ANON_KEY are set.

Env VarAppConfig fieldNotes
SUPABASE_URLsupabase.urlRequired to activate
SUPABASE_ANON_KEYsupabase.anonKeyRequired to activate
SUPABASE_SERVICE_ROLE_KEYsupabase.serviceRoleKeyOptional; elevated access

LLM

Env VarAppConfig fieldDefaultNotes
OPENROUTER_API_KEYopenrouterApiKey—Optional; enables LLM provider
OPENROUTER_APP_URLopenrouterAppUrlhttp://localhost:3000Reported to OpenRouter
OPENROUTER_APP_NAMEopenrouterAppNamepackage.json nameReported to OpenRouter
LLM_DEFAULT_MODELllmDefaultModelgoogle/gemini-2.5-flash-preview-05-20OpenRouter model ID
LLM_DEFAULT_TEMPERATUREllmDefaultTemperature—Float
LLM_DEFAULT_TOP_PllmDefaultTopP—Float
LLM_DEFAULT_MAX_TOKENSllmDefaultMaxTokens—Integer
LLM_DEFAULT_TOP_KllmDefaultTopK—Integer
LLM_DEFAULT_MIN_PllmDefaultMinP—Float

Telemetry

Env VarAppConfig fieldDefaultNotes
OTEL_ENABLEDopenTelemetry.enabledfalseEnable OpenTelemetry export
OTEL_SERVICE_NAMEopenTelemetry.serviceNamepackage.json name
OTEL_SERVICE_VERSIONopenTelemetry.serviceVersionpackage.json version
OTEL_EXPORTER_OTLP_TRACES_ENDPOINTopenTelemetry.tracesEndpoint—OTLP traces endpoint URL
OTEL_EXPORTER_OTLP_METRICS_ENDPOINTopenTelemetry.metricsEndpoint—OTLP metrics endpoint URL
OTEL_TRACES_SAMPLER_ARGopenTelemetry.samplingRatio1.00–1; fraction of traces to export
OTEL_LOG_LEVELopenTelemetry.logLevelINFOOTel SDK internal log level: NONE | ERROR | WARN | INFO | DEBUG | VERBOSE | ALL

Tasks

Env VarAppConfig fieldDefaultNotes
TASK_STORE_TYPEtasks.storeTypein-memoryin-memory | storage; aliases: mem/memory→in-memory, persistent→storage
TASK_STORE_TENANT_IDtasks.tenantIdsystem-tasksTenant ID for task state storage
TASK_STORE_DEFAULT_TTL_MStasks.defaultTtlMs—TTL for completed tasks (ms); null = no expiry

Speech (optional sub-object)

Activated when SPEECH_TTS_ENABLED or SPEECH_STT_ENABLED is set.

TTS (Text-to-Speech)

Env VarAppConfig fieldDefaultNotes
SPEECH_TTS_ENABLEDspeech.tts.enabledfalseEnable TTS
SPEECH_TTS_PROVIDERspeech.tts.providerelevenlabsCurrently only elevenlabs
SPEECH_TTS_API_KEYspeech.tts.apiKey—Provider API key
SPEECH_TTS_BASE_URLspeech.tts.baseUrl—Override provider base URL
SPEECH_TTS_DEFAULT_VOICE_IDspeech.tts.defaultVoiceId—Default voice identifier
SPEECH_TTS_DEFAULT_MODEL_IDspeech.tts.defaultModelId—Default model identifier
SPEECH_TTS_TIMEOUTspeech.tts.timeout—Request timeout (ms)

STT (Speech-to-Text)

Env VarAppConfig fieldDefaultNotes
SPEECH_STT_ENABLEDspeech.stt.enabledfalseEnable STT
SPEECH_STT_PROVIDERspeech.stt.provideropenai-whisperCurrently only openai-whisper
SPEECH_STT_API_KEYspeech.stt.apiKey—Provider API key
SPEECH_STT_BASE_URLspeech.stt.baseUrl—Override provider base URL
SPEECH_STT_DEFAULT_MODEL_IDspeech.stt.defaultModelId—Default model identifier
SPEECH_STT_TIMEOUTspeech.stt.timeout—Request timeout (ms)

Server config (separate schema)

Define your own Zod schema for domain-specific env vars. Never merge with core's schema.

Use the lazy init/accessor pattern — do not parse process.env at module top-level.

// src/config/server-config.ts
import { z } from '@cyanheads/mcp-ts-core';
import { parseEnvConfig } from '@cyanheads/mcp-ts-core/config';

const ServerConfigSchema = z.object({
  apiKey: z.string().describe('External API key'),
  maxResults: z.coerce.number().default(100),
});

export type ServerConfig = z.infer<typeof ServerConfigSchema>;

let _config: ServerConfig | undefined;

export function getServerConfig(): ServerConfig {
  _config ??= parseEnvConfig(ServerConfigSchema, {
    apiKey: 'MY_API_KEY',
    maxResults: 'MY_MAX_RESULTS',
  });
  return _config;
}

Why parseEnvConfig? It maps Zod schema paths to env var names so validation errors name the actual variable at fault. A missing MY_API_KEY produces:

Server config validation failed:
  - MY_API_KEY (apiKey): Invalid input: expected string, received undefined

Instead of a raw ZodError dump at startup. The framework catches the resulting ConfigurationError and prints a clean banner (full stack behind DEBUG=true).

Direct ServerConfigSchema.parse(...) still works — the framework intercepts raw ZodError thrown from setup() and converts it — but error messages won't know about env var names, so they show the Zod path (apiKey) instead of the variable name (MY_API_KEY).

Workers: Do not parse process.env at module top-level. In Workers, env bindings are injected at request time via injectEnvVars(), after all static imports. Lazy parsing is required.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.