tgrep-mcp 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Shizhy
3
+ Copyright (c) 2026 tgrep-mcp contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -47,7 +47,7 @@ Two details matter:
47
47
  MCP handshake stalls.
48
48
  - Set `cwd` to the repository you want to search. See [Search root](#search-root).
49
49
 
50
- To pin a version, use `"args": ["-y", "tgrep-mcp@0.3.0"]`.
50
+ To pin a version, use `"args": ["-y", "tgrep-mcp@0.3.1"]`.
51
51
 
52
52
  To run from a checkout instead:
53
53
 
package/package.json CHANGED
@@ -1,9 +1,8 @@
1
1
  {
2
2
  "name": "tgrep-mcp",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "MCP server that exposes tgrep, a trigram-indexed regex search tool, over stdio.",
5
5
  "license": "MIT",
6
- "author": "Shizhy <usstpeter@163.com>",
7
6
  "type": "module",
8
7
  "bin": {
9
8
  "tgrep-mcp": "server.mjs"
package/server.mjs CHANGED
@@ -71,7 +71,7 @@ function resolveVersion() {
71
71
  } catch {
72
72
  // no manifest available
73
73
  }
74
- return '0.3.0'
74
+ return '0.3.1'
75
75
  }
76
76
 
77
77
  const VERSION = resolveVersion()
@@ -1408,29 +1408,30 @@ const ERROR_SCHEMA = Object.freeze({
1408
1408
  })
1409
1409
 
1410
1410
  /**
1411
- * The three output schemas below are `{ oneOf: [...] }` with NO sibling keywords, on purpose.
1411
+ * Every output schema is one root-level `{ type: 'object' }` with `ok` as the only required field.
1412
1412
  *
1413
- * The harness enforces a JSON Schema subset (dsh-tools assertSupportedJsonSchema, reached through
1414
- * dsh-mcp-client's supportedOutputSchema) that rejects a node declaring `type`, `properties`,
1415
- * `required`, `additionalProperties`, `items`, `enum` or `const` *beside* `oneOf` and a rejected
1416
- * schema is silently discarded, which would quietly relax structuredContent from required back to
1417
- * optional without anyone noticing. So every branch is a complete object schema standing alone, and
1418
- * the discriminating `const` carries its own `type` (the subset requires a type-correct const).
1413
+ * Two constraints meet here and rule out the obvious `{ type: 'object', oneOf: [...] }` shape:
1414
+ * - The MCP spec, enforced by the SDK's ToolSchema, requires `type: 'object'` at the root of
1415
+ * `outputSchema`. A schema without it makes the client reject the entire tools/list result, so
1416
+ * the server connects but registers no tools at all.
1417
+ * - The harness's enforced subset (dsh-tools assertSupportedJsonSchema, reached through
1418
+ * dsh-mcp-client's supportedOutputSchema) rejects `type` beside `oneOf`, and silently drops the
1419
+ * schema, which relaxes structuredContent from required back to optional.
1420
+ * Because no union keyword satisfies both, the union is flattened rather than nested: branch-specific
1421
+ * fields become optional siblings of `ok`. Success and error payloads both validate; the per-branch
1422
+ * strictness that `oneOf` would have given is lost.
1419
1423
  */
1420
- const OK_BRANCH = (properties, required) => ({
1424
+ const outputSchema = (properties) => Object.freeze({
1421
1425
  type: 'object',
1422
- properties: { ok: { type: 'boolean', const: true }, ...properties },
1423
- required: ['ok', ...required],
1426
+ properties: {
1427
+ ok: { type: 'boolean', description: 'True on success; false when the result carries an error.' },
1428
+ error: ERROR_SCHEMA,
1429
+ ...properties,
1430
+ },
1431
+ required: ['ok'],
1424
1432
  additionalProperties: false,
1425
1433
  })
1426
1434
 
1427
- const ERROR_BRANCH = {
1428
- type: 'object',
1429
- properties: { ok: { type: 'boolean', const: false }, error: ERROR_SCHEMA },
1430
- required: ['ok', 'error'],
1431
- additionalProperties: false,
1432
- }
1433
-
1434
1435
  const SEARCH_SUCCESS_PROPERTIES = {
1435
1436
  root: { type: 'string', description: 'Indexed root the search ran against.' },
1436
1437
  target: { type: 'string', description: 'Exact file or directory searched.' },
@@ -1452,52 +1453,37 @@ const SEARCH_SUCCESS_PROPERTIES = {
1452
1453
  warnings: { type: 'array', items: { type: 'string' } },
1453
1454
  }
1454
1455
 
1455
- const SEARCH_OUTPUT_SCHEMA = Object.freeze({
1456
- oneOf: [
1457
- OK_BRANCH(SEARCH_SUCCESS_PROPERTIES, ['root', 'target', 'kind', 'backend', 'elapsedMs', 'total', 'files', 'returned', 'truncated', 'matches']),
1458
- ERROR_BRANCH,
1459
- ],
1460
- })
1456
+ const SEARCH_OUTPUT_SCHEMA = outputSchema(SEARCH_SUCCESS_PROPERTIES)
1461
1457
 
1462
- const INDEX_OUTPUT_SCHEMA = Object.freeze({
1463
- oneOf: [
1464
- OK_BRANCH({
1465
- root: { type: 'string' },
1466
- status: { type: 'string', enum: ['ready', 'failed'] },
1467
- builtMs: { type: 'number' },
1468
- indexDir: { type: 'string' },
1469
- indexAgeMs: { type: 'number' },
1470
- daemonRestarted: { type: 'boolean' },
1471
- }, ['root', 'status', 'indexDir']),
1472
- ERROR_BRANCH,
1473
- ],
1458
+ const INDEX_OUTPUT_SCHEMA = outputSchema({
1459
+ root: { type: 'string' },
1460
+ status: { type: 'string', enum: ['ready', 'failed'] },
1461
+ builtMs: { type: 'number' },
1462
+ indexDir: { type: 'string' },
1463
+ indexAgeMs: { type: 'number' },
1464
+ daemonRestarted: { type: 'boolean' },
1474
1465
  })
1475
1466
 
1476
- const STATUS_OUTPUT_SCHEMA = Object.freeze({
1477
- oneOf: [
1478
- OK_BRANCH({
1479
- status: { type: 'string', enum: ['healthy', 'degraded', 'unhealthy'] },
1480
- version: { type: 'string' },
1481
- checks: {
1482
- type: 'array',
1483
- items: {
1484
- type: 'object',
1485
- properties: {
1486
- name: { type: 'string' },
1487
- status: { type: 'string', enum: ['healthy', 'degraded', 'unhealthy'] },
1488
- message: { type: 'string' },
1489
- responseTimeMs: { type: 'number' },
1490
- details: { type: 'object' },
1491
- },
1492
- required: ['name', 'status', 'message'],
1493
- additionalProperties: false,
1494
- },
1467
+ const STATUS_OUTPUT_SCHEMA = outputSchema({
1468
+ status: { type: 'string', enum: ['healthy', 'degraded', 'unhealthy'] },
1469
+ version: { type: 'string' },
1470
+ checks: {
1471
+ type: 'array',
1472
+ items: {
1473
+ type: 'object',
1474
+ properties: {
1475
+ name: { type: 'string' },
1476
+ status: { type: 'string', enum: ['healthy', 'degraded', 'unhealthy'] },
1477
+ message: { type: 'string' },
1478
+ responseTimeMs: { type: 'number' },
1479
+ details: { type: 'object' },
1495
1480
  },
1496
- config: { type: 'object' },
1497
- metrics: { type: 'object' },
1498
- }, ['status', 'version', 'checks', 'config', 'metrics']),
1499
- ERROR_BRANCH,
1500
- ],
1481
+ required: ['name', 'status', 'message'],
1482
+ additionalProperties: false,
1483
+ },
1484
+ },
1485
+ config: { type: 'object' },
1486
+ metrics: { type: 'object' },
1501
1487
  })
1502
1488
 
1503
1489
  /**