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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

### Fixes

- **CLI metadata flags**: Handle `--help` and `--version` before server startup so users can inspect usage and version information without requiring Mapbox environment configuration.
- **Prompt descriptions**: Add missing `driving-traffic` transport mode to `get-directions`, `search-along-route`, and `show-reachable-areas` prompt descriptions
- **ground_location_tool**: Use `mapbox/` prefix for isochrone profiles and add `driving-traffic` support
- **ground_location_tool**: Reverse geocode now returns neighborhood/locality/place name instead of street address by default
Expand Down
88 changes: 88 additions & 0 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Copyright (c) Mapbox, Inc.
// Licensed under the MIT License.

interface CliVersionInfo {
name: string;
version: string;
}

interface CliMetadataResult {
handled: boolean;
exitCode: number;
output?: string;
error?: string;
}

const OPTIONS = [
'--help, -h Show this help message',
'--version, -v Show the server version',
'--enable-tools Enable only the comma-separated tools',
'--disable-tools Disable the comma-separated tools',
'--disable-mcp-ui Disable MCP-UI resources'
];

const OPTIONS_WITH_VALUES = new Set(['--enable-tools', '--disable-tools']);
const KNOWN_FLAGS = new Set([
'--help',
'-h',
'--version',
'-v',
'--enable-tools',
'--disable-tools',
'--disable-mcp-ui'
]);

function formatHelp(versionInfo: CliVersionInfo): string {
return [
`${versionInfo.name} ${versionInfo.version}`,
'',
'Usage: mcp-server [options]',
'',
'Options:',
...OPTIONS.map((option) => ` ${option}`),
''
].join('\n');
}

export function handleCliMetadataArgs(
args: string[],
versionInfo: CliVersionInfo
): CliMetadataResult {
if (args.includes('--help') || args.includes('-h')) {
return {
handled: true,
exitCode: 0,
output: formatHelp(versionInfo)
};
}

if (args.includes('--version') || args.includes('-v')) {
return {
handled: true,
exitCode: 0,
output: `${versionInfo.version}\n`
};
}

for (let i = 0; i < args.length; i++) {
const arg = args[i];

if (OPTIONS_WITH_VALUES.has(arg)) {
i++;
continue;
}

if (arg.startsWith('-') && !KNOWN_FLAGS.has(arg)) {
return {
handled: true,
exitCode: 1,
error: `Unknown option: ${arg}\n`
};
}
}

return {
handled: false,
exitCode: 0
};
}
15 changes: 15 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { getAllResources } from './resources/resourceRegistry.js';
import { getAllPrompts, getPromptByName } from './prompts/promptRegistry.js';
import { completePromptArgument } from './completions/index.js';
import { getVersionInfo } from './utils/versionUtils.js';
import { handleCliMetadataArgs } from './cli.js';
import {
initializeTracing,
shutdownTracing,
Expand Down Expand Up @@ -61,6 +62,20 @@ if (existsSync(envPath)) {
}

const versionInfo = getVersionInfo();
const cliMetadataResult = handleCliMetadataArgs(
process.argv.slice(2),
versionInfo
);

if (cliMetadataResult.handled) {
if (cliMetadataResult.output) {
process.stdout.write(cliMetadataResult.output);
}
if (cliMetadataResult.error) {
process.stderr.write(cliMetadataResult.error);
}
process.exit(cliMetadataResult.exitCode);
}

// Parse configuration from command-line arguments
const config = parseToolConfigFromArgs();
Expand Down
74 changes: 74 additions & 0 deletions test/cli.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright (c) Mapbox, Inc.
// Licensed under the MIT License.

import { describe, expect, it } from 'vitest';
import { handleCliMetadataArgs } from '../src/cli.js';

const versionInfo = {
name: 'Mapbox MCP server',
version: '1.2.3'
};

describe('CLI metadata arguments', () => {
it('handles --help before server startup', () => {
const result = handleCliMetadataArgs(['--help'], versionInfo);

expect(result).toEqual({
handled: true,
exitCode: 0,
output: expect.stringContaining('Usage: mcp-server [options]')
});
});

it('handles -h before server startup', () => {
const result = handleCliMetadataArgs(['-h'], versionInfo);

expect(result).toEqual({
handled: true,
exitCode: 0,
output: expect.stringContaining('Usage: mcp-server [options]')
});
});

it('handles --version before server startup', () => {
const result = handleCliMetadataArgs(['--version'], versionInfo);

expect(result).toEqual({
handled: true,
exitCode: 0,
output: '1.2.3\n'
});
});

it('handles -v before server startup', () => {
const result = handleCliMetadataArgs(['-v'], versionInfo);

expect(result).toEqual({
handled: true,
exitCode: 0,
output: '1.2.3\n'
});
});

it('rejects unknown flags before server startup', () => {
const result = handleCliMetadataArgs(['--bogus'], versionInfo);

expect(result).toEqual({
handled: true,
exitCode: 1,
error: 'Unknown option: --bogus\n'
});
});

it('does not handle server configuration flags', () => {
const result = handleCliMetadataArgs(
['--enable-tools', 'version_tool'],
versionInfo
);

expect(result).toEqual({
handled: false,
exitCode: 0
});
});
});
Loading