mcp-framework
repository·main·Indexed 21 days ago
https://github.com/quantgeekdev/mcp-frameworkA TypeScript framework for building Model Context Protocol (MCP) servers. It provides architectural abstractions for tools, resources, and prompts with automatic directory-based discovery and built-in validation. The framework includes support for OAuth 2.1 authentication (JWT and Token Introspection) with integrations for Auth0, Okta, AWS Cognito, and Azure AD/Entra ID, as well as a documentation server package (@mcpframework/docs) for exposing documentation sites via MCP tools.
What's inside mcp-framework
- mcp-framework is a TypeScript framework designed for building Model Context Protocol (MCP) servers. It provides an opinionated architecture that simplifies the creation of MCP servers by using automatic directory-based discovery for tools, resources, and prompts. It is built to provide full type safety using Zod schema validation.
Understand the MCP Specification Compliance of mcp-framework
mainAs of the audit on 2026-04-01,
mcp-framework(v0.2.19) is targeting an older version of the Model Context Protocol (MCP) specification (approximately the 2025-03-26 era).Key Limitations to Note:
- Missing Spec Features: The framework lacks support for several features introduced in the June and November 2025 spec revisions, including tool annotations, structured content, elicitation, tasks, logging protocol, progress tracking, and audio content.
- SDK Version: The framework uses
@modelcontextprotocol/sdk@1.11.0, which is significantly behind the latest version (1.29.0). - Protocol Gaps: It does not yet support the
MCP-Protocol-VersionHTTP header or theImplementation.descriptionfield required by newer Streamable HTTP specifications.
Use this framework if you need a stable implementation of core primitives like tools, prompts, resources, sampling, and completions, but be aware that advanced protocol features and the latest spec enhancements are not yet available.
MCP Specification Compliance Roadmap
mainThe
mcp-frameworkis undergoing a multi-phase implementation plan to align with the MCP 2025-11-25 specification. The roadmap follows a strict dependency graph where foundational SDK upgrades and security hardening must occur before schema evolution and advanced features like audio content or task management are implemented.Execution Order
- Phase 0: SDK Upgrade (Foundation)
- Phase 1: Security Hardening (Origin validation, protocol version headers, localhost binding)
- Phase 2: Core Schema Evolution (Titles, icons, tool annotations, structured output schemas)
- Phase 3: New Content Types (Audio, resource links, content annotations)
- Phase 4: Protocol Utilities (Logging, progress tracking, cancellation)
- Phase 5: Client Features (Elicitation/Form mode, roots support, sampling)
- Phase 6: Advanced Features (Experimental Tasks, Elicitation URL mode)
Understand the OAuth 2.1 Authorization Flow in MCP
mainThe MCP Framework implements a standard OAuth 2.1 flow with PKCE. The sequence of interactions is as follows:
- Initial Request: Client attempts
GET /messageswithout a token. - Challenge: Server returns
401 UnauthorizedwithWWW-Authenticateheaders containing theauthorization_uriandresourceidentifier. - Discovery: Client fetches metadata from
/.well-known/oauth-protected-resourceto identify authorization servers. - Authorization: Client initiates the flow via
GET /authorizeusing PKCE (code_challenge). - Callback: After user authorization, the Authorization Server redirects to the server's
/oauth/callbackwith acodeandstate. - Token Exchange: The server exchanges the
codeandcode_verifier(PKCE) for anaccess_tokenviaPOST /token. - Authenticated Access: Client uses the
access_tokenin theAuthorization: Bearerheader to successfully access protected resources.
- Initial Request: Client attempts
Understand OAuth 2.1 Authentication Components
mainThe OAuth 2.1 implementation in MCP Framework consists of several key components:
OAuthAuthProvider: The primary provider implementing theAuthProviderinterface.JWTValidator: Handles asynchronous JWT validation with JWKS support (validates signature, expiration, audience, and issuer).IntrospectionValidator: Handles OAuth token introspection via RFC 7662.ProtectedResourceMetadata: Generates RFC 9728 metadata.
Metadata Endpoint:
- Path:
/.well-known/oauth-protected-resource - Access: Public (no authentication required).
- Function: Returns authorization server URLs and the resource identifier to clients.
How directory-based discovery works in mcp-framework
mainmcp-framework uses an automatic directory-based discovery pattern. Instead of manually registering every tool or resource, you organize your code into specific directories within your
src/folder. The framework automatically discovers and loads these components at startup based on their location.Recommended project structure:
my-mcp-server/ ├── src/ │ ├── tools/ # Automatically discovered tools │ ├── resources/ # Automatically discovered resources │ ├── prompts/ # Automatically discovered prompts │ ├── apps/ # Automatically discovered MCP Apps │ ├── app-views/ # HTML templates for MCP Apps │ └── index.ts # Server entry point ├── package.json └── tsconfig.jsonmy-mcp-server/ ├── src/ │ ├── tools/ │ ├── resources/ │ ├── prompts/ │ ├── apps/ │ ├── app-views/ │ └── index.ts ├── package.json └── tsconfig.jsonCore capabilities of mcp-framework
mainmcp-framework supports several key MCP primitives and communication methods:
MCP Primitives
- Tools: Functions that AI models can invoke for data fetching, processing, and transformations.
- Resources: Readable data sources with subscription capabilities for external data access.
- Prompts: Reusable template systems for structured conversations.
- Apps: Interactive HTML UIs (dashboards, forms, charts) that render inline in hosts like Claude, ChatGPT, and VS Code.
Communication Transports
- STDIO: Used for CLI tools and local integrations.
- HTTP Stream: Recommended for web applications.
- SSE: For legacy web applications (deprecated).
Authentication
- Built-in support for OAuth 2.1, JWT, and API key authentication.
Security Best Practices for OAuth in MCP
mainWhen deploying OAuth with MCP Framework, follow these security guidelines:
- HTTPS in Production: Never transmit OAuth tokens over unencrypted HTTP. Use a TLS terminator like Nginx, Caddy, or AWS ALB in production.
- Token Storage: On the client side, store tokens in
httpOnlycookies or secure storage. Never uselocalStoragedue to XSS vulnerabilities. - Token Lifespan: Use short-lived access tokens (15-60 minutes) and implement a refresh token flow.
- Audience Validation: Always configure unique audiences for different services to prevent cross-service token reuse.
Request structured user input via Elicitation (Form Mode)
mainYou can enable MCP servers to pause tool execution and request structured user input from the client using the
elicit()method within a tool. This uses theelicitation/createmethod informmode, presenting the user with a schema-validated form.Important Constraints:
- Flat Schemas Only: The schema must be a flat object. Nested objects and arrays are not supported (except for multi-select enums).
- Client Support: Always ensure the client supports the
elicitationcapability before callingelicit(). If the client does not support it, the server should throw an error:"Client does not support elicitation. Cannot request user input." - Security: Do not use elicitation to request sensitive data like passwords or API keys.
- Response Handling: You must handle three possible user actions:
accept,decline, andcancel.
// Inside a class extending BaseTool protected async elicit( message: string, requestedSchema: { type: 'object'; properties: Record<string, ElicitationFieldSchema>; required?: string[]; } ): Promise<ElicitationResult> { // Implementation uses this.server.request with method 'elicitation/create' }Understand the difference between `name` and `title`
mainIn the MCP Framework,
nameandtitleserve distinct purposes:name: The programmatic identifier. It is used for dispatching commands (e.g.,tools/calluses thenameto identify which tool to execute).title: The human-readable display label. It is intended for UI presentation.
Crucial Rule: The framework MUST NOT use
titlefor any dispatch or matching logic. Always usenamefor programmatic operations.How resource discovery and registration works
mainThe MCP Framework handles resource discovery automatically through two primary methods:
1. Auto-discovery
If you place your resource classes in
src/resources/(or any nested subdirectories) and useexport defaultfor each class, the framework will automatically discover and register them at startup. When a client callsresources/list, these resources will be included in the response.2. Programmatic Registration
You can manually register resources using
server.addResource(ResourceClass)before callingserver.start().Note: If a resource is both auto-discovered and programmatically registered with the same URI, the programmatic registration takes precedence.
import { MCPServer } from "mcp-framework"; const server = new MCPServer({ name: "my-server", version: "1.0.0" }); server.addResource(ConfigResource); server.addResource(MarketDataResource); await server.start();Understand ContentAnnotations validation and behavior
mainWhen providing
annotations, the framework performs soft validation (logging warnings) rather than rejecting or clamping values. This ensures compatibility with various server implementations.Validation Rules
priority: Expected range is0.0to1.0. If a value is outside this range (e.g.,-0.1or1.5), a warning is logged, but the value is still passed through to the response.lastModified: Expected to be an ISO 8601 timestamp (e.g.,2025-01-12T15:00:58Zor2025-01-12). If the string is not parseable, a warning is logged, but the value is passed through.audience: Must contain only'user'or'assistant'. If other values are provided, a warning is logged.
Edge Cases
- Empty Audience: An empty array
audience: []is treated as unspecified. It is recommended not to emit an empty array in the final output. - Resource Definitions vs. Content: Annotations can exist on both the resource definition (the metadata describing the resource) and the resource content (the actual data returned when reading a resource). These values can differ.
- Missing Annotations: If no annotations are provided, the
annotationsfield will be absent from the output.