@bluealba/pae-mcp-sdk
v0.2.0-feature-rename-platform-to-pillar-502
Published
Utilities for Blue Alba Platform in-house MCP servers: forwarded-identity extraction and on-behalf-of (RFC 8693) gateway calls with public-origin propagation.
Downloads
581
Readme
@bluealba/pae-mcp-sdk
Utilities for Pillar in-house MCP servers that act on behalf of the user against the Pillar gateway.
It embeds the identity plumbing every such server needs:
- reading the federated identity the gateway forwards (
x-forwarded-mcp-token,x-forwarded-host,x-forwarded-proto); - OAuth 2.0 Token Exchange (RFC 8693) — trading the user's MCP token for a short-lived on-behalf-of access token, no service secret;
- public-origin propagation: the server reaches the gateway by its internal
hostname, but the gateway derives the OAuth issuer/audience of its self-issued
tokens from the request
Host. Without forwarding the public origin, token exchange and the on-behalf-of re-entry are validated against the internal host and rejected withUntrusted issuer. This SDK forwards it automatically.
Usage
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { PlatformGatewayClient, runOnBehalfOfUser } from '@bluealba/pae-mcp-sdk';
const GATEWAY_URL = process.env.GATEWAY_URL ?? 'http://pae-nestjs-gateway-service';
// `resource` is THIS server's base path (RFC 8707) — one per MCP server.
const gateway = new PlatformGatewayClient({ gatewayUrl: GATEWAY_URL, resource: '/my-mcp' });
server.registerTool('list_things', { description: '…', inputSchema: {} }, (_args, extra) =>
runOnBehalfOfUser(extra, gateway, (client, token) =>
client.request('GET', '/things', { accessToken: token }),
),
);runOnBehalfOfUser reads the token from extra, binds the client to the
request's public origin, exchanges the token, runs the action with the scoped
client + access token, and maps errors to an MCP tool error. Reuse the single
exchanged token across every gateway call the action makes.
Domain clients
Extend PlatformGatewayClient with typed domain methods; scoping preserves the
subclass, so domain methods remain available on the client passed to the action:
class MyApiClient extends PlatformGatewayClient {
constructor(opts: { gatewayUrl: string }) {
super({ ...opts, resource: '/my-mcp' });
}
listThings(token: string) {
return this.request('GET', '/things', { accessToken: token });
}
}API
getForwardedMcpToken(extra)/getForwardedOrigin(extra)— read the forwarded identity.PlatformGatewayClient—exchangeToken,request,withForwardedOrigin.runOnBehalfOfUser(extra, client, action)— the full on-behalf-of tool flow.okResult/errorResult/ToolResult— MCP tool result helpers.GatewayApiError— thrown on non-2xx gateway responses.
