Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
3c6fff7
feat(mcp): introduce Model Context Protocol (MCP) command and server …
vscheuber Mar 31, 2026
665fa68
feat(mcp): add pre-authentication for MCP server and enhance error ha…
vscheuber Mar 31, 2026
d4230c0
refactor(mcp): streamline request context handling and improve transp…
vscheuber Apr 1, 2026
4339480
feat(mcp): summarize oversized MCP responses
vscheuber Apr 3, 2026
3fb0278
feat: Add config-manager push managed-objects (#579)
dallinjsevy Apr 3, 2026
4d0082b
Update snapshots
vscheuber Apr 3, 2026
85febbd
Updated changelog and version for release v4.0.0-38
github-actions[bot] Apr 3, 2026
2c1dd23
deployment type adjustments and switched to constant usage over strin…
devintrivir Apr 3, 2026
df164ae
Updated changelog and version for release v4.0.0-39
github-actions[bot] Apr 3, 2026
4b5fc45
feat: Add config-manager push access-config command (#581)
dallinjsevy Apr 3, 2026
935ffac
Updated changelog and version for release v4.0.0-40
github-actions[bot] Apr 3, 2026
c491f4a
feat: Add config-manager push audit command (#582)
dallinjsevy Apr 3, 2026
4096259
Updated changelog and version for release v4.0.0-41
github-actions[bot] Apr 3, 2026
c23210d
fix: update @rockcarver/frodo-lib to version 4.0.0-36 and normalize a…
vscheuber Apr 8, 2026
573ef7d
Updated changelog and version for release v4.0.0-42
github-actions[bot] Apr 8, 2026
318de47
feat: Add config-manager push cookie-domains command (#583)
dallinjsevy Apr 8, 2026
52db6ff
feat: Add config-manager-push service-object command (#584)
dallinjsevy Apr 8, 2026
de4835c
feat: Add config-manager push ui-config command (#585)
dallinjsevy Apr 8, 2026
20622c1
Updated changelog and version for release v4.0.0-43
github-actions[bot] Apr 8, 2026
d96aa18
feat(mcp): introduce Model Context Protocol (MCP) command and server …
vscheuber Mar 31, 2026
58360d7
feat: Add config-manager push managed-objects (#579)
dallinjsevy Apr 3, 2026
7da099d
feat(mcp): introduce Model Context Protocol (MCP) command and server …
vscheuber Mar 31, 2026
795fec2
fix: update @rockcarver/frodo-lib to version 4.0.0-36 and normalize a…
vscheuber Apr 8, 2026
a4b9ae4
Update -M, --modified-properties to remove creation timestamps (#587)
brycentrivir Apr 17, 2026
58f45cf
Updated changelog and version for release v4.0.0-44
github-actions[bot] Apr 17, 2026
1c6557a
Make extraction the default for exports (#588)
brycentrivir Apr 17, 2026
eb8c0f8
Updated changelog and version for release v4.0.0-45
github-actions[bot] Apr 17, 2026
7120faa
Initial plan
Copilot Apr 19, 2026
9a1612c
feat: add label-driven release bumping and integration batching workflow
Copilot Apr 19, 2026
36db3dc
chore: address workflow/docs review nits
Copilot Apr 19, 2026
c15fb01
Initial plan
Copilot Apr 19, 2026
ef16120
fix: emit compact JSON outputs in integration-batch workflow
Copilot Apr 19, 2026
055c9b0
Initial plan
Copilot Apr 19, 2026
09131d8
fix: use check-runs criteria for integration batch selection
Copilot Apr 19, 2026
30df339
chore: harden check-runs parsing in integration workflow
Copilot Apr 19, 2026
ddd29fd
Initial plan
Copilot Apr 19, 2026
8f33756
feat: automate integration batch merge conflict recovery
Copilot Apr 19, 2026
eaf6bb5
fix: address review feedback for integration merge automation
Copilot Apr 19, 2026
c92866c
fix: apply PR review feedback for merge script output handling
Copilot Apr 19, 2026
f5fd73f
Initial plan
Copilot Apr 19, 2026
b802588
fix: auto-regenerate lockfile on integration merge conflicts
Copilot Apr 19, 2026
202b409
chore: simplify snapshot conflict condition
Copilot Apr 19, 2026
1ae63e7
fix: add lockfile regeneration failure handling
Copilot Apr 19, 2026
9857274
chore: refine lockfile regeneration diagnostics
Copilot Apr 19, 2026
865f9ee
Update .github/integration/scripts/merge_prs.sh
vscheuber Apr 19, 2026
50b5edd
Update .github/workflows/integration-batch.yml
vscheuber Apr 19, 2026
7e930e4
fix: report lockfile auto-resolution from regeneration summary
Copilot Apr 19, 2026
7901ace
Initial plan
Copilot Apr 19, 2026
3c39add
fix: prepare frodo cli before snapshot updates in integration batching
Copilot Apr 19, 2026
1ea165e
fix: rebuild frodo before each snapshot update batch
Copilot Apr 20, 2026
a335ed5
fix: refresh frodo install on each snapshot update pass
Copilot Apr 20, 2026
dcacd39
Initial plan
Copilot Apr 20, 2026
791156d
feat: run post-push integration tests in integration-batch workflow
Copilot Apr 20, 2026
4ff951b
chore: harden npm global bin resolution in integration test step
Copilot Apr 20, 2026
56102a2
Updated changelog and version for release v4.0.0-46
github-actions[bot] Apr 20, 2026
e8189e7
feat: Add config-manager push authentication command
github-actions[bot] Mar 19, 2026
4d8512f
feat: Add config-manager push connector-definitions command
dallinjsevy Jun 25, 2023
3a18ea8
test: update snapshots for integration conflict resolution
github-actions[bot] Apr 20, 2026
2279348
feat: add config-manager-pull command for custom nodes
brycentrivir Apr 13, 2026
7626768
refactor: remove unused printMessage import from config-manager-pull-…
vscheuber Apr 20, 2026
b0efb1c
add missing help menus for config-manager commands
d-rex14 Mar 19, 2026
0cd0855
do not export scheduler objects provided by the API
devintrivir Mar 27, 2026
0832803
Updated changelog and version for release v4.0.0-47
github-actions[bot] Apr 20, 2026
81f0fb2
Initial plan
Copilot Apr 20, 2026
cde45c1
ci: label integration PR when snapshot updates are present
Copilot Apr 20, 2026
6433ced
ci: add snapshot-review label to generated integration PR
Copilot Apr 20, 2026
da2a19b
Update .github/workflows/integration-batch.yml
vscheuber Apr 21, 2026
30d6c34
Updated changelog and version for release v4.0.0-48
github-actions[bot] Apr 21, 2026
31e7700
Update to frodo-lib 4.0.0-38 and updated recordings for authz-set-imp…
vscheuber Apr 25, 2026
0867337
Merge branch 'main' into mcp-server
vscheuber Apr 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
841 changes: 839 additions & 2 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@
]
},
"devDependencies": {
"@rockcarver/frodo-lib": "4.0.0-37",
"@modelcontextprotocol/sdk": "^1.29.0",
"@rockcarver/frodo-lib": "4.0.0-39",
"@types/colors": "^1.2.1",
"@types/fs-extra": "^11.0.1",
"@types/jest": "^29.2.3",
Expand Down Expand Up @@ -138,6 +139,7 @@
"tsup": "^8.1.0",
"typescript": "^5.2.2",
"uuid": "^11.1.0",
"yesno": "^0.4.0"
"yesno": "^0.4.0",
"zod": "^4.3.6"
}
}
2 changes: 2 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import info from './cli/info/info';
import journey from './cli/journey/journey';
import log from './cli/log/log';
import mapping from './cli/mapping/mapping';
import mcp from './cli/mcp/mcp';
import node from './cli/node/node';
import oauth from './cli/oauth/oauth';
import promote from './cli/promote/promote';
Expand Down Expand Up @@ -93,6 +94,7 @@ process.argv = normalizeExpandedHelpArgv(process.argv);
program.addCommand(journey());
program.addCommand(log());
program.addCommand(mapping());
program.addCommand(mcp().helpGroup(utilitiesCommandsHeading));
program.addCommand(node());
program.addCommand(oauth());
program.addCommand(promote());
Expand Down
15 changes: 15 additions & 0 deletions src/cli/mcp/mcp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { FrodoStubCommand } from '../FrodoCommand';
import mcpServer from './server/server.js';

/**
* Top-level MCP command group.
*/
export default function setup() {
const program = new FrodoStubCommand('mcp')
.description('Manage Model Context Protocol (MCP) integrations.')
.withStability('experimental');

program.addCommand(mcpServer());

return program;
}
190 changes: 190 additions & 0 deletions src/cli/mcp/server/server-start.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
import { createMcpService, frodo, state } from '@rockcarver/frodo-lib';
import { Option } from 'commander';

import {
startHttpTransport,
startStdioTransport,
} from '../../../ops/McpServerOps.js';
import { printMessage } from '../../../utils/Console';
import { FrodoCommand } from '../../FrodoCommand';

type McpPolicyPreset = 'read-only' | 'standard' | 'admin';

/** Parsed options for `frodo mcp server start`. */
type McpStartOptions = {
/** Policy preset controlling capability exposure. */
policy: McpPolicyPreset;
/** Optional allow-list of top-level capability domains. */
includeDomains?: string[];
/** Optional deny-list of top-level capability domains. */
excludeDomains?: string[];
/** Whether to include the `utils` top-level domain. */
includeUtils?: boolean;
/** Transport mode to launch. */
transport?: 'stdio' | 'http';
/** Bind host for HTTP transport. */
bindHost?: string;
/** Bind port for HTTP transport. */
port?: string;
/** Build and validate service composition without launching transport. */
dryRun?: boolean;
/** Print startup summary as JSON. */
json?: boolean;
};

/**
* MCP server start command.
*/
export default function setup() {
const program = new FrodoCommand('frodo mcp server start', [])
.description('Start an MCP server session from frodo-lib capabilities.')
.withStability('experimental')
.addOption(
new Option('--policy <preset>', 'Capability policy preset.')
.choices(['read-only', 'standard', 'admin'])
.default('standard')
)
.addOption(
new Option(
'--include-domains <domain...>',
'Only include the listed top-level domains in capability discovery.'
)
)
.addOption(
new Option(
'--exclude-domains <domain...>',
'Exclude listed top-level domains from capability discovery.'
)
)
.addOption(
new Option(
'--include-utils',
'Include the utils domain in discovery.'
).default(false)
)
.addOption(
new Option('--transport <transport>', 'Server transport mode.')
.choices(['stdio', 'http'])
.default('stdio')
)
.addOption(
new Option('--bind-host <host>', 'Bind host for HTTP transport.').default(
'127.0.0.1'
)
)
.addOption(
new Option('--port <port>', 'Bind port for HTTP transport.').default(
'6277'
)
)
.addOption(
new Option(
'--dry-run',
'Build and validate MCP service composition, then exit.'
).default(false)
)
.addOption(
new Option('--json', 'Print startup summary as JSON.').default(false)
)
.action(async (host, realm, username, password, options, command) => {
command.handleDefaultArgsAndOpts(
host,
realm,
username,
password,
options,
command
);

const opts = options as McpStartOptions;
const service = createMcpService({
policyPreset: opts.policy,
inventoryOptions: {
includeTopLevelDomains: opts.includeDomains,
excludeTopLevelDomains: opts.excludeDomains,
includeUtils: !!opts.includeUtils,
},
// Reuse the preconfigured frodo singleton; the CLI has already
// applied connection credentials via handleDefaultArgsAndOpts.
runtimeOptions: {
resolveFrodoForRequest: async () => frodo,
},
});

const startupSummary = {
policy: service.policy.name,
transport: opts.transport,
http: {
bindHost: opts.bindHost,
port: Number(opts.port),
},
authMode: inferAuthModeFromState(),
toolCounts: {
total: service.manifest.totalToolCount,
generic: service.manifest.genericTools.length,
special: service.manifest.specialTools.length,
},
descriptorCount: service.manifest.backingDescriptorCount,
};

if (opts.json) {
printMessage(JSON.stringify(startupSummary, null, 2), 'data');
} else {
printMessage('MCP server startup summary:', 'info');
printMessage(` Policy: ${startupSummary.policy}`);
printMessage(` Transport: ${startupSummary.transport}`);
printMessage(` Auth mode: ${startupSummary.authMode}`);
printMessage(
` Tools: ${startupSummary.toolCounts.total} total (${startupSummary.toolCounts.generic} generic, ${startupSummary.toolCounts.special} special)`
);
printMessage(
` Backing descriptors: ${startupSummary.descriptorCount}`
);
if (opts.transport === 'http') {
printMessage(
` HTTP endpoint (planned): http://${startupSummary.http.bindHost}:${startupSummary.http.port}/mcp`
);
}
}

if (opts.dryRun) {
printMessage('Dry run completed successfully.', 'info');
return;
}

const transport = opts.transport ?? 'stdio';
if (transport === 'stdio') {
await startStdioTransport(service);
} else {
await startHttpTransport(
service,
opts.bindHost ?? '127.0.0.1',
Number(opts.port ?? '6277')
);
}
});

return program;
}

/**
* Infers runtime auth mode from currently configured global state.
*/
function inferAuthModeFromState():
| 'service-account'
| 'admin-account'
| 'state-config' {
const serviceAccountId = state.getServiceAccountId();
const serviceAccountJwk = state.getServiceAccountJwk();
if (serviceAccountId && serviceAccountJwk) {
return 'service-account';
}

const username = state.getUsername();
const password = state.getPassword();
if (username && password) {
return 'admin-account';
}

return 'state-config';
}
100 changes: 100 additions & 0 deletions src/cli/mcp/server/server-tools.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { createMcpService } from '@rockcarver/frodo-lib';
import { Option } from 'commander';

import { printMessage } from '../../../utils/Console';
import { FrodoCommand } from '../../FrodoCommand';

type McpPolicyPreset = 'read-only' | 'standard' | 'admin';

/** Parsed options for `frodo mcp server tools`. */
type McpToolsOptions = {
/** Policy preset controlling capability exposure. */
policy: McpPolicyPreset;
/** Optional allow-list of top-level capability domains. */
includeDomains?: string[];
/** Optional deny-list of top-level capability domains. */
excludeDomains?: string[];
/** Whether to include the `utils` top-level domain. */
includeUtils?: boolean;
/** Print tool definitions as JSON. */
json?: boolean;
};

/**
* Lists the current MCP tool surface derived from frodo-lib descriptors.
*/
export default function setup() {
const program = new FrodoCommand('frodo mcp server tools', ['realm'])
.description('List MCP tools exposed under the current policy/profile.')
.withStability('experimental')
.addOption(
new Option('--policy <preset>', 'Capability policy preset.')
.choices(['read-only', 'standard', 'admin'])
.default('standard')
)
.addOption(
new Option(
'--include-domains <domain...>',
'Only include the listed top-level domains in capability discovery.'
)
)
.addOption(
new Option(
'--exclude-domains <domain...>',
'Exclude listed top-level domains from capability discovery.'
)
)
.addOption(
new Option(
'--include-utils',
'Include the utils domain in discovery.'
).default(false)
)
.addOption(new Option('--json', 'Print tool list as JSON.').default(false))
.action(async (host, username, password, options, command) => {
command.handleDefaultArgsAndOpts(
host,
username,
password,
options,
command
);

const opts = options as McpToolsOptions;
const service = createMcpService({
policyPreset: opts.policy,
inventoryOptions: {
includeTopLevelDomains: opts.includeDomains,
excludeTopLevelDomains: opts.excludeDomains,
includeUtils: !!opts.includeUtils,
},
});

const tools = service.listTools();
if (opts.json) {
printMessage(
JSON.stringify(
{
policy: service.policy.name,
total: tools.length,
tools,
},
null,
2
),
'data'
);
return;
}

printMessage(
`MCP tools (${tools.length}) for policy '${service.policy.name}':`,
'info'
);
for (const tool of tools) {
printMessage(`- ${tool.name}: ${tool.description}`);
}
});

return program;
}
17 changes: 17 additions & 0 deletions src/cli/mcp/server/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { FrodoStubCommand } from '../../FrodoCommand';
import startCmd from './server-start.js';
import toolsCmd from './server-tools.js';

/**
* MCP server command group.
*/
export default function setup() {
const program = new FrodoStubCommand('server')
.description('Manage Frodo MCP server lifecycle and metadata.')
.withStability('experimental');

program.addCommand(startCmd().name('start'));
program.addCommand(toolsCmd().name('tools'));

return program;
}
Loading