Skip to main content

@hile/mcp

Expose tools, resources, and prompts from independently deployed Hile microservices through one discovered, multi-instance MCP gateway.
Start with the distributed MCP gateway guide for an end-to-end multi-service composition.

Use When

  • Different microservices own different MCP tools, resources, and prompts.
  • One MCP endpoint must expose a unified, dynamically discovered catalog.
  • Providers need independent deployments, replicas, scopes, and failure isolation.
  • Existing exact-peer Application.streamPeer() semantics such as cancellation and backpressure must carry MCP execution frames.
  • Remote clients use Streamable HTTP or a local MCP host launches a stdio process.

Do Not Use When

  • One process owns a small static MCP server and does not need Hile discovery or distributed routing.
  • Work must survive process crashes or be retried later; use a durable queue rather than an MCP invocation stream.
  • The Micro network is untrusted and no gateway-to-provider credential verifier is configured.
  • A resource should be renamed by the gateway. Resource URIs are provider-owned identities and are never rewritten.

Install

Node.js 20.12.0 or newer is required. @hile/mcp uses the official @modelcontextprotocol/server and @modelcontextprotocol/node v2 packages internally; applications do not need to register protocol handlers by hand.

Imports

Copy-Paste Example

Create one default-exported capability per mcps/**/*.mcp.ts file:
Attach the provider only after its Application is listening:
The loader accepts *.mcp.ts, *.mcp.js, *.mcp.tsx, *.mcp.jsx, and *.mcp.mjs. Every matched file must default-export one value created by defineMcpTool, defineMcpResource, or defineMcpPrompt. A load or registration failure rolls back the whole provider batch. For a programmatic provider, compose already-defined capabilities with defineMcpProvider() and pass the immutable result directly to attachMcpProvider():
Record keys must equal the capability’s local name. A tool, resource, or prompt cannot be placed in the wrong record.

More Examples

Public entry points: Static resource:
RFC 6570 resource template:
Prompt:
completions is supported only for declared prompt arguments and RFC 6570 template variables. The gateway routes completion requests to the selected provider instance; static resources do not have completion arguments. After mutable resource data changes, publish the official resource-updated notification through the attachment. Template variables are expanded with the SDK’s RFC 6570 implementation:
The provider uses one shared update publication per Micro Application. The source validates provider ID, instance ID, fingerprint, and URI before the gateway notifies subscribed MCP clients. Sessionful stdio connections keep a per-connection resource subscription set; the Streamable HTTP adapter publishes through the official endpoint notifier and subscription event bus. Stateless HTTP requests do not retain subscriptions across requests. Unified gateway and Streamable HTTP adapter:
For an OAuth 2.0 protected resource, use the SDK-backed OAuth mode. It validates Bearer tokens and serves the RFC 9728 and RFC 8414 discovery documents on the same existing HTTP server:
@hile/mcp acts only as the OAuth Resource Server. Token issuance, client registration, consent, and authorization-server persistence remain owned by your identity platform. Process-local stdio adapter:
Use gateway.inspect() for health endpoints and diagnostics. It returns each provider’s ready or conflict state, instance count, fingerprints, conflict reasons, and the currently exposed public names.

Public API Reference

Definitions and handler context

Names must match [A-Za-z0-9._-]{1,128}. Metadata is cloned and frozen when the definition is created. Invalid schemas, annotations, cache hints, completion keys, access policies, timer values, URIs, or retry combinations fail before publication. Every handler receives McpInvocationContext: the ingress-owned Hile executionContext, an abort signal, a verified or explicitly trusted principal, optional inputResponses, requestState, and awaited emit.progress() / emit.log() methods. Completion handlers receive the same executionContext, and capability access.authorize(principal, input, executionContext) receives it as its third argument. Credential mode binds the serialized execution context into the signed invocation descriptor, so a carrier cannot be substituted after signing. Treat requestState as untrusted unless the gateway configures the official SDK verifier. Template resource variables use the SDK Variables shape, so a variable may be a string or string array.

Provider and discovery APIs

One Application may attach multiple providers. The provider host shares one dispatcher and resource-update publication per Application, while manifests and attachment cleanup remain instance-scoped.

Gateway API

createMcpGateway(options) starts the source, builds the initial catalog, and returns McpGateway with inspect() and close(). inspect() is read-only operational state. It reports provider readiness, instance counts, fingerprints, conflicts, and currently exposed names; it does not invoke discovery or providers.

HTTP and stdio adapters

Close the HTTP endpoint or stdio handle before closing the shared gateway. authInfo is process-level stdio identity; without it, scoped capabilities remain hidden.

Invocation credentials, testing, and errors

HileMcpErrorCode values are INVALID_DEFINITION, DUPLICATE_CAPABILITY, PROVIDER_ATTACH_FAILED, PROVIDER_UNAVAILABLE, CATALOG_CONFLICT, and GATEWAY_CLOSED. Transport-level MCP failures are still returned according to the official SDK behavior; callers should not assume every tool error rejects the client promise.

Compose With

  • @hile/micro supplies Registry snapshots, retained provider manifests, exact-peer routing, cancellation, and streaming.
  • @hile/http mounts the Streamable HTTP middleware without creating a second public listener.
  • @hile/core owns startup and reverse-order cleanup.
  • Standard Schema implementations such as Zod provide tool and prompt schemas.
  • @hile/redis-idempotency can protect side effects inside tools; MCP retry annotations are not a business idempotency guarantee.

Runtime And Lifecycle Notes

  • Provider files are immutable definitions. Runtime instance IDs, fingerprints, Registry topics, and message routes are owned by the attachment.
  • One Application may attach multiple providers. A shared application-scoped dispatcher routes by provider instance and remains registered until the last attachment closes.
  • Every provider instance publishes a retained manifest. Discovery retrieves all matching manifests and their Registry-observed publisher addresses in one batched snapshot.
  • A provider is exposed only when every live instance for its provider ID has the same fingerprint. Mixed rolling deployments are reported as conflicts and fail closed.
  • Public tool and prompt names default to providerId.localName. Configure naming.aliases and the ., -, or _ separator when required. Resource URIs remain unchanged.
  • Compatible instances are selected round-robin. Invocation is bound to the selected instance ID, fingerprint, and publisher address so a stale catalog cannot execute a replacement implementation.
  • idempotent-failover performs at most one alternate-instance retry and is legal only for tools annotated both read-only and idempotent. A completed result, client cancellation, or downstream notification failure is never retried.
  • Provider execution emits progress, log, and one terminal-result frame through a bounded internal channel. Producer emits await capacity, and request cancellation reaches validation, authorization, handlers, connection establishment, and streaming.
  • Concurrent cold calls to one provider address share connection establishment. Registry discovery is polled into a cached catalog instead of queried per MCP request.
  • Long-lived stdio and subscription-capable servers receive catalog diffs and list_changed notifications. Stateless HTTP requests use the cached current projection.
  • Prompt and resource-template completion uses the official SDK completion API and executes on the owning provider. Resource updates use official subscription notifications, are delivered only to matching subscriptions, and are accepted from every currently discovered compatible instance fingerprint.
  • Capability metadata supports official titles, descriptions, icons, annotations, _meta, resource size, and cache hints. Gateway-level list/read cache hints are configured with cacheHints.
  • OAuth mode delegates Bearer verification, challenges, and metadata documents to official SDK helpers; the package does not implement an authorization server.
  • HTTP authentication determines the external principal and scopes. Capability access.scopes, access.authorize, and gateway isCapabilityExposed are separate defense layers.
  • Credential mode signs a short-lived, replay-protected envelope bound to the provider, instance, fingerprint, capability, input, and principal. Prefer one Ed25519 Gateway authority: the Gateway keeps the private key, while every Provider can consume the same non-secret public key from deployment configuration. Providers cannot mint Gateway credentials. Verifiers bound accepted lifetime and allow a small explicit clock tolerance. During rotation, Providers may accept overlapping publicKeys before the Gateway switches its private key. HMAC remains available for compatibility and requires a different key per provider or trust domain.
  • Capability-required scopes are part of the discovered Provider manifest. MCP_SCOPE_ALL (*) is an explicit administrator grant covering every discovered capability scope; use it only when automatic access to future Providers is intended.
  • trusted-internal is explicit, propagates an unsigned principal, and is appropriate only when every peer able to reach the Micro operation is trusted.
  • Client-echoed requestState stays unknown unless requestState.verify is configured on the gateway.
  • Close the external transport first, then the gateway, then provider attachments, and finally the underlying Micro applications. Close operations are serialized; provider teardown withdraws discovery before removing handlers.

Anti-Patterns

  • Writing MCP capabilities in arbitrary boot files instead of default-exported mcps/**/*.mcp.* files.
  • Omitting explicit HTTP authentication mode or gateway-to-provider invocation security.
  • Reusing one HMAC secret across unrelated providers or security domains.
  • Setting idempotent-failover on a write tool or treating a retry annotation as exactly-once execution.
  • Querying the Registry for every tool call instead of using createHileMcpProviderSource().
  • Routing by namespace after selecting an instance; use the built-in exact-peer source.
  • Trusting requestState, client claims, resource variables, or handler input before validation.
  • Creating a second HTTP listener only for MCP when an existing Hile HTTP server can mount the middleware.

Verification Checklist

  • Every *.mcp.* file has one default export created by the matching defineMcp* function.
  • Tool inputSchema, optional outputSchema, prompt argsSchema, and resource URIs/templates compile successfully.
  • The provider application is listening before attachMcpProvider() runs.
  • Provider and gateway use matching credential configuration, with distinct secrets per provider.
  • Host, Origin, and authentication policies are explicit on the HTTP adapter.
  • OAuth deployments return protected-resource metadata and a Bearer challenge that points to it.
  • gateway.inspect() reports ready and the expected tool, resource, and prompt names.
  • Two compatible replicas appear under one provider ID and receive calls; a mixed-fingerprint rollout produces a conflict instead of routing.
  • Progress/log delivery, client cancellation, timeout, and bounded backpressure are exercised.
  • Scoped capabilities are hidden without the scope and callable with it over both HTTP and configured stdio.
  • Adding or removing a provider updates a long-lived client’s catalog notification.
  • Prompt and resource-template completion returns provider-owned suggestions, and a subscribed resource receives notifications/resources/updated after notifyResourceUpdated().
  • Transport, gateway, attachments, and applications close without retained manifests, live handlers, sockets, or timers.

Complete Tutorial

Continue with the distributed MCP gateway guide for provider layout, gateway boot, HTTP and stdio transports, multi-instance routing, security boundaries, performance, failure semantics, and verification.

Package-Local References

The npm package ships README.md, AI.md, and ARCHITECTURE.md alongside its runtime entry points.