mcp-core API
Everything the package exports, by the path you import it from. Open an export for its signature and options.
@evolve-framework/mcp-core
The MCP server: tool, prompt and resource registration, the GraphQL client the tools call, the OAuth authorization server, JWT validation and token refresh.
Classes
GraphQLClientGraphQL client for communicating with the Evolve GraphQL Gateway.
import { GraphQLClient } from "@evolve-framework/mcp-core";This client sends HTTP requests to the Apollo Gateway, which federates queries across all backend microservices (catalog, checkout, orders, etc.).
Usage:
const data = await graphqlClient.query(MyQuery, { id: "123" });
new GraphQLClient(config: GraphQLClientConfig)| Option | Type | Description |
|---|---|---|
gatewayEndpoint | string | |
componentName | string | |
componentVersion? | string | |
persistedDocumentIdSeparator? | stringDefault: "~" | Joins component name, version and hash into a persisted document id. MoreHive Router expects a tilde. A gateway that resolves the id as a CDN path
( |
includeQueryWithDocumentId? | booleanDefault: false | Send the raw query next to MoreSome gateways reject a payload carrying only a |
| Method | Description |
|---|---|
buildDocumentId(hash: string): string | undefined | Build a full document ID path for use with persisted documents. |
query<TResult, TVariables>(
document: DocumentTypeDecoration<TResult, TVariables>,
variables: TVariables | undefined,
options: GraphQLRequestContext,
): Promise<TResult> | Execute a GraphQL query or mutation. |
queryForSession<TResult>(
query: string,
variables: Record<string, unknown> | undefined,
options: GraphQLRequestContext,
documentId?: string,
): Promise<GraphQLResultWithSessionTokens & {
data: TResult;
}> | Execute a GraphQL query/mutation and return response headers. |
McpCodegenErrorThrown when codegen has not been run or generated files are missing.
import { McpCodegenError } from "@evolve-framework/mcp-core";Extends McpError
new McpCodegenError(message: string, cause?: unknown)MCPCoreConfigBase configuration class for MCP services.
import { MCPCoreConfig } from "@evolve-framework/mcp-core";Extends BaseConfig
new MCPCoreConfig()McpServerHigh-level MCP server that provides a simpler API for working with resources, tools, and prompts.
import { McpServer } from "@evolve-framework/mcp-core";new McpServer(serverInfo: { version: string; name: string; websiteUrl?: string | undefined; description?: string | undefined; icons?: { src: string; mimeType?: string | undefined; sizes?…, options?: McpServerOptions)| Method | Description |
|---|---|
toolInputSchemaJson(name: string): Record<string, unknown> | undefined | The JSON-serialized inputSchema of a registered tool, or undefined when no such tool is registered. |
connect(transport: Transport): Promise<void> | Attaches to the given transport, starts it, and starts listening for messages. |
close(): Promise<void> | Closes the connection. |
registerResource(
name: string,
uriOrTemplate: string,
config: ResourceMetadata & { cacheHint?: CacheHint | undefined; scopeChallenge?: ScopeChallengeHandler | undefined; },
readCallback: ReadResourceCallback,
): RegisteredResource | Registers a resource with a config object and callback. |
registerTool<OutputArgs, InputArgs>(
name: string,
config: { title?: string | undefined; description?: string | undefined; inputSchema?: InputArgs | undefined; outputSchema?: OutputArgs | undefined; annotations?: { title?: string | undefined; readOnlyHint?: boolean | undefined; destructiveHint?: boolean | undefined; idempotentHint?: boolean | undefined; openWorldHint?: boolean | undefined; } | undefined; icons?: { src: string; mimeType?: string | undefined; sizes?: string[] | undefined; theme?: "light" | "dark" | undefined; }[] | undefined; scopeChallenge?: ScopeChallengeHandler | undefined; _meta?: Record<string, unknown> | undefined; },
cb: BaseToolCallback<{ [x: string]: unknown; content: ({ type: "text"; text: string; annotations?: { audience?: ("user" | "assistant")[] | undefined; priority?: number | undefined; lastModified?: string | undefined; } | undefined; _meta?: { [x: string]: unknown; } | undefined; } | { type: "image"; data: string; mimeType: string; annotations?: { audience?: ("user" | "assistant")[] | undefined; priority?: number | undefined; lastModified?: string | undefined; } | undefined; _meta?: { [x: string]: unknown; } | undefined; } | { type: "audio"; data: string; mimeType: string; annotations?: { audience?: ("user" | "assistant")[] | undefined; priority?: number | undefined; lastModified?: string | undefined; } | undefined; _meta?: { [x: string]: unknown; } | undefined; } | { uri: string; name: string; type: "resource_link"; description?: string | undefined; mimeType?: string | undefined; size?: number | undefined; annotations?: { audience?: ("user" | "assistant")[] | undefined; priority?: number | undefined; lastModified?: string | undefined; } | undefined; _meta?: { [x: string]: unknown; } | undefined; icons?: { src: string; mimeType?: string | undefined; sizes?: string[] | undefined; theme?: "light" | "dark" | undefined; }[] | undefined; title?: string | undefined; } | { type: "resource"; resource: { uri: string; text: string; mimeType?: string | undefined; _meta?: { [x: string]: unknown; } | undefined; } | { uri: string; blob: string; mimeType?: string | undefined; _meta?: { [x: string]: unknown; } | undefined; }; annotations?: { audience?: ("user" | "assistant")[] | undefined; priority?: number | undefined; lastModified?: string | undefined; } | undefined; _meta?: { [x: string]: unknown; } | undefined; })[]; _meta?: { [x: string]: unknown; "io.modelcontextprotocol/serverInfo"?: { version: string; name: string; websiteUrl?: string | undefined; description?: string | undefined; icons?: { src: string; mimeType?: string | undefined; sizes?: string[] | undefined; theme?: "light" | "dark" | undefined; }[] | undefined; title?: string | undefined; } | undefined; } | undefined; structuredContent?: unknown; isError?: boolean | undefined; } | InputRequiredResult, ServerContext, InputArgs>,
): RegisteredTool | Registers a tool with a config object and callback. |
registerPrompt(
name: string,
config: { title?: string | undefined; description?: string | undefined; argsSchema?: undefined; icons?: { src: string; mimeType?: string | undefined; sizes?: string[] | undefined; theme?: "light" | "dark" | undefined; }[] | undefined; scopeChallenge?: ScopeChallengeHandler | undefined; _meta?: Record<string, unknown> | undefined; },
cb: (ctx: ServerContext) => InputRequiredResult | { [x: string]: unknown; messages: { role: "user" | "assistant"; content: { type: "text"; text: string; annotations?: { audience?: ("user" | "assistant")[] | undefined; priority?: number | undefined; lastModified?: string | undefined; } | undefined; _meta?: { [x: string]: unknown; } | undefined; } | { type: "image"; data: string; mimeType: string; annotations?: { audience?: ("user" | "assistant")[] | undefined; priority?: number | undefined; lastModified?: string | undefined; } | undefined; _meta?: { [x: string]: unknown; } | undefined; } | { type: "audio"; data: string; mimeType: string; annotations?: { audience?: ("user" | "assistant")[] | undefined; priority?: number | undefined; lastModified?: string | undefined; } | undefined; _meta?: { [x: string]: unknown; } | undefined; } | { uri: string; name: string; type: "resource_link"; description?: string | undefined; mimeType?: string | undefined; size?: number | undefined; annotations?: { audience?: ("user" | "assistant")[] | undefined; priority?: number | undefined; lastModified?: string | undefined; } | undefined; _meta?: { [x: string]: unknown; } | undefined; icons?: { src: string; mimeType?: string | undefined; sizes?: string[] | undefined; theme?: "light" | "dark" | undefined; }[] | undefined; title?: string | undefined; } | { type: "resource"; resource: { uri: string; text: string; mimeType?: string | undefined; _meta?: { [x: string]: unknown; } | undefined; } | { uri: string; blob: string; mimeType?: string | undefined; _meta?: { [x: string]: unknown; } | undefined; }; annotations?: { audience?: ("user" | "assistant")[] | undefined; priority?: number | undefined; lastModified?: string | undefined; } | undefined; _meta?: { [x: string]: unknown; } | undefined; }; }[]; _meta?: { [x: string]: unknown; "io.modelcontextprotocol/serverInfo"?: { version: string; name: string; websiteUrl?: string | undefined; description?: string | undefined; icons?: { src: string; mimeType?: string | undefined; sizes?: string[] | undefined; theme?: "light" | "dark" | undefined; }[] | undefined; title?: string | undefined; } | undefined; } | undefined; description?: string | undefined; } | Promise<InputRequiredResult | { [x: string]: unknown; messages: { role: "user" | "assistant"; content: { type: "text"; text: string; annotations?: { audience?: ("user" | "assistant")[] | undefined; priority?: number | undefined; lastModified?: string | undefined; } | undefined; _meta?: { [x: string]: unknown; } | undefined; } | { type: "image"; data: string; mimeType: string; annotations?: { audience?: ("user" | "assistant")[] | undefined; priority?: number | undefined; lastModified?: string | undefined; } | undefined; _meta?: { [x: string]: unknown; } | undefined; } | { type: "audio"; data: string; mimeType: string; annotations?: { audience?: ("user" | "assistant")[] | undefined; priority?: number | undefined; lastModified?: string | undefined; } | undefined; _meta?: { [x: string]: unknown; } | undefined; } | { uri: string; name: string; type: "resource_link"; description?: string | undefined; mimeType?: string | undefined; size?: number | undefined; annotations?: { audience?: ("user" | "assistant")[] | undefined; priority?: number | undefined; lastModified?: string | undefined; } | undefined; _meta?: { [x: string]: unknown; } | undefined; icons?: { src: string; mimeType?: string | undefined; sizes?: string[] | undefined; theme?: "light" | "dark" | undefined; }[] | undefined; title?: string | undefined; } | { type: "resource"; resource: { uri: string; text: string; mimeType?: string | undefined; _meta?: { [x: string]: unknown; } | undefined; } | { uri: string; blob: string; mimeType?: string | undefined; _meta?: { [x: string]: unknown; } | undefined; }; annotations?: { audience?: ("user" | "assistant")[] | undefined; priority?: number | undefined; lastModified?: string | undefined; } | undefined; _meta?: { [x: string]: unknown; } | undefined; }; }[]; _meta?: { [x: string]: unknown; "io.modelcontextprotocol/serverInfo"?: { version: string; name: string; websiteUrl?: string | undefined; description?: string | undefined; icons?: { src: string; mimeType?: string | undefined; sizes?: string[] | undefined; theme?: "light" | "dark" | undefined; }[] | undefined; title?: string | undefined; } | undefined; } | undefined; description?: string | undefined; }>,
): RegisteredPrompt | Registers a prompt with a config object and callback. |
isConnected(): boolean | Checks if the server is connected to a transport. |
sendLoggingMessage(
params: { level: "error" | "debug" | "info" | "notice" | "warning" | "critical" | "alert" | "emergency"; data: unknown; _meta?: { [x: string]: unknown; progressToken?: string | number | undefined; "io.modelcontextprotocol/related-task"?: { taskId: string; } | undefined; } | undefined; logger?: string | undefined; },
sessionId?: string,
): Promise<void> | Sends a logging message to the client, if connected. |
sendResourceListChanged(): void | Sends a resource list changed event to the client, if connected. |
sendToolListChanged(): void | Sends a tool list changed event to the client, if connected. |
sendPromptListChanged(): void | Sends a prompt list changed event to the client, if connected. |
Functions
createGuestSessionFactoryCreates a guest session factory function.
import { createGuestSessionFactory } from "@evolve-framework/mcp-core";function createGuestSessionFactory( graphqlClient: GraphQLClient, tokenConfig: TokenValidationConfig, documentHash?: string, options?: GuestSessionOptions,): (storeContext: StoreContext) => Promise<SessionAuthContext>| Option | Type | Description |
|---|---|---|
jwtIssuer | string | string[] | |
jwtAudience | string | string[] | |
tokenRefreshThresholdSeconds | number | |
mutation? | string | Mutation that opens a guest session. MoreOnly the tokens on the response headers are read, so the response shape
does not matter. Supply your own when your schema names the operation
differently. If the operation is marked |
Returns (storeContext: StoreContext) => Promise<SessionAuthContext>
createHealthcheckHandler
import { createHealthcheckHandler } from "@evolve-framework/mcp-core";function createHealthcheckHandler(componentName: string): RouteHandlerReturns RouteHandler
createMcpRouteHandlersCreates MCP route handlers with the given server factory.
import { createMcpRouteHandlers } from "@evolve-framework/mcp-core";function createMcpRouteHandlers( options: McpRouteHandlerOptions,): { postHandler: RouteHandler; /** * The optional server-to-client SSE stream. Every reply is a JSON body, so * there is nothing to stream, and a long-lived stream behind a buffering * ingress stalls until an idle timeout and blocks the client. */ getHandler: RouteHandler; /** Session termination. There are no sessions to terminate. */ deleteHandler: RouteHandler;}| Option | Type | Description |
|---|---|---|
createServer | CreateServerWithContext | Factory that creates a new MCP Server instance per request. |
clientId | string | Client identifier used for requests through these handlers. |
storeDefaults? | StoreContext | Fallbacks for store context headers. When omitted, all three
|
jwtValidation? | JwtValidationConfig | Pre-validates a bearer JWT. Ignored when |
proxyAuthEnabled? | booleanDefault: false | Accept a pre-authenticated session forwarded by a trusted proxy through X-Access-Token / X-Data-Token / X-Refresh-Token. Takes precedence over a bearer token. |
oauth? | OAuthResourceServer | Requires every request to carry an access token issued by this service. |
Returns { postHandler: RouteHandler; /** * The optional server-to-client SSE stream. Every reply is a JSON body, so * there is nothing to stream, and a long-lived stream behind a buffering * ingress stalls until an idle timeout and blocks the client. */ getHandler: RouteHandler; /** Session termination. There are no sessions to terminate. */ deleteHandler: RouteHandler; }
createMcpServerFactoryCreates the createServer that registerMcpRoutes and startStdioServer take: a server exposing the generated tools, with guest sessions and token refresh wired to the gateway.
import { createMcpServerFactory } from "@evolve-framework/mcp-core";function createMcpServerFactory( options: McpServiceOptions,): CreateServerWithContext| Option | Type | Description |
|---|---|---|
config | MCPCoreConfig | The service's configuration, already loaded when the factory runs. |
name | string | The MCP server name, shown to clients. |
loadTools | () => Promise<GeneratedTools> | Imports the generated tools, for example |
version? | stringDefault: "1.0.0" | The server version. |
plugins? | MCPPlugin[] | |
contextArguments? | ((tools: GeneratedTools) => ToolContextArgument[]) | Arguments that select the context a tool runs in. |
Returns CreateServerWithContext
createRateLimitOptionsCreates rate limit plugin options for Fastify.
import { createRateLimitOptions } from "@evolve-framework/mcp-core";function createRateLimitOptions( config?: RateLimitOptions, grantOf?: GrantOf,): RateLimitPluginOptions| Option | Type | Description |
|---|---|---|
max? | numberDefault: 100 | Maximum number of requests per time window. |
addressMax? | numberDefault: 1000 | With OAuth, |
timeWindowSeconds? | numberDefault: 60 (1 minute) | Time window in seconds. |
allowList? | string[] | ((req: FastifyRequest<RouteGenericInterface, RawServerDefault, IncomingMessage, FastifySchema, FastifyTypeProviderDefault, unknown, FastifyBaseLogger… | Keys or a predicate that are exempt from rate limiting. Use this for infrastructure probes or internal callers that must never be throttled. An array is matched against the generated key. |
keyGenerator? | ((req: FastifyRequest<RouteGenericInterface, RawServerDefault, IncomingMessage, FastifySchema, FastifyTypeProviderDefault, unknown, FastifyBaseLogger, ResolveFa… | Overrides how a request is bucketed. The default keys on the connection
with OAuth, and otherwise on |
store? | FastifyRateLimitStoreCtor | Custom store implementation for the request counters. The default store is in-process, so counters are per-instance and reset when the process restarts — provide a shared store to limit across instances. MoreTakes precedence over |
redis? | any | Redis client used to share counters across instances. MoreSilently ignored when |
Returns RateLimitPluginOptions
createSessionLoggerCreates a child logger with session context (clientId and sessionId).
import { createSessionLogger } from "@evolve-framework/mcp-core";This branches off the root logger rather than the context-aware one: a session logger outlives the request that opened the session and is reused for every later request on it, so binding the opening request's trace id and path into it would label all subsequent traffic with the wrong trace.
function createSessionLogger( context: { clientId: string; sessionId: string; },): Logger$1| Option | Type | Description |
|---|---|---|
clientId | string | |
sessionId | string |
Returns Logger$1
createTokenRefresherCreates the token refresher helpers used by the tool execution flow: - ensureRefreshTokens proactively refreshes tokens if they are near expiry (best-effort: returns the original context if refresh fails).
import { createTokenRefresher } from "@evolve-framework/mcp-core";function createTokenRefresher( graphqlClient: GraphQLClient, tokenConfig: TokenValidationConfig, documentHash?: string, options?: TokenRefresherOptions,): { ensureRefreshTokens: EnsureRefreshTokens; refreshSessionTokens: RefreshSessionTokens;}| Option | Type | Description |
|---|---|---|
jwtIssuer | string | string[] | |
jwtAudience | string | string[] | |
tokenRefreshThresholdSeconds | number | |
mutation? | string | Mutation that renews the session tokens. MoreIf the operation is marked |
isRefreshSuccessful? | ((data: unknown) => boolean) | Reads success out of the mutation response. Response shapes differ across
schemas, so a consumer whose mutation does not return |
Returns { ensureRefreshTokens: EnsureRefreshTokens; refreshSessionTokens: RefreshSessionTokens; }
createToolFromGeneratedCreates an executable MCP tool from a generated tool definition.
import { createToolFromGenerated } from "@evolve-framework/mcp-core";The handler executes the GraphQL query/mutation using the queryString
and passes the arguments as variables. Blank string arguments are stripped
via stripBlankStrings before they reach the gateway.
function createToolFromGenerated(generated: GeneratedMCPTool): ExecutableMCPTool| Option | Type | Description |
|---|---|---|
name | string | |
description | string | |
inputSchema | { type: "object"; properties: Record<string, unknown>; required?: string[] | undefined; } | |
documentId | string | |
queryString | string | |
requiredScopes? | string[] | |
businessUnit? | "REQUIRED" | "NONE" | From |
Returns ExecutableMCPTool
endToolInvocation
import { endToolInvocation } from "@evolve-framework/mcp-core";function endToolInvocation( timer: ToolInvocationTimer, success: boolean, errorType?: string,): void| Option | Type | Description |
|---|---|---|
toolName | string | |
startTime | number |
Returns void
getToolDurationHistogram
import { getToolDurationHistogram } from "@evolve-framework/mcp-core";function getToolDurationHistogram(): Histogram<Attributes>Returns Histogram
getToolInvocationsCounter
import { getToolInvocationsCounter } from "@evolve-framework/mcp-core";function getToolInvocationsCounter(): Counter<Attributes>Returns Counter
oauthFromConfigThe authorization server for a service's configuration, or undefined while MCP_OAUTH_SECRETS is unset, which leaves OAuth off.
import { oauthFromConfig } from "@evolve-framework/mcp-core";function oauthFromConfig( config: MCPCoreConfig, options: OAuthFromConfigOptions,): OAuthServerOptions | undefined| Option | Type | Description |
|---|---|---|
scopes | string[] | The scopes this service offers. |
resourceName? | string | The display name of this resource in its metadata. |
accessTokenTtlSeconds? | numberDefault: 900 | Access token lifetime. |
refreshTokenTtlSeconds? | numberDefault: 2592000 (30 days) | Refresh token lifetime. |
authorizationCodeTtlSeconds? | numberDefault: 60 | Authorization code lifetime. |
replayStore? | OAuthReplayStore | Enforces single use across instances. When given, a used refresh token is refused as well, which is what makes rotation mean anything. |
clients? | OAuthClient[] | Clients known ahead of time, next to metadata documents. |
allowClient? | ((client: OAuthClient) => boolean | Promise<boolean>)Default: every client with a valid registration | Decides whether a client may connect. |
refreshSession? | ((session: SealedSession) => Promise<SealedSession | null>) | Renews a session through the gateway, or returns null when it ended. |
reapplySession? | ((session: SealedSession) => Promise<SealedSession>) | Restores what a refresh reset, such as the customer's selection. |
revokeSession? | ((session: SealedSession) => Promise<void>) | Ends a session through the gateway, for token revocation. |
generated? | GeneratedTools |
Returns OAuthServerOptions | undefined
preValidateJwtPre-validates a JWT token for use with the MCP server.
import { preValidateJwt } from "@evolve-framework/mcp-core";Why Pre-validation?
This function provides defense in depth by validating tokens before they are forwarded to the GraphQL Gateway. Benefits include:
Fail Fast: Invalid tokens are rejected immediately at the MCP layer, providing faster feedback to clients and reducing unnecessary Gateway calls.
Better Error Messages: Specific validation errors (expired, wrong issuer, etc.) can be returned to clients instead of generic authentication failures.
Reduced Load: Obviously invalid tokens never reach the Gateway, reducing load on downstream services.
Security Logging: Token validation failures can be logged at the edge for security monitoring.
Important Notes
- This does NOT verify the token signature. Signature verification requires access to the signing keys and is performed by the GraphQL Gateway.
- This validates claims (iss, aud, exp) against configured values.
- The Gateway remains the authoritative source for authentication decisions.
function preValidateJwt( token: string, config: JwtValidationConfig,): JwtValidationResult| Option | Type | Description |
|---|---|---|
jwtIssuer | string | string[] | |
jwtAudience | string | string[] |
Returns JwtValidationResult
recordToolInvocation
import { recordToolInvocation } from "@evolve-framework/mcp-core";function recordToolInvocation( toolName: string, durationMs: number, success: boolean, errorType?: string,): voidReturns void
registerMcpRateLimitRegisters the rate limiter with MCP-aware defaults on a Fastify instance.
import { registerMcpRateLimit } from "@evolve-framework/mcp-core";For a service that registers its own MCP routes — several endpoints in one process, for instance. Register it inside an encapsulated scope if the instance also carries routes that must not be throttled.
function registerMcpRateLimit( app: FastifyInstance<RawServerDefault, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTypeProviderDefault>, options?: RateLimitOptions,): void| Option | Type | Description |
|---|---|---|
max? | numberDefault: 100 | Maximum number of requests per time window. |
addressMax? | numberDefault: 1000 | With OAuth, |
timeWindowSeconds? | numberDefault: 60 (1 minute) | Time window in seconds. |
allowList? | string[] | ((req: FastifyRequest<RouteGenericInterface, RawServerDefault, IncomingMessage, FastifySchema, FastifyTypeProviderDefault, unknown, FastifyBaseLogger… | Keys or a predicate that are exempt from rate limiting. Use this for infrastructure probes or internal callers that must never be throttled. An array is matched against the generated key. |
keyGenerator? | ((req: FastifyRequest<RouteGenericInterface, RawServerDefault, IncomingMessage, FastifySchema, FastifyTypeProviderDefault, unknown, FastifyBaseLogger, ResolveFa… | Overrides how a request is bucketed. The default keys on the connection
with OAuth, and otherwise on |
store? | FastifyRateLimitStoreCtor | Custom store implementation for the request counters. The default store is in-process, so counters are per-instance and reset when the process restarts — provide a shared store to limit across instances. MoreTakes precedence over |
redis? | any | Redis client used to share counters across instances. MoreSilently ignored when |
Returns void
registerMcpRoutes
import { registerMcpRoutes } from "@evolve-framework/mcp-core";function registerMcpRoutes( app: FastifyInstance<RawServerDefault, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTypeProviderDefault>, options: CreateAppOptions,): void| Option | Type | Description |
|---|---|---|
createServer | CreateServerWithContext | Factory function that creates a new MCP Server instance. |
clientId | string | Client identifier used for sessions created by this MCP service. |
mcpEndpointPath? | stringDefault: "/mcp" | The endpoint path for MCP requests. |
storeDefaults? | StoreContext | Fallbacks for store context headers. When omitted, all three
|
jwtValidation? | JwtValidationConfig | JWT validation configuration for pre-validating tokens. If not provided, JWT pre-validation is skipped. |
proxyAuthEnabled? | boolean | Enable trusted-proxy auth via X-Access-Token / X-Data-Token / X-Refresh-Token headers (takes precedence over Authorization: Bearer). |
oauth? | OAuthServerOptions | Serves an OAuth 2.1 authorization server next to the MCP endpoint and
requires its tokens on every request. Takes the place of |
rateLimit? | RateLimitOptions | Rate limiting configuration for the MCP routes. MoreRate limiting is opt-in: the limiter is only registered when this option is provided. Pass an empty object to accept the defaults (100 requests per 60 seconds), or omit it to run without a limiter. |
healthcheck? | boolean | Serves |
Returns void
registerPromptsRegisters all MCP prompts on the server.
import { registerPrompts } from "@evolve-framework/mcp-core";Prompts are templated messages that MCP clients can use to provide context or instructions to AI assistants.
function registerPrompts( mcp: McpServer, graphqlClient: GraphQLClient, prompts?: MCPPrompt[],): voidReturns void
registerResourcesRegisters all MCP resources on the server.
import { registerResources } from "@evolve-framework/mcp-core";Resources are read-only data sources that MCP clients can fetch. Each resource executes a GraphQL query to retrieve data.
function registerResources( mcp: McpServer, graphqlClient: GraphQLClient, resources?: MCPResource[],): voidReturns void
registerToolsRegisters all MCP tools on the server with authentication and plugin support.
import { registerTools } from "@evolve-framework/mcp-core";function registerTools(options: RegisterToolsOptions): void| Option | Type | Description |
|---|---|---|
mcp | McpServer | |
tools | ExecutableMCPTool[] | |
graphqlClient | GraphQLClient | |
getSessionContext | GetSessionContext | |
setSessionAuth | SetSessionAuth | |
plugins | MCPPlugin[] | |
ensureRefreshTokens | EnsureRefreshTokens | |
refreshSessionTokens | RefreshSessionTokens | |
createGuestSession | CreateGuestSession | |
contextArguments? | ToolContextArgument[] | Arguments that select the context a tool runs in, added to its schema. |
Returns void
startStdioServerStarts the MCP Server with stdio transport.
import { startStdioServer } from "@evolve-framework/mcp-core";The server communicates via stdin/stdout, making it compatible with MCP clients like Claude Desktop.
function startStdioServer(config: StdioTransportConfig): Promise<void>| Option | Type | Description |
|---|---|---|
clientId | string | |
storeDefaults | StoreContext | |
createMCPServer | (clientId: string, getSessionContext: () => SessionContext, setSessionAuth: SetSessionAuth, setSessionStoreContext: SetSessionStoreContext) => Promise<McpServer… |
Returns Promise<void>
startToolInvocation
import { startToolInvocation } from "@evolve-framework/mcp-core";function startToolInvocation(toolName: string): ToolInvocationTimerReturns ToolInvocationTimer
Constants
loggerThe logger to be used by all applications.
import { logger } from "@evolve-framework/mcp-core";const logger: LoggerTypes
AuthChallengeWhat ends an HTTP request instead of its tool result, so the client can authorize: 401 to renew its token, 403 to ask for the scopes in scope.
import { type AuthChallenge } from "@evolve-framework/mcp-core";export type AuthChallenge = { status: 401 | 403; scope?: string[]; description?: string;};CreateServerWithContextFactory function type for creating MCP servers with request context callbacks.
import { type CreateServerWithContext } from "@evolve-framework/mcp-core";export type CreateServerWithContext = (clientId: string, getSessionContext: GetSessionContext, setSessionAuth: SetSessionAuth, setSessionStoreContext: SetSessionStoreContext) => Promise<McpServer>;ExecutableMCPToolExecutable MCP tool with a handler function.
import { type ExecutableMCPTool } from "@evolve-framework/mcp-core";Tools are actions that MCP clients can execute. Each tool can perform GraphQL mutations or queries against the Evolve GraphQL Gateway.
export type ExecutableMCPTool = MCPToolBase & { requiredScopes?: string[]; handler: (client: GraphQLClient, args: Record<string, unknown>, context: SessionContext) => Promise<unknown>;};GeneratedMCPToolGenerated MCP tool definition (data-only, serializable).
import { type GeneratedMCPTool } from "@evolve-framework/mcp-core";This type represents tool metadata extracted from GraphQL operations marked with
export type GeneratedMCPTool = MCPToolBase & { documentId: string; queryString: string; requiredScopes?: string[]; businessUnit?: "REQUIRED" | "NONE";};GeneratedToolsWhat codegen/tools writes to mcp-tools.generated.ts.
import { type GeneratedTools } from "@evolve-framework/mcp-core";export type GeneratedTools = { generatedMcpTools: GeneratedMCPTool[]; persistedDocumentIds?: Record<string, string>; excludedOperationQueries?: Record<string, string>;};GetSessionContextCallback to retrieve the context of the current request or process.
import { type GetSessionContext } from "@evolve-framework/mcp-core";export type GetSessionContext = () => SessionContext | undefined;InitialSessionContextThe context of one HTTP request.
import { type InitialSessionContext } from "@evolve-framework/mcp-core";Store fields are resolved by the route handler before this point, from headers first and configured defaults second.
export type InitialSessionContext = StoreContext & { auth?: SessionAuthContext; scopes?: ReadonlySet<string>;};JwtValidationErrorStructured JWT validation error
import { type JwtValidationError } from "@evolve-framework/mcp-core";export type JwtValidationError = { code: JwtValidationErrorCode; message: string;};JwtValidationErrorCodeError codes for JWT validation failures
import { type JwtValidationErrorCode } from "@evolve-framework/mcp-core";export type JwtValidationErrorCode = "MALFORMED_TOKEN" | "INVALID_STRUCTURE" | "DECODE_FAILED" | "TOKEN_EXPIRED" | "INVALID_ISSUER" | "INVALID_AUDIENCE" | "MISSING_CLAIMS";JwtValidationResultResult of JWT pre-validation
import { type JwtValidationResult } from "@evolve-framework/mcp-core";export type JwtValidationResult = { valid: true; payload: JWTPayload;} | { valid: false; error: JwtValidationError;};MCPPluginMCP Plugin interface.
import { type MCPPlugin } from "@evolve-framework/mcp-core";Plugins can intercept tool calls and add custom behavior. They are registered when creating an MCP service and are applied in order of registration.
export interface MCPPlugin { name: string; version: string; interceptTools?: string[]; handleTool?: (toolName: string, args: Record<string, unknown>, context: SessionContext, setSessionAuth: SetSessionAuth) => Promise<ToolHandlerResult | undefined>;}MCPPromptMCP Prompt definition.
import { type MCPPrompt } from "@evolve-framework/mcp-core";Prompts are templated messages that MCP clients can use to provide context or instructions to AI assistants.
export type MCPPrompt = { name: string; description: string; arguments?: Array<{ name: string; description: string; required?: boolean; }>; handler: (client: GraphQLClient, args: Record<string, unknown>) => Promise<PromptMessage[]>;};MCPResourceMCP Resource definition.
import { type MCPResource } from "@evolve-framework/mcp-core";Resources are read-only data sources that MCP clients can fetch. Each resource executes a GraphQL query to retrieve data from the Evolve GraphQL Gateway.
export type MCPResource = { uri: string; name: string; description: string; mimeType: string; handler: (client: GraphQLClient) => Promise<unknown>;};OAuthClientA client as the authorization server knows it.
import { type OAuthClient } from "@evolve-framework/mcp-core";export type OAuthClient = { clientId: string; name: string; redirectUris: string[]; host?: string;};OAuthReplayStoreRemembers what may only happen once.
import { type OAuthReplayStore } from "@evolve-framework/mcp-core";export type OAuthReplayStore = { consumeOnce: (key: string, ttlSeconds: number) => Promise<boolean>;};OAuthServerOptionsConfiguration of the authorization server and the MCP resource.
import { type OAuthServerOptions } from "@evolve-framework/mcp-core";export type OAuthServerOptions = OAuthSecretOptions & { resource: string; loginUrl: string; interactionSecret: string; scopes: string[]; resourceName?: string; accessTokenTtlSeconds?: number; refreshTokenTtlSeconds?: number; authorizationCodeTtlSeconds?: number; replayStore?: OAuthReplayStore; clients?: OAuthClient[]; allowClient?: (client: OAuthClient) => boolean | Promise<boolean>; refreshSession: (session: SealedSession) => Promise<SealedSession | null>; reapplySession?: (session: SealedSession) => Promise<SealedSession>; revokeSession: (session: SealedSession) => Promise<void>;};PluginContextPlugin context provided to plugins during lifecycle events.
import { type PluginContext } from "@evolve-framework/mcp-core";export interface PluginContext { sessionId: string; clientId: string; auth?: SessionAuthContext;}RegisterMcpRoutesOptions
import { type RegisterMcpRoutesOptions } from "@evolve-framework/mcp-core";export type RegisterMcpRoutesOptions = CreateAppOptions;SealedSessionA gateway session, sealed into the tokens a client holds.
import { type SealedSession } from "@evolve-framework/mcp-core";export type SealedSession = { accessToken: string; dataToken?: string; refreshToken?: string; isAuthenticated: boolean; store: StoreSelection; selection?: Record<string, string>;};SessionAuthContextAuthentication context for a request.
import { type SessionAuthContext } from "@evolve-framework/mcp-core";export type SessionAuthContext = { accessToken: string; refreshToken: string; dataToken?: string; createdAt: number; expiresAt?: number; isAuthenticated: boolean;};SessionContextEverything a tool call runs with.
import { type SessionContext } from "@evolve-framework/mcp-core";export type SessionContext = { sessionId: string; clientId: string; logger: Logger; auth?: SessionAuthContext; storeKey: string; locale: string; currency: string; headers?: Record<string, string>; scopes?: ReadonlySet<string>; challenge?: (challenge: AuthChallenge) => void;};SetSessionAuthCallback to update the authentication state of the current context, which is one request over HTTP and the process over stdio.
import { type SetSessionAuth } from "@evolve-framework/mcp-core";export type SetSessionAuth = (auth: SessionAuthContext | null) => void;SetSessionStoreContextCallback to change the store context, for example from a tool that switches store or storefront variant.
import { type SetSessionStoreContext } from "@evolve-framework/mcp-core";export type SetSessionStoreContext = (update: Partial<StoreContext>) => void;StoreContextStore scoping for a GraphQL request.
import { type StoreContext } from "@evolve-framework/mcp-core";Structurally identical to the framework's own store context, declared here so mcp-core carries no runtime dependency on the framework package.
export type StoreContext = { storeKey: string; locale: string; currency: string; headers?: Record<string, string>;};StoreContextDefaultsStore context defaults.
import { type StoreContextDefaults } from "@evolve-framework/mcp-core";Structurally identical to StoreContext — this alias exists so
transport-facing options can keep their established name.
export type StoreContextDefaults = StoreContext;StoreSelectionThe store a session was created in.
import { type StoreSelection } from "@evolve-framework/mcp-core";export type StoreSelection = Pick<StoreContext, "storeKey" | "locale" | "currency">;ToolContextArgumentAn argument that selects the context a tool runs in rather than reaching the GraphQL operation, such as a business unit.
import { type ToolContextArgument } from "@evolve-framework/mcp-core";export type ToolContextArgument = { name: string; description: string; requiredForTools?: string[]; exceptTools?: string[]; apply: (value: string, context: SessionContext, client: GraphQLClient) => Promise<SessionContext>; read: (context: SessionContext) => string | undefined;};ToolHandlerResultResult returned by a tool handler.
import { type ToolHandlerResult } from "@evolve-framework/mcp-core";export type ToolHandlerResult = { success: boolean; message?: string; error?: string; data?: unknown;};ToolInvocationTimer
import { type ToolInvocationTimer } from "@evolve-framework/mcp-core";export type ToolInvocationTimer = { toolName: string; startTime: number;};@evolve-framework/mcp-core/codegen
The codegen plugins and transforms that generate tools from operations, plus persisted-document validation.
Functions
createMcpToolTransformDocument transform that filters operations to only include those marked with the
import { createMcpToolTransform } from "@evolve-framework/mcp-core/codegen";function createMcpToolTransform( options?: McpToolTransformOptions,): Types.DocumentTransformObject| Option | Type | Description |
|---|---|---|
stripDirectives? | booleanDefault: false | Strip |
Returns Types.DocumentTransformObject
createPersistedDocumentsTerraformHookCreates a codegen hook that copies persisted documents to Terraform cloud folders.
import { createPersistedDocumentsTerraformHook } from "@evolve-framework/mcp-core/codegen";Each copied operation is sanitized by stripping
function createPersistedDocumentsTerraformHook( options?: PersistedDocumentsTerraformHookOptions,): () => void| Option | Type | Description |
|---|---|---|
cwd? | stringDefault: process.cwd() | Directory from which paths are resolved. |
sourcePath? | stringDefault: "generated/persisted-documents.json" | Source persisted-documents file path, relative to cwd. |
clouds? | string[]Default: ["aws", "gcp", "azure"] | Target cloud folder names under terraform/. |
Returns () => void
runPersistedDocumentsValidationCLI runner - validates terraform persisted documents and exits with code 1 on errors.
import { runPersistedDocumentsValidation } from "@evolve-framework/mcp-core/codegen";function runPersistedDocumentsValidation( options: ValidatePersistedDocumentsOptions,): void| Option | Type | Description |
|---|---|---|
schemaPath | string | Path to GraphQL schema file (supergraph SDL), relative to cwd. |
clouds? | string[] | Cloud folder names under terraform/. |
cwd? | string | Base directory for resolving relative paths (defaults to process.cwd()). |
Returns void
toolsPluginGraphQL Codegen plugin that generates MCP tool definitions from persisted documents.
import { toolsPlugin } from "@evolve-framework/mcp-core/codegen";This plugin reads the persisted-documents.json file generated by the client-preset and extracts tool definitions from operations marked with
function toolsPlugin( schema: GraphQLSchema, documents: DocumentFile[], config: MCPToolConfig, info?: { [key: string]: any; outputFile?: string | undefined; allPlugins?: ConfiguredPlugin[] | undefined; pluginContext?: { [key: string]: any; } | undefined; },): Types.Promisable<TOutput>| Option | Type | Description |
|---|---|---|
persistedDocumentsPath? | stringDefault: "./generated/persisted-documents.json" | Path to the persisted-documents.json file (relative to codegen.ts). |
outputFile? | string | |
allPlugins? | ConfiguredPlugin[] | |
pluginContext? | { [key: string]: any; } |
Returns Types.Promisable<TOutput>
validatePersistedDocumentsValidates terraform persisted documents against a schema SDL.
import { validatePersistedDocuments } from "@evolve-framework/mcp-core/codegen";function validatePersistedDocuments( options: ValidatePersistedDocumentsOptions,): PersistedDocumentsValidationResult| Option | Type | Description |
|---|---|---|
schemaPath | string | Path to GraphQL schema file (supergraph SDL), relative to cwd. |
clouds? | string[] | Cloud folder names under terraform/. |
cwd? | string | Base directory for resolving relative paths (defaults to process.cwd()). |
Returns PersistedDocumentsValidationResult
Constants
mcpToolTransform
import { mcpToolTransform } from "@evolve-framework/mcp-core/codegen";const mcpToolTransform: DocumentTransformObject<object>Types
PersistedDocumentsValidationError
import { type PersistedDocumentsValidationError } from "@evolve-framework/mcp-core/codegen";export type PersistedDocumentsValidationError = { cloud: string; hash: string; message: string; line?: number; column?: number;};PersistedDocumentsValidationResult
import { type PersistedDocumentsValidationResult } from "@evolve-framework/mcp-core/codegen";export type PersistedDocumentsValidationResult = { success: boolean; errors: PersistedDocumentsValidationError[]; operationCount: number; checkedClouds: number;};@evolve-framework/mcp-core/codegen/tools
The codegen plugin that generates the tool definitions.
Functions
pluginGraphQL Codegen plugin that generates MCP tool definitions from persisted documents.
import { plugin } from "@evolve-framework/mcp-core/codegen/tools";This plugin reads the persisted-documents.json file generated by the client-preset and extracts tool definitions from operations marked with
function plugin( schema: GraphQLSchema, documents: DocumentFile[], config: MCPToolConfig, info?: { [key: string]: any; outputFile?: string | undefined; allPlugins?: ConfiguredPlugin[] | undefined; pluginContext?: { [key: string]: any; } | undefined; },): Types.Promisable<TOutput>| Option | Type | Description |
|---|---|---|
persistedDocumentsPath? | stringDefault: "./generated/persisted-documents.json" | Path to the persisted-documents.json file (relative to codegen.ts). |
outputFile? | string | |
allPlugins? | ConfiguredPlugin[] | |
pluginContext? | { [key: string]: any; } |
Returns Types.Promisable<TOutput>
stripMcpDirectivesStrip
import { stripMcpDirectives } from "@evolve-framework/mcp-core/codegen/tools";function stripMcpDirectives(query: string): stringReturns string
@evolve-framework/mcp-core/codegen/persisted-queries
The persisted-documents transform that keeps the tool operations registered with the gateway.
Functions
createMcpToolTransformDocument transform that filters operations to only include those marked with the
import { createMcpToolTransform } from "@evolve-framework/mcp-core/codegen/persisted-queries";function createMcpToolTransform( options?: McpToolTransformOptions,): Types.DocumentTransformObject| Option | Type | Description |
|---|---|---|
stripDirectives? | booleanDefault: false | Strip |
Returns Types.DocumentTransformObject
Constants
mcpToolTransform
import { mcpToolTransform } from "@evolve-framework/mcp-core/codegen/persisted-queries";const mcpToolTransform: DocumentTransformObject<object>@evolve-framework/mcp-core/codegen/validate-persisted-documents
A check that every tool's operation is registered with the gateway.
Functions
runPersistedDocumentsValidationCLI runner - validates terraform persisted documents and exits with code 1 on errors.
import { runPersistedDocumentsValidation } from "@evolve-framework/mcp-core/codegen/validate-persisted-documents";function runPersistedDocumentsValidation( options: ValidatePersistedDocumentsOptions,): void| Option | Type | Description |
|---|---|---|
schemaPath | string | Path to GraphQL schema file (supergraph SDL), relative to cwd. |
clouds? | string[] | Cloud folder names under terraform/. |
cwd? | string | Base directory for resolving relative paths (defaults to process.cwd()). |
Returns void
validatePersistedDocumentsValidates terraform persisted documents against a schema SDL.
import { validatePersistedDocuments } from "@evolve-framework/mcp-core/codegen/validate-persisted-documents";function validatePersistedDocuments( options: ValidatePersistedDocumentsOptions,): PersistedDocumentsValidationResult| Option | Type | Description |
|---|---|---|
schemaPath | string | Path to GraphQL schema file (supergraph SDL), relative to cwd. |
clouds? | string[] | Cloud folder names under terraform/. |
cwd? | string | Base directory for resolving relative paths (defaults to process.cwd()). |
Returns PersistedDocumentsValidationResult
Types
PersistedDocumentsValidationError
import { type PersistedDocumentsValidationError } from "@evolve-framework/mcp-core/codegen/validate-persisted-documents";export type PersistedDocumentsValidationError = { cloud: string; hash: string; message: string; line?: number; column?: number;};PersistedDocumentsValidationResult
import { type PersistedDocumentsValidationResult } from "@evolve-framework/mcp-core/codegen/validate-persisted-documents";export type PersistedDocumentsValidationResult = { success: boolean; errors: PersistedDocumentsValidationError[]; operationCount: number; checkedClouds: number;};@evolve-framework/mcp-core/plugins
The plugin interface for adding tools, prompts and resources.
Types
MCPPluginMCP Plugin interface.
import { type MCPPlugin } from "@evolve-framework/mcp-core/plugins";Plugins can intercept tool calls and add custom behavior. They are registered when creating an MCP service and are applied in order of registration.
export interface MCPPlugin { name: string; version: string; interceptTools?: string[]; handleTool?: (toolName: string, args: Record<string, unknown>, context: SessionContext, setSessionAuth: SetSessionAuth) => Promise<ToolHandlerResult | undefined>;}PluginContextPlugin context provided to plugins during lifecycle events.
import { type PluginContext } from "@evolve-framework/mcp-core/plugins";export interface PluginContext { sessionId: string; clientId: string; auth?: SessionAuthContext;}@evolve-framework/mcp-core/application
createMcpModule, a service as an application module with OAuth when given oauth, and startMcpStdio, the same service over stdio. createMcpHttpDomainService is deprecated.
Functions
createMcpModuleCreates the MCP routes, the healthcheck and OAuth as an application module, from the service's configuration, which must be loaded by then.
import { createMcpModule } from "@evolve-framework/mcp-core/application";function createMcpModule( options: McpModuleOptions,): Promise<McpModule>| Option | Type | Description |
|---|---|---|
config | MCPCoreConfig | The service's configuration, already loaded when the factory runs. |
name | string | The MCP server name, shown to clients. |
loadTools | () => Promise<GeneratedTools> | Imports the generated tools, for example |
version? | stringDefault: "1.0.0" | The server version. |
plugins? | MCPPlugin[] | |
contextArguments? | ((tools: GeneratedTools) => ToolContextArgument[]) | Arguments that select the context a tool runs in. |
oauth? | McpOAuthOptions | |
rateLimit? | RateLimitOptions | On top of the configuration, such as |
healthcheck? | boolean | Serves |
Returns Promise<McpModule>
startMcpStdioServes a service over stdin and stdout, for a client that spawns the process.
import { startMcpStdio } from "@evolve-framework/mcp-core/application";function startMcpStdio(service: McpServiceOptions): Promise<void>| Option | Type | Description |
|---|---|---|
config | MCPCoreConfig | The service's configuration, already loaded when the factory runs. |
name | string | The MCP server name, shown to clients. |
loadTools | () => Promise<GeneratedTools> | Imports the generated tools, for example |
version? | stringDefault: "1.0.0" | The server version. |
plugins? | MCPPlugin[] | |
contextArguments? | ((tools: GeneratedTools) => ToolContextArgument[]) | Arguments that select the context a tool runs in. |
Returns Promise<void>
Types
CreateMcpHttpDomainServiceConfig
import { type CreateMcpHttpDomainServiceConfig } from "@evolve-framework/mcp-core/application";export type HttpDomainServiceConfig = { name: string; host: string; port: number; mcpEndpointPath?: string; storeDefaults: StoreContextDefaults; jwtValidation?: JwtValidationConfig; proxyAuthEnabled?: boolean; rateLimit?: RegisterMcpRoutesOptions["rateLimit"]; createServer: CreateServerWithContext; onStart?: ApplicationOptions["onStart"]; onShutdown?: ApplicationOptions["onShutdown"];};McpOAuthOptionsWhat a service decides about OAuth.
import { type McpOAuthOptions } from "@evolve-framework/mcp-core/application";export type McpOAuthOptions = Omit<OAuthFromConfigOptions, "generated" | "scopes">;Deprecated
Still exported so existing code keeps working. Each one says what replaces it.
createMcpHttpDomainServiceCreates an HTTP domain service for the MCP module.
import { createMcpHttpDomainService } from "@evolve-framework/mcp-core/application";function createMcpHttpDomainService( config: HttpDomainServiceConfig,): Promise<Application>| Option | Type | Description |
|---|---|---|
name | string | A unique name for the domain service, used for logging and identification purposes. |
host | string | Host to bind the HTTP server to. |
port | number | Port to bind the HTTP server to. |
storeDefaults | StoreContext | Default store context values. |
createServer | CreateServerWithContext | Factory function that creates a new MCP Server instance. This will be called for each incoming request to create a server with the appropriate context. |
mcpEndpointPath? | stringDefault: "/mcp" | The endpoint path for MCP requests. |
jwtValidation? | JwtValidationConfig | JWT validation configuration for pre-validating tokens. If provided, tokens will be validated before session creation. |
proxyAuthEnabled? | boolean | Enable trusted-proxy auth via X-Access-Token / X-Data-Token / X-Refresh-Token headers (takes precedence over Authorization: Bearer). |
rateLimit? | RateLimitOptions | Rate limiting configuration for incoming requests. If not provided, defaults will be applied (e.g., 100 requests per minute). |
onStart? | (() => void | Promise<void>) | Sets up what the servers share, such as the cache connection, in
|
onShutdown? | (() => void | Promise<void>) | Releases what |
Returns Promise<Application>
Not listed: 14 options types. They appear as the tables under the constructors and functions they type.

