Skip to content
Open
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
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,28 @@ fi

### Config File Format

The CLI uses `mcp_servers.json`, compatible with Claude Desktop, Gemini or VS Code:
The CLI uses `mcp_servers.json`, compatible with Claude Desktop, Gemini or VS Code.
A JSON Schema is included at the repo root as [`mcp_servers.schema.json`](./mcp_servers.schema.json) for editor validation/autocomplete.

### JSON Schema / editor integration

If your editor supports JSON Schema associations, point `mcp_servers.json` at the published raw file:

```json
{
"$schema": "https://raw.githubusercontent.com/philschmid/mcp-cli/main/mcp_servers.schema.json",
"mcpServers": {
"local-server": {
"command": "node",
"args": ["./server.js"]
}
}
}
```

Then your editor can validate fields like `command`, `args`, `url`, `headers`, `allowedTools`, and `disabledTools` while you edit the config.

The config file itself looks like this:

```json
{
Expand Down Expand Up @@ -347,6 +368,8 @@ The CLI searches for configuration in this order:
4. `~/.mcp_servers.json`
5. `~/.config/mcp/mcp_servers.json`

If you use a local config file in the project root, adding the `$schema` field shown above gives you immediate editor feedback before running `mcp-cli`.

### Environment Variables

| Variable | Description | Default |
Expand Down
102 changes: 102 additions & 0 deletions mcp_servers.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://raw.githubusercontent.com/philschmid/mcp-cli/main/mcp_servers.schema.json",
"title": "mcp-cli configuration",
"type": "object",
"additionalProperties": false,
"required": ["mcpServers"],
"properties": {
"mcpServers": {
"type": "object",
"description": "Named MCP server definitions.",
"additionalProperties": { "$ref": "#/$defs/serverConfig" }
}
},
"$defs": {
"globArray": {
"type": "array",
"items": { "type": "string" }
},
"stringMap": {
"type": "object",
"additionalProperties": { "type": "string" }
},
"baseServerConfig": {
"type": "object",
"properties": {
"allowedTools": {
"$ref": "#/$defs/globArray",
"description": "Optional glob patterns for tools to allow."
},
"disabledTools": {
"$ref": "#/$defs/globArray",
"description": "Optional glob patterns for tools to exclude."
}
}
},
"stdioServerConfig": {
"allOf": [
{ "$ref": "#/$defs/baseServerConfig" },
{
"type": "object",
"additionalProperties": false,
"required": ["command"],
"properties": {
"command": {
"type": "string",
"description": "Executable used to start the MCP server."
},
"args": {
"type": "array",
"items": { "type": "string" },
"description": "Optional command-line arguments passed to the server."
},
"env": {
"$ref": "#/$defs/stringMap",
"description": "Optional environment variables passed to the stdio server process."
},
"cwd": {
"type": "string",
"description": "Optional working directory used when launching the stdio server."
},
"allowedTools": { "$ref": "#/$defs/globArray" },
"disabledTools": { "$ref": "#/$defs/globArray" }
}
}
]
},
"httpServerConfig": {
"allOf": [
{ "$ref": "#/$defs/baseServerConfig" },
{
"type": "object",
"additionalProperties": false,
"required": ["url"],
"properties": {
"url": {
"type": "string",
"format": "uri",
"description": "HTTP endpoint for the remote MCP server."
},
"headers": {
"$ref": "#/$defs/stringMap",
"description": "Optional HTTP headers sent when connecting to the MCP server."
},
"timeout": {
"type": "number",
"description": "Optional per-request timeout in milliseconds."
},
"allowedTools": { "$ref": "#/$defs/globArray" },
"disabledTools": { "$ref": "#/$defs/globArray" }
}
}
]
},
"serverConfig": {
"oneOf": [
{ "$ref": "#/$defs/stdioServerConfig" },
{ "$ref": "#/$defs/httpServerConfig" }
]
}
}
}
4 changes: 0 additions & 4 deletions src/output.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,8 @@ export function formatServerDetails(

if (isHttpServer(config)) {
lines.push(`${color('Transport:', colors.bold)} HTTP`);
lines.push(`${color('URL:', colors.bold)} ${config.url}`);
} else {
lines.push(`${color('Transport:', colors.bold)} stdio`);
lines.push(
`${color('Command:', colors.bold)} ${config.command} ${(config.args || []).join(' ')}`,
);
}

if (instructions) {
Expand Down
36 changes: 36 additions & 0 deletions tests/output.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import { describe, test, expect } from 'bun:test';
import {
formatServerDetails,
formatServerList,
formatSearchResults,
formatToolSchema,
Expand Down Expand Up @@ -101,6 +102,41 @@ describe('output', () => {
});
});

describe('formatServerDetails', () => {
test('shows transport without stdio command details', () => {
const output = formatServerDetails(
'filesystem',
{
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-filesystem', '.'],
},
[],
);

expect(output).toContain('Server:');
expect(output).toContain('filesystem');
expect(output).toContain('Transport:');
expect(output).toContain('stdio');
expect(output).not.toContain('Command:');
expect(output).not.toContain('@modelcontextprotocol/server-filesystem');
});

test('shows transport without http endpoint details', () => {
const output = formatServerDetails(
'deepwiki',
{ url: 'https://mcp.deepwiki.com/mcp' },
[],
);

expect(output).toContain('Server:');
expect(output).toContain('deepwiki');
expect(output).toContain('Transport:');
expect(output).toContain('HTTP');
expect(output).not.toContain('URL:');
expect(output).not.toContain('https://mcp.deepwiki.com/mcp');
});
});

describe('formatToolSchema', () => {
test('formats tool with schema', () => {
const tool = {
Expand Down