@gleanwork/mcp-config-schema
Type-safe configuration schemas and builders for MCP (Model Context Protocol) clients.
The Problem
MCP servers need to work across many different AI coding assistants—Claude Code, VS Code, Cursor, Claude Desktop, Windsurf, Goose, Codex, and more. Each client has its own:
- Configuration format: JSON, YAML, or TOML
- File location: Different paths on macOS, Linux, and Windows
- Property names:
url vs serverUrl vs uri, command vs cmd, mcpServers vs servers vs extensions
- Transport support: Some support HTTP natively, others require the
mcp-remote bridge
- Authentication patterns: Headers, environment variables, or OAuth
Without a unified solution, MCP server authors face a maintenance nightmare: writing and maintaining separate configuration logic for each client, tracking which clients support which features, and keeping up with changes across the ecosystem.
The Solution
This package provides a single source of truth for MCP client configurations. You describe your connection once, and it generates the correct configuration for any supported client:
import { MCPConfigRegistry } from '@gleanwork/mcp-config-schema';
const registry = new MCPConfigRegistry();
const options = {
transport: 'http',
serverUrl: 'https://api.example.com/mcp/default',
serverName: 'my-server',
headers: { Authorization: 'Bearer token' },
};
registry.createBuilder('cursor').buildConfiguration(options);
registry.createBuilder('vscode').buildConfiguration(options);
registry.createBuilder('goose').buildConfiguration(options);
registry.createBuilder('claude-desktop').buildConfiguration(options);
The package handles all the complexity: format differences, property mapping, platform-specific paths, transport bridging, and one-click installation URLs.
Installation
npm install @gleanwork/mcp-config-schema
Quick Start
stdio Transport (Local Server)
For stdio transport, provide registry options with your package names, then pass environment variables directly:
import { MCPConfigRegistry } from '@gleanwork/mcp-config-schema';
const registry = new MCPConfigRegistry({
serverPackage: '@your-org/mcp-server',
});
const builder = registry.createBuilder('cursor');
const config = builder.buildConfiguration({
transport: 'stdio',
env: {
MY_INSTANCE: 'my-instance',
MY_API_TOKEN: 'my-api-token',
},
});
HTTP Transport (Remote Server)
For connecting to HTTP-based MCP servers, no additional configuration is needed:
import { MCPConfigRegistry } from '@gleanwork/mcp-config-schema';
const registry = new MCPConfigRegistry();
const builder = registry.createBuilder('cursor');
const config = builder.buildConfiguration({
transport: 'http',
serverUrl: 'https://your-server.com/mcp/default',
serverName: 'my-server',
});
await builder.writeConfiguration({
transport: 'http',
serverUrl: 'https://your-server.com/mcp/default',
serverName: 'my-server',
});
const oneClickUrl = builder.buildOneClickUrl({
transport: 'http',
serverUrl: 'https://your-server.com/mcp/default',
serverName: 'my-server',
});
For HTTP transport with authentication or custom headers:
const config = builder.buildConfiguration({
transport: 'http',
serverUrl: 'https://api.example.com/mcp/default',
serverName: 'my-server',
headers: {
Authorization: 'Bearer my-api-token',
'X-Custom-Header': 'custom-value',
},
});
URL Templates with Variables
For dynamic URLs with template variables (aligned with MCP registry specification):
const config = builder.buildConfiguration({
transport: 'http',
serverUrl: 'https://api.example.com/{region}/mcp/{endpoint}',
urlVariables: {
region: 'us-east-1',
endpoint: 'default',
},
serverName: 'my-server',
});
What This Package Does
This package serves as the Single Source of Truth for MCP client configurations. It provides:
- Registry of all MCP clients and their capabilities
- Configuration builders that generate correct configs for each client
- Type-safe schemas with TypeScript types and Zod validation
- Browser support for web-based configuration tools
- Client detection to identify which clients need special handling
Supported Clients
For detailed configuration examples and requirements for each client, see CLIENTS.md.
Centrally Managed Clients
- ChatGPT - Requires web UI configuration
- Claude for Teams/Enterprise - Managed by organization admins
Core Usage
Query Client Capabilities
import { MCPConfigRegistry } from '@gleanwork/mcp-config-schema';
const registry = new MCPConfigRegistry();
const cursorConfig = registry.getConfig('cursor');
console.log(cursorConfig.displayName);
console.log(cursorConfig.userConfigurable);
console.log(cursorConfig.transports);
console.log(cursorConfig.types);
const httpClients = registry.getNativeHttpClients();
const bridgeClients = registry.getBridgeRequiredClients();
const macClients = registry.getClientsByPlatform('darwin');
Client Types
Every client declares one or more types describing where it runs. A client can be more than one (e.g. Goose ships both a desktop app and a CLI). Use these to group or filter clients by surface — for example, to build a filterable list of supported hosts:
import {
MCPConfigRegistry,
CLIENT_TYPES,
TYPE_LABELS,
type ClientType,
} from '@gleanwork/mcp-config-schema';
const registry = new MCPConfigRegistry();
const all = registry.getAllConfigs();
const cliClients = all.filter((c) => c.types.includes('cli'));
for (const type of CLIENT_TYPES) {
const inType = all.filter((c) => c.types.includes(type));
console.log(`${TYPE_LABELS[type]}: ${inType.map((c) => c.displayName).join(', ')}`);
}
Installability is a separate axis (userConfigurable): user-installable clients vs. centrally managed ones.
Consumers can provide setup destinations for centrally managed clients without
adding vendor-specific URLs to the shared client metadata:
const registry = new MCPConfigRegistry({
managedSetupUrls: {
'cursor-team': 'https://example.com/admin/mcp',
},
});
registry.getManagedSetupUrl('cursor-team');
Generate Configurations
const builder = registry.createBuilder('claude-code');
const remoteConfig = builder.buildConfiguration({
transport: 'http',
serverUrl: 'https://api.example.com/mcp/default',
serverName: 'my-server',
headers: { Authorization: 'Bearer your-token' },
});
const dynamicConfig = builder.buildConfiguration({
transport: 'http',
serverUrl: 'https://api.example.com/{region}/mcp/{endpoint}',
urlVariables: { region: 'us-east-1', endpoint: 'default' },
serverName: 'my-server',
});
const localConfig = builder.buildConfiguration({
transport: 'stdio',
env: {
YOUR_INSTANCE: 'your-instance',
YOUR_API_TOKEN: 'your-api-token',
},
});
const partialConfig = builder.buildConfiguration({
transport: 'http',
serverUrl: 'https://api.example.com/mcp/default',
serverName: 'my-server',
includeRootObject: false,
});
Partial Configuration (without root object)
The includeRootObject option allows you to generate just the server configuration entry without the outer wrapper (mcpServers, servers, or extensions depending on the client). This is useful when you need to merge configurations into an existing setup:
const partialConfig = builder.buildConfiguration({
transport: 'http',
serverUrl: 'https://api.example.com/mcp/default',
serverName: 'my_server',
includeRootObject: false,
});
const existingConfig = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
existingConfig.mcpServers = {
...existingConfig.mcpServers,
...partialConfig,
};
fs.writeFileSync(configPath, JSON.stringify(existingConfig, null, 2));
Validate Configurations
import {
validateConnectionOptions,
safeValidateConnectionOptions,
} from '@gleanwork/mcp-config-schema';
const result = safeValidateConnectionOptions({
transport: 'http',
serverUrl: 'https://your-server.com/mcp/default',
});
if (!result.success) {
console.error('Validation errors:', result.error.issues);
}
Browser Support
This package works in browsers! Use the /browser import path:
import { MCPConfigRegistry, ConfigBuilder } from '@gleanwork/mcp-config-schema/browser';
const registry = new MCPConfigRegistry();
const builder = registry.createBuilder('cursor');
const config = builder.buildConfiguration({
transport: 'http',
serverUrl: 'https://your-server.com/mcp/default',
});
navigator.clipboard.writeText(JSON.stringify(config, null, 2));
Note: File operations (writeConfiguration, getConfigPath) are not available in browsers and will throw clear error messages.
React Example
import React from 'react';
import { MCPConfigRegistry, ClientId } from '@gleanwork/mcp-config-schema/browser';
function MCPConfigGenerator() {
const registry = new MCPConfigRegistry();
const handleGenerateConfig = (clientId: ClientId, serverUrl: string) => {
const builder = registry.createBuilder(clientId);
const config = builder.buildConfiguration({
transport: 'http',
serverUrl,
serverName: 'my-server',
});
navigator.clipboard.writeText(JSON.stringify(config, null, 2));
};
const clients = registry.getSupportedClients();
return (
<div>
{clients.map((client) => (
<button
key={client.id}
onClick={() => handleGenerateConfig(client.id, 'https://api.example.com/mcp')}
>
Configure {client.displayName}
</button>
))}
</div>
);
}
Configuration Examples
📖 For complete configuration examples for all clients, see CLIENTS.md
Native HTTP Client (Claude Code, VS Code)
{
"mcpServers": {
"my-server": {
"type": "http",
"url": "https://your-server.com/mcp/default"
}
}
}
stdio-only Clients (Claude Desktop, Junie, JetBrains AI)
These clients require mcp-remote bridge for HTTP servers:
{
"mcpServers": {
"my-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "mcp-remote", "https://your-server.com/mcp/default"]
}
}
}
Goose (YAML format with native HTTP)
extensions:
my-server:
enabled: true
name: my-server
type: streamable_http
uri: https://your-server.com/mcp/default
envs: {}
env_keys: []
headers: {}
description: ''
timeout: 300
bundled: null
available_tools: []
API Reference
For complete API documentation, see the TypeScript definitions in src/types.ts and src/registry.ts. All exports include JSDoc comments.
Key exports:
MCPConfigRegistry - Main entry point for creating configuration builders
BaseConfigBuilder - Base class for client-specific builders
MCPConnectionOptions - Options for buildConfiguration()
RegistryOptions - Options for customizing the registry
ClientId - Union type of all supported client identifiers
Development
npm install
npm run build
npm run test
npm run test:all
npm run generate:docs
Documentation
- CLIENTS.md - Comprehensive client compatibility matrix with detailed configuration examples
- API Reference - Complete API documentation
Icons
Each client ships an SVG host icon, available as an inline string (no bundler/loader setup) and as a raw file under icons/:
import { CLIENT, CLIENT_ICONS, getClientIcon } from '@gleanwork/mcp-config-schema';
getClientIcon(CLIENT.CURSOR);
<span style={{ color: '#111' }} dangerouslySetInnerHTML={{ __html: getClientIcon(clientId) ?? '' }} />
Icons are optional per client; getClientIcon returns undefined when one isn't shipped. Internal SVG ids are namespaced per icon, so multiple icons can be inlined on the same page without collisions. See icons/README.md to add or update one.
Trademarks
Product names and the client icons under icons/ are trademarks of their respective owners. They are included only to identify the MCP host applications this package supports (nominative use); their inclusion does not imply affiliation with or endorsement by those owners. Brand icons are sourced from svgl, Simple Icons (CC0), and official brand assets.
License
MIT - See LICENSE file for details
Contributing
This package is part of the Glean MCP ecosystem. For issues and contributions, please visit the repository.