Skip to content

SFDC HTTP Transport MCP Server with OAuth from CLI - #2

Merged
alexandergroman merged 16 commits into
mainfrom
test
Feb 12, 2026
Merged

SFDC HTTP Transport MCP Server with OAuth from CLI #2
alexandergroman merged 16 commits into
mainfrom
test

Conversation

@alexandergroman

@alexandergroman alexandergroman commented Feb 11, 2026

Copy link
Copy Markdown
Collaborator

Key Changes

HTTP Server & Transport Layer

  • New http-server.ts: Express-based HTTP server implementing the MCP StreamableHTTP transport protocol
  • Handles POST requests for MCP tool calls
  • GET endpoint with SSE keepalive pings (30s interval) to prevent gateway timeouts
  • Stateless architecture - no server-side session state
  • Health check endpoint at /
  • MCP endpoint at /mcp

AsyncLocalStorage for Request Isolation

  • New request-context.ts: Implements Node.js AsyncLocalStorage for per-request context isolation
  • Enables multi-tenant support where each request carries its own OAuth credentials
  • runWithContext() wraps tool execution to ensure auth context propagates through async operations
  • Prevents credential leakage between concurrent requests from different users
  • Shims process.chdir() to no-op in HTTP mode (directory changes not applicable in stateless context)

OAuth Authentication

  • New oauth-middleware.ts: Validates Authorization: Bearer and X-Salesforce-Instance-URL headers
  • Exempts protocol methods (initialize, ping, tools/list) from auth requirements
  • Header normalization for string | string[] types
  • New auth-helper.ts: Extracts OAuth context from MCP SDK request headers
  • Updated auth.ts: Connection creation prioritizes OAuth tokens over CLI credentials

Tool Updates for OAuth Mode

  • get_username.ts / list_all_orgs.ts: Conditionally detect OAuth mode and return helpful messages explaining that usernameOrAlias is ignored
  • New CRUD tools: create_record, update_record, delete_record, get_record, describe_object, search_records

Docker & CI/CD

  • New Dockerfile: Multi-stage build for production deployment
  • New docker-compose.yml: Local development setup
  • New .github/workflows/ci-asc.yml: Build and push to ECR registry (amd64 only)
  • New .github/workflows/image_deploy.yml: Deployment workflow

Architecture

Client Request (Jarvis Registry)
↓ Authorization: Bearer
↓ X-Salesforce-Instance-URL: (optional for now, custom header later)
OAuth Middleware (validates headers)

Express HTTP Server

AsyncLocalStorage.run(context, ...)

MCP StreamableHTTP Transport

Tool.exec(args, extra)

Auth Helper (extracts token from context)

jsforce Connection (per-request, isolated)

@copilot

@alexandergroman
alexandergroman requested review from Copilot and ryohang and removed request for ryohang February 12, 2026 17:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an Express-based StreamableHTTP transport for the Salesforce MCP server with OAuth header-based auth, request isolation via AsyncLocalStorage, and a new --api-only mode for cloud/serverless deployments.

Changes:

  • Introduces HTTP transport server (/mcp) with SSE keepalives, OAuth discovery endpoints, and an Express auth middleware.
  • Adds AsyncLocalStorage request context propagation and updates auth to prefer per-request OAuth tokens over CLI creds.
  • Adds/updates several provider tools (CRUD + search/describe) and introduces an --api-only tool registration filter.

Reviewed changes

Copilot reviewed 34 out of 36 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
packages/mcp/tsconfig.json Adds DOM lib typings for fetch/HTTP mode compilation.
packages/mcp/src/utils/request-context.ts Adds AsyncLocalStorage request context + chdir shim for HTTP mode.
packages/mcp/src/utils/registry-utils.ts Adds --api-only tool filtering during registration.
packages/mcp/src/utils/auth.ts Prefers OAuth connection (AsyncLocalStorage) over CLI auth in HTTP mode.
packages/mcp/src/utils/auth-helper.ts Implements OAuth header extraction + userinfo slow path + Connection creation.
packages/mcp/src/types/auth-context.ts Defines OAuth auth context type used by helper.
packages/mcp/src/sf-mcp-server.ts Wraps tool execution in per-request AsyncLocalStorage context.
packages/mcp/src/middleware/oauth-middleware.ts Adds Express middleware enforcing Bearer auth for tool calls.
packages/mcp/src/index.ts Adds CLI flags for HTTP transport + forces --api-only in HTTP mode.
packages/mcp/src/http-server.ts Adds Express StreamableHTTP server, OAuth discovery routes, SSE keepalive.
packages/mcp/package.json Adds Express/CORS/Helmet dependencies and typings.
packages/mcp-test-client/tsconfig.json Enables skipLibCheck for test client compilation.
packages/mcp-test-client/tsconfig.build.json Enables skipLibCheck for test client build.
packages/mcp-provider-dx-core/src/tools/update_record.ts Adds new update_record CRUD tool.
packages/mcp-provider-dx-core/src/tools/search_records.ts Adds new SOSL-based search_records tool.
packages/mcp-provider-dx-core/src/tools/list_all_orgs.ts Adds HTTP transport detection messaging for OAuth mode.
packages/mcp-provider-dx-core/src/tools/get_username.ts Adds HTTP transport detection messaging for OAuth mode.
packages/mcp-provider-dx-core/src/tools/get_record.ts Adds new get_record tool.
packages/mcp-provider-dx-core/src/tools/describe_object.ts Adds new describe_object tool.
packages/mcp-provider-dx-core/src/tools/delete_record.ts Adds new delete_record tool.
packages/mcp-provider-dx-core/src/tools/create_record.ts Adds new create_record tool.
packages/mcp-provider-dx-core/src/shared/utils.ts Adds isHttpTransport() helper for HTTP vs stdio detection.
packages/mcp-provider-dx-core/src/index.ts Registers new CRUD/search/describe tools in provider.
packages/mcp-provider-devops/tsconfig.build.json Enables skipLibCheck for provider build.
packages/mcp-provider-code-analyzer/tsconfig.build.json Enables skipLibCheck for provider build.
packages/mcp-provider-api/tsconfig.json Enables skipLibCheck for provider API build.
packages/EXAMPLE-MCP-PROVIDER/tsconfig.build.json Enables skipLibCheck for example provider build.
package.json Adds Yarn resolutions for MCP SDK and eventsource types.
docker-compose.yml Adds container configuration for running HTTP server locally.
Dockerfile Adds multi-stage image build + default HTTP OAuth-only runtime flags.
.github/workflows/image_deploy.yml Adds deployment workflow using kubectl + EKS.
.github/workflows/ci-asc.yml Adds ECR build/push workflow for Docker image.
.env.example Adds SF_USERINFO_URL env example.
.dockerignore Adds Docker build context ignore rules.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/mcp-provider-dx-core/src/tools/search_records.ts
Comment thread docker-compose.yml Outdated
Comment thread packages/mcp/src/http-server.ts Outdated
Comment thread packages/mcp/src/middleware/oauth-middleware.ts Outdated
Comment thread packages/mcp/src/utils/auth-helper.ts Outdated
Comment thread packages/mcp/src/index.ts Outdated
Comment thread packages/mcp-provider-dx-core/src/tools/create_record.ts
Comment thread packages/mcp/src/utils/request-context.ts
Comment thread packages/mcp/src/http-server.ts
Comment thread .env.example Outdated
:(

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

@ryohang ryohang left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please make a PR to the upstream without the workflow changes.


export async function getDefaultTargetDevHub(): Promise<OrgConfigInfo | undefined> {
return getDefaultConfig(OrgConfigProperties.TARGET_DEV_HUB);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

packages/mcp/src/utils/auth.ts - Major refactor

❌ Gutted core auth functions (commented out getAllAllowedOrgs, getDefaultTargetOrg, etc.)
❌ Changed getConnection() to OAuth-only
Impact: Upstream auth changes will cause merge conflicts
Recommendation: Consider a wrapper pattern instead:
typescript

Copy code
// Keep original auth.ts intact
// Create new oauth-auth.ts with OAuth-specific logic
// Use strategy pattern in getConnection() to switch modes

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

completed with wrapper pattern, no merge conflicts

Comment thread packages/mcp/src/utils/auth.ts Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 94 out of 96 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@alexandergroman
alexandergroman merged commit 0c35b26 into main Feb 12, 2026
13 of 15 checks passed
@alexandergroman
alexandergroman deleted the test branch February 12, 2026 21:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants