@omnidev-ai/core 0.6.2 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +61 -4
- package/dist/index.js +172 -42
- package/package.json +1 -1
- package/src/capability/sources.ts +33 -9
- package/src/config/capabilities.ts +5 -3
- package/src/config/loader.ts +113 -38
- package/src/index.ts +1 -0
- package/src/mcp-json/manager.ts +62 -3
- package/src/templates/omni.ts +25 -0
- package/src/types/index.ts +26 -1
package/dist/index.d.ts
CHANGED
|
@@ -190,12 +190,37 @@ interface McpToolSchema {
|
|
|
190
190
|
description: string;
|
|
191
191
|
inputSchema: Record<string, unknown>;
|
|
192
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* MCP server configuration supporting multiple transport types:
|
|
195
|
+
*
|
|
196
|
+
* - **stdio**: Local process using stdin/stdout (default)
|
|
197
|
+
* - Requires: command
|
|
198
|
+
* - Optional: args, env, cwd
|
|
199
|
+
*
|
|
200
|
+
* - **http**: Remote HTTP server (recommended for remote servers)
|
|
201
|
+
* - Requires: url
|
|
202
|
+
* - Optional: headers (for authentication)
|
|
203
|
+
*
|
|
204
|
+
* - **sse**: Server-Sent Events (deprecated, use http instead)
|
|
205
|
+
* - Requires: url
|
|
206
|
+
* - Optional: headers (for authentication)
|
|
207
|
+
*/
|
|
193
208
|
interface McpConfig {
|
|
194
|
-
|
|
209
|
+
/** Executable to run (required for stdio transport) */
|
|
210
|
+
command?: string;
|
|
211
|
+
/** Command arguments (stdio transport only) */
|
|
195
212
|
args?: string[];
|
|
213
|
+
/** Environment variables (stdio transport only) */
|
|
196
214
|
env?: Record<string, string>;
|
|
215
|
+
/** Working directory (stdio transport only) */
|
|
197
216
|
cwd?: string;
|
|
217
|
+
/** Transport type: stdio (default), http, or sse */
|
|
198
218
|
transport?: McpTransport;
|
|
219
|
+
/** URL for remote servers (required for http/sse transport) */
|
|
220
|
+
url?: string;
|
|
221
|
+
/** HTTP headers for authentication (http/sse transport only) */
|
|
222
|
+
headers?: Record<string, string>;
|
|
223
|
+
/** Tool schemas (optional, for documentation) */
|
|
199
224
|
tools?: McpToolSchema[];
|
|
200
225
|
}
|
|
201
226
|
interface Skill {
|
|
@@ -585,6 +610,12 @@ declare function validateEnv(declarations: Record<string, EnvDeclaration | Recor
|
|
|
585
610
|
*/
|
|
586
611
|
declare function isSecretEnvVar(key: string, declarations: Record<string, EnvDeclaration | Record<string, never>>): boolean;
|
|
587
612
|
/**
|
|
613
|
+
* Load only the base config file (omni.toml) without merging local overrides.
|
|
614
|
+
* Use this when you need to modify and write back to omni.toml.
|
|
615
|
+
* @returns OmniConfig from omni.toml only
|
|
616
|
+
*/
|
|
617
|
+
declare function loadBaseConfig(): Promise<OmniConfig>;
|
|
618
|
+
/**
|
|
588
619
|
* Load and merge config and local configuration files
|
|
589
620
|
* @returns Merged OmniConfig object
|
|
590
621
|
*
|
|
@@ -697,14 +728,34 @@ declare function buildManifestFromCapabilities(capabilities: LoadedCapability[])
|
|
|
697
728
|
*/
|
|
698
729
|
declare function cleanupStaleResources(previousManifest: ResourceManifest, currentCapabilityIds: Set<string>): Promise<CleanupResult>;
|
|
699
730
|
/**
|
|
700
|
-
* MCP server configuration in .mcp.json
|
|
731
|
+
* MCP server configuration in .mcp.json for stdio transport
|
|
701
732
|
*/
|
|
702
|
-
interface
|
|
733
|
+
interface McpServerStdioConfig {
|
|
703
734
|
command: string;
|
|
704
735
|
args?: string[];
|
|
705
736
|
env?: Record<string, string>;
|
|
706
737
|
}
|
|
707
738
|
/**
|
|
739
|
+
* MCP server configuration in .mcp.json for HTTP transport
|
|
740
|
+
*/
|
|
741
|
+
interface McpServerHttpConfig {
|
|
742
|
+
type: "http";
|
|
743
|
+
url: string;
|
|
744
|
+
headers?: Record<string, string>;
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* MCP server configuration in .mcp.json for SSE transport
|
|
748
|
+
*/
|
|
749
|
+
interface McpServerSseConfig {
|
|
750
|
+
type: "sse";
|
|
751
|
+
url: string;
|
|
752
|
+
headers?: Record<string, string>;
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Union type for all MCP server configurations
|
|
756
|
+
*/
|
|
757
|
+
type McpServerConfig = McpServerStdioConfig | McpServerHttpConfig | McpServerSseConfig;
|
|
758
|
+
/**
|
|
708
759
|
* Structure of .mcp.json file
|
|
709
760
|
*/
|
|
710
761
|
interface McpJsonConfig {
|
|
@@ -817,9 +868,15 @@ declare function generateClaudeTemplate(): string;
|
|
|
817
868
|
*/
|
|
818
869
|
declare function generateInstructionsTemplate(): string;
|
|
819
870
|
/**
|
|
871
|
+
* Template for OMNI.md - the user's project instructions file.
|
|
872
|
+
* This is the single source of truth that gets transformed into
|
|
873
|
+
* provider-specific files (CLAUDE.md, AGENTS.md, etc.) during sync.
|
|
874
|
+
*/
|
|
875
|
+
declare function generateOmniMdTemplate(): string;
|
|
876
|
+
/**
|
|
820
877
|
* Debug logger that writes to stdout when OMNIDEV_DEBUG=1
|
|
821
878
|
*/
|
|
822
879
|
declare function debug(message: string, data?: unknown): void;
|
|
823
880
|
declare const version = "0.1.0";
|
|
824
881
|
declare function getVersion(): string;
|
|
825
|
-
export { writeRules, writeProviderConfig, writeMcpJson, writeEnabledProviders, writeConfig, writeActiveProfileState, version, validateEnv, syncMcpJson, syncAgentConfiguration, sourceToGitUrl, setProfile, setActiveProfile, saveManifest, saveLockFile, resolveEnabledCapabilities, readMcpJson, readEnabledProviders, readActiveProfileState, parseSourceConfig, parseProviderFlag, parseOmniConfig, parseCapabilityConfig, loadSubagents, loadSkills, loadRules, loadProviderConfig, loadProfileConfig, loadManifest, loadLockFile, loadEnvironment, loadDocs, loadConfig, loadCommands, loadCapabilityConfig, loadCapability, isSecretEnvVar, isProviderEnabled, installCapabilityDependencies, getVersion, getSourceCapabilityPath, getLockFilePath, getEnabledCapabilities, getActiveProviders, getActiveProfile, generateInstructionsTemplate, generateClaudeTemplate, generateAgentsTemplate, fetchCapabilitySource, fetchAllCapabilitySources, enableProvider, enableCapability, discoverCapabilities, disableProvider, disableCapability, debug, clearActiveProfileState, cleanupStaleResources, checkForUpdates, buildSyncBundle, buildRouteMap, buildManifestFromCapabilities, buildCommand, buildCapabilityRegistry, SyncResult, SyncOptions, SyncConfig, SyncBundle, SubagentPermissionMode, SubagentModel, SubagentHooks, SubagentHookConfig, SubagentExport, Subagent, SourceUpdateInfo, SkillExport, Skill, Rule, ResourceManifest, ProvidersState, ProviderSyncResult, ProviderManifest, ProviderInitResult, ProviderId, ProviderContext, ProviderConfig, ProviderAdapter, Provider, ProfileConfig, OmniConfig, McpTransport, McpToolSchema, McpServerConfig, McpJsonConfig, McpConfig, LoadedCapability, GitCapabilitySourceConfig, FileContent, FetchResult, EnvDeclaration, DocExport, Doc, DiscoveredContent, CommandExport, Command, CliConfig, CleanupResult, CapabilitySourceType, CapabilitySourceConfig, CapabilitySource, CapabilityResources, CapabilityRegistry, CapabilityMetadata, CapabilityLockEntry, CapabilityExports, CapabilityExport, CapabilityConfig, CapabilitiesLockFile, CapabilitiesConfig };
|
|
882
|
+
export { writeRules, writeProviderConfig, writeMcpJson, writeEnabledProviders, writeConfig, writeActiveProfileState, version, validateEnv, syncMcpJson, syncAgentConfiguration, sourceToGitUrl, setProfile, setActiveProfile, saveManifest, saveLockFile, resolveEnabledCapabilities, readMcpJson, readEnabledProviders, readActiveProfileState, parseSourceConfig, parseProviderFlag, parseOmniConfig, parseCapabilityConfig, loadSubagents, loadSkills, loadRules, loadProviderConfig, loadProfileConfig, loadManifest, loadLockFile, loadEnvironment, loadDocs, loadConfig, loadCommands, loadCapabilityConfig, loadCapability, loadBaseConfig, isSecretEnvVar, isProviderEnabled, installCapabilityDependencies, getVersion, getSourceCapabilityPath, getLockFilePath, getEnabledCapabilities, getActiveProviders, getActiveProfile, generateOmniMdTemplate, generateInstructionsTemplate, generateClaudeTemplate, generateAgentsTemplate, fetchCapabilitySource, fetchAllCapabilitySources, enableProvider, enableCapability, discoverCapabilities, disableProvider, disableCapability, debug, clearActiveProfileState, cleanupStaleResources, checkForUpdates, buildSyncBundle, buildRouteMap, buildManifestFromCapabilities, buildCommand, buildCapabilityRegistry, SyncResult, SyncOptions, SyncConfig, SyncBundle, SubagentPermissionMode, SubagentModel, SubagentHooks, SubagentHookConfig, SubagentExport, Subagent, SourceUpdateInfo, SkillExport, Skill, Rule, ResourceManifest, ProvidersState, ProviderSyncResult, ProviderManifest, ProviderInitResult, ProviderId, ProviderContext, ProviderConfig, ProviderAdapter, Provider, ProfileConfig, OmniConfig, McpTransport, McpToolSchema, McpServerStdioConfig, McpServerSseConfig, McpServerHttpConfig, McpServerConfig, McpJsonConfig, McpConfig, LoadedCapability, GitCapabilitySourceConfig, FileContent, FetchResult, EnvDeclaration, DocExport, Doc, DiscoveredContent, CommandExport, Command, CliConfig, CleanupResult, CapabilitySourceType, CapabilitySourceConfig, CapabilitySource, CapabilityResources, CapabilityRegistry, CapabilityMetadata, CapabilityLockEntry, CapabilityExports, CapabilityExport, CapabilityConfig, CapabilitiesLockFile, CapabilitiesConfig };
|
package/dist/index.js
CHANGED
|
@@ -691,13 +691,16 @@ function mergeConfigs(base, override) {
|
|
|
691
691
|
}
|
|
692
692
|
return merged;
|
|
693
693
|
}
|
|
694
|
-
async function
|
|
695
|
-
let baseConfig = {};
|
|
696
|
-
let localConfig = {};
|
|
694
|
+
async function loadBaseConfig() {
|
|
697
695
|
if (existsSync8(CONFIG_PATH)) {
|
|
698
696
|
const content = await readFile8(CONFIG_PATH, "utf-8");
|
|
699
|
-
|
|
697
|
+
return parseOmniConfig(content);
|
|
700
698
|
}
|
|
699
|
+
return {};
|
|
700
|
+
}
|
|
701
|
+
async function loadConfig() {
|
|
702
|
+
const baseConfig = await loadBaseConfig();
|
|
703
|
+
let localConfig = {};
|
|
701
704
|
if (existsSync8(LOCAL_CONFIG)) {
|
|
702
705
|
const content = await readFile8(LOCAL_CONFIG, "utf-8");
|
|
703
706
|
localConfig = parseOmniConfig(content);
|
|
@@ -726,10 +729,6 @@ function generateConfigToml(config) {
|
|
|
726
729
|
lines.push("# 3. Run: omnidev sync");
|
|
727
730
|
lines.push("# 4. Switch profiles: omnidev profile use <name>");
|
|
728
731
|
lines.push("");
|
|
729
|
-
if (config.project) {
|
|
730
|
-
lines.push(`project = "${config.project}"`);
|
|
731
|
-
lines.push("");
|
|
732
|
-
}
|
|
733
732
|
if (config.providers?.enabled && config.providers.enabled.length > 0) {
|
|
734
733
|
lines.push("# AI providers to enable (claude, codex, or both)");
|
|
735
734
|
lines.push("[providers]");
|
|
@@ -759,16 +758,30 @@ function generateConfigToml(config) {
|
|
|
759
758
|
lines.push("# Fetch capabilities from Git repositories. On sync, these are");
|
|
760
759
|
lines.push("# cloned/updated and made available to your profiles.");
|
|
761
760
|
lines.push("#");
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
761
|
+
const sources = config.capabilities?.sources;
|
|
762
|
+
if (sources && Object.keys(sources).length > 0) {
|
|
763
|
+
lines.push("[capabilities.sources]");
|
|
764
|
+
for (const [name, sourceConfig] of Object.entries(sources)) {
|
|
765
|
+
if (typeof sourceConfig === "string") {
|
|
766
|
+
lines.push(`${name} = "${sourceConfig}"`);
|
|
767
|
+
} else if (sourceConfig.path) {
|
|
768
|
+
lines.push(`${name} = { source = "${sourceConfig.source}", path = "${sourceConfig.path}" }`);
|
|
769
|
+
} else {
|
|
770
|
+
lines.push(`${name} = "${sourceConfig.source}"`);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
} else {
|
|
774
|
+
lines.push("# [capabilities.sources]");
|
|
775
|
+
lines.push("# # GitHub shorthand (uses latest commit)");
|
|
776
|
+
lines.push('# tasks = "github:example-org/tasks-capability"');
|
|
777
|
+
lines.push("#");
|
|
778
|
+
lines.push("# # With subdirectory path");
|
|
779
|
+
lines.push('# ralph = { source = "github:example-org/ralph", path = "plugins/my-cap" }');
|
|
780
|
+
lines.push("#");
|
|
781
|
+
lines.push("# # Other Git sources");
|
|
782
|
+
lines.push('# private = "git@github.com:company/private-cap.git"');
|
|
783
|
+
lines.push('# gitlab = "https://gitlab.com/user/capability.git"');
|
|
784
|
+
}
|
|
772
785
|
lines.push("");
|
|
773
786
|
lines.push("# =============================================================================");
|
|
774
787
|
lines.push("# MCP Servers");
|
|
@@ -776,25 +789,66 @@ function generateConfigToml(config) {
|
|
|
776
789
|
lines.push("# Define MCP servers that automatically become capabilities.");
|
|
777
790
|
lines.push('# Reference in profiles using the MCP name directly, e.g. capabilities = ["filesystem"]');
|
|
778
791
|
lines.push("#");
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
792
|
+
const mcps = config.mcps;
|
|
793
|
+
if (mcps && Object.keys(mcps).length > 0) {
|
|
794
|
+
for (const [name, mcpConfig] of Object.entries(mcps)) {
|
|
795
|
+
lines.push(`[mcps.${name}]`);
|
|
796
|
+
if (mcpConfig.transport && mcpConfig.transport !== "stdio") {
|
|
797
|
+
lines.push(`transport = "${mcpConfig.transport}"`);
|
|
798
|
+
}
|
|
799
|
+
if (mcpConfig.command) {
|
|
800
|
+
lines.push(`command = "${mcpConfig.command}"`);
|
|
801
|
+
}
|
|
802
|
+
if (mcpConfig.args && mcpConfig.args.length > 0) {
|
|
803
|
+
const argsStr = mcpConfig.args.map((a) => `"${a}"`).join(", ");
|
|
804
|
+
lines.push(`args = [${argsStr}]`);
|
|
805
|
+
}
|
|
806
|
+
if (mcpConfig.cwd) {
|
|
807
|
+
lines.push(`cwd = "${mcpConfig.cwd}"`);
|
|
808
|
+
}
|
|
809
|
+
if (mcpConfig.url) {
|
|
810
|
+
lines.push(`url = "${mcpConfig.url}"`);
|
|
811
|
+
}
|
|
812
|
+
if (mcpConfig.env && Object.keys(mcpConfig.env).length > 0) {
|
|
813
|
+
lines.push(`[mcps.${name}.env]`);
|
|
814
|
+
for (const [key, value] of Object.entries(mcpConfig.env)) {
|
|
815
|
+
lines.push(`${key} = "${value}"`);
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
if (mcpConfig.headers && Object.keys(mcpConfig.headers).length > 0) {
|
|
819
|
+
lines.push(`[mcps.${name}.headers]`);
|
|
820
|
+
for (const [key, value] of Object.entries(mcpConfig.headers)) {
|
|
821
|
+
lines.push(`${key} = "${value}"`);
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
lines.push("");
|
|
825
|
+
}
|
|
826
|
+
} else {
|
|
827
|
+
lines.push("# [mcps.filesystem]");
|
|
828
|
+
lines.push('# command = "npx"');
|
|
829
|
+
lines.push('# args = ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]');
|
|
830
|
+
lines.push('# transport = "stdio" # stdio (default), sse, or http');
|
|
831
|
+
lines.push("#");
|
|
832
|
+
lines.push("# [mcps.database]");
|
|
833
|
+
lines.push('# command = "node"');
|
|
834
|
+
lines.push('# args = ["./servers/database.js"]');
|
|
835
|
+
lines.push('# cwd = "./mcp-servers"');
|
|
836
|
+
lines.push("# [mcps.database.env]");
|
|
837
|
+
lines.push('# DB_URL = "${DATABASE_URL}"');
|
|
838
|
+
lines.push("");
|
|
839
|
+
}
|
|
791
840
|
lines.push("# =============================================================================");
|
|
792
841
|
lines.push("# Always Enabled Capabilities");
|
|
793
842
|
lines.push("# =============================================================================");
|
|
794
843
|
lines.push("# Capabilities that load in ALL profiles, regardless of profile config.");
|
|
795
844
|
lines.push("# Useful for essential tools needed everywhere.");
|
|
796
845
|
lines.push("#");
|
|
797
|
-
|
|
846
|
+
if (config.always_enabled_capabilities && config.always_enabled_capabilities.length > 0) {
|
|
847
|
+
const caps = config.always_enabled_capabilities.map((c) => `"${c}"`).join(", ");
|
|
848
|
+
lines.push(`always_enabled_capabilities = [${caps}]`);
|
|
849
|
+
} else {
|
|
850
|
+
lines.push('# always_enabled_capabilities = ["git-tools", "linting"]');
|
|
851
|
+
}
|
|
798
852
|
lines.push("");
|
|
799
853
|
lines.push("# =============================================================================");
|
|
800
854
|
lines.push("# Profiles");
|
|
@@ -883,7 +937,7 @@ async function getEnabledCapabilities() {
|
|
|
883
937
|
return resolveEnabledCapabilities(config, activeProfile);
|
|
884
938
|
}
|
|
885
939
|
async function enableCapability(capabilityId) {
|
|
886
|
-
const config = await
|
|
940
|
+
const config = await loadBaseConfig();
|
|
887
941
|
const activeProfile = await getActiveProfile() ?? config.active_profile ?? "default";
|
|
888
942
|
if (!config.profiles) {
|
|
889
943
|
config.profiles = {};
|
|
@@ -897,7 +951,7 @@ async function enableCapability(capabilityId) {
|
|
|
897
951
|
await writeConfig(config);
|
|
898
952
|
}
|
|
899
953
|
async function disableCapability(capabilityId) {
|
|
900
|
-
const config = await
|
|
954
|
+
const config = await loadBaseConfig();
|
|
901
955
|
const activeProfile = await getActiveProfile() ?? config.active_profile ?? "default";
|
|
902
956
|
if (!config.profiles?.[activeProfile]) {
|
|
903
957
|
return;
|
|
@@ -1389,6 +1443,8 @@ async function fetchCapabilitySource(id, sourceConfig, options) {
|
|
|
1389
1443
|
return fetchGitCapabilitySource(id, config, options);
|
|
1390
1444
|
}
|
|
1391
1445
|
function generateMcpCapabilityTomlContent(id, mcpConfig) {
|
|
1446
|
+
const transport = mcpConfig.transport ?? "stdio";
|
|
1447
|
+
const isRemote = transport === "http" || transport === "sse";
|
|
1392
1448
|
let tomlContent = `# Auto-generated by OmniDev from omni.toml [mcps] section - DO NOT EDIT
|
|
1393
1449
|
|
|
1394
1450
|
[capability]
|
|
@@ -1402,21 +1458,42 @@ wrapped = true
|
|
|
1402
1458
|
generated_from_omni_toml = true
|
|
1403
1459
|
|
|
1404
1460
|
[mcp]
|
|
1405
|
-
command = "${mcpConfig.command}"
|
|
1406
1461
|
`;
|
|
1407
|
-
if (
|
|
1408
|
-
tomlContent += `
|
|
1462
|
+
if (isRemote) {
|
|
1463
|
+
tomlContent += `transport = "${transport}"
|
|
1409
1464
|
`;
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1465
|
+
if (mcpConfig.url) {
|
|
1466
|
+
tomlContent += `url = "${mcpConfig.url}"
|
|
1467
|
+
`;
|
|
1468
|
+
}
|
|
1469
|
+
} else {
|
|
1470
|
+
if (mcpConfig.command) {
|
|
1471
|
+
tomlContent += `command = "${mcpConfig.command}"
|
|
1472
|
+
`;
|
|
1473
|
+
}
|
|
1474
|
+
if (mcpConfig.args && mcpConfig.args.length > 0) {
|
|
1475
|
+
tomlContent += `args = ${JSON.stringify(mcpConfig.args)}
|
|
1476
|
+
`;
|
|
1477
|
+
}
|
|
1478
|
+
if (mcpConfig.transport) {
|
|
1479
|
+
tomlContent += `transport = "${mcpConfig.transport}"
|
|
1480
|
+
`;
|
|
1481
|
+
}
|
|
1482
|
+
if (mcpConfig.cwd) {
|
|
1483
|
+
tomlContent += `cwd = "${mcpConfig.cwd}"
|
|
1413
1484
|
`;
|
|
1485
|
+
}
|
|
1414
1486
|
}
|
|
1415
|
-
if (mcpConfig.
|
|
1416
|
-
tomlContent += `
|
|
1487
|
+
if (isRemote && mcpConfig.headers && Object.keys(mcpConfig.headers).length > 0) {
|
|
1488
|
+
tomlContent += `
|
|
1489
|
+
[mcp.headers]
|
|
1417
1490
|
`;
|
|
1491
|
+
for (const [key, value] of Object.entries(mcpConfig.headers)) {
|
|
1492
|
+
tomlContent += `"${key}" = "${value}"
|
|
1493
|
+
`;
|
|
1494
|
+
}
|
|
1418
1495
|
}
|
|
1419
|
-
if (mcpConfig.env && Object.keys(mcpConfig.env).length > 0) {
|
|
1496
|
+
if (!isRemote && mcpConfig.env && Object.keys(mcpConfig.env).length > 0) {
|
|
1420
1497
|
tomlContent += `
|
|
1421
1498
|
[mcp.env]
|
|
1422
1499
|
`;
|
|
@@ -1653,6 +1730,36 @@ async function writeMcpJson(config) {
|
|
|
1653
1730
|
`, "utf-8");
|
|
1654
1731
|
}
|
|
1655
1732
|
function buildMcpServerConfig(mcp) {
|
|
1733
|
+
const transport = mcp.transport ?? "stdio";
|
|
1734
|
+
if (transport === "http") {
|
|
1735
|
+
if (!mcp.url) {
|
|
1736
|
+
throw new Error("HTTP transport requires a URL");
|
|
1737
|
+
}
|
|
1738
|
+
const config2 = {
|
|
1739
|
+
type: "http",
|
|
1740
|
+
url: mcp.url
|
|
1741
|
+
};
|
|
1742
|
+
if (mcp.headers && Object.keys(mcp.headers).length > 0) {
|
|
1743
|
+
config2.headers = mcp.headers;
|
|
1744
|
+
}
|
|
1745
|
+
return config2;
|
|
1746
|
+
}
|
|
1747
|
+
if (transport === "sse") {
|
|
1748
|
+
if (!mcp.url) {
|
|
1749
|
+
throw new Error("SSE transport requires a URL");
|
|
1750
|
+
}
|
|
1751
|
+
const config2 = {
|
|
1752
|
+
type: "sse",
|
|
1753
|
+
url: mcp.url
|
|
1754
|
+
};
|
|
1755
|
+
if (mcp.headers && Object.keys(mcp.headers).length > 0) {
|
|
1756
|
+
config2.headers = mcp.headers;
|
|
1757
|
+
}
|
|
1758
|
+
return config2;
|
|
1759
|
+
}
|
|
1760
|
+
if (!mcp.command) {
|
|
1761
|
+
throw new Error("stdio transport requires a command");
|
|
1762
|
+
}
|
|
1656
1763
|
const config = {
|
|
1657
1764
|
command: mcp.command
|
|
1658
1765
|
};
|
|
@@ -2046,6 +2153,27 @@ No capabilities enabled yet. Run \`omnidev capability enable <name>\` to enable
|
|
|
2046
2153
|
<!-- END OMNIDEV GENERATED CONTENT -->
|
|
2047
2154
|
`;
|
|
2048
2155
|
}
|
|
2156
|
+
// src/templates/omni.ts
|
|
2157
|
+
function generateOmniMdTemplate() {
|
|
2158
|
+
return `# Project Instructions
|
|
2159
|
+
|
|
2160
|
+
<!-- This file is your project's instruction manifest for AI agents. -->
|
|
2161
|
+
<!-- It will be combined with capability-generated content during sync. -->
|
|
2162
|
+
|
|
2163
|
+
## Project Description
|
|
2164
|
+
|
|
2165
|
+
<!-- TODO: Add 2-3 sentences describing your project -->
|
|
2166
|
+
[Describe what this project does and its main purpose]
|
|
2167
|
+
|
|
2168
|
+
## Conventions
|
|
2169
|
+
|
|
2170
|
+
<!-- Add your project conventions, coding standards, and guidelines here -->
|
|
2171
|
+
|
|
2172
|
+
## Architecture
|
|
2173
|
+
|
|
2174
|
+
<!-- Describe your project's architecture and key components -->
|
|
2175
|
+
`;
|
|
2176
|
+
}
|
|
2049
2177
|
// src/types/index.ts
|
|
2050
2178
|
function getActiveProviders(config) {
|
|
2051
2179
|
if (config.providers)
|
|
@@ -2111,6 +2239,7 @@ export {
|
|
|
2111
2239
|
loadCommands,
|
|
2112
2240
|
loadCapabilityConfig,
|
|
2113
2241
|
loadCapability,
|
|
2242
|
+
loadBaseConfig,
|
|
2114
2243
|
isSecretEnvVar,
|
|
2115
2244
|
isProviderEnabled,
|
|
2116
2245
|
installCapabilityDependencies,
|
|
@@ -2120,6 +2249,7 @@ export {
|
|
|
2120
2249
|
getEnabledCapabilities,
|
|
2121
2250
|
getActiveProviders,
|
|
2122
2251
|
getActiveProfile,
|
|
2252
|
+
generateOmniMdTemplate,
|
|
2123
2253
|
generateInstructionsTemplate,
|
|
2124
2254
|
generateClaudeTemplate,
|
|
2125
2255
|
generateAgentsTemplate,
|
package/package.json
CHANGED
|
@@ -752,6 +752,9 @@ function generateMcpCapabilityTomlContent(
|
|
|
752
752
|
id: string,
|
|
753
753
|
mcpConfig: import("../types/index.js").McpConfig,
|
|
754
754
|
): string {
|
|
755
|
+
const transport = mcpConfig.transport ?? "stdio";
|
|
756
|
+
const isRemote = transport === "http" || transport === "sse";
|
|
757
|
+
|
|
755
758
|
let tomlContent = `# Auto-generated by OmniDev from omni.toml [mcps] section - DO NOT EDIT
|
|
756
759
|
|
|
757
760
|
[capability]
|
|
@@ -765,22 +768,43 @@ wrapped = true
|
|
|
765
768
|
generated_from_omni_toml = true
|
|
766
769
|
|
|
767
770
|
[mcp]
|
|
768
|
-
command = "${mcpConfig.command}"
|
|
769
771
|
`;
|
|
770
772
|
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
773
|
+
// For remote transports (http/sse), url is required
|
|
774
|
+
if (isRemote) {
|
|
775
|
+
tomlContent += `transport = "${transport}"\n`;
|
|
776
|
+
if (mcpConfig.url) {
|
|
777
|
+
tomlContent += `url = "${mcpConfig.url}"\n`;
|
|
778
|
+
}
|
|
779
|
+
} else {
|
|
780
|
+
// For stdio transport, command is required
|
|
781
|
+
if (mcpConfig.command) {
|
|
782
|
+
tomlContent += `command = "${mcpConfig.command}"\n`;
|
|
783
|
+
}
|
|
774
784
|
|
|
775
|
-
|
|
776
|
-
|
|
785
|
+
if (mcpConfig.args && mcpConfig.args.length > 0) {
|
|
786
|
+
tomlContent += `args = ${JSON.stringify(mcpConfig.args)}\n`;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
if (mcpConfig.transport) {
|
|
790
|
+
tomlContent += `transport = "${mcpConfig.transport}"\n`;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
if (mcpConfig.cwd) {
|
|
794
|
+
tomlContent += `cwd = "${mcpConfig.cwd}"\n`;
|
|
795
|
+
}
|
|
777
796
|
}
|
|
778
797
|
|
|
779
|
-
|
|
780
|
-
|
|
798
|
+
// Headers for remote transports
|
|
799
|
+
if (isRemote && mcpConfig.headers && Object.keys(mcpConfig.headers).length > 0) {
|
|
800
|
+
tomlContent += `\n[mcp.headers]\n`;
|
|
801
|
+
for (const [key, value] of Object.entries(mcpConfig.headers)) {
|
|
802
|
+
tomlContent += `"${key}" = "${value}"\n`;
|
|
803
|
+
}
|
|
781
804
|
}
|
|
782
805
|
|
|
783
|
-
|
|
806
|
+
// Env variables for stdio transport
|
|
807
|
+
if (!isRemote && mcpConfig.env && Object.keys(mcpConfig.env).length > 0) {
|
|
784
808
|
tomlContent += `\n[mcp.env]\n`;
|
|
785
809
|
for (const [key, value] of Object.entries(mcpConfig.env)) {
|
|
786
810
|
tomlContent += `${key} = "${value}"\n`;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { loadConfig, writeConfig } from "./loader.js";
|
|
1
|
+
import { loadBaseConfig, loadConfig, writeConfig } from "./loader.js";
|
|
2
2
|
import { getActiveProfile, resolveEnabledCapabilities } from "./profiles.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -17,7 +17,8 @@ export async function getEnabledCapabilities(): Promise<string[]> {
|
|
|
17
17
|
* @param capabilityId - The ID of the capability to enable
|
|
18
18
|
*/
|
|
19
19
|
export async function enableCapability(capabilityId: string): Promise<void> {
|
|
20
|
-
|
|
20
|
+
// Use loadBaseConfig to avoid writing local overrides to omni.toml
|
|
21
|
+
const config = await loadBaseConfig();
|
|
21
22
|
const activeProfile = (await getActiveProfile()) ?? config.active_profile ?? "default";
|
|
22
23
|
|
|
23
24
|
if (!config.profiles) {
|
|
@@ -39,7 +40,8 @@ export async function enableCapability(capabilityId: string): Promise<void> {
|
|
|
39
40
|
* @param capabilityId - The ID of the capability to disable
|
|
40
41
|
*/
|
|
41
42
|
export async function disableCapability(capabilityId: string): Promise<void> {
|
|
42
|
-
|
|
43
|
+
// Use loadBaseConfig to avoid writing local overrides to omni.toml
|
|
44
|
+
const config = await loadBaseConfig();
|
|
43
45
|
const activeProfile = (await getActiveProfile()) ?? config.active_profile ?? "default";
|
|
44
46
|
|
|
45
47
|
if (!config.profiles?.[activeProfile]) {
|
package/src/config/loader.ts
CHANGED
|
@@ -35,6 +35,19 @@ function mergeConfigs(base: OmniConfig, override: OmniConfig): OmniConfig {
|
|
|
35
35
|
return merged;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Load only the base config file (omni.toml) without merging local overrides.
|
|
40
|
+
* Use this when you need to modify and write back to omni.toml.
|
|
41
|
+
* @returns OmniConfig from omni.toml only
|
|
42
|
+
*/
|
|
43
|
+
export async function loadBaseConfig(): Promise<OmniConfig> {
|
|
44
|
+
if (existsSync(CONFIG_PATH)) {
|
|
45
|
+
const content = await readFile(CONFIG_PATH, "utf-8");
|
|
46
|
+
return parseOmniConfig(content);
|
|
47
|
+
}
|
|
48
|
+
return {};
|
|
49
|
+
}
|
|
50
|
+
|
|
38
51
|
/**
|
|
39
52
|
* Load and merge config and local configuration files
|
|
40
53
|
* @returns Merged OmniConfig object
|
|
@@ -43,14 +56,9 @@ function mergeConfigs(base: OmniConfig, override: OmniConfig): OmniConfig {
|
|
|
43
56
|
* Local config takes precedence over main config. Missing files are treated as empty configs.
|
|
44
57
|
*/
|
|
45
58
|
export async function loadConfig(): Promise<OmniConfig> {
|
|
46
|
-
|
|
59
|
+
const baseConfig = await loadBaseConfig();
|
|
47
60
|
let localConfig: OmniConfig = {};
|
|
48
61
|
|
|
49
|
-
if (existsSync(CONFIG_PATH)) {
|
|
50
|
-
const content = await readFile(CONFIG_PATH, "utf-8");
|
|
51
|
-
baseConfig = parseOmniConfig(content);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
62
|
if (existsSync(LOCAL_CONFIG)) {
|
|
55
63
|
const content = await readFile(LOCAL_CONFIG, "utf-8");
|
|
56
64
|
localConfig = parseOmniConfig(content);
|
|
@@ -93,12 +101,6 @@ function generateConfigToml(config: OmniConfig): string {
|
|
|
93
101
|
lines.push("# 4. Switch profiles: omnidev profile use <name>");
|
|
94
102
|
lines.push("");
|
|
95
103
|
|
|
96
|
-
// Project name
|
|
97
|
-
if (config.project) {
|
|
98
|
-
lines.push(`project = "${config.project}"`);
|
|
99
|
-
lines.push("");
|
|
100
|
-
}
|
|
101
|
-
|
|
102
104
|
// Note: active_profile is stored in .omni/state/active-profile, not in config.toml
|
|
103
105
|
// We still read it from config.toml for backwards compatibility, but don't write it here
|
|
104
106
|
|
|
@@ -132,26 +134,46 @@ function generateConfigToml(config: OmniConfig): string {
|
|
|
132
134
|
}
|
|
133
135
|
lines.push("");
|
|
134
136
|
|
|
135
|
-
// Capability sources
|
|
137
|
+
// Capability sources
|
|
136
138
|
lines.push("# =============================================================================");
|
|
137
139
|
lines.push("# Capability Sources");
|
|
138
140
|
lines.push("# =============================================================================");
|
|
139
141
|
lines.push("# Fetch capabilities from Git repositories. On sync, these are");
|
|
140
142
|
lines.push("# cloned/updated and made available to your profiles.");
|
|
141
143
|
lines.push("#");
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
144
|
+
|
|
145
|
+
const sources = config.capabilities?.sources;
|
|
146
|
+
if (sources && Object.keys(sources).length > 0) {
|
|
147
|
+
lines.push("[capabilities.sources]");
|
|
148
|
+
for (const [name, sourceConfig] of Object.entries(sources)) {
|
|
149
|
+
if (typeof sourceConfig === "string") {
|
|
150
|
+
// Simple string source
|
|
151
|
+
lines.push(`${name} = "${sourceConfig}"`);
|
|
152
|
+
} else if (sourceConfig.path) {
|
|
153
|
+
// Full config object with path
|
|
154
|
+
lines.push(
|
|
155
|
+
`${name} = { source = "${sourceConfig.source}", path = "${sourceConfig.path}" }`,
|
|
156
|
+
);
|
|
157
|
+
} else {
|
|
158
|
+
// Full config object without path - just write the source
|
|
159
|
+
lines.push(`${name} = "${sourceConfig.source}"`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
} else {
|
|
163
|
+
lines.push("# [capabilities.sources]");
|
|
164
|
+
lines.push("# # GitHub shorthand (uses latest commit)");
|
|
165
|
+
lines.push('# tasks = "github:example-org/tasks-capability"');
|
|
166
|
+
lines.push("#");
|
|
167
|
+
lines.push("# # With subdirectory path");
|
|
168
|
+
lines.push('# ralph = { source = "github:example-org/ralph", path = "plugins/my-cap" }');
|
|
169
|
+
lines.push("#");
|
|
170
|
+
lines.push("# # Other Git sources");
|
|
171
|
+
lines.push('# private = "git@github.com:company/private-cap.git"');
|
|
172
|
+
lines.push('# gitlab = "https://gitlab.com/user/capability.git"');
|
|
173
|
+
}
|
|
152
174
|
lines.push("");
|
|
153
175
|
|
|
154
|
-
// MCP servers
|
|
176
|
+
// MCP servers
|
|
155
177
|
lines.push("# =============================================================================");
|
|
156
178
|
lines.push("# MCP Servers");
|
|
157
179
|
lines.push("# =============================================================================");
|
|
@@ -160,19 +182,67 @@ function generateConfigToml(config: OmniConfig): string {
|
|
|
160
182
|
'# Reference in profiles using the MCP name directly, e.g. capabilities = ["filesystem"]',
|
|
161
183
|
);
|
|
162
184
|
lines.push("#");
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
185
|
+
|
|
186
|
+
const mcps = config.mcps;
|
|
187
|
+
if (mcps && Object.keys(mcps).length > 0) {
|
|
188
|
+
for (const [name, mcpConfig] of Object.entries(mcps)) {
|
|
189
|
+
lines.push(`[mcps.${name}]`);
|
|
190
|
+
|
|
191
|
+
// Transport type (default is stdio)
|
|
192
|
+
if (mcpConfig.transport && mcpConfig.transport !== "stdio") {
|
|
193
|
+
lines.push(`transport = "${mcpConfig.transport}"`);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// For stdio transport
|
|
197
|
+
if (mcpConfig.command) {
|
|
198
|
+
lines.push(`command = "${mcpConfig.command}"`);
|
|
199
|
+
}
|
|
200
|
+
if (mcpConfig.args && mcpConfig.args.length > 0) {
|
|
201
|
+
const argsStr = mcpConfig.args.map((a) => `"${a}"`).join(", ");
|
|
202
|
+
lines.push(`args = [${argsStr}]`);
|
|
203
|
+
}
|
|
204
|
+
if (mcpConfig.cwd) {
|
|
205
|
+
lines.push(`cwd = "${mcpConfig.cwd}"`);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// For http/sse transport
|
|
209
|
+
if (mcpConfig.url) {
|
|
210
|
+
lines.push(`url = "${mcpConfig.url}"`);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Environment variables (sub-table)
|
|
214
|
+
if (mcpConfig.env && Object.keys(mcpConfig.env).length > 0) {
|
|
215
|
+
lines.push(`[mcps.${name}.env]`);
|
|
216
|
+
for (const [key, value] of Object.entries(mcpConfig.env)) {
|
|
217
|
+
lines.push(`${key} = "${value}"`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Headers (sub-table)
|
|
222
|
+
if (mcpConfig.headers && Object.keys(mcpConfig.headers).length > 0) {
|
|
223
|
+
lines.push(`[mcps.${name}.headers]`);
|
|
224
|
+
for (const [key, value] of Object.entries(mcpConfig.headers)) {
|
|
225
|
+
lines.push(`${key} = "${value}"`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
lines.push("");
|
|
230
|
+
}
|
|
231
|
+
} else {
|
|
232
|
+
lines.push("# [mcps.filesystem]");
|
|
233
|
+
lines.push('# command = "npx"');
|
|
234
|
+
lines.push('# args = ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]');
|
|
235
|
+
lines.push('# transport = "stdio" # stdio (default), sse, or http');
|
|
236
|
+
lines.push("#");
|
|
237
|
+
lines.push("# [mcps.database]");
|
|
238
|
+
lines.push('# command = "node"');
|
|
239
|
+
lines.push('# args = ["./servers/database.js"]');
|
|
240
|
+
lines.push('# cwd = "./mcp-servers"');
|
|
241
|
+
lines.push("# [mcps.database.env]");
|
|
242
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: Example of env var syntax
|
|
243
|
+
lines.push('# DB_URL = "${DATABASE_URL}"');
|
|
244
|
+
lines.push("");
|
|
245
|
+
}
|
|
176
246
|
|
|
177
247
|
// Always enabled capabilities
|
|
178
248
|
lines.push("# =============================================================================");
|
|
@@ -181,7 +251,12 @@ function generateConfigToml(config: OmniConfig): string {
|
|
|
181
251
|
lines.push("# Capabilities that load in ALL profiles, regardless of profile config.");
|
|
182
252
|
lines.push("# Useful for essential tools needed everywhere.");
|
|
183
253
|
lines.push("#");
|
|
184
|
-
|
|
254
|
+
if (config.always_enabled_capabilities && config.always_enabled_capabilities.length > 0) {
|
|
255
|
+
const caps = config.always_enabled_capabilities.map((c) => `"${c}"`).join(", ");
|
|
256
|
+
lines.push(`always_enabled_capabilities = [${caps}]`);
|
|
257
|
+
} else {
|
|
258
|
+
lines.push('# always_enabled_capabilities = ["git-tools", "linting"]');
|
|
259
|
+
}
|
|
185
260
|
lines.push("");
|
|
186
261
|
|
|
187
262
|
// Profiles
|
package/src/index.ts
CHANGED
package/src/mcp-json/manager.ts
CHANGED
|
@@ -4,14 +4,37 @@ import type { LoadedCapability, McpConfig } from "../types";
|
|
|
4
4
|
import type { ResourceManifest } from "../state/manifest";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* MCP server configuration in .mcp.json
|
|
7
|
+
* MCP server configuration in .mcp.json for stdio transport
|
|
8
8
|
*/
|
|
9
|
-
export interface
|
|
9
|
+
export interface McpServerStdioConfig {
|
|
10
10
|
command: string;
|
|
11
11
|
args?: string[];
|
|
12
12
|
env?: Record<string, string>;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* MCP server configuration in .mcp.json for HTTP transport
|
|
17
|
+
*/
|
|
18
|
+
export interface McpServerHttpConfig {
|
|
19
|
+
type: "http";
|
|
20
|
+
url: string;
|
|
21
|
+
headers?: Record<string, string>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* MCP server configuration in .mcp.json for SSE transport
|
|
26
|
+
*/
|
|
27
|
+
export interface McpServerSseConfig {
|
|
28
|
+
type: "sse";
|
|
29
|
+
url: string;
|
|
30
|
+
headers?: Record<string, string>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Union type for all MCP server configurations
|
|
35
|
+
*/
|
|
36
|
+
export type McpServerConfig = McpServerStdioConfig | McpServerHttpConfig | McpServerSseConfig;
|
|
37
|
+
|
|
15
38
|
/**
|
|
16
39
|
* Structure of .mcp.json file
|
|
17
40
|
*/
|
|
@@ -52,7 +75,43 @@ export async function writeMcpJson(config: McpJsonConfig): Promise<void> {
|
|
|
52
75
|
* Build MCP server config from capability's mcp section
|
|
53
76
|
*/
|
|
54
77
|
function buildMcpServerConfig(mcp: McpConfig): McpServerConfig {
|
|
55
|
-
const
|
|
78
|
+
const transport = mcp.transport ?? "stdio";
|
|
79
|
+
|
|
80
|
+
// HTTP transport - remote server
|
|
81
|
+
if (transport === "http") {
|
|
82
|
+
if (!mcp.url) {
|
|
83
|
+
throw new Error("HTTP transport requires a URL");
|
|
84
|
+
}
|
|
85
|
+
const config: McpServerHttpConfig = {
|
|
86
|
+
type: "http",
|
|
87
|
+
url: mcp.url,
|
|
88
|
+
};
|
|
89
|
+
if (mcp.headers && Object.keys(mcp.headers).length > 0) {
|
|
90
|
+
config.headers = mcp.headers;
|
|
91
|
+
}
|
|
92
|
+
return config;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// SSE transport - remote server (deprecated)
|
|
96
|
+
if (transport === "sse") {
|
|
97
|
+
if (!mcp.url) {
|
|
98
|
+
throw new Error("SSE transport requires a URL");
|
|
99
|
+
}
|
|
100
|
+
const config: McpServerSseConfig = {
|
|
101
|
+
type: "sse",
|
|
102
|
+
url: mcp.url,
|
|
103
|
+
};
|
|
104
|
+
if (mcp.headers && Object.keys(mcp.headers).length > 0) {
|
|
105
|
+
config.headers = mcp.headers;
|
|
106
|
+
}
|
|
107
|
+
return config;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// stdio transport - local process (default)
|
|
111
|
+
if (!mcp.command) {
|
|
112
|
+
throw new Error("stdio transport requires a command");
|
|
113
|
+
}
|
|
114
|
+
const config: McpServerStdioConfig = {
|
|
56
115
|
command: mcp.command,
|
|
57
116
|
};
|
|
58
117
|
if (mcp.args) {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template for OMNI.md - the user's project instructions file.
|
|
3
|
+
* This is the single source of truth that gets transformed into
|
|
4
|
+
* provider-specific files (CLAUDE.md, AGENTS.md, etc.) during sync.
|
|
5
|
+
*/
|
|
6
|
+
export function generateOmniMdTemplate(): string {
|
|
7
|
+
return `# Project Instructions
|
|
8
|
+
|
|
9
|
+
<!-- This file is your project's instruction manifest for AI agents. -->
|
|
10
|
+
<!-- It will be combined with capability-generated content during sync. -->
|
|
11
|
+
|
|
12
|
+
## Project Description
|
|
13
|
+
|
|
14
|
+
<!-- TODO: Add 2-3 sentences describing your project -->
|
|
15
|
+
[Describe what this project does and its main purpose]
|
|
16
|
+
|
|
17
|
+
## Conventions
|
|
18
|
+
|
|
19
|
+
<!-- Add your project conventions, coding standards, and guidelines here -->
|
|
20
|
+
|
|
21
|
+
## Architecture
|
|
22
|
+
|
|
23
|
+
<!-- Describe your project's architecture and key components -->
|
|
24
|
+
`;
|
|
25
|
+
}
|
package/src/types/index.ts
CHANGED
|
@@ -62,12 +62,37 @@ export interface McpToolSchema {
|
|
|
62
62
|
inputSchema: Record<string, unknown>;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
/**
|
|
66
|
+
* MCP server configuration supporting multiple transport types:
|
|
67
|
+
*
|
|
68
|
+
* - **stdio**: Local process using stdin/stdout (default)
|
|
69
|
+
* - Requires: command
|
|
70
|
+
* - Optional: args, env, cwd
|
|
71
|
+
*
|
|
72
|
+
* - **http**: Remote HTTP server (recommended for remote servers)
|
|
73
|
+
* - Requires: url
|
|
74
|
+
* - Optional: headers (for authentication)
|
|
75
|
+
*
|
|
76
|
+
* - **sse**: Server-Sent Events (deprecated, use http instead)
|
|
77
|
+
* - Requires: url
|
|
78
|
+
* - Optional: headers (for authentication)
|
|
79
|
+
*/
|
|
65
80
|
export interface McpConfig {
|
|
66
|
-
|
|
81
|
+
/** Executable to run (required for stdio transport) */
|
|
82
|
+
command?: string;
|
|
83
|
+
/** Command arguments (stdio transport only) */
|
|
67
84
|
args?: string[];
|
|
85
|
+
/** Environment variables (stdio transport only) */
|
|
68
86
|
env?: Record<string, string>;
|
|
87
|
+
/** Working directory (stdio transport only) */
|
|
69
88
|
cwd?: string;
|
|
89
|
+
/** Transport type: stdio (default), http, or sse */
|
|
70
90
|
transport?: McpTransport;
|
|
91
|
+
/** URL for remote servers (required for http/sse transport) */
|
|
92
|
+
url?: string;
|
|
93
|
+
/** HTTP headers for authentication (http/sse transport only) */
|
|
94
|
+
headers?: Record<string, string>;
|
|
95
|
+
/** Tool schemas (optional, for documentation) */
|
|
71
96
|
tools?: McpToolSchema[];
|
|
72
97
|
}
|
|
73
98
|
|