|
| 1 | +/** |
| 2 | + * CLI argv parsing for `src/index.ts`. All flags map into {@link ConfigOverrides} |
| 3 | + * for {@link resolveConfig}; environment variables remain the fallback there. |
| 4 | + */ |
| 5 | + |
| 6 | +import { |
| 7 | + DEFAULT_INDEX_NAME, |
| 8 | + DEFAULT_RERANK_MODEL, |
| 9 | + SERVER_VERSION, |
| 10 | +} from './constants.js'; |
| 11 | +import type { ConfigOverrides } from './config.js'; |
| 12 | + |
| 13 | +export type ParseCliResult = |
| 14 | + | { kind: 'help' } |
| 15 | + | { kind: 'version' } |
| 16 | + | { kind: 'config'; overrides: ConfigOverrides }; |
| 17 | + |
| 18 | +function parsePositiveInt(raw: string | undefined): number | undefined { |
| 19 | + if (raw === undefined || raw === '') return undefined; |
| 20 | + const n = parseInt(raw, 10); |
| 21 | + return Number.isFinite(n) && n > 0 ? n : undefined; |
| 22 | +} |
| 23 | + |
| 24 | +/** Parse `process.argv` (slice 2..) into help/version/config result. */ |
| 25 | +export function parseCli(argv: string[] = process.argv.slice(2)): ParseCliResult { |
| 26 | + const overrides: ConfigOverrides = {}; |
| 27 | + |
| 28 | + for (let i = 0; i < argv.length; i++) { |
| 29 | + const arg = argv[i]; |
| 30 | + const next = argv[i + 1]; |
| 31 | + |
| 32 | + switch (arg) { |
| 33 | + case '--help': |
| 34 | + case '-h': |
| 35 | + return { kind: 'help' }; |
| 36 | + case '--version': |
| 37 | + case '-v': |
| 38 | + return { kind: 'version' }; |
| 39 | + case '--api-key': |
| 40 | + if (next !== undefined) { |
| 41 | + overrides.apiKey = next; |
| 42 | + i++; |
| 43 | + } |
| 44 | + break; |
| 45 | + case '--index-name': |
| 46 | + if (next !== undefined) { |
| 47 | + overrides.indexName = next; |
| 48 | + i++; |
| 49 | + } |
| 50 | + break; |
| 51 | + case '--sparse-index-name': |
| 52 | + if (next !== undefined) { |
| 53 | + overrides.sparseIndexName = next; |
| 54 | + i++; |
| 55 | + } |
| 56 | + break; |
| 57 | + case '--rerank-model': |
| 58 | + if (next !== undefined) { |
| 59 | + overrides.rerankModel = next; |
| 60 | + i++; |
| 61 | + } |
| 62 | + break; |
| 63 | + case '--top-k': { |
| 64 | + const n = parsePositiveInt(next); |
| 65 | + if (n !== undefined) { |
| 66 | + overrides.defaultTopK = n; |
| 67 | + i++; |
| 68 | + } |
| 69 | + break; |
| 70 | + } |
| 71 | + case '--log-level': |
| 72 | + if (next !== undefined) { |
| 73 | + overrides.logLevel = next; |
| 74 | + i++; |
| 75 | + } |
| 76 | + break; |
| 77 | + case '--log-format': |
| 78 | + if (next !== undefined) { |
| 79 | + overrides.logFormat = next; |
| 80 | + i++; |
| 81 | + } |
| 82 | + break; |
| 83 | + case '--cache-ttl-seconds': { |
| 84 | + const n = parsePositiveInt(next); |
| 85 | + if (n !== undefined) { |
| 86 | + overrides.cacheTtlSeconds = n; |
| 87 | + i++; |
| 88 | + } |
| 89 | + break; |
| 90 | + } |
| 91 | + case '--request-timeout-ms': { |
| 92 | + const n = parsePositiveInt(next); |
| 93 | + if (n !== undefined) { |
| 94 | + overrides.requestTimeoutMs = n; |
| 95 | + i++; |
| 96 | + } |
| 97 | + break; |
| 98 | + } |
| 99 | + case '--disable-suggest-flow': |
| 100 | + overrides.disableSuggestFlow = true; |
| 101 | + break; |
| 102 | + case '--check-indexes': |
| 103 | + overrides.checkIndexes = true; |
| 104 | + break; |
| 105 | + default: |
| 106 | + break; |
| 107 | + } |
| 108 | + } |
| 109 | + |
| 110 | + return { kind: 'config', overrides }; |
| 111 | +} |
| 112 | + |
| 113 | +/** Print CLI usage (stdout). */ |
| 114 | +export function printHelp(): void { |
| 115 | + process.stdout.write(` |
| 116 | +Pinecone Read-Only MCP Server |
| 117 | +
|
| 118 | +Usage: pinecone-read-only-mcp [options] |
| 119 | +
|
| 120 | +Options: |
| 121 | + --api-key TEXT Pinecone API key (or PINECONE_API_KEY) |
| 122 | + --index-name TEXT Dense index [default: ${DEFAULT_INDEX_NAME}] |
| 123 | + --sparse-index-name TEXT Sparse index [default: {index-name}-sparse] |
| 124 | + --rerank-model TEXT Reranker model [default: ${DEFAULT_RERANK_MODEL}] |
| 125 | + --top-k N Default top-k for queries [env: PINECONE_TOP_K] |
| 126 | + --log-level LEVEL DEBUG | INFO | WARN | ERROR [default: INFO] |
| 127 | + --log-format FORMAT text | json [default: text] |
| 128 | + --cache-ttl-seconds N Namespace / suggest-flow cache TTL [env: PINECONE_CACHE_TTL_SECONDS] |
| 129 | + --request-timeout-ms N Per Pinecone call timeout [env: PINECONE_REQUEST_TIMEOUT_MS] |
| 130 | + --disable-suggest-flow Bypass suggest_query_params gate (PINECONE_DISABLE_SUGGEST_FLOW) |
| 131 | + --check-indexes Verify dense + sparse indexes then exit 0/1 (PINECONE_CHECK_INDEXES) |
| 132 | + --help, -h Show this message |
| 133 | + --version, -v Print package version |
| 134 | +
|
| 135 | +Environment variables are documented in README.md (CLI overrides win when both are set). |
| 136 | +
|
| 137 | +Examples: |
| 138 | + pinecone-read-only-mcp --api-key YOUR_KEY |
| 139 | + export PINECONE_API_KEY=YOUR_KEY && pinecone-read-only-mcp --index-name my-index |
| 140 | +`); |
| 141 | +} |
| 142 | + |
| 143 | +/** Print package version (stdout). */ |
| 144 | +export function printVersion(): void { |
| 145 | + process.stdout.write(`${SERVER_VERSION}\n`); |
| 146 | +} |
0 commit comments