You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@mcp-apps-kit/core

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@mcp-apps-kit/core - npm Package Compare versions

Comparing version
0.2.2
to
0.2.3
+5
-2
package.json
{
"name": "@mcp-apps-kit/core",
"version": "0.2.2",
"version": "0.2.3",
"description": "Server-side framework for building MCP applications",

@@ -47,6 +47,9 @@ "type": "module",

"express": "^5.1.0",
"jsonwebtoken": "^9.0.3",
"jwks-rsa": "^3.2.0",
"zod": "^4.0.0"
},
"devDependencies": {
"@types/express": "^5.0.0"
"@types/express": "^5.0.0",
"@types/jsonwebtoken": "^9.0.7"
},

@@ -53,0 +56,0 @@ "peerDependencies": {

+194
-14

@@ -82,6 +82,2 @@ # @mcp-apps-kit/core

### Alternative: Object Syntax with Type Assertions
If you prefer not to use `defineTool`, you can use the object syntax directly, but you'll need type assertions:
```ts

@@ -112,8 +108,15 @@ // Define schema separately

````ts
handler: async (input, context) => {
const typedInput = input as z.infer<typeof myInputSchema>;
// Now typedInput has full type safety
const value = typedInput.someProperty;
}
```ts
const myTool = defineTool({
description: "Search for items",
input: z.object({
query: z.string().describe("Search query text"),
maxResults: z.number().optional().describe("Maximum number of results to return"),
}),
handler: async (input) => {
// input is fully typed
return { results: [] };
},
});
```

@@ -157,3 +160,3 @@ ## Attach UI to tool outputs

});
````
```

@@ -256,3 +259,3 @@ ## Plugins, Middleware & Events

**See the [kanban example](../../examples/kanban/src/index.ts) for a complete demonstration.**
**See the [kanban-mcp-example](https://github.com/AndurilCode/kanban-mcp-example) for a complete demonstration.**

@@ -274,3 +277,3 @@ ## Debug Logging

debug: {
enabled: true, // Enable debug logging
logTool: true, // Enable debug logging
level: "debug", // "debug" | "info" | "warn" | "error"

@@ -313,2 +316,179 @@ },

## OAuth 2.1 Authentication
Secure your MCP server with OAuth 2.1 bearer token validation. The framework includes built-in JWT verification with automatic JWKS discovery, complying with RFC 6750 (Bearer Token Usage) and RFC 8414 (Authorization Server Metadata).
### Quick Start
```ts
import { createApp } from "@mcp-apps-kit/core";
const app = createApp({
name: "my-app",
version: "1.0.0",
tools: {
/* ... */
},
oauth: {
protectedResource: "http://localhost:3000",
authorizationServer: "https://auth.example.com",
scopes: ["mcp:read", "mcp:write"], // Optional: required scopes
},
});
```
### Configuration
| Option | Type | Required | Description |
| --------------------- | -------------------- | -------- | --------------------------------------------------------------- |
| `protectedResource` | `string` | ✅ | Public URL of this MCP server (used as default audience) |
| `authorizationServer` | `string` | ✅ | Issuer URL of OAuth 2.1 authorization server |
| `jwksUri` | `string` | ❌ | Explicit JWKS URI (auto-discovered if not provided) |
| `algorithms` | `string[]` | ❌ | Allowed JWT algorithms (default: `["RS256"]`) |
| `audience` | `string \| string[]` | ❌ | Expected audience claim (default: `protectedResource`) |
| `scopes` | `string[]` | ❌ | Required OAuth scopes for all requests |
| `tokenVerifier` | `TokenVerifier` | ❌ | Custom token verification (for non-JWT tokens or introspection) |
### How It Works
1. **Automatic Discovery**: Framework discovers JWKS endpoint via `/.well-known/oauth-authorization-server`
2. **Request Validation**: Bearer tokens are validated before tool execution
3. **Auth Context Injection**: Authenticated user info is injected into tool handlers
> **Important**: This server is a **protected resource** (API/service that requires OAuth tokens), NOT an authorization server. The OAuth endpoints exposed by this framework provide metadata about the external authorization server that issues tokens, not authentication functionality itself.
#### OAuth Metadata Endpoints
When OAuth is enabled, the framework exposes two metadata endpoints:
- **`/.well-known/oauth-authorization-server`**: Returns metadata about your external authorization server (e.g., Auth0, Keycloak)
- **`/.well-known/oauth-protected-resource`**: Returns metadata about this protected resource (scopes, authorization servers)
These endpoints help clients discover OAuth configuration, but do not provide token issuance or user authentication.
```ts
tools: {
get_user_data: defineTool({
description: "Get authenticated user data",
input: z.object({}),
handler: async (input, context) => {
// Access authenticated user information
const auth = context.auth;
console.log("User ID:", auth.subject);
console.log("Scopes:", auth.scopes);
console.log("Expires at:", new Date(auth.expiresAt * 1000));
return { userId: auth.subject };
},
}),
}
```
### Auth Context Properties
When OAuth is enabled, tool handlers receive authenticated context via `context.auth`:
```ts
interface AuthContext {
subject: string; // User identifier (JWT 'sub' claim)
scopes: string[]; // OAuth scopes granted to token
expiresAt: number; // Token expiration (Unix timestamp)
clientId: string; // OAuth client ID
issuer: string; // Token issuer (authorization server)
audience: string | string[]; // Token audience
token?: string; // Original bearer token
extra?: Record<string, unknown>; // Additional JWT claims
}
```
### Error Responses
The framework returns RFC 6750-compliant error responses:
```http
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="http://localhost:3000",
error="invalid_token",
error_description="Token expired"
```
| Error Code | Status | Description |
| -------------------- | ------ | ------------------------------------ |
| `invalid_request` | 400 | Malformed request |
| `invalid_token` | 401 | Token expired, revoked, or malformed |
| `insufficient_scope` | 403 | Token missing required scopes |
### Custom Token Verification
For non-JWT tokens or token introspection:
```ts
import type { TokenVerifier } from "@mcp-apps-kit/core";
const customVerifier: TokenVerifier = {
async verifyAccessToken(token: string) {
// Call your token introspection endpoint
const response = await fetch("https://auth.example.com/introspect", {
method: "POST",
body: new URLSearchParams({ token }),
});
const data = await response.json();
if (!data.active) {
throw new Error("Token inactive");
}
return {
token,
clientId: data.client_id,
scopes: data.scope.split(" "),
expiresAt: data.exp,
extra: { subject: data.sub },
};
},
};
const app = createApp({
oauth: {
protectedResource: "http://localhost:3000",
authorizationServer: "https://auth.example.com",
tokenVerifier: customVerifier, // Use custom verifier
},
});
```
### Security Features
- ✅ **JWT Signature Verification**: RSA/ECDSA signature validation via JWKS
- ✅ **Claim Validation**: Automatic validation of `iss`, `aud`, `exp`, `sub`, `client_id`
- ✅ **Scope Enforcement**: Optional scope validation for all requests
- ✅ **Issuer Normalization**: Handles trailing slash differences
- ✅ **Clock Skew Tolerance**: 5-second tolerance for timestamp validation
- ✅ **HTTPS Enforcement**: JWKS URIs must use HTTPS in production
- ✅ **Subject Override**: Framework overrides client-provided subject for security
### Production Considerations
1. **HTTPS Required**: JWKS URIs must use HTTPS in production environments
2. **Key Caching**: JWKS keys are cached with automatic refresh (10-minute TTL)
3. **Rate Limiting**: Built-in rate limiting for JWKS requests (10 requests/minute)
4. **Error Handling**: All validation errors return proper WWW-Authenticate headers
### Testing Without OAuth
Disable OAuth for development/testing:
```ts
const app = createApp({
name: "my-app",
version: "1.0.0",
tools: {
/* ... */
},
// No oauth config = OAuth disabled
});
```
## What you get

@@ -324,3 +504,3 @@

- Examples:
- ../../examples/kanban
- [kanban-mcp-example](https://github.com/AndurilCode/kanban-mcp-example) (comprehensive demo)
- ../../examples/minimal

@@ -327,0 +507,0 @@ - ../../examples/restaurant-finder

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display