Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions .github/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,8 @@ If you are a node developer and want to use frodo as a cli tool or as a library

### MCP Server

For instructions on configuring a specific MCP client (VS Code Copilot, Claude Code, Claude Desktop, and others) to connect to this server, see the [MCP client setup guide](../docs/MCP_CLIENT_SETUP.md).

Start the MCP server with a saved connection profile:

```console
Expand Down
71 changes: 71 additions & 0 deletions docs/MCP_CLIENT_SETUP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Setting up Frodo MCP in an MCP Client

This guide covers how to configure an MCP client to connect to Frodo's MCP server (`frodo mcp server start`). For what the server does once connected -- skill discovery, policy presets, profiles, logging -- see the [MCP Server](../.github/README.md#mcp-server) section of the main README. This guide is only about the client-side wiring: where each client's config file lives and what to put in it.

MCP client configuration file formats are still evolving and differ from client to client. The examples below were verified against each client's own documentation at the time of writing; if a client has since changed its config schema, trust that client's own current docs over this file, and please open an issue or PR to update this guide.

## Prerequisites

- Frodo installed and on `PATH` (`npm i -g @rockcarver/frodo-cli`), or invoked via `npx @rockcarver/frodo-cli`.
- A saved [connection profile](../.github/README.md#connection-profiles) for the tenant you want the MCP server to target (`frodo conn add ...`), so `frodo mcp server start <profile>` doesn't need credentials on the command line or in a client config file.

Frodo's MCP server supports two transports (`frodo mcp server start --help` for the full flag list):

- **stdio** (default): the client launches `frodo mcp server start ...` as a subprocess and talks to it over stdin/stdout. This is what every example below uses -- it's the simplest, most widely supported option and needs no separate process management.
- **http** (`--transport http --bind-host <host> --port <port>`, default `127.0.0.1:6277`): you start the server yourself as a long-running process, and point a client that supports HTTP/SSE-based MCP servers at its URL instead of a launch command. Support for this varies more by client than stdio does, so prefer stdio unless you have a specific reason to run the server long-lived and shared across multiple client sessions.

## VS Code Copilot (Agent Mode)

VS Code reads MCP server definitions from a `.vscode/mcp.json` file in the workspace root (or from VS Code's user-level MCP settings for a config you want available across projects). Its schema uses a top-level `servers` key -- not `mcpServers`, which is what Claude Desktop and some other clients use -- and requires an explicit `"type": "stdio"` on each entry.

`.vscode/mcp.json`:

```json
{
"servers": {
"frodo": {
"type": "stdio",
"command": "frodo",
"args": ["mcp", "server", "start", "my-tenant"]
}
}
}
```

Replace `my-tenant` with the name of a saved connection profile. Restart VS Code (or reload the window) after adding or changing this file. Once the workspace opens, Copilot starts the server and its tools become available in Agent Mode.

## Claude Code

Claude Code is configured via the `claude mcp add` command rather than by hand-editing a config file directly (though it does write one under the hood). For a stdio server, options come before the server name, and `--` separates the server name from the command Claude Code should run:

```console
claude mcp add --transport stdio frodo -- frodo mcp server start my-tenant
```

Use `--scope project` instead of the default user scope if you want this registered only for the current project rather than for all of Claude Code. Verify with `claude mcp list`.

## Claude Desktop

Claude Desktop reads `claude_desktop_config.json`:

- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`

Its schema uses `mcpServers` as the top-level key, and typically infers stdio transport from the presence of `command`/`args` rather than requiring an explicit `type` field (unlike VS Code):

```json
{
"mcpServers": {
"frodo": {
"command": "frodo",
"args": ["mcp", "server", "start", "my-tenant"]
}
}
}
```

Restart Claude Desktop after editing this file for the change to take effect.

## Other MCP clients

Any MCP client that supports launching a local stdio server should work the same way: point it at the `frodo` executable with args `["mcp", "server", "start", "<profile>"]` (or the fully-qualified path/`npx @rockcarver/frodo-cli` invocation, if `frodo` isn't globally on `PATH` in that client's execution environment). Consult the client's own documentation for its specific config file location and key names.
18 changes: 18 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ const tsConfigs = compat
'no-console': 'warn',
'no-underscore-dangle': 'off',
'no-restricted-syntax': ['error', 'LabeledStatement', 'WithStatement'],
'no-restricted-imports': [
'error',
{
paths: [
{
name: 'tinyrainbow',
message:
"Import color from './utils/ColorTheme' (relative path may vary) instead of 'tinyrainbow' directly, so the color palette stays centralized in one place.",
},
],
},
],
'no-multi-str': 'off',
'simple-import-sort/imports': 'error',
'simple-import-sort/exports': 'error',
Expand All @@ -47,4 +59,10 @@ export default [
ignores: ['src/**/*.test.ts', 'src/**/*.test_.ts', 'test/**/*.test.ts', 'test/**/*.test_.ts', 'tsup.config.ts'],
},
...tsConfigs,
{
files: ['src/utils/ColorTheme.ts'],
rules: {
'no-restricted-imports': 'off',
},
},
];
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@
"@modelcontextprotocol/client": "^2.0.0",
"@modelcontextprotocol/node": "^2.0.0",
"@modelcontextprotocol/server": "^2.0.0",
"@rockcarver/frodo-lib": "4.4.2",
"@rockcarver/frodo-lib": "4.5.0",
"@types/colors": "^1.2.1",
"@types/fs-extra": "^11.0.1",
"@types/jest": "^29.2.3",
Expand Down
2 changes: 1 addition & 1 deletion src/cli/_template/something-delete.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';
import c from 'tinyrainbow';

import * as s from '../../help/SampleData';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { FrodoCommand } from '../FrodoCommand';

const { DEPLOYMENT_TYPES } = frodo.utils.constants;
Expand Down
2 changes: 1 addition & 1 deletion src/cli/_template/something-describe.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';
import c from 'tinyrainbow';

import * as s from '../../help/SampleData';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { FrodoCommand } from '../FrodoCommand';

const { DEPLOYMENT_TYPES } = frodo.utils.constants;
Expand Down
2 changes: 1 addition & 1 deletion src/cli/_template/something-else-delete.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';
import c from 'tinyrainbow';

import * as s from '../../help/SampleData';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { FrodoCommand } from '../FrodoCommand';

const { DEPLOYMENT_TYPES } = frodo.utils.constants;
Expand Down
2 changes: 1 addition & 1 deletion src/cli/_template/something-else-describe.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';
import c from 'tinyrainbow';

import * as s from '../../help/SampleData';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { FrodoCommand } from '../FrodoCommand';

const { DEPLOYMENT_TYPES } = frodo.utils.constants;
Expand Down
2 changes: 1 addition & 1 deletion src/cli/_template/something-else-export.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';
import c from 'tinyrainbow';

import * as s from '../../help/SampleData';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { FrodoCommand } from '../FrodoCommand';

const { DEPLOYMENT_TYPES } = frodo.utils.constants;
Expand Down
2 changes: 1 addition & 1 deletion src/cli/_template/something-else-import.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';
import c from 'tinyrainbow';

import * as s from '../../help/SampleData';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { FrodoCommand } from '../FrodoCommand';

const { DEPLOYMENT_TYPES } = frodo.utils.constants;
Expand Down
2 changes: 1 addition & 1 deletion src/cli/_template/something-else-list.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';
import c from 'tinyrainbow';

import * as s from '../../help/SampleData';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { FrodoCommand } from '../FrodoCommand';

const { DEPLOYMENT_TYPES } = frodo.utils.constants;
Expand Down
2 changes: 1 addition & 1 deletion src/cli/_template/something-export.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';
import c from 'tinyrainbow';

import * as s from '../../help/SampleData';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { FrodoCommand } from '../FrodoCommand';

const { DEPLOYMENT_TYPES } = frodo.utils.constants;
Expand Down
2 changes: 1 addition & 1 deletion src/cli/_template/something-import.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';
import c from 'tinyrainbow';

import * as s from '../../help/SampleData';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { FrodoCommand } from '../FrodoCommand';

const { DEPLOYMENT_TYPES } = frodo.utils.constants;
Expand Down
2 changes: 1 addition & 1 deletion src/cli/_template/something-list.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';
import c from 'tinyrainbow';

import * as s from '../../help/SampleData';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { FrodoCommand } from '../FrodoCommand';

const { DEPLOYMENT_TYPES } = frodo.utils.constants;
Expand Down
2 changes: 1 addition & 1 deletion src/cli/_template/something-other-delete.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';
import c from 'tinyrainbow';

import * as s from '../../help/SampleData';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { FrodoCommand } from '../FrodoCommand';

const { DEPLOYMENT_TYPES } = frodo.utils.constants;
Expand Down
2 changes: 1 addition & 1 deletion src/cli/_template/something-other-describe.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';
import c from 'tinyrainbow';

import * as s from '../../help/SampleData';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { FrodoCommand } from '../FrodoCommand';

const { DEPLOYMENT_TYPES } = frodo.utils.constants;
Expand Down
2 changes: 1 addition & 1 deletion src/cli/_template/something-other-export.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';
import c from 'tinyrainbow';

import * as s from '../../help/SampleData';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { FrodoCommand } from '../FrodoCommand';

const { DEPLOYMENT_TYPES } = frodo.utils.constants;
Expand Down
2 changes: 1 addition & 1 deletion src/cli/_template/something-other-import.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';
import c from 'tinyrainbow';

import * as s from '../../help/SampleData';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { FrodoCommand } from '../FrodoCommand';

const { DEPLOYMENT_TYPES } = frodo.utils.constants;
Expand Down
2 changes: 1 addition & 1 deletion src/cli/_template/something-other-list.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';
import c from 'tinyrainbow';

import * as s from '../../help/SampleData';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { FrodoCommand } from '../FrodoCommand';

const { DEPLOYMENT_TYPES } = frodo.utils.constants;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { frodo, state } from '@rockcarver/frodo-lib';
import Table from 'cli-table3';
import { Option } from 'commander';
import c from 'tinyrainbow';
import { v4 as uuidv4 } from 'uuid';

import {
createLongLivedToken,
createOAuth2ClientWithAdminPrivileges,
} from '../../ops/AdminOps';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { printError, printMessage } from '../../utils/Console.js';
import { FrodoCommand } from '../FrodoCommand';

Expand Down
2 changes: 1 addition & 1 deletion src/cli/admin/admin-execute-rfc7523-authz-grant-flow.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { JwkRsa } from '@rockcarver/frodo-lib/types/ops/JoseOps.js';
import { Option } from 'commander';
import fs from 'fs';
import c from 'tinyrainbow';
import { v4 as uuidv4 } from 'uuid';

import * as s from '../../help/SampleData';
import { executeRfc7523AuthZGrantFlow } from '../../ops/AdminOps.js';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { printMessage } from '../../utils/Console.js';
import { FrodoCommand } from '../FrodoCommand.js';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { state } from '@rockcarver/frodo-lib';
import { JwkRsa } from '@rockcarver/frodo-lib/types/ops/JoseOps.js';
import { Option } from 'commander';
import fs from 'fs';
import c from 'tinyrainbow';
import { v4 as uuidv4 } from 'uuid';

import * as s from '../../help/SampleData';
import { generateRfc7523AuthZGrantArtefacts } from '../../ops/AdminOps.js';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { printMessage } from '../../utils/Console.js';
import { FrodoCommand } from '../FrodoCommand.js';

Expand Down
2 changes: 1 addition & 1 deletion src/cli/app/app-delete.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';
import c from 'tinyrainbow';

import * as s from '../../help/SampleData';
import {
deleteApplication,
deleteApplications,
} from '../../ops/ApplicationOps';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { verboseMessage } from '../../utils/Console';
import { FrodoCommand } from '../FrodoCommand';

Expand Down
2 changes: 1 addition & 1 deletion src/cli/app/app-describe.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';
import c from 'tinyrainbow';

import * as s from '../../help/SampleData';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { FrodoCommand } from '../FrodoCommand';

const { CLOUD_DEPLOYMENT_TYPE_KEY, FORGEOPS_DEPLOYMENT_TYPE_KEY } =
Expand Down
2 changes: 1 addition & 1 deletion src/cli/app/app-export.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';
import c from 'tinyrainbow';

import * as s from '../../help/SampleData';
import {
Expand All @@ -9,6 +8,7 @@ import {
exportApplicationToFile,
} from '../../ops/ApplicationOps';
import { getTokens } from '../../ops/AuthenticateOps';
import c from '../../utils/ColorTheme';
import { verboseMessage } from '../../utils/Console.js';
import { FrodoCommand } from '../FrodoCommand';

Expand Down
Loading
Loading